千家信息网

微信小程序如何实现云支付

发表于:2025-01-18 作者:千家信息网编辑
千家信息网最后更新 2025年01月18日,这篇文章给大家分享的是有关微信小程序如何实现云支付的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、前言稍微玩过微信小程序云开发的同学都基本知道微信小程序云开发目前已经支持
千家信息网最后更新 2025年01月18日微信小程序如何实现云支付

这篇文章给大家分享的是有关微信小程序如何实现云支付的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

一、前言

稍微玩过微信小程序云开发的同学都基本知道微信小程序云开发目前已经支持云支付这一能力。

那么在云支付的能力支持之下,整个支付的流程是怎样的呢?

例如:用户发起支付前、支付中、支付后的逻辑处理应该是怎样的,该如何设计会比较保险,降低出错的概率。

那么本文主要介绍云支付的使用以及在云支付下的订单系统、支付流程该如何设计。

顺便提一下:微信支付功能仅支持企业主体调用

二、思路分析

云支付的调用流程大致分为以下四步:

1、获取免鉴权参数

小程序端传入金额、商品信息等基本参数后,调用云函数获取免鉴权参数。

2、将免鉴权参数传入小程序端的支付API

云函数返回免鉴权参数,作为小程序端支付API的入参。

3、用户支付

调起微信支付,用户进行支付/取消支付操作

4、微信端回调指定的云函数

支付成功后回调此云函数。

如果用户取消支付,则不会回调此云函数。

那么,根据以上四个步骤就可以分析出,订单的创建、订单支付状态的改变应该是在什么时候了。

订单的创建应该是在第一步的获取免鉴权参数的时候,获取免鉴权参数后将订单号等信息插入数据库。

此时的订单支付状态应该是待支付状态。

同时也可以知道,订单支付状态的改变,应该是在第四步中去进行改变,如果支付成功,将订单的支付状态改为支付成功即可。

相关的官方文档链接:

  • 云支付文档

  • 云支付回调文档

  • 小程序端调起支付API文档

三、云支付小案例

1.云函数

1-1.获取免鉴权参数云函数(wxPay)

此云函数主要是获取支付API所需的参数,以及创建订单插入数据库。

成功调用示例结果截图

实现代码

// 云函数入口文件const cloud = require('wx-server-sdk')cloud.init({  env: cloud.DYNAMIC_CURRENT_ENV})const db = cloud.database()exports.main = async (event) => {  const wxContent = cloud.getWXContext() // openid等信息  const openid = wxContent.OPENID  const appid = wxContent.APPID  const totalFee = event.totalFee // 支付金额(单位:分)  const body = event.body // 商品名  const outTradeNo = createOutTradeNo() // 订单号  // 获取免鉴权支付参数  const payMent = await cloud.cloudPay.unifiedOrder({    "body": body,    "outTradeNo": outTradeNo,    "spbillCreateIp": "127.0.0.1",    "subMchId": "商户号", // 商户号    "totalFee": totalFee,    "envId": "对应的云环境id", // 云环境id    "functionName": "payCallBack" // 支付回调云函数  })  // 创建订单  const nowTime = new Date().getTime()  const orderObj = {    _openid: openid,    appid: appid,    outTradeNo: outTradeNo,    totalFee: totalFee * 0.01,    payStatus: 'wait',    createTime: nowTime,    updateTime: nowTime,    deleteTime: null,  }  await addOrder(orderObj)  return payMent}/** 创建随机的唯一订单号(32位) */const createOutTradeNo = () => {  let outTradeNo = new Date().getTime() // 获取当前13位时间戳  let numStr = '0123456789';  let randomStr = '';  for (let i = (32 - 13); i > 0; --i) {    randomStr += numStr[Math.floor(Math.random() * numStr.length)];  }  outTradeNo += randomStr  return outTradeNo}/** 向数据库创建订单 */const addOrder = async (orderObj) => {  return await db.collection('order')    .add({      data: orderObj    })    .then(res => {      console.log("创建订单成功 =====>", res, orderObj)    })    .catch(err => {      console.log("创建订单异常 =====>", err, orderObj)    })}
1-2.支付回调云函数(payCallBack)

