小程式接入微信支付的流程

shadowalker_wei發表於2018-04-13

近日開發一個順風小巴的小程式,開發還是比較簡單的,只是有些語法真是反人類,主要難點是微信支付,其他的調調介面渲染一下資料就ok了,下面就詳細說一下整個流程及中間遇到的坑。

1、準備工作

a、小程式賬號申請

像申請公眾號一樣,要求企業資質,另外交給企鵝300塊錢。

b、微信支付商家平臺申請

申請支付功能必不可少的部分,期間踩了一個坑,老闆為了節省三百塊錢,用一個老的商戶平臺id繫結到小程式上,結果除錯的時候一直報錯,提示appid與商家MCHID不匹配,然後小程式無法解綁商戶號,只能重新申請小程式和商戶號。既耽誤了時間又多花了錢。

c、下載商家證照

在商家平臺上下載證照,解壓放到sdk檔案儲存證照對應位置

d、伺服器https驗證

小程式要求伺服器必須是https的,並且不是所有https都可以,https://www.qcloud.com/product/ssl 這個地址可以進行測試,測試通過即可使用,否則可能出現真機測試無法獲取資料的問題。

e、下載jsapi的SDK

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1 SDK文件下載地址
之後修改SDK的配置檔案WxPay.Config.php

const APPID = `wx97fs3234d88desb`;
const APPSECRET = `ef103ba456be043244238f7b721e957`;
const MCHID = `1444333112`;
const KEY = `Niskh5WfdsdfsdWYkr8lrddwsHyE78m2sE`;

2、開發

a、微信登入

通過code到伺服器獲取使用者openid,然後儲存到小程式本地,用以後續與伺服器互動

    wx.login({
        success: function (res1) {
        var code = res1.code;
          wx.request({
            url: `https://伺服器/example/login.php`,
            method:`GET`,
            data: {
              code: code
            },
            success: function (res) {
              var uid = res.data;
              console.log(uid)
              wx.setStorage({
                key: "uid",
                data: uid
              })
              console.log(`同步儲存成功`)
            }
          }),
            wx.getUserInfo({
              success: function (res) {
              console.log(res.data)
                that.globalData.userInfo = res.userInfo
                typeof cb == "function" && cb(that.globalData.userInfo)
              }
            })
        }
      })

b、獲取列表
  wx.request({
      url: `https://介面地址`,
      method: `GET`,
      success: function (res) {
        var noStartList = res.data.noStartList;
        that.setData({
          noStartList: noStartList,
          hiddenLoading: !that.data.hiddenLoading
        });
      }
    })

c、微信支付

小程式端先呼叫伺服器,讓伺服器建立訂單,然後伺服器去請求微信支付服務後臺生成預支付交易單,返回正確的預支付交易後由小程式端調起支付。

      wx.request({
          url: `https://呼叫伺服器獲取微信統一下單資料`,
          method: `GET`,
          data: { uid: uid, id: id },
          success: function (res) {
            var nowTime = new Date()
            var appId = res.data.appid
            var timeStamp1 = Math.round((nowTime.getTime()) / 1000)
            var timeStamp = timeStamp1.toString()
            var nonceStr = res.data.nonce_str
            var package = "prepay_id=" + res.data.prepay_id
            var signType = "MD5"
            var key = "Niskh5234234WYk4323HyE78m2sE"//商戶平臺的key
            var sign = res.data.sign
            var paySign = md5.hexMD5("appId=" + appId + "&nonceStr=" + nonceStr + "&package=" + package + "&signType=MD5&timeStamp=" + timeStamp + "&key=" + key)
            wx.requestPayment({
              timeStamp: timeStamp,
              //隨機字串,長度為32個字元以下。
              nonceStr: nonceStr,
              //統一下單介面返回的 prepay_id 引數值,提交格式如:prepay_id=*
              package: package,
              //簽名演算法,暫支援 MD5
              signType: `MD5`,
              paySign: paySign,
              success: function (res) {
              },
              fail: function (res) {
              },
              complete: function (res) {
              }
            })
          }
        })

伺服器端邏輯

//①、獲取傳遞引數

//②、生成訂單

//3、統一向微信端下單
$input = new WxPayUnifiedOrder();
$input->SetBody("順風小巴購票");
$input->SetAttach("順風小巴購票");
$input->SetOut_trade_no($data[`oId`]);
$input->SetTotal_fee($data[`price`]*100);
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetNotify_url("http://伺服器/notify.php");
$input->SetTrade_type("JSAPI");
$input->SetOpenid($openId);
$order = WxPayApi::unifiedOrder($input);
header("Content-Type: application/json");
echo json_encode($order);
exit;

這時候還需要在伺服器端完善回撥函式notify.php

//重寫回撥處理函式
public function NotifyProcess($data, &$msg)
{
    Log::DEBUG("call back:" . json_encode($data));
    $notfiyOutput = array();

    if(!array_key_exists("transaction_id", $data)){
        $msg = "輸入引數不正確";
        return false;
    }
    //查詢訂單,判斷訂單真實性
    if(!$this->Queryorder($data["transaction_id"])){
        $msg = "訂單查詢失敗";
        return false;
    }
            //根據 $data["out_trade_no"] 訂單號 更新訂單狀態
            //更新訂單狀態邏輯程式碼
    return true;
}

整個支付過程就完成了,尤其注意的就是支付需要的引數及引數加密順序,其他的除錯一下基本就ok了。


相關文章