微信生态开发:支付、登录与开放平台的坑

微信生态不是"一个 API",是一套规则:小程序、公众号、开放平台、支付,每个都有自己的凭证、接口和坑。这篇文章是六年微信开发(小程序/服务号/支付/开放平台)的踩坑总结。

一、三种身份凭证

凭证 用途 有效期
AppID + AppSecret 公众号/小程序的身份 永久
access_token 调用接口的令牌 2 小时,需缓存刷新
openid / unionid 用户身份 永久

核心概念

o u p n e i n o i n d i d u n i o / n i d o p e n i d I D I D + + A p p

二、微信登录(自动授权)

w x . c l o o d t g e o i 2 k n S e ( e n ) s s i o n c o d e o p e n i d + s e s s i o n _ k e y
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 后端(小程序登录)
func WxLogin(ctx, code string) (*LoginResult, error) {
    resp, _ := http.Get(fmt.Sprintf(
        "https://api.weixin.qq.com/sns/jscode2session"+
        "?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
        appid, secret, code))
    // resp: {openid, session_key, unionid}
    user := findOrCreateByOpenid(resp.Openid)
    return issueToken(user), nil
}

c c s o o e d d s e e s i o n _ k s 5 e e y s s i o n _ k e y

三、微信支付

核心流程

+ n o t i f y _ u r l

关键:支付回调(最容易错的)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
func PayNotify(w http.ResponseWriter, r *http.Request) {
    // 1. 读回调(XML/JSON)
    body := readBody(r)
    // 2. 验签(用 APIv3 密钥/证书)
    if !verifySignature(r, body) {
        w.WriteHeader(401); return   // 验签失败:不返回成功
    }
    // 3. 查单确认(别只信回调!回调可能重复/伪造)
    order := wx.QueryOrder(body.OutTradeNo)
    if order.Status != "SUCCESS" {
        w.WriteHeader(400); return
    }
    // 4. 幂等更新(回调可能来多次!)
    if !markOrderPaid(order.OutTradeNo) {   // DB 幂等
        w.WriteHeader(200); return          // 已处理过:返回成功(不重发)
    }
    // 5. 必须返回成功(否则微信会重试 24h!)
    w.WriteHeader(200)
}

回调的铁律

" " = 2 4 / =

退款

退 1 2 3 4 . . . . 退 退 退 退 退 A P I 退 v 3 退 退 v 退 s / 退

四、开放平台

1 2 3 4 . . . . / " u n " i o n i d

五、防重与安全

a c c e s s _ t o o p k e I e n P n i / d t o + k e n

六、踩坑记录

  1. access_token 并发刷新互踢:多个实例同时刷新 → 旧的失效,新的也失效 → 加分布式锁 + 本地缓存
  2. 金额用浮点:0.1 + 0.2 = 0.30000000000000004 → 订单金额错 → 一律用"分"(整数)
  3. 回调重复触发:返回非 200 → 微信重试 24h → 幂等处理 + 必须返回成功
  4. unionid 拿不到:小程序没绑开放平台 → 调接口没 unionid → 先绑再开发

总结

微信生态的核心认知:

  1. 三种凭证 + 两种用户 ID:openid 应用内唯一,unionid 跨应用打通
  2. 支付回调四铁律:验签、查单、幂等、必返成功
  3. 金额用分:整数运算,浮点是事故源
  4. access_token 全局管理:缓存 + 刷新锁,防互踢

微信生态的复杂度不在"接口多",在"状态机多":登录态、支付态、退款态,每个状态转换都有规则和坑。把状态机画清楚,微信开发就成功了一半。