Skip to content

在 UniApp 开发的微信小程序里接入微信支付,只需“小程序端负责调起、后端负责拿预支付单”,把两端各 3 个关键步骤跑通即可上线。下面给出 2025 年仍适用的完整流程、代码示例与常见坑位。


一、前置条件(必须先把“账号、证书、域名”配好)

  1. 小程序已开通微信支付(微信商户平台 → 产品中心 → 小程序支付)
  2. 在商户后台拿到 5 个核心参数:
    mchId、apiV3Key、证书(apiclient_cert.pem / key)、appId、appSecret
    (2025 年新申请默认就是 APIv3,不再用 v2)
  3. 小程序后台配置「业务域名」「支付授权目录」:
    必须是后端接收回调的公网地址,例如 https://pay.xxx.com/wx/callback

二、整体时序(一张图记牢)

小程序端 ——1.下单请求→ Java/Node 后端 ——2.统一下单→ 微信 ——3.prepay_id→ 后端
后端二次签名后 ——4.支付参数→ 小程序端 ——5.uni.requestPayment→ 微信客户端
用户输密完成 ——6.异步通知→ 后端更新订单


三、后端(以 SpringBoot + 微信支付 SDK 为例)

  1. 引入依赖(2025 稳定版)
xml
<dependency>
    <groupId>com.github.wechatpay-apiv3</groupId>
    <artifactId>wechatpay-java</artifactId>
    <version>0.4.12</version>
</dependency>
  1. 统一下单 + 二次签名(关键代码,可直接复制)
java
@PostMapping("/wx/createOrder")
public Map<String,String> createOrder(@RequestBody OrderDTO dto) throws Exception {
    // 1. 先写一条业务订单,状态=PAYING
    String outTradeNo = IdUtil.getSnowflake().nextIdStr();
    saveOrder(outTradeNo, dto.getAmount());

    // 2. 构建微信请求
    HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
    httpPost.addHeader("Accept", "application/json");
    httpPost.addHeader("Content-type","application/json; charset=utf-8");

    String reqdata = JSONUtil.toJsonStr(MapUtil.builder()
            .put("appid", "wx123456789")          // 小程序 appId
            .put("mchid", "1900000001")           // 商户号
            .put("description", dto.getBody())
            .put("out_trade_no", outTradeNo)
            .put("notify_url", "https://pay.xxx.com/wx/callback")
            .put("amount", MapUtil.of("total", dto.getAmount()))
            .put("payer", MapUtil.of("openid", dto.getOpenid()))
            .build());

    httpPost.setEntity(new StringEntity(reqdata, "utf-8"));
    // 使用 SDK 的 RSA 自动签名
    CloseableHttpResponse resp = wxPayClient.execute(httpPost);

    String prepayId = JSONUtil.parseObj(EntityUtils.toString(resp.getEntity()))
                               .getStr("prepay_id");

    // 3. 二次签名,返回给 uniapp 的 5 个参数
    String timeStamp = String.valueOf(System.currentTimeMillis()/1000);
    String nonceStr = IdUtil.fastSimpleUUID();
    String packageStr = "prepay_id=" + prepayId;

    String signStr = Stream.of("wx123456789", timeStamp, nonceStr, packageStr)
                           .collect(Collectors.joining("\n", "", "\n"));
    String paySign = SignUtil.signRSA(signStr, merchantPrivateKey);

    return MapUtil.builder()
            .put("appId", "wx123456789")
            .put("timeStamp", timeStamp)
            .put("nonceStr", nonceStr)
            .put("package", packageStr)
            .put("signType", "RSA")
            .put("paySign", paySign)
            .build();
}
  1. 回调验签 & 修改订单
java
@PostMapping("/wx/callback")
public String callback(HttpServletRequest req) throws Exception {
    String body = IoUtil.read(req.getInputStream(), "utf-8");
    // 微信 2025 仍是 XML,先解析
    Map<String,String> map = WXPayUtil.xmlToMap(body);
    boolean ok = WXPayUtil.isSignatureValid(map, apiV3Key, SignType.HMACSHA256);
    if(ok && "SUCCESS".equals(map.get("result_code"))){
        String outTradeNo = map.get("out_trade_no");
        updateOrderPaid(outTradeNo);   // 把订单状态改成 PAID
    }
    return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
}

四、小程序端(UniApp)

  1. 获取用户 openid(第一次必须走 wx.login
js
wx.login({
  success({code}) {
    uni.request({
      url:`${baseUrl}/wx/getOpenid?code=${code}`,
      success:res=>{ uni.setStorageSync('openid', res.data.openid) }
    })
  }
})
  1. 下单并调起收银台
js
async function toPay(){
  const openid = uni.getStorageSync('openid');
  const res = await uni.request({
    url: `${baseUrl}/wx/createOrder`,
    method:'POST',
    data:{ amount:1, body:'测试商品', openid }
  });
  const pay = res.data;
  uni.requestPayment({
    provider:'wxpay',
    timeStamp: pay.timeStamp,
    nonceStr:  pay.nonceStr,
    package:   pay.package,
    signType:  pay.signType,
    paySign:   pay.paySign,
    success:()=>{ uni.showToast({title:'支付成功'}) },
    fail:(e)=>{ console.log('支付失败',e) }
  });
}

provider 必须写 'wxpay';package 必须是 prepay_id=xxx 这种格式,否则微信会提示 “验签失败”。