微信小程序--雲開發支付閉環

雲開發支付流程閉環

extends

微信小程序--使用雲開發完成支付閉環

在上述文章中,我們對支付結果的處理更多依賴於小程序端的操作

  1. 訂單號存儲在小程序端
  2. 支付結果採用小程序端定時觸發器輪詢

現在我對該流程進行了優化處理

1.流程介紹

2.小程序端

  1. 請求統一下單雲函數
  2. 調用支付接口
  3. 偵聽器獲取支付結果
// pages/index/details.js
const app = getApp();
const db = wx.cloud.database();
var watcher = null
Page({

  /**
   * 頁面的初始數據
   */
  data: {
    
  },
  //付費解鎖
  payUnlock() {
    var that = this;
   
    this.setData({
      vis: true
    })
    //用戶ID 即爲OPENID
    let userid = this.data.selfcard._id;
    wx.cloud.callFunction({
      name: 'userpay',
      data: {
        fee: 1,
        paydata: {
          userid
        }
      },
      success: res => {
        console.log(res)
        //統一下單雲函數中需要返回偵聽器 需要的記錄id
        that.payWatcher(res.result.docid);
        that.setData({
          vis: false
        })     
        //根據統一下單參數 請求支付接口
        const payment = res.result.payment
        wx.requestPayment({
          ...payment,
          success(ans) {
            console.log(ans)
          },
          fail(ans) {
            that.setData({
              errMsg: '調用支付失敗'
            })
          }
        })
      }
    })
  },
  payWatcher(docid){
    var that = this;
    //爲用戶支付記錄表設置偵聽器,偵聽docid信息的變動
    this.watcher =  db.collection('USERPAYLOG').doc(docid).watch({
      onChange: async function (snapshot) {
        //只打印變動的信息
        // console.log(snapshot)
        if (snapshot.docChanges.length != 0) {
          console.log(snapshot.docChanges)
          let paydoc = snapshot.docChanges[0].doc;
          //偵聽到支付成功
          if(paydoc.paystatus == 1){
            that.setData({
              succMsg:'支付成功',
              locked:false,
              bottom:0
            })
          }
          // await that.watcher.close();
        }
      },
      onError: function (err) {
        console.error('the watch closed because of error', err)
      }
    })
  },
  /**
   * 生命週期函數--監聽頁面加載
   */
  onLoad: function (options) {

  },
  /**
   * 生命週期函數--監聽頁面卸載
   */
  onUnload: function () {
    try {
      this.watcher.close();
    } catch (error) {
      console.log('暫未啓動支付偵聽器')
    }
  }
})

3.雲函數端

userpay

  1. 雲調用統一下單【CloudPay.unifiedOrder】
  2. 數據庫中存入訂單記錄並設置爲未支付狀態

需要配置商戶(雲開發控制檯)

const cloud = require('wx-server-sdk')
//需要在此處修改你的雲環境ID
cloud.init({
  env: ''
})
const db = cloud.database();
const _ = db.command;
// 雲函數入口函數
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  var openid = event.openid || wxContext.OPENID
  //獲取統一下單金額
  var fee = parseInt(event.fee);
  let paydata = event.paydata;
  //生成訂單號
  let tradeno = GetTradeNo();
  //調用統一下單接口
  const res = await cloud.cloudPay.unifiedOrder({
    //填寫你的商戶主體信息 例如 xx商貿
    "body": "",
    "outTradeNo": tradeno,
    "spbillCreateIp": "127.0.0.1",
    //填寫你的商戶ID -- 可在雲開發控制檯中綁定獲得(上圖所示)
    "subMchId": "",
    "totalFee": fee,
    //填寫你的雲環境ID
    "envId": "",
    //填寫你的回調函數名稱
    "functionName": "userpaynotify"
  })
  console.log(res)
  res.outTradeNo = tradeno
  res.totalFee = fee
  //支付狀態 0 爲未支付
  paydata.tradeno = tradeno
  paydata.paystatus = 0
  paydata.totalfee = fee
  paydata.openid = openid
  paydata.paytime = TimeCode()
  //統一下單shuju
  paydata.uniOrder = res
  //攔截處理 爲保持數據庫字段一致性
  if (res.returnCode == 'SUCCESS' && res.resultCode == 'SUCCESS') {
    //在雲數據庫中寫入未支付的訂單信息
    let tdata = await db.collection('USERPAYLOG').add({
      data: paydata
    })
    console.log(tdata)
    //將該記錄ID攜帶返回給小程序端
    res.docid = tdata._id;
    return res;
  }else{
    return res;
  }
}

function GetTradeNo() {
  var outTradeNo = ""; //訂單號
  for (var i = 0; i < 6; i++) //6位隨機數,用以加在時間戳後面。
  {
    outTradeNo += Math.floor(Math.random() * 10);
  }
  outTradeNo = "COP" + new Date().getTime() + outTradeNo; //時間戳,用來生成訂單號。
  return outTradeNo;
}

function TimeCode() {
  var date = new Date();
  var year = date.getFullYear()
  var month = date.getMonth() + 1
  var day = date.getDate()

  var hour = date.getHours()
  var minute = date.getMinutes()
  var second = date.getSeconds()

  return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}

function formatNumber(n) {
  n = n.toString()
  return n[1] ? n : '0' + n
}

支付成功後觸發雲環境中該回調函數

回調函數攜帶的請求信息請在參考文檔中查看

userpaynotify

  1. 修改數據庫中訂單狀態

  2. 返回給回調請求SUCCESS數據【Cloud.paymentCallback】

    訂單在支付成功時會觸發該回調函數

    該回調函數必須有返回值,且必須是固定格式

    根據回調函數攜帶的訂單號,修改對應訂單號的訂單狀態,並且返回對應格式的返回信息

    字段名 變量名 必填 類型 描述
    錯誤碼 errcode Number 0
    錯誤信息 errmsg String
const cloud = require('wx-server-sdk')
//填寫你的雲環境ID
cloud.init({
  env: ''
})
const db = cloud.database();
const _ = db.command;
// 雲函數入口函數
exports.main = async (event, context) => {

  console.log('支付成功回調函數觸發')
  console.log(event)
  let tradeno = event.outTradeNo;
  try {
    //修改數據庫中訂單狀態 爲已支付
    db.collection('USERPAYLOG').where({
      tradeno:tradeno
    }).update({
      data:{
        paystatus:1
      }
    })
  } catch (error) {
    return {
      errmsg: 'SERVER_ERROR',
      errcode: -1
    }
  }
  return {
    errmsg: 'SUCCESS',
    errcode: 0
  }
}

參考文檔

  1. 雲開發文檔 Cloud.CloudPay | 微信開放文檔 (qq.com)

  2. 回調函數請求攜帶參數

{
	appid: '',

	bankType: 'OTHERS',

	cashFee: 1,

	feeType: 'CNY',

	isSubscribe: 'N',

	mchId: '',

	nonceStr: '',

	openid: '',

	outTradeNo: '',

	resultCode: 'SUCCESS',

	returnCode: 'SUCCESS',

	subAppid: '',

	subIsSubscribe: 'N',

	subMchId: '',

	subOpenid: '',

	timeEnd: '',

	totalFee: 1,

	tradeType: 'JSAPI',

	transactionId: '',

	userInfo:

	{
		appId: '',

		openId: ''
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章