小程序下单支付在我司的应用

0.需求简介:

本期接到的开发需求是:在我们已经开发好的App中,当用户点击立即购买时跳转到小程序端,用户进而在小程序可以浏览商品,下单,查看订单相关操作。这样做的目的是为了打通支付的痛点,目前在原生App的支付因为不同的机型,支付比较复杂,而且IOS还需要经过苹果审核,可能面临审核不通过的烦恼。

1.小程序端准备工作

既然是在小程序端做开发,首先必须要申请小程序,注意:这里有个坑的地方,必须要申请微信开放平台账号下的小程序,或者在公众平台下申请的小程序要绑定微信开放平台,单纯的微信公众平台账号下的小程序无法解密unionId(可以解密其它敏感性不高的信息)。注册完成之后就可以拿到AppId和AppSecret了,需要牢记,后面要用。
点击跳转微信开发平台

1.1 以jsCode换取SessionKey

通过调用小程序的wx.login()方法,可以获得一个jsCode(一个jsCode使用一次就会失效),此jsCode可以用于生成sessionKey,而sessionKey又是解密获得unionId或手机号的必须字段,所以第一步很重要。

前端通过wx.login()方法拿到jsCode之后,传给后台,后台将jsCode,appId,appSecret等字段组装,调用微信服务器的获取sessionKey的地址拿到sessionKey,点击查看官方文档

在后台我拿到这个sessionKey是直接返给前端,让前端保存在本地了,后端需要用的时候再传给后台,如果你的系统安全性要求比较高,也可以有更严格的管理策略。比如:生成一个随机串作为key,将sessionKey作为value存在redis中,只给前端返key,后台要用时前端将key传给后台,后台根据key从redis中取出sessionKey;或者后台将生成的sessionKey对称加密,给前端密文,后台在需要时,前端将密文传给后台,后台解密,拿到真正的sessionKey,具体看项目要求,我这里是直接将sessionKey交给前端保存了。

1.2 解密获取用户的unionId

这里有两个注意点:
(1)unionId是用户的唯一标识,同一个微信用户在你司一个账号主体下,无论是小程序还是服务号,公众号都是一样的,所以可以使用此字段来标识用户;
(2)获取unionId和获取手机号的方法其实是一样的,只是传的参数值不一样

小程序端调用wx.getUserInfo()方法获取到encryptedData和iv,连同上一步获取到的sessionKey传给后台,后台进行解密,可以获取到unionId,openId,昵称,头像等信息,传给前端。点击查看官方文档

1.3 解密获取用户的手机号

获取手机号需要用户主动点击授权,而且前端需要写一个button事件,调用微信的getPhoneNumber()方法,拿到encryptedData和iv,连同第一步获取到的sessionkey传给后台(与解密用户unionId一致),后台解密即可获取到该微信号绑定的手机号。

2.小程序端浏览商品相关

这一步需要注意的点是:日常网站基本都是读多写少,而且这是在入口页面,很靠上,必须要用缓存,优先走缓存,缓存没有,再从数据库查询并保存在缓存中,数据库必须要加索引,如果有要从很多表查询取数据库,可以开多个线程并行执行,使用CountDownLatch或者java8的CompletableFuture.supplyAsync开启线程并回收执行结果,注意需要设置超时处理,避免一直等待,总的来说这一步都是java的常用操作。

3.提交订单

3.1 订单号生成策略和IP获取

3.1.1 订单号生成

订单号生成策略我这里采用的是:
1位下单标识+15时间戳+用户id后4位+4位随机数,共计24位,如下示例:
W20190710110201200234471
w代指微信下单,201907101102012代表时间戳,0023代表用户id后4位,不足4位前面补0,4471代表4位随机数

3.1.2 IP获取

下单时微信需要下单用户的ip,我们自己也要将用户的ip在日志中打印出来,所以需要写工具类获取用户的ip

3.2 预下单

前端提交订单时需要将短信验证码,商品id,价格等带给后台,后台需要校验短信验证码是否正确,商品是否有库存,价格是否与后台计算的一致(所有牵涉到价格类的,前端只负责展示给用户,必须以后台计算的为准,以防金额损失),而且为了防止用户重复提交,在表单接口入口需要加入分布式锁。

上面所有的校验完成之后就可以处理你自己的业务了,我这里是插入订单,只是订单状态是无效,支付状态是待支付,插入收货地址等。

业务处理完之后可以调用微信的统一下单接口执行预下单了,点击查看官方文档
传入这个接口需要的参数,腾讯会返回一个prepay_id的字段,这是预支付交易会话标识,很重要的一个字段。

如果要在小程序下单,根据小程序的文档 描述,需要将prepay_id,签名,时间戳什么的由小程序给腾讯,我这里处理的时候这些步骤都是在服务端进行的,即拿到prepayid之后,根据时间戳,随机数等生成签名,再把这些参数统一返回给前端

4.支付回调

在上一步把参数都返回给前端之后,前端使用wx.requestPayment方法,将参数传给微信,就可以调起微信支付弹窗了,点击查看官方文档

支付完成后微信会调用你传给他的支付回调地址(支付回调接口是你写的,旨在处理支付成功或失败后你自己的业务逻辑),这个回调接口也需要加分布式锁,点击查看官方文档,在回调参数中有个叫out_trade_no的字段,这是你传给微信的订单号,现在它又传给你了,拿到这个订单号,你要先查看你订单是否存在,订单是否待付款,同时对它传过来的的参数进行验签(防止中间金额错误),一系列操作完成后再更新你的订单状态为已完成,并处理其他的业务逻辑。

整个支付环节,只有输密码那一步是在前端操作。其他的调用统一下单接口完成预下单,生成时间戳、签名给前端,支付后的接口回调都是在后台服务端操作的,保证了操作的安全。

5.其它

5.1缓存同步

因为查看商品,查看订单,详情等都用到了缓存,所以在内部系统修改完商品信息,或者用户购买成功课,要同步商品,订单等缓存。

优化

如果订单量非常大,下订单的时候可以优化成消息队列发送的形式异步的往数据库里生成订单,推荐使用rocketmq或robbitmq,有ack确认机制;同时,此时去调用第三方支付,生成预下单id。
存在的问题有以下分类:
1.订单表插入成功,调用支付失败。此时订单就是待支付状态,用户可以去未完成订单继续支付;
2.订单表插入失败,调用支付失败。此时是操作失败,要给用户相应的提示;
3.订单表插入失败,调用支付成功。这也分两种情况,调用支付成功后,用户实际付款成功,如果此时消息队列有延迟,用户订单信息还未插入表中,此时虽不能更新订单状态,问题不大,因为第三方支付公司,往往都有失败重试,第一次调用未更新订单状态后,隔一段支付公司还会调用,这时如果订单入库了就会更新状态,唯一不足的就是前段是展示的订单未支付状态;第二种情况是,因为某种原因导致订单插入订单表失败,此时第三方公司的支付回调请求过来后,未查到订单,就没法更新订单状态,此时可以记录回调请求信息至流水表中,每隔一段时间定时扫描流水表,如果发现有流水表中有的数据,订单表中没有,就做补单处理。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值