关于微信小程序调起微信支付的调研

调研文档 微信小程序 微信支付 yangchuan 2018-04-02

一 背景

  基于团队目前正在展开的关于平台帮助车企推广业务的战略构想,就目前微信小程序(以下简称小程序)新增的入口越来越多,推广的方式层出不穷。与微信账户体系高度集成,用户无需注册即可使用。相较于传统APP的独立账户体系或被切割化的第三方授权,微信小程序的授权过程简单、友好、快速。得益于微信的用户量,我们拟采用微信小程序来开始逐步实现我们构想。
  为满足业务需要,我们需要对小程序中前端发起”微信在线支付”前端开发实现层面的可行性进行调研。

二 目标

  1. 我们需要在小程序端(需求方)主动调起微信支付来完成收款。
  2. 支付的金额可以由用户自定义(根据@姜炜的设计)
  3. 支付过程中的异常我们能捕获并正确反馈给用户。
  4. 其他

三 术语解释

术语 说明 备注
AppID 一个微信小程序的唯一标识 一般用来获取一些账号信息
AppSecret 一个微信小程序的安全密钥 主要用作鉴权,例如获取微信小程序用户的openID
OpenId 微信小程序用户的唯一标识
UserCode 用户在小程序端登陆后由微信直接返回 它是获取用户的OpenId的必要信息
Sign 这里特指调用微信统一下单API需要的签名
PaySign 小程序调起微信支付时需要的签名
ApiSecret 这里特指微信支付的API密钥 它是调用微信统一下单API和在小程序端调起微信支付的必须信息
prepay_id 这里是指在微信商户创建的一个还未完成支付的订单的唯一标识。 只有调用微信统一下单API才能生成

四 调研过程

  完成微信小程序调起微信支付的必要条件是我们的小程序必须完成微信支付认证并且绑定我们的微信支付商户。为此,我们已经完成了微信商户的申请并通过了审核。在此基础上我们获取到了ApiSecret。有了试用的大前提。
  小程序支付的交互图如图-4.01所示:

@图-4.01 小程序调起微信支付的交互流程

图-4.01 小程序调起微信支付的交互流程

4.1 下单

  这个过程其实是在为了生成一个prepay_id,可以简述为:用户请求下单,我们的业务系统调用微信后台的API来获取用户的信息并生成我们自己的订单,并且调用微信统一下单接口来获取一个支付订单。其中牵涉两个微信API:

1.{
2. url: "https://api.weixin.qq.com/sns/jscode2session",
3. method: "GET",
4. params: {
5. /** 小程序唯一标识 **/
6. appid: "23323",
7. /** 小程序小程序安全密钥 **/
8. secret: `${AppSecret}`,
9. /** 用户登陆后小程序(客户端)可以去到 **/
10. js_code: `${UserCode}`
11. },
12. reseponse:{
13. /** 用户唯一标识 **/
14. openid:`${OpenID}`,
15. /** 会话密钥 **/
16. session_key:`${session_key}`,
17. }
18.}
1.{
2. url: "https://api.weixin.qq.com/sns/jscode2session",
3. method: "POST",
4. params: {
5. ```
6. <xml>
7. <appid>wxa84c8b24b926fbf7</appid> //小程序唯一标识
8. <body>testing</body> //商品描述
9. <mch_id>1501251441</mch_id> //商户ID
10. <nonce_str>5K8264ILTKCH16CQ2502SI8ZNMTM67V4</nonce_str> //随机32位字符串
11. <notify_url>path/to/notify </notify_url> //配置我们的通知接口
12. <openid>opwTM4lqnzQN7bQc9bVAsDOv8R9E</openid> //上一步获取到的用户标识
13. <out_trade_no>12346</out_trade_no> //我们的订单号
14. <spbill_create_ip>123.12.12.123</spbill_create_ip> //掉期支付的机器IP
15. <total_fee>16</total_fee> //金额
16. <trade_type>JSAPI</trade_type> //交易类型:默认是JSAPI
17. <sign>DD8BE054AD3348A04E1BF63EBEC0415F</sign> //签名值,用作鉴权
18. </xml>
19. ```
20. }
21.}

此时可以在商户平台的订单查询中找到这个订单所在:

@图-4.02 微信支付商户平台>订单查询

图-4.02 微信支付商户平台>订单查询

注意:需要生成签名值时我们必须要使用 ApiSecret ,所以这一动作必然是由服务端来完成的
返回值如下所示,我们最终需要获取的是prepay_id。

1.<xml>
2. <return_code><![CDATA[SUCCESS]]></return_code>
3. <return_msg><![CDATA[OK]]></return_msg>
4. <appid><![CDATA[wxa84c8b24b926fbf7]]></appid>
5. <mch_id><![CDATA[1501251441]]></mch_id>
6. <nonce_str><![CDATA[lomfrl7MOLIw89pk]]></nonce_str>
7. <sign><![CDATA[165786AFF6CF616C588BC2541323E262]]></sign>
8. <result_code><![CDATA[SUCCESS]]></result_code>
9. <prepay_id><![CDATA[wx2018040214525479c5c4cd960650504533]]></prepay_id>
10. <trade_type><![CDATA[JSAPI]]></trade_type>
11.</xml>

4.2 签名(PaySign)并调起支付

@图-4.03 调起支付数据签名字段

图-4.03 调起支付数据签名字段

1.var params = "appId=wxd678efh567hg6787&nonceStr=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&package=prepay_id=wx2017033010242291fcfe0db70013231072&signType=MD5&timeStamp=1490840662";
2.var signStr = params+ "&key="+ ${ApiSecret}
3.var paySign=MD5(signStr) = 22D9B4E54AB1950F51E0649E8810ACD6
1.const sucFunc = (res) => {
2. console.log("调起支付成功:", res)
3.}
4.const errFunc = (res) => {
5. console.log("调起支付失败:", res)
6.}
7.const compFunc = (res) => {
8. console.log("调起支付完成:", res)
9.}
10.wx.requestPayment({
11. appId: 'wxa84c8b24b926fbf7',
12. nonceStr: '5K8264ILTKCH16CQ2502SI8ZNMTM67V4',
13. package: 'prepay_id=wx2018040214525479c5c4cd960650504533',
14. signType: 'MD5',
15. timeStamp: '1522651992',
16. paySign: 'B6F32329A7A4DDE5C271B70A0957F328',
17. success: sucFunc,
18. fail: errFunc,
19. complete: compFunc
20.})

效果如图-4.04所示。

@图-4.04 小程序调起微信支付|350*600

图-4.04 小程序调起微信支付

五 结论

综合以上章节可见,基于微信小程序前端调起微信支付是可行的。以下目标也是可以达到的;

我们需要在小程序端(需求方)主动调起微信支付来完成收款。-
支付的金额可以由用户自定义
支付过程中的异常我们能捕获并正确反馈给用户。