微信支付接入全流程:JSAPI支付、小程序支付与H5支付

0 阅读3分钟

微信支付三种模式


1️⃣ JSAPI支付(微信内H5)

JSAPI支付有两种调用方式:

方式特点适用场景
方式A:JSSDK需引入wxjssdk,需wx.config配置签名需要更多微信能力(分享、扫码等)
方式B:WeixinJSBridge无需引入SDK,直接调用微信内置桥只需要支付,代码更简单

方式A:JSSDK(wx.chooseWXPay)

// 1. 引入JSSDK
// <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>

// 2. 后端提供签名(appId、timestamp、nonceStr、signature)
wx.config({
  appId: 'xxx',
  timestamp: '时间戳',
  nonceStr: '随机串',
  signature: '后端签名',
  jsApiList: ['chooseWXPay']
});

// 3. 发起支付
wx.ready(() => {
  wx.chooseWXPay({
    timestamp: '时间戳',
    nonceStr: '随机串',
    package: 'prepay_id=xxx',
    signType: 'RSA',
    paySign: '签名',
    success: () => checkOrderStatus(orderId),
    fail: () => showCancelResult()
  });
});

方式B:WeixinJSBridge(推荐简单场景)

// 后端返回支付参数后,直接调用
function onBridgeReady() {
  WeixinJSBridge.invoke('getBrandWCPayRequest', {
    appId: 'xxx',           // 后端返回
    timeStamp: '时间戳',    // 后端返回
    nonceStr: '随机串',     // 后端返回
    package: 'prepay_id=xxx', // 后端返回
    signType: 'RSA',        // 后端返回
    paySign: '签名'         // 后端返回
  }, function(res) {
    if (res.err_msg === 'get_brand_wcpay_request:ok') {
      // 支付成功,但需查询后端确认
      checkOrderStatus(orderId);
    } else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
      // 用户取消
      showCancelResult();
    } else {
      // 支付失败
      showFailResult();
    }
  });
}

// 判断是否在微信环境
if (typeof WeixinJSBridge === 'undefined') {
  document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
} else {
  onBridgeReady();
}

JSAPI完整流程(两种方式通用)

前端                    后端                    微信
 │                      │                      │
 ├─ 1.点击支付 ────────→│                      │
 │                      ├─ 2.统一下单 ────────→│
 │                      │← 3.prepay_id ────────┤
 │← 4.签名参数 ─────────┤                      │
 ├─ 5.调起支付 ──────────────────────────────→│
 │← 6.用户完成/取消 ──────────────────────────┤
 │                      │← 7.异步通知 ─────────┤
 │                      ├─ 8.验签更新订单 ─────│
 │                      │                      │
 ├─ 9.查询订单状态 ────→│                      │
 │← 10.返回结果 ────────┤                      │
 ├─ 11.显示结果         │                      │

2️⃣ 小程序支付

完整流程:

前端                    后端                    微信
 │                      │                      │
 ├─ 1.点击支付 ────────→│                      │
 │                      ├─ 2.统一下单 ────────→│
 │                      │  (trade_type=JSAPI)  │
 │                      │← 3.prepay_id ────────┤
 │← 4.签名参数 ─────────┤                      │
 ├─ 5.调起支付 ──────────────────────────────→│
 │← 6.用户完成/取消 ──────────────────────────┤
 │                      │← 7.异步通知 ─────────┤
 │                      ├─ 8.验签更新订单 ─────│
 │                      │                      │
 ├─ 9.查询订单状态 ────→│                      │
 │← 10.返回结果 ────────┤                      │
 ├─ 11.显示结果         │                      │

前端代码:

// 1. 调用后端接口获取支付参数
async function handlePay(orderId) {
  const res = await api.createPay(orderId);
  
  // 2. 调用微信支付
  wx.requestPayment({
    timeStamp: res.timeStamp,     // 后端返回
    nonceStr: res.nonceStr,       // 后端返回
    package: res.package,         // 后端返回,格式:prepay_id=xxx
    signType: res.signType,       // 后端返回,固定RSA
    paySign: res.paySign,         // 后端返回
    success: () => {
      // 支付完成,查询后端确认结果
      checkOrderStatus(orderId);
    },
    fail: (err) => {
      if (err.errMsg === 'requestPayment:fail cancel') {
        // 用户取消
        showCancelResult();
      } else {
        // 支付失败
        showFailResult();
      }
    }
  });
}

// 3. 轮询查询订单状态
function checkOrderStatus(orderId) {
  let count = 0;
  const timer = setInterval(async () => {
    const res = await api.getOrderStatus(orderId);
    if (res.status === 'PAID') {
      clearInterval(timer);
      showSuccessPage();
    }
    if (++count >= 10) {
      clearInterval(timer);
      showPendingPage(); // 处理中
    }
  }, 2000);
}

小程序支付与JSAPI的区别:

对比项小程序支付JSAPI支付
运行环境微信小程序内微信内H5页面
调用APIwx.requestPaymentwx.chooseWXPay 或 WeixinJSBridge
是否需要SDK不需要(小程序内置)JSSDK方式需要,WeixinJSBridge不需要
签名方式RSARSA
返回结果success/fail回调res.err_msg判断

3️⃣ H5支付(微信外浏览器)

流程:

// 1. 获取支付链接
const res = await api.createH5Pay(orderId);
const mwebUrl = res.mweb_url;

// 2. 保存订单信息(支付后返回时查询)
localStorage.setItem('pendingOrderId', orderId);

// 3. 跳转到微信支付
window.location.href = mwebUrl;

// 4. 支付完成后微信跳回 redirect_url
// 在回调页查询订单状态
window.onload = async () => {
  const orderId = localStorage.getItem('pendingOrderId');
  if (orderId) {
    localStorage.removeItem('pendingOrderId');
    checkOrderStatus(orderId);
  }
};

公共逻辑:轮询查询订单状态

function checkOrderStatus(orderId) {
  let count = 0;
  const timer = setInterval(async () => {
    const res = await api.getOrderStatus(orderId);
    if (res.status === 'PAID') {
      clearInterval(timer);
      showSuccessPage();
    }
    if (++count >= 10) {
      clearInterval(timer);
      showPendingPage(); // 处理中
    }
  }, 2000);
}

前端开发清单

模块开发内容
公共① 订单状态查询接口
② 轮询逻辑
③ 结果页面(成功/失败/处理中)
JSAPI-AJSSDK配置 + wx.chooseWXPay
JSAPI-BWeixinJSBridge.invoke(无需SDK)
小程序wx.requestPayment
H5跳转mweb_url + 回调页查询

后端接口清单

POST /api/pay/create        // 创建支付(返回签名参数或mweb_url)
GET  /api/pay/status/:id    // 查询订单支付状态