微信小程序云支付踩坑指南(附:全流程代码开箱即用)

235 阅读2分钟

坑在哪里

前提:使用小程序云支付且使用小程序的云数据库来记录用户支付信息,没有后台接口参与的场景

坑:wx.requestPayment,该方法是用于微信的拉起支付请求,该方法的success回调触发节点点击图中完成按钮。 如果用户没有点击完成,直接关闭了小程序,则无法触发wx.requestPayment这个方法的success回调

image.png

如何解决:如果你自己使用云支付且记录小程序自己的云数据库的话,支付的云函数一定要在 cloud.cloudPay.unifiedOrder生成订单填写回调函数,在这个云支付回调函数内,去更新数据库订单信息,如下图所示

image.png

正常的云支付流程

  1. 编写云支付函数

// 云函数代码
const cloud = require('wx-server-sdk')
cloud.init({
    env: cloud.DYNAMIC_CURRENT_ENV
})
const db = cloud.database()

function pad(num) {
  return num.toString().padStart(2, "0");
}

function formatDateTime(date) {
  const year = date.getFullYear();
  const month = date.getMonth() + 1;
  const day = date.getDate();
  const hour = date.getHours();
  const minute = date.getMinutes();
  const second = date.getSeconds();
  return `${year}-${pad(month)}-${pad(day)} ${pad(hour)}:${pad(minute)}:${pad(
    second
  )}`;
}

exports.main = async (event, context) => {
    const outTradeNo = "1675520950" + new Date().getTime() + Math.floor(Math.random() * 10)
    const res = await cloud.cloudPay.unifiedOrder({
        "body": event.goodName, // 商品描述
        "outTradeNo": outTradeNo, // 商户订单号
        "spbillCreateIp": "127.0.0.1", // 终端 IP
        "subMchId": "", // 商户号
        "totalFee": event.totalFee, // 总金额
        "envId": "", // 云函数环境名称
        "functionName": "payCallBack" // 支付结果通知回调云函数名
    })
    let nowTime = formatDateTime(new Date())
    console.log('统一下单', outTradeNo, nowTime)
    // 这里落库数据记录用户有支付的操作,并不代表支付成功了
    await db.collection('xxxxx').add({
        data: {
            _openid: event.openId,
            outTradeNo: outTradeNo,
            payStatus: false,  // 这里记录是未支付成功
            time: nowTime,
            payMoney: event.payMoney
        }
    })
    return res
}
  1. 编写云支付回调函数

const cloud = require('wx-server-sdk')
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
}) // 使用当前云环境
const db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
  let {
      returnCode,
      outTradeNo
  } = event
  // 这里是真正支付成功之后才会更新数据的订单状态
  if (returnCode == 'SUCCESS') {
      // 这里的xxxx是云数据库的表名
      await db.collection('xxxx').where({
          outTradeNo: outTradeNo
      }).update({
          data: {
              payStatus: true
          }
      })
  }
  return {
    errcode: 0,
    errmsg: ''
  }
}
  1. 业务场景调用支付

goPay(formData) {
    let opid = wx.getStorageSync('openid')
    wx.showLoading({
      title: '加载中',
    })
    wx.cloud.callFunction({
      name: 'pay',
      data: {
        goodName: 'xxxx',
        totalFee: Number(this.data.payMoney) * 100,
        openId: opid,
        payMoney: this.data.payMoney,
        ...formData,
      },
      success: res => {
        const payment = res.result.payment
        wx.requestPayment({
          ...payment,
          success: (res) => {
            wx.hideLoading()
            wx.setStorageSync('payMoney', this.data.payMoney)
            this.clearFormData()
            wx.navigateTo({
              url: '/pages/business/paySuccess/index',
            });
            console.log('支付成功', res)
          },
          fail: (err) => {
            wx.hideLoading()
            wx.showToast({
              title: '支付失败',
              icon: 'none',
              duration: 4000,
            });
            console.log('支付失败', err)
          }
        })
      },
      fail: (res) => {
        console.log('云函数错误', res)
      }
    })
  },