溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

微信小程序如何實(shí)現(xiàn)云支付

發(fā)布時間:2021-09-08 13:40:14 來源:億速云 閱讀:166 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)微信小程序如何實(shí)現(xiàn)云支付的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

一、前言

稍微玩過微信小程序云開發(fā)的同學(xué)都基本知道微信小程序云開發(fā)目前已經(jīng)支持云支付這一能力。

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

例如:用戶發(fā)起支付前、支付中、支付后的邏輯處理應(yīng)該是怎樣的,該如何設(shè)計(jì)會比較保險,降低出錯的概率。

那么本文主要介紹云支付的使用以及在云支付下的訂單系統(tǒng)、支付流程該如何設(shè)計(jì)。

順便提一下:微信支付功能僅支持企業(yè)主體調(diào)用。

二、思路分析

云支付的調(diào)用流程大致分為以下四步:

1、獲取免鑒權(quán)參數(shù)

小程序端傳入金額、商品信息等基本參數(shù)后,調(diào)用云函數(shù)獲取免鑒權(quán)參數(shù)。

2、將免鑒權(quán)參數(shù)傳入小程序端的支付API

云函數(shù)返回免鑒權(quán)參數(shù),作為小程序端支付API的入?yún)ⅰ?/p>

3、用戶支付

調(diào)起微信支付,用戶進(jìn)行支付/取消支付操作

4、微信端回調(diào)指定的云函數(shù)

支付成功后回調(diào)此云函數(shù)。

如果用戶取消支付,則不會回調(diào)此云函數(shù)。

那么,根據(jù)以上四個步驟就可以分析出,訂單的創(chuàng)建、訂單支付狀態(tài)的改變應(yīng)該是在什么時候了。

訂單的創(chuàng)建應(yīng)該是在第一步的獲取免鑒權(quán)參數(shù)的時候,獲取免鑒權(quán)參數(shù)后將訂單號等信息插入數(shù)據(jù)庫。

此時的訂單支付狀態(tài)應(yīng)該是待支付狀態(tài)。

同時也可以知道,訂單支付狀態(tài)的改變,應(yīng)該是在第四步中去進(jìn)行改變,如果支付成功,將訂單的支付狀態(tài)改為支付成功即可。

相關(guān)的官方文檔鏈接:

  • 云支付文檔

  • 云支付回調(diào)文檔

  • 小程序端調(diào)起支付API文檔

三、云支付小案例

1.云函數(shù)

1-1.獲取免鑒權(quán)參數(shù)云函數(shù)(wxPay)

此云函數(shù)主要是獲取支付API所需的參數(shù),以及創(chuàng)建訂單插入數(shù)據(jù)庫。

成功調(diào)用示例結(jié)果截圖

微信小程序如何實(shí)現(xiàn)云支付

實(shí)現(xiàn)代碼

// 云函數(shù)入口文件
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() // 訂單號

  // 獲取免鑒權(quán)支付參數(shù)
  const payMent = await cloud.cloudPay.unifiedOrder({
    "body": body,
    "outTradeNo": outTradeNo,
    "spbillCreateIp": "127.0.0.1",
    "subMchId": "商戶號", // 商戶號
    "totalFee": totalFee,
    "envId": "對應(yīng)的云環(huán)境id", // 云環(huán)境id
    "functionName": "payCallBack" // 支付回調(diào)云函數(shù)
  })

  // 創(chuàng)建訂單
  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
}

/** 創(chuàng)建隨機(jī)的唯一訂單號(32位) */
const createOutTradeNo = () => {
  let outTradeNo = new Date().getTime() // 獲取當(dāng)前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
}

/** 向數(shù)據(jù)庫創(chuàng)建訂單 */
const addOrder = async (orderObj) => {
  return await db.collection('order')
    .add({
      data: orderObj
    })
    .then(res => {
      console.log("創(chuàng)建訂單成功 =====>", res, orderObj)
    })
    .catch(err => {
      console.log("創(chuàng)建訂單異常 =====>", err, orderObj)
    })
}
1-2.支付回調(diào)云函數(shù)(payCallBack)

在用戶支付成功后微信服務(wù)端將會調(diào)用此云函數(shù),并攜帶支付方的訂單號、openid、appid等信息。

開發(fā)者可以根據(jù)這個來判斷當(dāng)前回調(diào)的是哪個訂單。

回調(diào)文檔

成功回調(diào)結(jié)果示例截圖

