一、微信小程序购物车的支付功能

  1. 准备一些需要的支付配置信息,小程序 appid、微信商户号和商户密匙,如下所示:

微信认证-注册一个微信支付的商户号

https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2Findex.php%2F

生成微信支付的秘钥

https://www.jianshu.com/p/f0805f5792e3

关联微信支付的商户号

https://mp.weixin.qq.com/wxamp/frame/wxpay?t=wxpay%2Findex_frame&iframe=%2Fpay%2Fmp_wxopen&token=564334113&lang=zh_CN

  1. 对此,可以先分析一下支付功能的过程:

    • 发起订单,获取订单号 makeOrder()
    • 预支付 获取支付参数 pay()
    • 发送支付 wx.requestPayment()
    • 更新支付状态 updateStatus()
    • 清空购物车 clearCarts()
    • 跳转到订单页
  2. 创建 makeOrder 云函数,在 makeOrder.js 文件中,配置云函数入口文件,引入云函数的数据库,配置云函数入口函数。在入口函数中,创建一个随机订单号,组成一个对象,包括订单号、购物车数据和支付状态,0表示未支付,1 表示已支付。将这个对象添加到 orders 集合里面,最后返回数据,代码如下所示:

const cloud = require('wx-server-sdk')cloud.init()const db = cloud.database({env: 'prod-hswqx-ek3h5'
})
const orders_col = db.collection('orders')exports.main = async (event, context) => {let obj = {order_number: Date.now(),carts: event.carts,status: 0 }let res = await orders_col.add({data: obj})return {res,order_number: obj.order_number}}
  1. 在购物车文件 cart.js 中定义 startPay 开始支付的函数,在里面先进行第一步,发起订单到获取订单号。使用云函数 makeOrder 获取响应结果,解构赋值得到 order_number 订单号,代码如下所示:
    let res1 = await wx.cloud.callFunction({name: 'makeOrder',data: {carts: this.data.carts}})await ml_showToastSuccess('发起订单成功')const { order_number } = res1.resultconsole.log('发起订单', order_number)
  1. 创建 pay 云函数,需要使用到tenpay 这个包,需要通过 npm i tenpay命令进行下载。然后在 pay.js文件中,引入 tenpay,进行配置config。在 config 配置文件中,appid 是公众号IDmchid 是微信商户号,partnerKey 是微信支付安全密钥,notify_url是支付回调网址,spbill_create_ipIP 地址,其中appidmchidpartnerKey 这三个必须有。最后配置云函数入口函数,初始化 tenpay, 获取支付参数,在支付参数中包括out_trade_no 商户内部订单号,body 商品简单描述,total_fee订单金额,openid 付款用户的 openid, openid 是用户的唯一身份标识,然后返回结果,代码如下所示:
const cloud = require('wx-server-sdk')cloud.init()const tenpay = require('tenpay')
const config = {// 公众号ID appid: 'abcd',// 微信商户号mchid: '123456',// 微信支付安全密钥partnerKey: 'abcdefg',// 支付回调网址notify_url: 'http://127.112.255.255/orders',// IP 地址spbill_create_ip: '127.0.0.1'
}exports.main = async (event, context) => {const wxContext = cloud.getWXContext()const api = tenpay.init(config)let result = await api.getPayParams({// 商户内部订单号out_trade_no: event.order_number + '',// 商品简单描述body: '这是一次支付',// 订单金额 total_fee: 1,// 付款用户的 openidopenid: wxContext.OPENID})return result
}
  1. 继续在 startPay 函数中,写预支付,获取支付所需的5个参数,代码如下所示:
    let res2 = await wx.cloud.callFunction({name: 'pay',data: {order_number}})console.log('预支付', res2)
  1. 写一个发起支付的函数工具类ml_payment,对传过来的 pay参数进行解构赋值,会得到上面的参数,成功就执行 resolve, 失败就 reject,代码如下所示:
export const ml_payment = (pay) => {return new Promise((resolve, reject) => {wx.requestPayment({...pay,success: resolve,fail: reject})})
}
  1. 继续在 startPay 函数中,写发起支付的功能,异步调用 ml_payment 函数,将预支付的参数传入进来,此时会出现一个支付二维码,需要输入支付密码进行支付,代码如下所示:
      await ml_payment(res2.result)await ml_showToastSuccess('支付成功')
  1. 创建 updateStatus 云函数,更新支付状态。在里面配置云函数入口文件,引入云函数的数据,配置云函数入口函数。在里面更新status,通过订单号 order_number 去查询支付状态,将状态status 变为 1,代码如下所示:
const cloud = require('wx-server-sdk')cloud.init()const db = cloud.database({env: 'prod-hswqx-ek3h5'
})
const orders_col = db.collection('orders')exports.main = async (event, context) => {let res = await orders_col.where({order_number: event.order_number}).update({data: {status: 1}})return res}
  1. 继续在 startPay 函数中,写更新支付状态,变为已支付。调用 updateStatus 云函数去更新状态,代码如下所示:
    let res3 = await wx.cloud.callFunction({name: 'updateStatus',data: {order_number}})console.log('更新状态', res3)
  1. 创建 clearCarts 云函数,清空购物车。在里面配置云函数入口文件,引入云函数的数据,配置云函数入口函数。在入口函数中,清空购物车,将已支付的购物车数据进行清空,代码如下所示:
const cloud = require('wx-server-sdk')cloud.init()const db = cloud.database({env: 'prod-hswqx-ek3h5'
})
const carts_col = db.collection('carts')exports.main = async (event, context) => {let res = await carts_col.where({selected: true}).remove()return res
}
  1. 继续在 startPay 函数中,写清空购物车。调用 clearCarts 云函数,清空已支付的购物车数据,然后通过 this.setData 将购物车数据 carts 设置为空数组,总数量totalCount 设置为 0,总价格 totalPrice设置为 0,代码如下所示:
    let res4 = await wx.cloud.callFunction({name: 'clearCarts'})console.log('清空购物车', res4)this.setData({carts: [],totalCount: 0,totalPrice: 0})
  1. 继续在 startPay 函数中,写跳转到订单页,通过 wx.navigateTo 进行页面的跳转,代码如下所示:
    wx.navigateTo({url: '/pages/orders/orders',})