Skip to content

本文由 简悦 SimpRead 转码, 原文地址 mp.weixin.qq.com

大厂技术  坚持周更  精选好文

====================

背景

支付有多种渠道,在不同的宿主环境下,可能都不一样,比如 APP 内的支付、微信内支付、小程序支付、浏览器内 h5 支付等等。这篇文章主要理清常见场景下各个支付的流程和 api,后续一旦有新业务接入支付,能起到一个引导作用,少走弯路。

业务 APP 内支付

APP 内,主流支付方式分两种:IAP 支付和第三方支付。

IAPIn-App Purchase,即用户在业务 APP 内就能完成购买。排除支付过程中 APP Crash 等异常 case,个人认为,体验相对于第三方支付更好。对虚拟商品,苹果强制 APP 使用 IAP 支付,否则不给过审。因此,很多 APP 采用其他的方式骗过审核,通过一个开关,在审核期间,打开开关启用 IAP 支付,审核过后启用第三方支付。不过这也有风险,一旦被苹果发现,APP 可能会被下架。为什么不采用体验更好的 IAP 支付呢?原因可能跟苹果对每笔支付提成 30% 有关。当然,Android 也是支持 IAP 的,如 Google Play、Amazon Appstore,不过 Android 的 Appstore 百花齐放,如果要支持 IAP,就得支持非常多的 Appstore,并且 Appstore 不一定支持了 IAP 能力,因此,Android 内一般采用第三方支付。

第三方支付需要跳转到第三方 APP 才能完成支付行为,例如:微信和支付宝。

APP 内的支付,不管是 IAP 还是第三方,都需要借助 APP 的能力,前端需通过 jsbridge 跟 APP 交互。当然,在 APP 里面直接使用 h5 支付也是没问题的。下面就看下这两种支付方式的详细流程

第三方支付

支付流程图如下:涉及 5 个关联方,用户、业务 APP、业务 server 端、支付平台 C 端,支付平台 server 端。目前国内主要支付平台为微信和支付宝。详细流程如下:

  1. 用户发起支付

  2. 请求创建订单接口,获取订单 id

  3. 通过订单 id,业务 server 端请求支付平台 server 端下单接口,获取支付信息(主要是预支付订单 prepay_id)

  4. 业务 APP 在获取到支付信息后,通过支付平台提供的 SDK 拉起 APP,用户输入密码发起支付

  5. 支付平台 server 端通知业务平台 server 端支付状态

  6. 业务 APP 轮询获取支付状态

从上面来看完成整个支付流程前端需要做的事情如下:

  1. 调用业务创建订单接口,获取订单 id

  2. 调用业务发起支付接口,获取支付信息

  3. 调用 jsbridge,与客户端约定 jsbridge(由客户端同学接入第三方支付提供的 SDK),将支付信息传给客户端,由客户端拉起第三方支付平台并传递支付信息

  4. 获取支付状态,在成功调用 jsbridge 之后,就可以去服务端获取用户支付状态(轮询或 websocket),根据支付状态给用户 UI 反馈

IAP

涉及 4 个关联方,用户、业务 APP、业务 server、Apple Appstore。详细流程如下:

  1. 首先在 Appstore 后台,创建 IAP 商品,获取 IAP 产品 id,需要填写商品名称、简介、价格、销售范围等,这些信息在拉起支付弹窗的时候显示

  2. 将 IAP 产品 id 关联我们的商品 id,给用户售卖的是我们的商品 id

  3. 在 C 端售卖页,用户挑选商品,发起支付

  4. 业务 server 端创建订单,构造发起支付所需支付信息,包含当前商品 id 关联的 IAP 产品 id

  5. 业务 APP 拿到支付信息后,通过 Appstore 提供的 SDK 提交支付信息

  6. 拉起支付弹窗,用户确认支付后,回调给业务 APP 支付票据

  7. 业务 APP 上传支付票据给业务 server,这一步是必要的,得通知业务 server 用户支付了

  8. 业务 server 向 Appstore 验证支付票据是否有效,如果有效,server 记录支付成功了

  9. 业务 APP 轮询业务 server,获取用户支付状态

前端所要做的事情与上述第三方支付差不多,不再赘述。

区别

从上述分析来看,IAP 和第三方支付的区别在于

支付方式支付体验系统支持交易验证开发体验使用意愿
IAP 支付主流是 IOS,Android 虽然支持,但各个厂商不统一用户支付成功后,交易验证由业务 APP-> 业务 server -> Appstore,主要在业务侧完成,由业务侧保证差,需要关注的事情更多,如:支付完成后 APP crash,下次重启要重新关注这个支付;交易验证是在用户和 server 间传递的,网络环境复杂,要引入重试机制不太愿意,有交易抽成
第三方支付中等Android 和 IOS用户支付成功后,交易验证由第三方 server-> 业务 server,主要由第三方保证好,大量的事情由第三方完成愿意

业务 APP 外支付

APP 外支付,主要分微信内和微信外支付

微信内支付

指在微信 APP 内打开的 h5,小程序,发起的支付行为。

h5 支付

