最近一个多月加班比较严重,偶尔休息一天也是在补睡眠+陪家人,比较长时间没有来进行总结记录了。今天不加班,开始为这段时间做的东西进行下经验总结。
这段时间因为公司需要,接触了一些.Net前后台开发,慢慢了解了一些WCF、H5站点、WebService、Soap、Linq等,也了解了一些BLL、DAL相关内容。同时也参与了微信支付、微信医保支付相关功能的改版,以及为微信小程序增加微信支付、微信医保支付功能。
下面主要记录下小程序支付相关方案、实现及填坑。
一. 产品现状
首先,在接入微信支付功能以前,我们的产品情况是这样的:
1
有公众号和app的h5站点及相关配套功能
2
小程序已经有一些基础功能,这些功能没有使用web-view
3
小程序之前的服务器是与现有公众号h5站点不同的一个webapi站点
二. 备选方案
基于以上几点,当时提出了两套解决方案:
方案1. 支付相关功能使用小程序代码进行开发,并在webapi站点增加相应接口
方案2. 使用web-view嵌入公众号h5站点的支付功能,包括订单列表、订单详情、支付确认、支付下单、支付结果展示、支付历史等,仅实际支付时使用小程序代码进行开发
最终我们使用的是第二套方案,本来以为有了现成的h5页面,需要解决的仅仅是h5站点与webapi站点的登录同步以及小程序的支付界面唤起这两个问题,结果发现,坑还是不少的。
三. 方案实现
基本流程如上述示意图,订单相关页面及微信支付下单过程都在h5,下单成功后通过wx.program.navigateTo跳转回小程序,小程序执行wx.requestPayment唤起支付页面,获取的结果以h5展示。同时,在下单时会设置支付结果回调页(PayNotify),实际支付成功后,微信会主动调用PayNotify页面,在该页面操作订单支付表的支付状态。
小程序代码如下:
// 直接在onLoad中唤起支付页面(中间的部分参数需要用decodeURIComponent解码)
onLoad: function(options) {
var payType = options.type;
var timeStamp = options.timeStamp;
var nonceStr = decodeURIComponent(options.nonceStr);
var package = decodeURIComponent(options.package);
var signType = options.signType;
var paySign = decodeURIComponent(options.paySign);
if(type == 1) {
// 微信支付
this.wxPay(timeStamp, nonceStr, package, signType, paySign);
}else {
var payAppId = options.appid;
var payUrl = decodeURIComponent(options.payUrl);
// 医保支付,需要跳转到医保小程序进行支付,需要获取医保小程序appid和payurl
}
}
// 唤起微信支付窗口
wxPay: function(timeStamp, nonceStr, package, signType, paySign) {
wx.requestPayment({
'timeStamp': timeStamp,
'nonceStr': nonceStr,
'package': package,
'signType': signType,//'MD5',
'paySign': paySign,
'success':function(res){
// 成功跳转到h5结果页面
},
'fail':function(res){
// 失败提示并返回订单页
},
'complete': function(res){
// 较早版本,用户取消支付,不进入fail回调,仅回调complete
// res.errMsg为requestPayment:fail cancel
if(res.errMsg=='requestPayment:fail cancel') {
// 用户取消返回订单页
}
}
})
}
注意:
- 在生成订单表,下单成功后,即进入支付中状态
- 建议区分订单表和支付表
- 实际支付页面的唤起只能在小程序中进行,不能使用h5唤起微信支付页面
- 支付结果必须以微信回调为准,不能直接使用wx.program.navigateTo返回的结果
- 因为公众号和小程序使用的是同一套h5代码,所以必须将appid等设置为配置项,不同的入口,使用不同的appid;而且在支付表中,必须能明确是小程序还是公众号支付的,不然会出现无法退款等情况。(退款的appid必须是支付的appid)
四. 填坑
坑1
支付商户和小程序主体不一致,而且我们的商户是特约商户,导致小程序无法进行M-A授权并开通微信支付功能
解决方案:
这里有多种解决方案,最快捷的是找腾讯内部人员提交申请,提交信息后他们会帮忙进行M-A授权(我们下午提交第二天就ok了)
坑2
appid等信息不同导致需要h5站点兼容
解决方案:
增加支付相关的配置,不同的入口读取不同的配置项,包含appid, appsecret,mchid,回调地址等配置。
坑3
由于之前是在webapi进行登录,h5站点存在未登录的问题
解决方案:
我们webapi和h5使用的是同一个数据库,所以我们只是在h5站点再进行一次openid的绑定,当然,这里需要考虑的是小程序和公众号都存在openid,我们得分开建立绑定关系。
这是我们产品之前设计存在的问题,其实是可以通过unionid来建立绑定关系(因为这个才是对微信用户而言唯一不变的标识),同时也可以考虑缓存不同来源的openid
坑4
历史记录及退款问题
解决方案:
需要在支付记录中存储是哪个端下的订单,因为如果小程序支付的,一定要用小程序的appid等信息去退款,公众号也一样。所以支付记录表中应该有payType字段,最好支付的订单号生成时前两位用于记录支付方式,比如01开头的是公众号支付,02开头是小程序支付。
我们的订单号生成规则是 2位支付方式+1位交易订单类型(支付、退款等)+2位商品类型 + 时间戳 + 其他
个人博客: IT老五
微信公众号:【IT老五(it-lao5)】,一起源创,一起学习!
ps
时间有点紧张,还有一些具体方案实现和坑没总结,后续再补充。有什么错误或者不足欢迎指出...
另外,使用web-view在体验上感觉有点坑,坑1. h5加载比纯使用小程序要慢很多 坑2. 无法准确捕获到h5页面加载的进度...