从前端角度从零开始对接微信支付 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hzqcn
V2EX    前端开发

从前端角度从零开始对接微信支付

  •  
  •   hzqcn 2022-05-17 15:16:50 +08:00 2228 次点击
    这是一个创建于 1332 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

    微信支付业务,针对小程序、微信浏览器和非微信浏览器中的网页的三种场景,我们可以分别通过官方提供的 小程序支付、JSAPI 支付、H5 支付来开发。

    准备工作

    开通微信商户号、微信公众号然后按照步骤准备一堆资料审核,然后设置相关配置。所以最好提前准备资料审核以免耽误开发进度。配置的步骤:官方文档,直接按照官方文档配置就行了。需要特别注意的是配置商户号的支付授权目录和公众号的授权域名必须一致,不然会调起支付失败的!

    参考资料:
    JSAPI 支付配置文档
    H5 支付配置文档
    小程序支付
    JS-SDK

    H5 支付

    开发流程

    1. 请求创建订单接口拿到订单数据(orderId,订单号,支付金额)
    2. orderId请求支付接口,获得 mweb_url
    3. 跳转到微信支付中间页 mweb_url ,然后自动调用微信支付
    4. 支付成功后跳转到配置的返回页(请求支付时携带的参数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 支付

    开发流程

    1. 请求创建订单接口拿到订单数据(订单 id ,订单号,支付金额)
    2. 通过微信网页授权,携带授权 code 重定向到订单支付页,并把订单数据拼接在重定向的地址后面
    3. 到支付页后
      1. 获取地址栏上的 code、订单数据(orderId),
      2. 然后请求支付接口获得我们需要的数据(该数据保函了wx.configwx.chooseWXPay两个方法需要的传参)
      3. 通过 js-sdk 提供的方法发起支付
        1. 先通过 js-sdk 提供的 wx.config() 注入权限验证配置
        2. 再通过 wx.ready() 接口处理成功验证
        3. 再通过 wx.checkJsApi() 判断客户端版本是否支持指定 JS 接口
        4. 再在 wx.checkJsApi() 里成功回调函数中调用 wx.chooseWXPay() 发起微信支付请求
    4. 通过 wx.chooseWXPay() 支付成功回调:cancel: function(res){},支付失败回调:fail: function(err){},取消支付回调 cancel: function(res){}分别处理不同支付结果

    参考文档 JS-SDK

    实现代码

    封装好获取微信授权 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); }) }, 

    小程序支付

    开发流程

    1. 小程序端请求创建订单接口,后端统一下单获取 orderId 并返回
    2. 小程序端获取通过 wx.login() 获取 code
    3. 小程序端拿这 codeorderId 请求后端接口,获取支付所需数据
    4. 获取支付所需数据之后,小程序端调用 wx.requestPayment() 接口,直接调用起支付页面
    5. 判断是否支付成功后的逻辑

    小程序文档 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("支付失败"); } } 

    注意事项

    1. 申请微信小程序账号申请成功可拿到 AppID(小程序 id )和 AppSecret(小程序密钥)申请类型为企业性质,否则无法接入微信支付
    2. 微信小程序认证通过认证的小程序才能接入微信支付和绑定商户平台
    3. 申请商户平台账号需要第一步申请的 AppID 申请成功可拿到 MchID(商户 id )和 MchKey(商户密钥)
    4. 信小程序关联商户号微信和商户都认证成功后,在微信后台微信支付菜单中进行关联接入微信支付
    5. 在微信后台微信支付菜单中进行接入

    写在最后

    我是 AndyHu,目前暂时是一枚前端搬砖工程师。

    文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注呀

    未经许可禁止转载

    speak less ,do more.

    第 1 条附言    2022-05-17 17:49:13 +08:00

    刚刚有朋友提醒我 hash 模式下文中的JSAPI支付方式中步骤二:授权微信网页获取code会失败。
    如果你是hash模式的话步骤二建议看这篇文章

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5551 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 02:42 PVG 10:42 LAX 18:42 JFK 21:42
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86