• 當前位置:首頁 > IT技術 > 微信平臺 > 正文

    借助小程序云開發實現小程序支付功能(含源碼)
    2021-08-08 14:09:31

    我們在做小程序支付相關的開發時,總會遇到這些難題。小程序調用微信支付時,必須要有自己的服務器,有自己的備案域名,有自己的后臺開發。這就導致我們做小程序支付時的成本很大。本節就來教大家如何使用小程序云開發實現小程序支付功能的開發。不用搭建自己的服務器,不用有自己的備案域名。只需要簡簡單單的使用小程序云開發。

    老規矩先看效果圖:
    借助小程序云開發實現小程序支付功能(含源碼)_云開發小程序支付

    本節知識點

    1,云開發的部署和使用
    2,支付相關的云函數開發
    3,商品列表
    4,訂單列表
    5,微信支付與支付成功回調

    支付成功給用戶發送推送消息的功能會在后面講解。

    下面就來教大家如何借助云開發使用小程序支付功能。

    支付所需要用到的配置信息

    1,小程序appid
    2,云開發環境id
    3,微信商戶號
    4,商戶密匙

    一,準備工作

    1,已經申請小程序,獲取小程序 AppID 和 Secret 在小程序管理后臺中,【設置】 →【開發設置】 下可以獲取微信小程序 AppID 和 Secret。
    借助小程序云開發實現小程序支付功能(含源碼)_云開發小程序支付_02
    2,微信支付商戶號,獲取商戶號和商戶密鑰在微信支付商戶管理平臺中,【賬戶中心】→【商戶信息】 下可以獲取微信支付商戶號。
    借助小程序云開發實現小程序支付功能(含源碼)_小程序_03
    在【賬戶中心】 ?> 【API安全】 下可以設置商戶密鑰。
    借助小程序云開發實現小程序支付功能(含源碼)_小程序_04
    這里特殊說明下,個人小程序是沒有辦法使用微信支付的。所以如果想使用微信支付功能,必須是非個人賬號(當然個人可以辦個體戶工商執照來注冊非個人小程序賬號)

    ?

    二,商品列表的實現

    效果圖如下,由于本節重點是支付的實現,所以這里只簡單貼出關鍵代碼。
    借助小程序云開發實現小程序支付功能(含源碼)_小程序_05
    wxml布局如下:

    <view class="container">
      <view class="good-item" wx:for="{{goods}}" wx:key="*this" ontap="getDetail" data-goodid="{{item._id}}">
        <view class="good-image">
          <image src="{{pic}}"></image>
        </view>
        <view class="good-detail">
          <view class="title">商品: {{item.name}}</view>
          <view class="content">價格: {{item.price / 100}} 元 </view>
          <button
            class="button"
            type="primary"
            bindtap="makeOrder"
            data-goodid="{{item._id}}"
          >下單</button>
        </view>
      </view>
    </view>
    

    我們所需要做的就是借助云開發獲取云數據庫里的商品信息,然后展示到商品列表,關于云開發獲取商品列表并展示本節不做講解(感興趣的同學可以翻看我的歷史博客,有寫過的)
    借助小程序云開發實現小程序支付功能(含源碼)_云開發微信支付_06

    三,支付云函數的創建

    首先看下我們支付云函數都包含那些內容
    借助小程序云開發實現小程序支付功能(含源碼)_云開發小程序支付_07
    簡單先講解下每個的用處
    config下的index.js是做支付配置用的,主要配置支付相關的賬號信息
    lib是用的第三方的支付庫,這里不做講解。
    重點講解的是云函數入口 index.js

    下面就來教大家如何去配置

    1,配置config下的index.js,
    這一步所需要做的就是把小程序appid,云開發環境ID,商戶id,商戶密匙。填進去。
    借助小程序云開發實現小程序支付功能(含源碼)_云開發支付_08
    2,配置入口云函數
    借助小程序云開發實現小程序支付功能(含源碼)_云開發小程序支付_09
    詳細代碼如下,代碼里注釋很清除了,這里不再做單獨講解:

    const cloud = require('wx-server-sdk')
    cloud.init()
    
    const app = require('tcb-admin-node');
    const pay = require('./lib/pay');
    const {
     mpAppId,
     KEY
    } = require('./config/index');
    const {
     WXPayConstants,
     WXPayUtil
    } = require('wx-js-utils');
    const Res = require('./lib/res');
    const ip = require('ip');
    
    /**
     *
     * @param {obj} event
     * @param {string} event.type 功能類型
     * @param {} userInfo.openId 用戶的openid
     */
    exports.main = async function(event, context) {
     const {
      type,
      data,
      userInfo
     } = event;
     const wxContext = cloud.getWXContext()
     const openid = userInfo.openId;
     
     app.init();
     const db = app.database();
     const goodCollection = db.collection('goods');
     const orderCollection = db.collection('order');
    
     // 訂單文檔的status 0 未支付 1 已支付 2 已關閉
     switch (type) {
      // [在此處放置 unifiedorder 的相關代碼]
      case 'unifiedorder':
       {
        // 查詢該商品 ID 是否存在于數據庫中,并將數據提取出來
        const goodId = data.goodId
        let goods = await goodCollection.doc(goodId).get();
    
        if (!goods.data.length) {
         return new Res({
          code: 1,
          message: '找不到商品'
         });
        }
    
        // 在云函數中提取數據,包括名稱、價格才更合理安全,
        // 因為從端里傳過來的商品數據都是不可靠的
        let good = goods.data[0];
    
        // 拼湊微信支付統一下單的參數
        const curTime = Date.now();
        const tradeNo = `${goodId}-${curTime}`;
        const body = good.name;
        const spbill_create_ip = ip.address() || '127.0.0.1';
        // 云函數暫不支付 http 觸發器,因此這里回調 notify_url 可以先隨便填。
        const notify_url = 'http://www.qq.com'; //'127.0.0.1';
        const total_fee = good.price;
        const time_stamp = '' + Math.ceil(Date.now() / 1000);
        const out_trade_no = `${tradeNo}`;
        const sign_type = WXPayConstants.SIGN_TYPE_MD5;
    
        let orderParam = {
         body,
         spbill_create_ip,
         notify_url,
         out_trade_no,
         total_fee,
         openid,
         trade_type: 'JSAPI',
         timeStamp: time_stamp,
        };
    
        // 調用 wx-js-utils 中的統一下單方法
        const {
         return_code,
         ...restData
        } = await pay.unifiedOrder(orderParam);
    
        let order_id = null;
    
        if (return_code === 'SUCCESS' && restData.result_code === 'SUCCESS') {
         const {
          prepay_id,
          nonce_str
         } = restData;
    
         // 微信小程序支付要單獨進地簽名,并返回給小程序端
         const sign = WXPayUtil.generateSignature({
          appId: mpAppId,
          nonceStr: nonce_str,
          package: `prepay_id=${prepay_id}`,
          signType: 'MD5',
          timeStamp: time_stamp
         }, KEY);
    
         let orderData = {
          out_trade_no,
          time_stamp,
          nonce_str,
          sign,
          sign_type,
          body,
          total_fee,
          prepay_id,
          sign,
          status: 0, // 訂單文檔的status 0 未支付 1 已支付 2 已關閉
          _openid: openid,
         };
    
         let order = await orderCollection.add(orderData);
    
         order_id = order.id;
        }
    
        return new Res({
         code: return_code === 'SUCCESS' ? 0 : 1,
         data: {
          out_trade_no,
          time_stamp,
          order_id,
          ...restData
         }
        });
       }
       // [在此處放置 payorder 的相關代碼]
      case 'payorder':
       {
        // 從端里出來相關的訂單相信
        const {
         out_trade_no,
         prepay_id,
         body,
         total_fee
        } = data;
    
        // 到微信支付側查詢是否存在該訂單,并查詢訂單狀態,看看是否已經支付成功了。
        const {
         return_code,
         ...restData
        } = await pay.orderQuery({
         out_trade_no
        });
    
        // 若訂單存在并支付成功,則開始處理支付
        if (restData.trade_state === 'SUCCESS') {
         let result = await orderCollection
          .where({
           out_trade_no
          })
          .update({
           status: 1,
           trade_state: restData.trade_state,
           trade_state_desc: restData.trade_state_desc
          });
    
    
         let curDate = new Date();
         let time = `${curDate.getFullYear()}-${curDate.getMonth() +
              1}-${curDate.getDate()} ${curDate.getHours()}:${curDate.getMinutes()}:${curDate.getSeconds()}`;
    
       
    
        }
    
        return new Res({
         code: return_code === 'SUCCESS' ? 0 : 1,
         data: restData
        });
       }
      case 'orderquery':
       {
        const {
         transaction_id,
         out_trade_no
        } = data;
        // 查詢訂單
    
        const {
         data: dbData
        } = await orderCollection
        .where({
         out_trade_no
        })
        .get();
    
        const {
         return_code,
         ...restData
        } = await pay.orderQuery({
         transaction_id,
         out_trade_no
        });
    
        return new Res({
         code: return_code === 'SUCCESS' ? 0 : 1,
         data: { ...restData,
          ...dbData[0]
         }
        });
       }
    
      case 'closeorder':
       {
        // 關閉訂單
        const {
         out_trade_no
        } = data;
        const {
         return_code,
         ...restData
        } = await pay.closeOrder({
         out_trade_no
        });
        if (return_code === 'SUCCESS' &&
         restData.result_code === 'SUCCESS') {
         await orderCollection
          .where({
           out_trade_no
          })
          .update({
           status: 2,
           trade_state: 'CLOSED',
           trade_state_desc: '訂單已關閉'
          });
        }
    
        return new Res({
         code: return_code === 'SUCCESS' ? 0 : 1,
         data: restData
        });
       }
     }
    }
    

    其實我們支付的關鍵功能都在上面這些代碼里面了。
    借助小程序云開發實現小程序支付功能(含源碼)_微信支付_10

    再來看下,支付的相關流程截圖
    借助小程序云開發實現小程序支付功能(含源碼)_云開發小程序支付_11

    上圖就涉及到了我們的訂單列表,支付狀態,支付成功后的回調。
    今天就先講到這里,后面會繼續給大家講解支付的其他功能。比如支付成功后的消息推送,也是可以借助云開發實現的。

    ?

    本文摘自 :https://blog.51cto.com/u

    開通會員,享受整站包年服務
    国产呦精品一区二区三区网站|久久www免费人咸|精品无码人妻一区二区|久99久热只有精品国产15|中文字幕亚洲无线码