前言
微信支付业务,针对小程序、微信浏览器和非微信浏览器中的网页的三种场景,我们可以分别通过官方提供的 小程序支付、JSAPI支付、H5支付来开发。
准备工作
开通微信商户号、微信公众号然后按照步骤准备一堆资料审核,然后设置相关配置。所以最好提前准备资料审核以免耽误开发进度。配置的步骤:官方文档,直接按照官方文档配置就行了。需要特别注意的是配置商户号的支付授权目录和公众号的授权域名必须一致,不然会调起支付失败的!
参考资料:
JSAPI支付配置文档
H5支付配置文档
小程序支付
JS-SDK
H5 支付
开发流程
- 请求创建订单接口拿到订单数据(
orderId
,订单号,支付金额) - 带
orderId
请求支付接口,获得mweb_url
- 跳转到微信支付中间页
mweb_url
,然后自动调用微信支付 - 支付成功后跳转到配置的返回页(请求支付时携带的参数
redirectUrl
)
实现代码
伪代码
async wxPayByH5() {
// 商品信息
let goodsList = { goodsId: 1 };
let params = {
goodsList: goodsList,
}
// 1. 创建订单
let data = await createOrder(params);
// 获得 订单id:orderId;订单总金额:orderTotalPrice;订单号:orderNo
let { orderId, orderTotalPrice, orderNo } = data;
let paramsPay = {
orderId,
// redirectUrl: 支付完成后返回的页面
redirectUrl: `${location.origin}/orderList`
};
// 2.请求支付
let { mweb_url } = await wxPay(params);
// 3.跳转微信支付中间页
window.location.replace(mweb_url);
},
注意事项
- 商户号的支付授权目录和公众号的授权域名必须一致
- 需对
redirect_url
进行urlencode
处理(让后端处理吧) - 调试需在线上环境(需要部署到公网服务器并映射到公众号配置的安全域名)
- H5 支付只能在非微信浏览器中调起,JSAPI 支付是在微信浏览器环境调起的
JSAPI 支付
开发流程
- 请求创建订单接口拿到订单数据(订单id,订单号,支付金额)
- 通过微信网页授权,携带授权
code
重定向到订单支付页,并把订单数据拼接在重定向的地址后面(因为此步骤只适合history路由模式下,如果你项目是 hash 路由 建议此步骤看这篇文章) 到支付页后
- 获取地址栏上的
code
、订单数据(orderId
), - 然后请求支付接口获得我们需要的数据(该数据保函了
wx.config
和wx.chooseWXPay
两个方法需要的传参) 通过
js-sdk
提供的方法发起支付- 先通过
js-sdk
提供的wx.config()
注入权限验证配置 - 再通过
wx.ready()
接口处理成功验证 - 再通过
wx.checkJsApi()
判断客户端版本是否支持指定JS接口 - 再在
wx.checkJsApi()
里成功回调函数中调用wx.chooseWXPay()
发起微信支付请求
- 先通过
- 获取地址栏上的
- 通过
wx.chooseWXPay()
支付成功回调:cancel: function(res){}
,支付失败回调:fail: function(err){}
,取消支付回调cancel: function(res){}
分别处理不同支付结果
实现代码
封装好获取微信授权code的方法和获取地址栏中指定参数的方法
/**
* @description 截取url中的指定参数
* @param {*} queryName 需要截取的参数
* @returns
*/
export const getUrlParam = (queryName) => {
return decodeURIComponent((new RegExp('[?|&]' + queryName + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ""])[1].replace(/\+/g, '%20')) || null
}
/**
* 获取微信支付的code,并传入回调地址
* @param {*} url
*/
export function getWxCode(url) {
let wxUrlStart = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' + wechatAppId + '&redirect_uri=';
let wxUrlEnd = '&response_type=code&scope=snsapi_base&state=STATE&connect_redirect=1#wechat_redirect';
let redirect_uri = encodeURIComponent(url);
let allUrl = wxUrlStart + encodeURIComponent(redirect_uri) + wxUrlEnd;
window.location.replace(allUrl);
}
在订单页创建订单,并且微信授权拿到code,重定向到订单支付页(地址栏携带 orderId,订单金额等订单数据和code)
async createOrder() {
// 商品信息
let goodsList = { goodsId: 1 };
let params = {
goodsList: goodsList,
}
// 1. 创建订单
let data = await createOrder(params);
// 获得 订单id:orderId;订单总金额:orderTotalPrice;订单号:orderNo
let { orderId, orderTotalPrice, orderNo } = data;
// 微信网页授权后的重定向地址
let url = `${location.origin}/pay?orderTotalPrice=${orderTotalPrice}&orderNo=${orderNo}&orderId=${orderId}`
// 上面封装的微信授权网页方法
getWxCode(url);
},
支付页的代码
// jsapi支付
async wxPayByJsApi() {
let _this = this;
// 获取订单数据和授权code
const { orderTotalPrice, orderNo, orderId} = _this.$route.query;
this.orderInfo = {
orderTotalPrice, orderNo, orderId, orderSource
}
_this.code = getUrlParam('code');
let params = {
orderId: _this.orderInfo.orderId,
code: _this.code, // 授权微信拿到的code
}
// 请求后端接口支付
let resp = await wxPay(params);
// 调用后台接口
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: wechatAppId, // 必填,公众号的唯一标识
timestamp: resp.timeStamp, // 必填,生成签名的时间戳
nonceStr: resp.nonceStr, // 必填,生成签名的随机串
signature: resp.signature,// 必填,签名
jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表
});
// doc: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#1
// 注入权限验证配置
wx.ready(function () {
// 判断当前客户端版本是否支持指定JS接口
wx.checkJsApi({
jsApiList: ['chooseWXPay'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
success: (res) => {
// 以键值对的形式返回,可用的api值true,不可用为false
// 如:{ "checkResult": { "chooseImage": true }, "errMsg": "checkJsApi:ok" }
// 发起微信支付请求
wx.chooseWXPay({
timestamp: resp.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: resp.nonceStr, // 支付签名随机串,不长于 32 位
package: resp.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: resp.signType, // 微信支付V3的传入RSA,微信支付V2的传入格式与V2统一下单的签名格式保持一致
paySign: resp.paySign, // 支付签名
success: (res) => {
// 支付成功后的回调函数
_this.$router.push({
path: '/payResult',
query: {
orderTotalPrice: _this.orderInfo.amount,
orderNo: _this.orderInfo.orderNo,
orderId: _this.orderInfo.orderId
}
});
},
fail: (err) => {
_this.$router.go(-1);
},
cancel: function (err) {
// 用户取消支付
_this.$router.go(-1);
},
});
}
});
});
wx.error(err => {
_this.$router.go(-1);
})
},
小程序支付
开发流程
- 小程序端请求创建订单接口,后端统一下单获取
orderId
并返回 - 小程序端获取通过
wx.login()
获取code
- 小程序端拿这
code
和orderId
请求后端接口,获取支付所需数据 - 获取支付所需数据之后,小程序端调用
wx.requestPayment()
接口,直接调用起支付页面 - 判断是否支付成功后的逻辑
小程序文档wx.login()
小程序文档wx.requestPayment()
实现代码
async function wxPay(goodId) {
// 1. 创建订单 获取orderId
let CreateTheOrder = {
goodId, // 商品id
}
let orderId = await createOrder(params);
// 2. 获得 code
let code = await wxlogin(); // 基于pr封装的wx.login()方法
// 3. 获取支付的数据
let paramsPay = {
orderId,
code,
}
let payData = await wxXcxPay(paramsPay);
// 4. 发起支付
let res = await payment(payData); // 基于pr封装的wx.requestPayment()方法
// 5. 判断是否支付成功
let payResult = res.errMsg;
if (payResult == "requestPayment:ok") {
console.log("支付成功");
} else if (payResult == "requestPayment:fail cancel") {
console.log("用户取消支付");
} else {
console.log("支付失败");
}
}
注意事项
- 申请微信小程序账号申请成功可拿到
AppID
(小程序 id)和AppSecret
(小程序密钥)申请类型为企业性质,否则无法接入微信支付 - 微信小程序认证通过认证的小程序才能接入微信支付和绑定商户平台
- 申请商户平台账号需要第一步申请的
AppID
申请成功可拿到MchID
(商户 id)和MchKey
(商户密钥) - 信小程序关联商户号微信和商户都认证成功后,在微信后台微信支付菜单中进行关联接入微信支付
- 在微信后台微信支付菜单中进行接入
写在最后
我是 AndyHu,目前暂时是一枚前端搬砖工程师。
文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注呀
未经许可禁止转载
speak less,do more.