微信支付「WeChatPay」

预计阅读时间: 4 分钟

业务需求:

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

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

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

支付方式:

  • 方式一:微信支付【微信公众号】
    • 此支付方式需要在 HTML 页面中引入 JS 文件,即jweixin-1.6.0.js
    • 此 JS 文件链接支持httphttps两种形式,引用时需要匹配当前项目的请求-响应协议(即http、https);
    • 该 JS 文件支持使用AMD/CMD标准模块加载方式加载。
JSSDK 支付
1let WeChatPay = function() {
2	// 2、引入js后、获取公众号校验信息
3	let timestamp = '',
4		nonceStr = '',
5		signature = '';
6	let v = {
7		// 用于换取微信校验信息的参数:要求不可以包含 “#” 号
8		url: location.split('#')[0]
9	};
10
11	// 3、通过config接口注入权限验证配置(需要同步进行,在获取到校验信息后方可注入config,否则校验失败!)
12	wx.config({
13		debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
14		appId: '', // 必填,公众号的唯一标识
15		timestamp: , // 必填,生成签名的时间戳
16		nonceStr: '', // 必填,生成签名的随机串
17		signature: '', // 必填,签名
18		jsApiList: ["checkJsApi", "chooseWXPay", "updateAppMessageShareData", "updateTimelineShareData"] // 必填,需要使用的JS接口列表
19	});
20
21	axios.post('/wx/pay/orderPay_XXXX', data).then(res => {
22		// 支付成功状态
23		if (res.code == 200) {
24			// 获取支付必备的参数
25			let {
26				nonceStr,
27				package,
28				signType,
29				paySign
30			} = res.data;
31			// 4、通过ready接口处理成功验证
32			wx.ready(function() {
33				/* 微信支付 */
34				wx.chooseWXPay({
35					timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
36					nonceStr: nonceStr, // 支付签名随机串,不长于 32 位
37					package: package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
38					signType: signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
39					paySign: paySign, // 支付签名
40					success: function(res) {
41						// 前端判断返回方式,微信团队郑重提示:不保证绝对可靠,切记!
42						if (res.errMsg == 'chooseWXPay:ok') {
43							// 【支付成功】
44						} else if (res.errMsg == 'chooseWXPay:cancel') {
45							// 【支付取消】:用户取消支付不会进入这个判断,而是进入complate和cancel函数
46						} else {
47
48						}
49					},
50					complete: function(res) {
51						// 接口调用完成时执行的回调函数,无论成功或失败都会执行
52						if (res.errMsg == 'chooseWXPay:ok') {
53							// 【支付成功】:支付成功提示页面,点击完成按钮之后
54							wx.closeWindow(); /* 关闭微信窗口,调用时需要在config中进行校验 */
55						} else if (res.errMsg == 'chooseWXPay:cancel') {
56							// 【支付取消】
57						} else {
58
59						}
60						/**
61						 * iOS和Android支付成功点击“完成”后都会进入success和complete函数,都返回'chooseWXPay:ok'
62						 * (也有人说Android支付成功不进入success函数,)
63						 * 原因是【iOS和Android返回数据不同。支付成功后Android返回 {"errMsg":"getBrandWCPayRequest:ok"},iOS返回{"err_Info":"success","errMsg":"chooseWXPay:ok"},故Android找不到success方法,导致失败】
64						 * */
65					},
66					fail: function(err) {
67						// 接口调用失败
68					},
69					cancel: function(err) {
70						// 用户点击取消时的回调函数:用户取消支付后实际上进入cancel 和 complate函数
71					}
72				});
73			});
74		}
75	}).catch(err => {
76		console.log('支付失败:', err);
77	});
78}
  • 接口说明:【不要尝试在 trigger 中使用 ajax 异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用 ajax 的回包会还没有返回。

    1. success:接口调用成功时执行的回调函数。
    2. fail:接口调用失败时执行的回调函数。
    3. complete:接口调用完成时执行的回调函数,无论成功或失败都会执行。
    4. cancel:用户点击取消时的回调函数,仅部分有用户取消操作的 api 才会用到。
    5. trigger: 监听 Menu 中的按钮点击时触发的方法,该方法仅支持 Menu 中的相关接口。
  • 方式二:微信支付【 JSAPI 支付】(常用支付方式)

JSAPI 支付
1function onBridgeReady() {
2	WeixinJSBridge.invoke(
3		"getBrandWCPayRequest",
4		{
5			appId: "appId", //公众号名称,由商户传入
6			timeStamp: "timeStamp", //时间戳,自1970年以来的秒数
7			nonceStr: "nonceStr", //随机串
8			package: "package",
9			signType: "MD5", //微信签名方式:
10			paySign: "paySign" //微信签名
11		},
12		function (res) {
13			// 支付成功
14			if (res.err_msg == "get_brand_wcpay_request:ok") {
15				// 使用以上方式判断前端返回,微信团队郑重提示:
16				//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
17			}
18			// 支付过程中用户取消
19			if (res.err_msg == "get_brand_wcpay_request:cancel") {
20			}
21			// 支付失败
22			if (res.err_msg == "get_brand_wcpay_request:fail") {
23			}
24			/**
25			 * 其它
26			 * 1、请检查预支付会话标识prepay_id是否已失效
27			 * 2、请求的appid与下单接口的appid是否一致
28			 * */
29			if (res.err_msg == "调用支付JSAPI缺少参数:total_fee") {
30			}
31		}
32	);
33}
34// 检测支付环境中的 WeixinJSBridge
35if (typeof WeixinJSBridge == "undefined") {
36	if (document.addEventListener) {
37		document.addEventListener("WeixinJSBridgeReady", onBridgeReady, false);
38	} else if (document.attachEvent) {
39		document.attachEvent("WeixinJSBridgeReady", onBridgeReady);
40		document.attachEvent("onWeixinJSBridgeReady", onBridgeReady);
41	}
42} else {
43	onBridgeReady();
44}

JSAPI 调起支付注意事项:

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