1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 小程序:微信小程序支付流程

小程序:微信小程序支付流程

时间:2019-04-18 21:07:40

相关推荐

小程序:微信小程序支付流程

微信小程序支付流程

小程序微信支付的流程图:

1. 登录微信公众平台, 开通微信支付功能

这是准备工作的第一步, 确保小程序对应的支付功能已经开启

2. 登录微信商户平台

该步骤需要获取两个参数, 一个是商户号, 一个是支付秘钥, 如下图所示

注意秘钥自己要保护好,相当于支付密码,每次签名都需要该参数, 该参数只能设置的时候看得见,其余的时候是没法看得见.所以要记好了!

3. 准备完毕,上代码

微信小程序的商户系统一般是以接口的形式开发的,小程序通过调用与后端约定好的接口进行参数的传递以及数据的接收。在小程序支付这块,还需要跟微信服务器进行交互。过程大致是这样的:

一、小程序调用wx.login() 获取code,传递给商户服务器用来获取用户的openID

我们知道在微信平台中,同一个公众号的openID都是不同的,它是用户身份识别的id,也就是说,我们通过openID来区分不同的用户,这个有微信开发基础的应该都很熟悉。为了知道谁在支付,我们需要先获取当前用户的openid,那么openID应该怎么获取呢?看下图:

小程序调用wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。

开发者服务器以code换取 用户唯一标识openid 和 会话密钥session_key。

看不懂吗?不急,听我慢慢解释,这个业务流程大致就是首先你得先在小程序的代码中调用wx.login()来向微信获取到code,拿到了之后把code通过request传给商户服务器,再由商户服务器通过骚操作来跟微信服务器要session_key和openID。

代码如下(小程序端):

