> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# 微信 H5 支付

## 业务需求：

现在涉及到微信相关的项目有很多，主要涉及到的功能有 **【微信自定义分享】**、**【微信支付】** 等。开发微信公众号 H5 页面时，需要使用微信支付进行金融支付。当微信支付完成 **【支付成功 点击“完成”】** 时，需要出发相应的业务逻辑；比如：支付成功时跳转到订单页面；支付失败时跳转到下订单页面；支付取消时保持当前订单页面不变等。

前期开发微信 H5 页面时，大多考虑的就是 **【支付成功】** 之后如何处理，因为是刚接触微信支付，大多都是采用刷新页面获取新数据的方式来更新支付状态。这种方式可以解决当时面临的问题，但是从业务逻辑来看，处理的方式不是很合理。

支付场景越来越多，对微信支付流程有了进一步的了解和认识，现在回过头来对过去项目中使用 **【微信支付】** 的业务场景进行梳理和完善，进一步优化支付流程以及对支付后的不同状态做相应的处理和优化，并结合实际情况做相应的业务逻辑分析。

## 支付方式：

- **方式一：**[**微信支付【微信公众号】**](https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#58)
  - 此支付方式需要在 HTML 页面中引入 JS 文件，即[【 **jweixin-1.6.0.js** 】](http://res.wx.qq.com/open/js/jweixin-1.6.0.js)；
  - 此 JS 文件链接支持**http**和**https**两种形式，引用时需要匹配当前项目的**请求-响应协议**（即**http、https**）；
  - 该 JS 文件支持使用**AMD**/**CMD**标准模块加载方式加载。

```javascript title="JSSDK 支付"
let WeChatPay = function() {
	// 2、引入js后、获取公众号校验信息
	let timestamp = '',
		nonceStr = '',
		signature = '';
	let v = {
		// 用于换取微信校验信息的参数：要求不可以包含 “#” 号
		url: location.split('#')[0]
	};

	// 3、通过config接口注入权限验证配置（需要同步进行，在获取到校验信息后方可注入config，否则校验失败！）
	wx.config({
		debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来，若要查看传入的参数，可以在pc端打开，参数信息会通过log打出，仅在pc端时才会打印。
		appId: '', // 必填，公众号的唯一标识
		timestamp: , // 必填，生成签名的时间戳
		nonceStr: '', // 必填，生成签名的随机串
		signature: '', // 必填，签名
		jsApiList: ["checkJsApi", "chooseWXPay", "updateAppMessageShareData", "updateTimelineShareData"] // 必填，需要使用的JS接口列表
	});

	axios.post('/wx/pay/orderPay_XXXX', data).then(res => {
		// 支付成功状态
		if (res.code == 200) {
			// 获取支付必备的参数
			let {
				nonceStr,
				package,
				signType,
				paySign
			} = res.data;
			// 4、通过ready接口处理成功验证
			wx.ready(function() {
				/* 微信支付 */
				wx.chooseWXPay({
					timestamp: 0, // 支付签名时间戳，注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
					nonceStr: nonceStr, // 支付签名随机串，不长于 32 位
					package: package, // 统一支付接口返回的prepay_id参数值，提交格式如：prepay_id=\*\*\*）
					signType: signType, // 签名方式，默认为'SHA1'，使用新版支付需传入'MD5'
					paySign: paySign, // 支付签名
					success: function(res) {
						// 前端判断返回方式，微信团队郑重提示：不保证绝对可靠，切记！
						if (res.errMsg == 'chooseWXPay:ok') {
							// 【支付成功】
						} else if (res.errMsg == 'chooseWXPay:cancel') {
							// 【支付取消】：用户取消支付不会进入这个判断，而是进入complate和cancel函数
						} else {

						}
					},
					complete: function(res) {
						// 接口调用完成时执行的回调函数，无论成功或失败都会执行
						if (res.errMsg == 'chooseWXPay:ok') {
							// 【支付成功】：支付成功提示页面，点击完成按钮之后
							wx.closeWindow(); /* 关闭微信窗口，调用时需要在config中进行校验 */
						} else if (res.errMsg == 'chooseWXPay:cancel') {
							// 【支付取消】
						} else {

						}
						/**
						 * iOS和Android支付成功点击“完成”后都会进入success和complete函数，都返回'chooseWXPay:ok'
						 * （也有人说Android支付成功不进入success函数，）
						 * 原因是【iOS和Android返回数据不同。支付成功后Android返回 {"errMsg":"getBrandWCPayRequest:ok"}，iOS返回{"err_Info":"success","errMsg":"chooseWXPay:ok"}，故Android找不到success方法，导致失败】
						 * */
					},
					fail: function(err) {
						// 接口调用失败
					},
					cancel: function(err) {
						// 用户点击取消时的回调函数：用户取消支付后实际上进入cancel 和 complate函数
					}
				});
			});
		}
	}).catch(err => {
		console.log('支付失败：', err);
	});
}
```

- **接口说明：【**&#x4E0D;要尝试在 trigger 中使用 ajax 异步请求修改本次分享的内容，因为客户端分享操作是一个同步操作，这时候使用 ajax 的回包会还没有返回。**】**

  1. **success**：接口调用成功时执行的回调函数。
  2. **fail**：接口调用失败时执行的回调函数。
  3. **complete**：接口调用完成时执行的回调函数，无论成功或失败都会执行。
  4. **cancel**：用户点击取消时的回调函数，仅部分有用户取消操作的 api 才会用到。
  5. **trigger**: 监听 Menu 中的按钮点击时触发的方法，该方法仅支持 Menu 中的相关接口。

- **方式二：**[**微信支付【 JSAPI 支付】**](https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7\&index=6)（常用支付方式）

```javascript title="JSAPI 支付"
function onBridgeReady() {
    WeixinJSBridge.invoke(
        "getBrandWCPayRequest",
        {
            appId: "appId", //公众号名称，由商户传入
            timeStamp: "timeStamp", //时间戳，自1970年以来的秒数
            nonceStr: "nonceStr", //随机串
            package: "package",
            signType: "MD5", //微信签名方式：
            paySign: "paySign", //微信签名
        },
        function (res) {
            // 支付成功
            if (res.err_msg == "get_brand_wcpay_request:ok") {
                // 使用以上方式判断前端返回,微信团队郑重提示：
                //res.err_msg将在用户支付成功后返回ok，但并不保证它绝对可靠。
            }
            // 支付过程中用户取消
            if (res.err_msg == "get_brand_wcpay_request:cancel") {
            }
            // 支付失败
            if (res.err_msg == "get_brand_wcpay_request:fail") {
            }
            /**
             * 其它
             * 1、请检查预支付会话标识prepay_id是否已失效
             * 2、请求的appid与下单接口的appid是否一致
             * */
            if (res.err_msg == "调用支付JSAPI缺少参数：total_fee") {
            }
        }
    );
}
// 检测支付环境中的 WeixinJSBridge
if (typeof WeixinJSBridge == "undefined") {
    if (document.addEventListener) {
        document.addEventListener("WeixinJSBridgeReady", onBridgeReady, false);
    } else if (document.attachEvent) {
        document.attachEvent("WeixinJSBridgeReady", onBridgeReady);
        document.attachEvent("onWeixinJSBridgeReady", onBridgeReady);
    }
} else {
    onBridgeReady();
}
```

**JSAPI 调起支付注意事项：**

- 在微信浏览器里打开 H5 网页中执行 JS 调起支付；
- **WeixinJSBridge** 是微信浏览器内置对象，在其他浏览器中无效；
- 调用支付传递的参数注意 **区分大小写**。