在微信 APP 内打开 h5 页面,能让用户购买商品、支付。整个支付流程跟业务 APP 内第三方支付流程类似,主要区别在于拉起支付的主体。APP 内的第三方支付是由业务 APP 拉起第三方支付 APP,如 微信、支付宝,但微信内打开的 h5,使用的就是微信提供的 jsapi 能力(本质也是 jsbridge)。下面说一下详细流程:

  1. 配置支付目录,最后请求拉起微信支付收银台的页面地址称之为 “支付目录”,如果拉起支付的页面地址与配置的不一样,微信会提示 “当前页面的 URL 未注册”

  2. 需要获取用户 openid[1],业务 server 下单的时候需要,一旦获取到后,前端可以缓存起来,因为同一个用户在同一个 appid 下,openid 是不会变的。

  3. 用户发起支付,同样业务 server 创建订单,从微信支付 server 获取预支付信息

  4. h5 获取预支付信息后,结构为如下 PayParam,调用微信提供的 jsapi,代码如下,参考文档 [2]。其中支付参数除 appid 外,其他的都有业务 server 返回

//微信支付中间页
https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx162128390473563d952e4f371ca7d70000&package=2985141145&redirect_url=https%3A%2F%2Fwww.ggl.cn%2Feggl%2Fh5%2Fsale%2Fpay%2Fresult%3Forder_id%3D6974383092475680542
// 其中prepay_id、package等是支付相关参数,
// redirect_url就是支付成功、取消、超时返回浏览器要打开的页面地址

小程序支付

微信小程序的支付能力,跟 h5 支付的类似,不过比 h5 的 jsapi 支付接起来更简洁。

  1. 获取 openid,小程序获取 openid 比 h5 要方便得多,详细可见 wx.login[3]

  2. 户发起支付,同样业务 server 创建订单,从微信支付 server 获取预支付信息

  3. 小程序获取预支付信息后,调用 wx.requestPayment,代码如下,参考文档 [4]。

weixin://wap/pay?prepayid%3Dwx162128390473563d952e4f371ca7d70000&package=2985141145&noncestr=1623850119&sign=bfc799bb3c643e44c0a334b531b26b17

微信外支付

主要场景为用户在手机浏览器打开网页,购买、发起支付,从外部浏览器唤起微信或者支付宝支付。这个场景的实现方式跟上述所有场景不同,以拉起微信支付为例,流程图如下:

涉及 6 个关联方,用户、浏览器、微信 h5 支付中间页、微信客户端、微信支付 server 端、业务 server 端。详细流程如下:

  1. 用户发起支付

  2. 请求创建订单接口,业务 server 端请求微信支付 server 端,获取微信支付中间页 h5 地址,示例:

//微信支付中间页
https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx162128390473563d952e4f371ca7d70000&package=2985141145&redirect_url=https%3A%2F%2Fwww.ggl.cn%2Feggl%2Fh5%2Fsale%2Fpay%2Fresult%3Forder_id%3D6974383092475680542
// 其中prepay_id、package等是支付相关参数,
// redirect_url就是支付成功、取消、超时返回浏览器要打开的页面地址

3. 获取到微信支付中间页 h5 地址后打开这个页面,这个页面会检测支付网络环境,确认 OK,通过 deeplink 的方式拉起微信 APP,deeplink demo 如下:

weixin://wap/pay?prepayid%3Dwx162128390473563d952e4f371ca7d70000&package=2985141145&noncestr=1623850119&sign=bfc799bb3c643e44c0a334b531b26b17

4. 拉起微信支付弹窗,用户确认支付后,微信支付 server 端通知到业务 server 端用户支付状态

5. 另一方面,打开支付中间件 5s 后,如果拉起中间页有传入 redirect_url 参数,就会打开 redirect_url,否则返回发起支付的页面

6. 从微信 APP 回到浏览器后,建议让用户选择是否支付,才开始轮询用户支付结果,因为无法保证支付中间页回跳时,支付流程已结束

最佳实践

基于以上支付流程,列举出常见支付场景及其最佳的支付方式

平台IAP 支付第三方支付jsapi 支付小程序支付h5 支付
业务 APP 内 Android支持,但需要兼容各个厂商推荐不支持不支持支持,但体验不好
业务 APP 内 IOS支持,体验好,但厂商会提成推荐不支持不支持支持,但体验不好
微信内 h5不支持不支持推荐不支持不支持
微信内小程序不支持不支持不支持推荐不支持
微信外 h5(浏览器场景)不支持不支持不支持不支持推荐

Q&A

  1. 嵌入到小程序中的 h5 页面,能用 h5 原本的支付能力吗?应用场景,想直接复用原有 h5 做好的东西。

    答:不可以,但是也有解决方案,只是体验没有小程序支付好,具体是在发起支付的时候通过 window.wx.miniProgram.navigateTo 这个 api 从 h5 跳转到小程序页面支付

  2. h5 支持在浏览器拉起微信和支付宝支付,嵌入业务 APP,能正常发起支付吗?应用场景,不同 APP 中复用同一套 h5 售卖。

    答:可以,但是可能需要客户端支持拦截第三方 APP 的 deeplink,通用也不太好,如 拉起第三方支付 APP 后,取消支付无法返回原来的 APP

参考资料

[1]

需要获取用户 openid: _https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_4_

[2]

参考文档: _https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_3.shtml#part-6_

[3]

wx.login: _https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html_

[4]

参考文档: _https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_2.shtml#part-6_

❤️ 爱心三连

  1. 如果觉得这篇文章还不错,来个分享、点赞、在看三连吧,让更多的人也看到~

  2. 关注公众号前端森林,定期为你推送新鲜干货好文。

  3. 特殊阶段,带好口罩,做好个人防护。