在用户支付成功后微信服务端将会调用此云函数,并携带支付方的订单号、openid、appid等信息。

开发者可以根据这个来判断当前回调的是哪个订单。

回调文档

成功回调结果示例截图

实现代码

// 云函数入口文件const cloud = require('wx-server-sdk')cloud.init({  env: cloud.DYNAMIC_CURRENT_ENV})const db = cloud.database()// 云函数入口函数exports.main = async (event) => {  console.log("回调返回对象 =====>", event)        // 判断条件  if (event.returnCode == 'SUCCESS') {    if (event.resultCode == 'SUCCESS') {      // 查询条件      const whereObj = {        appid: event.subAppid, // 小程序的APPID        _openid: event.subOpenid, // 小程序用户的openid        outTradeNo: event.outTradeNo, // 商户号的订单号      }      // 更新对象      const updateObj = {        transactionId: event.transactionId, // 微信方的订单号        totalFee: event.totalFee * 0.01, // 微信方收到的金额        timeEnd: event.timeEnd, // 支付结束时间        payStatus: 'success',        updateTime: new Date().getTime()      }      // 更新订单      await updateOrder(whereObj, updateObj)    }  }  // 支付回调的返回协议和入参协议(必须返回此结构体,详见文档)  return {    errcode: 0,    errmsg: event.resultCode  }}/** 更新订单的支付状态 */const updateOrder = async (whereObj, updateObj) => {  return await db.collection('order')    .where(whereObj)    .update({      data: updateObj    })}

2.小程序端(js代码)

// pages/wxPay/wxPay.jsPage({  /**   * 页面的初始数据   */  data: {  },  /**   * 生命周期函数--监听页面加载   */  onLoad() {},  /**   * 生命周期函数--监听页面显示   */  onShow() {},  /** 支付点击监听 */  async payTap() {    const totalFee = 2    const body = '支付测试'    wx.showLoading({      title: '调起微信支付中',      mask: true    })    // 获取支付免鉴权参数    const payMentRes = await this.getPayMent(totalFee, body)    wx.hideLoading({      success: (res) => {},    })    // 小程序支付API    const payRes = await this.wxPay(payMentRes.result.payment)    // 支付API返回结果打印    console.log(payRes)  },  /**   * 小程序支付API   * @param {object} payment 支付免鉴权参数   */  wxPay(payment) {    return new Promise((resolve, rejects) => {      wx.requestPayment({        ...payment,        success(res) {          resolve({            status: 'success',            res: res          })        },        fail(err) {          resolve({            status: 'fail',            res: err          })        }      })    })  },  /**   * 获取支付免鉴权参数   * @param {number} totalFee 支付金额, 单位:分   * @param {string} body 商品名称   */  getPayMent(totalFee, body) {    return new Promise((resolve, rejects) => {      wx.cloud.callFunction({        name: 'wxPay',        data: {          totalFee,          body        },        success(res) {          resolve(res)        },        fail(err) {          resolve(err)        }      })    })  },})

3.支付结果

用户端

商家端

4、代码目录结构

四、为什么这样写

或许有的同学也使用过微信云支付的能力,但是不曾使用到上面说到的支付回调云函数。

但是也可以做到获取用户的支付结果。

如下图

事实上,小程序端的支付API(wx.requestPayment())也可以返回当前的支付结果。也确实可以使用这个回调的结果来判断支付是否成功。

那既然这样,为什么还要多此一举写个支付回调云函数来获取支付的结果呢?

看到这里也说明你看完了整个实现过程了,如果你有为什么要用这种方式实现的疑问,也应该多少能够自己给自己找到一些答案。

除去开发规范、优化相关的小问题,我这里说一个很致命的原因。

微信小程序支付API(wx.requestPayment())在IOS端有一个致命的问题,

当用户支付后会进入下面这个页面

当用户不点击完成按钮,微信小程序的支付API(wx.requestPayment())回调是不会触发的。

也就说,小程序自身拿不到用户的支付结果了。

假设用户直接退出了微信,小程序也就销毁了。这时,订单状态该如何改变呢?

tips: 在安卓端不会出现这个问题。有兴趣的同学可以自己去实践以下。

感谢各位的阅读!关于"微信小程序如何实现云支付"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

0