微信小程序如何實(shí)現(xiàn)云支付

實(shí)現(xiàn)代碼

// 云函數(shù)入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})

const db = cloud.database()

// 云函數(shù)入口函數(shù)
exports.main = async (event) => {
  console.log("回調(diào)返回對象 =====>", 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, // 支付結(jié)束時間
        payStatus: 'success',
        updateTime: new Date().getTime()
      }
      // 更新訂單
      await updateOrder(whereObj, updateObj)
    }
  }
  // 支付回調(diào)的返回協(xié)議和入?yún)f(xié)議(必須返回此結(jié)構(gòu)體,詳見文檔)
  return {
    errcode: 0,
    errmsg: event.resultCode
  }
}

/** 更新訂單的支付狀態(tài) */
const updateOrder = async (whereObj, updateObj) => {
  return await db.collection('order')
    .where(whereObj)
    .update({
      data: updateObj
    })
}

2.小程序端(js代碼)

// pages/wxPay/wxPay.js
Page({

  /**
   * 頁面的初始數(shù)據(jù)
   */
  data: {

  },

  /**
   * 生命周期函數(shù)--監(jiān)聽頁面加載
   */
  onLoad() {},

  /**
   * 生命周期函數(shù)--監(jiān)聽頁面顯示
   */
  onShow() {},

  /** 支付點(diǎn)擊監(jiān)聽 */
  async payTap() {
    const totalFee = 2
    const body = '支付測試'
    wx.showLoading({
      title: '調(diào)起微信支付中',
      mask: true
    })

    // 獲取支付免鑒權(quán)參數(shù)
    const payMentRes = await this.getPayMent(totalFee, body)
    wx.hideLoading({
      success: (res) => {},
    })
    // 小程序支付API
    const payRes = await this.wxPay(payMentRes.result.payment)
    // 支付API返回結(jié)果打印
    console.log(payRes)
  },

  /**
   * 小程序支付API
   * @param {object} payment 支付免鑒權(quán)參數(shù)
   */
  wxPay(payment) {
    return new Promise((resolve, rejects) => {
      wx.requestPayment({
        ...payment,
        success(res) {
          resolve({
            status: 'success',
            res: res
          })
        },
        fail(err) {
          resolve({
            status: 'fail',
            res: err
          })
        }
      })
    })
  },

  /**
   * 獲取支付免鑒權(quán)參數(shù)
   * @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.支付結(jié)果

用戶端

微信小程序如何實(shí)現(xiàn)云支付

商家端

微信小程序如何實(shí)現(xiàn)云支付

4、代碼目錄結(jié)構(gòu)

微信小程序如何實(shí)現(xiàn)云支付

四、為什么這樣寫

或許有的同學(xué)也使用過微信云支付的能力,但是不曾使用到上面說到的支付回調(diào)云函數(shù)。

但是也可以做到獲取用戶的支付結(jié)果。

如下圖

微信小程序如何實(shí)現(xiàn)云支付

事實(shí)上,小程序端的支付API(wx.requestPayment())也可以返回當(dāng)前的支付結(jié)果。也確實(shí)可以使用這個回調(diào)的結(jié)果來判斷支付是否成功。

那既然這樣,為什么還要多此一舉寫個支付回調(diào)云函數(shù)來獲取支付的結(jié)果呢?

看到這里也說明你看完了整個實(shí)現(xiàn)過程了,如果你有為什么要用這種方式實(shí)現(xiàn)的疑問,也應(yīng)該多少能夠自己給自己找到一些答案。

除去開發(fā)規(guī)范、優(yōu)化相關(guān)的小問題,我這里說一個很致命的原因。

微信小程序支付API(wx.requestPayment())在IOS端有一個致命的問題,

當(dāng)用戶支付后會進(jìn)入下面這個頁面

微信小程序如何實(shí)現(xiàn)云支付

當(dāng)用戶不點(diǎn)擊完成按鈕,微信小程序的支付API(wx.requestPayment())回調(diào)是不會觸發(fā)的。

也就說,小程序自身拿不到用戶的支付結(jié)果了。

假設(shè)用戶直接退出了微信,小程序也就銷毀了。這時,訂單狀態(tài)該如何改變呢?

tips: 在安卓端不會出現(xiàn)這個問題。有興趣的同學(xué)可以自己去實(shí)踐以下。

感謝各位的閱讀!關(guān)于“微信小程序如何實(shí)現(xiàn)云支付”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI