1. 程式人生 > >小程式服務端整合微信支付

小程式服務端整合微信支付

理論上整合微信支付的全部工作可以在小程式端完成,因為小程式js有訪問網路的能力,但是為了安全,不暴露敏感key,也更好地跨平臺(對於iOS與Android原生APP開發來說,哪天小程式的支付介面也納入了開放平臺了,這條也就成立了),而且可以使用官方提供的現成php demo更省力,於是在服務端完成簽名與發起請求,小程式端只做一個wx.requestPayment(OBJECT)介面的對接。

整體整合過程與JSAPI、APP類似,先統一下單,然後拿返回的結果來請求支付。

一共三步:

1.小程式端通過wx.login的返回的code換取openid

2.服務端向微信統一下單

3.小程式端發起支付

事先準備好這幾樣東西:

APPID = 'wx426b3015555a46be';
MCHID = '1900009851';
KEY = '8934e7d15453e97507ef794cf7b0519d';
APPSECRET = '7813490da6f1265e4901ffb80afaa36f';

PHP SDK,下載連結見文尾

第1、4樣是申請小程式時獲得的,第2、3樣是申請開通微信支付時獲得的,注意第3、4樣長得比較像,其實是2個東西,兩者混淆將導致簽名通不過

向微信端下單,得到prepay_id

1. 建立一個Controller,引並WxPay.Api.php類

<?php
require_once
__DIR__ . '/BaseController.php'; require_once __DIR__ . '/../third_party/wxpay/WxPay.Api.php'; classWXPayextendsBaseController{ functionindex(){ } }

之後可以通過index.php/wxpay來作訪問請求

2. 修改配置檔案WxPay.Config.php

改成自己申請得到相應key

3. 實現index方法

        functionindex(){
//         初始化值物件
        $input = new WxPayUnifiedOrder();
//         文件提及的引數規範:商家名稱-銷售商品類目
$input->SetBody("靈動商城-手機"); // 訂單號應該是由小程式端傳給服務端的,在使用者下單時即生成,demo中取值是一個生成的時間戳 $input->SetOut_trade_no('123123123'); // 費用應該是由小程式端傳給服務端的,在使用者下單時告知服務端應付金額,demo中取值是1,即1分錢 $input->SetTotal_fee("1"); $input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php"); $input->SetTrade_type("JSAPI"); // 由小程式端傳給服務端 $input->SetOpenid($this->input->post('openId')); // 向微信統一下單,並返回order,它是一個array陣列 $order = WxPayApi::unifiedOrder($input); // json化返回給小程式端 header("Content-Type: application/json"); echo json_encode($order); }

說明1:文件上提到的nonce_str不是沒提交,而是sdk幫我們填上的

出處在WxPay.Api.php第55行

$inputObj->SetNonce_str(self::getNonceStr());//隨機字串

說明2:sign也已經好心地給setSign了,出處在WxPay.Data.php第111行,MakeSign()中

    /**
     * 生成簽名
     * @return 簽名,本函式不覆蓋sign成員變數,如要設定簽名需要呼叫SetSign方法賦值
     */
    public functionMakeSign(){
        //簽名步驟一:按字典序排序引數
        ksort($this->values);
        $string = $this->ToUrlParams();
        //簽名步驟二:在string後加入KEY
        $string = $string . "&key=".WxPayConfig::KEY;
        //簽名步驟三:MD5加密
        $string = md5($string);
        //簽名步驟四:所有字元轉為大寫
        $result = strtoupper($string);
        return $result;
    }

4. 小程式內呼叫登入介面,獲取openid

向微信登入請求,拿到code,再將code提交換取openId

wx.login({
          success: function(res) {
            if (res.code) {
              //發起網路請求
              wx.request({
                url: 'https://api.weixin.qq.com/sns/jscode2session?appid=wx9114b997bd86f***&secret=d27551c7803cf16015e536b192******&js_code='+res.code+'&grant_type=authorization_code',
                data: {
                  code: res.code
                },
                success: function (response) {
                    console.log(response);
                }
              })
            } else {
              console.log('獲取使用者登入態失敗!' + res.errMsg)
            }
          }
        });

從控制檯看到已經成功拿到openid,剩下的事情就是將它傳到服務端就好了,服務端那邊$this->input->post('openId')等著收呢。

輸入圖片說明

                    //統一下單介面對接
                    wx.request({
                        url: 'https://lendoo.leanapp.cn/index.php/WXPay',
                        data: {
                            openId: openId
                        },
                        success: function (response) {
                            console.log(response);

                        },
                                header: {
                        'content-type': 'application/x-www-form-urlencoded'
                },
                    });

得到如下結果

{
  "appid": "wx9114b997bd86f8ed",
  "mch_id": "1414142302",
  "nonce_str": "eEICgYFuGqxFRK6f",
  "prepay_id": "wx201701022235141fc713b8f80137935406",
  "result_code": "SUCCESS",
  "return_code": "SUCCESS",
  "return_msg": "OK",
  "sign": "63E60C8CD90394FB50E612D085F5362C",
  "trade_type": "JSAPI"
}

輸入圖片說明

6. 小程式端調起支付API

// 發起支付
var appId = response.data.appid;
var timeStamp = (Date.parse(new Date()) / 1000).toString();
var pkg = 'prepay_id=' + response.data.prepay_id;
var nonceStr = response.data.nonce_str;
var paySign = md5.hex_md5('appId='+appId+'&nonceStr='+nonceStr+'&package='+pkg+'&signType=MD5&timeStamp='+timeStamp+"&key=d27551c7803cf16***e536b192d5d03b").toUpperCase();
console.log(paySign);
console.log(appId);
wx.requestPayment({
    'timeStamp': timeStamp,
    'nonceStr': nonceStr,
    'package': pkg,
    'signType': 'MD5',
    'paySign': paySign,
    'success':function(res){
        console.log('success');
        console.log(res);
    }
});

模擬器測試,將彈出一個二維碼供掃描

輸入圖片說明

結果報了一個錯誤:

輸入圖片說明

errMsg:"requestPayment:fail"
err_code:2
err_desc:"支付驗證簽名失敗"

key需要加入到簽名中!!!'appId='+appId+'&nonceStr='+nonceStr+'&package='+pkg+'&signType=MD5&timeStamp='+timeStamp+"&key=d27551c7803cf16*e536b192d5d03b"這才是完整的。

可是文件裡明明沒提到key啊

輸入圖片說明

7. 支付成功截圖

輸入圖片說明

輸入圖片說明

吐槽完文件再吐槽下命名規則,GetSpbill_create_ip()、IsSpbill_create_ipSet()都是些什麼鬼一會兒下劃線分隔一會兒駝峰分隔,成員方法首字母還大寫,unifiedOrder()這種正經寫法也不忘來比劃兩下,看來網上說大公司的sdk都是實習生撰寫是真事,可code reviewer又在哪裡?

【2016-1-5】

番外篇 - 服務端生成與二次簽名與引數

之前的作法可視為服務端與小程式雙重請求混合使用的一個範例。

接下來將演示純服務端的方式,小程式只關注wx.requestPayment對接。

二次簽名也通過服務端,讓小程式端呼叫更加簡潔,前端不再關心生成timeStamp,md5,paySign,全部將服務端返回得到。

這種做法應該是更為主流的作法。

        public functiongetJsApiParameters($UnifiedOrderResult){
        if(!array_key_exists("appid", $UnifiedOrderResult)
        || !array_key_exists("prepay_id", $UnifiedOrderResult)
        || $UnifiedOrderResult['prepay_id'] == "")
        {
            throw new WxPayException("引數錯誤");
        }
        $jsapi = new WxPayJsApiPay();
        $jsapi->SetAppid($UnifiedOrderResult["appid"]);
        $timeStamp = time();
        $jsapi->SetTimeStamp("$timeStamp");
        $jsapi->SetNonceStr(WxPayApi::getNonceStr());
        $jsapi->SetPackage("prepay_id=" . $UnifiedOrderResult['prepay_id']);
        $jsapi->SetSignType("MD5");
        $jsapi->SetPaySign($jsapi->MakeSign());
        $parameters = json_encode($jsapi->GetValues());
        return $parameters;
    }

呼叫getJsApiParameters

//         json化返回給小程式端
header("Content-Type: application/json");
echo $this->getJsApiParameters($order);

小程式端發起支付

//統一下單介面對接
wx.request({
    url: 'https://lendoo.leanapp.cn/index.php/WXPay',
    data: {
        openId: openId
    },
    method: 'POST',
    header: {
        'content-type': 'application/x-www-form-urlencoded'
    },
    success: function (response) {
        // 發起支付
        wx.requestPayment({
            'timeStamp': response.data.timeStamp,
            'nonceStr': response.data.nonceStr,
            'package': response.data.package,
            'signType': 'MD5',
            'paySign': response.data.paySign,
            'success':function(res){
                console.log('success');
                console.log(res);
            }
        });
    }
});

省去了timeStamp、paySign的生成,連帶md5.js也省掉了,小程式端呼叫起來就清爽多了。

中間出現了一個小插曲,package被我畫蛇添足地寫成了"prepayid"+response.data.package

報了缺少引數total_fee的錯誤,既不是報引數錯誤,也不是報prepay_id錯誤,相當無厘頭。

輸入圖片說明

相關推薦

程式服務整合支付

理論上整合微信支付的全部工作可以在小程式端完成,因為小程式js有訪問網路的能力,但是為了安全,不暴露敏感key,也更好地跨平臺(對於iOS與Android原生APP開發來說,哪天小程式的支付介面也納入了開放平臺了,這條也就成立了),而且可以使用官方提供的現成php dem

程式、app整合支付

一、微信小程式支付 申請小程式開發者賬號,進行微信認證,獲取appid,開通微信支付,即繫結申請的微信支付商戶號。 1.小程式支付流程: 2.商戶系統和微信支付系統主要互動:       1、小程式內呼叫登入介面,獲取到使用者的openid。       2

支付總結--程式與H5頁面支付

專案開發過程中,涉及到了微信支付功能,這裡做一個詳細的記錄。 小程式和H5的後端程式碼是通用的,前端呼叫不同的程式碼實現,這裡不是重點,會簡單的給出相關的程式碼。 微信支付,官方給了開發文件,但是其中還是有一部分需要自己去摸索一下,剛開始接觸走一點彎路踩一點坑也比較正常。 當然微信支付這

程式踩坑之支付提示商戶未開通支付許可權

繼上次踩坑事件後 我們現在API祕藥都是採用數字+小寫字母 後面不多久公司就成為了微信服務商 工作起來 效率提高不少 然鵝我今天又踩了一個坑 給客戶開通了微信支付客戶不給賬號給我登入 拿不到裡面的一些資料 和APPID授權啥的 都是指導客戶開通 這些弄完之後 測試小程式支付

java服務支付功能的實現

     接入微信的支付功能在java服務端,現在記錄下來這個過程,方便以後用到。程式碼都是參考網路,功能可以實現      實際參考https://github.com/wxpay/WXPay-SDK-Java     ①,寫一個介面,作為引數配置的介面,當然也可以不用介

程式與php 實現支付

小程式訪問地址: payfee.php: include 'WeixinPay.php'; $appid=''; $openid= $_GET['id']; $mch_id=''; $key=''; $out_trade_no = $mch_id. time(); $t

程式服務請求必須HTTPS 程式服務請求必須HTTPS

微信小程式服務端請求必須HTTPS SSL證書的作用 HTTP明文協議是不安全的傳輸協議,無法進行伺服器端真實身份校驗,也不能為傳輸資料提供加密保護,通過HTTP協議傳輸的資料時刻處在被竊聽、篡改、冒充的風險

.net服務獲取程式使用者資訊

1 public void RequestWxUserInfo(string code, string iv, string encryptedData, string rawData, string signature) 2 { 3 string res

3步搭建程式服務環境筆記

本實踐筆記基於nginx+uwsgi+django 2,在django專案根目錄下建立wechatapp_wsgi_debug.ini和wechatapp_wsgi.ini wechatapp_wsgi_debug.ini [uwsgi] # Dja

支付程式開發之與程式不同的地方

前言: 本文僅彙總微信小程式移植支付寶小程式過程中遇到的一些不同的地方,詳細請參考官方開發文件。 網路請求: 對於網路請求,基本上改動不大,也就支付寶小程式沒有responseType屬性及響應碼欄位改成了status。 使用者授權登入: 1. 登入: wx.login   ====&nb

nodejs服務實現遊戲登入

nodejs服務端實現微信小遊戲登入的驗證與解密資訊 本文章主要借鑑於微信公眾平臺開放介面進行相應功能的開發,參照流程時序圖如: 目錄 文章目錄 nodejs服務端實現微信小遊戲登入的驗證與解密資訊 目錄 小遊戲客戶端

整合支付遇到的幾個坑(已解決)

1,MD5               檢查MD5的正確性,C盤使用者下的.android裡的簽名是debug的,瀏覽器搜尋用命令檢視MD5通常是debug的,如果不是用得這個簽名,可以用這個命令ke

java實現沙箱測試環境支付支付(demo)和整合支付支付支付到ssm

mar 文件 fun Go examples IT === throws 由於 文章有不當之處,歡迎指正,如果喜歡微信閱讀,你也可以關註我的微信公眾號:好好學java,獲取優質學習資源。 一、支付寶測試環境代碼測試 1.下載電腦網站的官方demo: 下載地址:https:

程序騙局套路深,支付寶發布提示別上當|極限工坊淘

ces 消息 平臺 能夠 什麽 com 要去 商家 功能 前段時間隨著百度上線了智能小程序,支付寶也開放了小程序首頁入口,微信小程序也開放了更多入口。隨著BAT同時進入小程序賽道,也徹底攪熱了小程序市場。 許多商家與自媒體創作者紛紛推出了自家的小程序,希望借助這一新產品能

JAVA項目實戰,項目架構,高並發,分布式,服務架構,支付支付支付,理財系統,並發編程

等等 搭建 服務器 net 三方庫 必須 服務發現 netflix 分布式 Spring Cloud集成項目有很多,下面我們列舉一下和Spring Cloud相關的優秀項目,我們的企業架構中用到了很多的優秀項目,說白了,也是站在巨人的肩膀上去整合的。在學習Spring Cl

iOS客戶支付接入

對於一個iOS的APP,如果有一些虛擬的商品或者服務需要通過線上支付來收費的話,一般有幾種主流的選擇。 如果是通過APP呼叫支付平臺APP的思路的話,一個是調起支付寶客戶端,一個則是調起微信支付。 實際上,從程式碼的角度,調起支付APP就是把一些關鍵的引數通過一定方式打包成為一個訂單,

Androd整合支付支付支付

文章目錄 前言 微信支付 支付寶支付 前言 我們在做App的時候,可能需要接入支付功能,常見的支付有微信支付和支付寶支付。這裡只說明下前端的程式碼邏輯。 微信支付 微信支付開發

ThinkPHP整合支付之發現金紅包

大家好,微信支付系列教程四種方式已經結束,如果你以為結束了就錯了,有同學跟我提到微信還有紅包功能,我開始也沒注意這一塊,於是看了下微信商戶平臺上有講到這一塊,微信支付平臺上也早就有了,於是趁熱打鐵,研究了下,繼續發出關於微信紅包的教程文章。接下來請看微信支付發紅包之現金紅包教程! 現在微信商戶

程式--獲取已釋出遊戲和程式原始碼

最近一直在做微信小遊戲的開發,發現了一個好玩的事 ,在這裡記錄一下。 這段時間一直在做一些小遊戲 ,小程式的開發,但有的時候會發現效能上總是不那麼的盡如人意(畢竟我這小菜鳥水平有限),於是就想到,想要看看別的大神們是怎麼處理這些問題的(其實就是想看一下大神們的程式碼怎麼寫!)。但是,有一個問題就

會員預約程式定製化開發-開發

使用會議室可以進行提前預約,參加培訓課程可以進行提前預約,場館參觀可以進行提前預約……“預約”正在越來越多的出現在我們的生活中。預約系統實現了商家和顧客的時間、資源精準匹配,為我們的生活帶來了很多的便捷。 但是我發現身邊有不少朋友對預約系統的使用和操作不熟悉。