getToken: function () {//调用登录接口wx.login({success: function (res) {var code = res.code;wx.request({url: 商户服务器接口地址, data: {code: code},method: 'POST', success: function (res) {wx.setStorageSync('token', res.data.token); //存在小程序缓存中},fail: function (res) {console.log(res.data);}})}})}

调用这几行代码就可以向跟微信服务器要code,并且将code传到商户服务器中,记住这里最好使用post发送请求,安全性的东西我应该不用讲了,因为避免其他人滥用接口,于是我们使用token来进行验证。并将商户服务器返回的token存在小程序缓存中。

那么服务器端应该怎么做呢?

我门通过小程序提交的code,和小程序的APPID以及APPSECRET和拼接下列的url,并用curl进行get请求。

https://api./sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

返回的数据是一个json对象,我门通过使用json_decode(JSON,true)解析为数组,数据包括用户的openID以及session_key,获取到了后我们应该将openID存入数据库中,它代表着用户的身份,那么令牌应该怎么生成呢。

二、token的生成以及缓存

我们根据一个用户表将id和openid联系起来,对应openID的id则是用户的uid,我们可以这么封装

//要缓存的数据数组$cacheValue = $result; //包含openID和session_key$cacheValue['uid'] =$uid; //用户id$cacheValue['scope'] =ScopeEnum::User; //用户权限级别

缓存的方式我们可以选择redis,memcache, 文件缓存等等,采用键值对(key-value)的方式进行存储,记得设置好过期时间。这里的key我们用token来赋值,token可以通过这样的方式进行生成:

//获取32位随机字符串$str = getRandChar(32); //自定义方法生成32位随机串//三组字符串进行md5加密$timeStamp =$_SERVER['REQUEST_TIME_FLOAT'];//salt$salt = config('secure.token_salt'); //随机字符串//返回tokenreturn md5($str.$timeStamp.$salt);

这种算法基本保障了token的唯一性。因为值是我们获取到的openID和session_key所在的数组,所以需要将数组转成json才能存进去。以后的代码当我们需要openID或者uid等时可以直接通过取缓存的方式来取。

三、调用统一下单接口,获取prepay_id,再次签名(后端完成,不详解)

点击‘提交订单’按钮,创建订单,清空购物车,完成支付

<van-submit-barprice="{{ allGoodsAndYunPrice*100 }}"suffix-label="+{{totalScoreToPay}} 积分"button-text="提交订单"bind:submit="goCreateOrder"/>

创建订单,清空购物车,调用支付函数

const wxpay = require('../../utils/pay.js')'//去创建订单goCreateOrder(){//检测实名认证状态//创建订单 this.createOrder(true)}//创建订单createOrder(){var that = this;var loginToken = wx.getStorageSync('token') // 用户登录 tokenvar remark = this.data.remark; // 备注信息let postData = {//创建订单需要的参数token: loginToken,//tokengoodsJsonStr: that.data.goodsJsonStr, //购买的商品数据列表remark: remark,//备注信息peisongType: that.data.peisongType// // 配送方式 kd,zq 分别表示快递/到店自取};//调用创建订单接口,传递此次订单相关数据 WXAPI.orderCreate(postData).then(function (res) {that.data.pageIsEnd = true if (res.code != 0) {that.data.pageIsEnd = falsewx.showModal({title: '错误',content: res.msg,showCancel: false})return;}if ("buyNow" != that.data.orderType) {//订单类型,购物车下单或立即支付下单,默认是购物车,// 清空购物车数据WXAPI.shippingCarInfoRemoveAll(loginToken)}that.setData({totalScoreToPay: res.data.score, //积分isNeedLogistics: res.data.isNeedLogistics, 是否需要物流信息allGoodsAndYunPrice: res.data.amountReal,//总价=总商品价+总运费yunPrice: res.data.amountLogistics,//运费hasNoCoupons,//没有优惠券coupons,//优惠券couponAmount: res.data.couponAmount //优惠金额});that.data.pageIsEnd = falsereturn;}//创建订单后的操作that.processAfterCreateOrder(res)})//创建订单后的操作 async processAfterCreateOrder(res) {// 直接弹出支付,取消支付的话,去订单列表const balance = this.data.balanceif (balance || res.data.amountReal*1 == 0) {// 有余额const money = (res.data.amountReal * 1 - balance*1).toFixed(2)if (money <= 0) {// 余额足够wx.showModal({title: '请确认支付',content: `您当前可用余额¥${balance},使用余额支付¥${res.data.amountReal}?`,confirmText: "确认支付",cancelText: "暂不付款",success: res2 => {if (res2.confirm) {// 使用余额支付,传token,和订单idWXAPI.orderPay(wx.getStorageSync('token'), res.data.id).then(res3 => {if (res3.code != 0) {wx.showToast({title: res3.msg,icon: 'none'})return}wx.redirectTo({url: "/pages/order-list/index"})})} else {wx.redirectTo({url: "/pages/order-list/index"})}}})} else {// 余额不够wx.showModal({title: '请确认支付',content: `您当前可用余额¥${balance},仍需支付¥${money}`,confirmText: "确认支付",cancelText: "暂不付款",success: res2 => {if (res2.confirm) {// 使用余额支付wxpay.wxpay('order', money, res.data.id, "/pages/order-list/index");} else {wx.redirectTo({url: "/pages/order-list/index"})}}})}} else {// 没余额wxpay.wxpay('order', res.data.amountReal, res.data.id, "/pages/order-list/index");}},//查看用户资产async userAmount() {const res = await WXAPI.userAmount(wx.getStorageSync('token'))if (res.code == 0) {this.setData({balance: res.data.balance})}},}

四、小程序获取五个参数后,鉴权调起支付

const WXAPI = require('apifm-wxapi')/*** type: order 支付订单 recharge 充值 paybill 优惠买单* data: 扩展数据对象,用于保存参数*/function wxpay(type, money, orderId, redirectUrl, data) {WXAPI.wxpay(postData).then(function (res) {if (res.code == 0) {// 发起支付wx.requestPayment({timeStamp: res.data.timeStamp, //时间戳nonceStr: res.data.nonceStr,,//随机字符串package: res.data.package,//订单详情扩展字符串signType: res.data.signType//签名方式paySign: res.data.paySign,//签名fail: function (aaa) {console.error(aaa)wx.showToast({title: '支付失败:' + aaa})},success: function () {// 提示支付成功wx.showToast({title: '支付成功'})wx.redirectTo({url: redirectUrl});}})} else {wx.showModal({title: '出错了',content: JSON.stringify(res),showCancel: false})}})}module.exports = {wxpay: wxpay}

五、支付回调

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。