微信公眾號(hào)支付


前言

首先,微信有四種支付方式,如下圖所示:

Paste_Image.png

其次,PHP能夠?qū)崿F(xiàn)的只有前三種。因?yàn)锳PP支付很顯然是需要iOS和Android來(lái)開(kāi)發(fā)的。而本文針對(duì)的是公眾號(hào)支付的PHP開(kāi)發(fā)。


開(kāi)發(fā)步驟

  1. 申請(qǐng)微信公眾號(hào),這里注意必須是服務(wù)號(hào)才可以

  2. 開(kāi)通微信支付。微信支付需要相關(guān)的企業(yè)資質(zhì)認(rèn)證。這個(gè)流程快的話(huà)1天就能下來(lái),慢也不會(huì)超過(guò)3、4天。微信的員工效率還是很高的。

  3. 當(dāng)公眾號(hào)微信支付開(kāi)通后,微信會(huì)給你的郵箱中發(fā)一封郵件。這封郵件內(nèi)含有以下內(nèi)容:


    Paste_Image.png

    你需要登錄商戶(hù)平臺(tái)進(jìn)行相關(guān)設(shè)置,而登陸的賬號(hào)密碼正是郵件中所提供的賬號(hào)密碼。

  4. 登錄商戶(hù)平臺(tái)后,第一步需要進(jìn)行銀行賬號(hào)的綁定驗(yàn)證。第二步則需要你設(shè)置API密鑰。這個(gè)密鑰為32位,是之后調(diào)用微信支付接口的關(guān)鍵參數(shù)之一,如果你不知道怎么生成密匙,可以使用這個(gè)密碼隨機(jī)生成器。密鑰如果忘記可以重新設(shè)置,但是相關(guān)的微信支付接口設(shè)置也要記得更改。還有就是在API密鑰設(shè)置界面你還需要下載相關(guān)的證書(shū),證書(shū)也是微信支付的必要條件之一,這一點(diǎn)之后會(huì)詳細(xì)說(shuō)明。

    Paste_Image.png

  5. 到了這一步,商戶(hù)平臺(tái)的操作就全部完成了?,F(xiàn)在需要返回公眾號(hào)平臺(tái),設(shè)置測(cè)試目錄。因?yàn)槟壳爸皇菧y(cè)試階段,所以可以不設(shè)置正式授權(quán)目錄,但是注意授權(quán)目錄不能與測(cè)試目錄url地址相同。同時(shí)請(qǐng)測(cè)試人員將自己的微信號(hào)加入白名單中。


    Paste_Image.png
  6. 到此為止,所有的前期準(zhǔn)備工作就全部做完了。之后便是真正的代碼開(kāi)發(fā)階段。為了快速了解微信的支付流程,我們可以下載微信支付的官方DEMO。官方DEMO目前支持三種語(yǔ)言,分別是:JAVA、PHP和.NET C#。點(diǎn)擊DEMO可以跳轉(zhuǎn)到下載鏈接。

  7. 整個(gè)微信公眾號(hào)支付的流程如下:

  8. 用戶(hù)點(diǎn)擊公眾號(hào)內(nèi)微信商城打開(kāi)H5的支付頁(yè)面

  9. H5頁(yè)面通過(guò)JS調(diào)用微信支付接口

  10. 微信服務(wù)器通過(guò)判斷輸入的JSON數(shù)據(jù),返回給客戶(hù)端相應(yīng)的成功或失敗信息


DEMO

請(qǐng)點(diǎn)擊上面提供的連接,下載PHP微信支付的DEMO。解壓縮后,我們會(huì)看到如下結(jié)構(gòu)的數(shù)個(gè)PHP文件:

SDK目錄結(jié)構(gòu)
    |-- cert
    |   |-- apiclient_cert.pem ----- 微信證書(shū)
    |   `-- apiclient_key.pem ----- 微信證書(shū)
    |-- index.php ----- 入口
    |-- lib ----- 封裝好的類(lèi)(一般不需要?jiǎng)樱?    |   |-- WxPay.Api.php ----- 包括所有微信支付API接口的封裝
    |   |-- WxPay.Config.php ----- 商戶(hù)配置
    |   |-- WxPay.Data.php ----- 輸入?yún)?shù)封裝
    |   |-- WxPay.Exception.php ----- 異常類(lèi)
    |   `-- WxPay.Notify.php ----- 回調(diào)通知基類(lèi)
    `-- example ----- DEMO
        |-- WxPay.JsApiPay.php ----- 微信公眾號(hào)支付類(lèi)
        |-- WxPay.MicroPay.php ----- 刷卡支付類(lèi)
        |-- WxPay.NativePay.php ----- 二維碼支付類(lèi)
        |-- download.php ----- 下載訂單 
        |-- micropay.php ----- 刷卡支付
        |-- native.php ----- 掃碼支付
        |-- native_notify.php ----- 回調(diào)處理(二維碼支付)
        |-- notify.php ----- 回調(diào)處理
        |-- orderquery.php ----- 訂單查詢(xún)
        |-- qrcode.php ----- 生成二維碼
        |-- refund.php ----- 訂單退款
        |-- refundquery.php ----- 退款查詢(xún)
        |-- jsapi.php ----- 公眾號(hào)支付
        |-- log.php ----- 日志
        `-- phpqrcode ----- 開(kāi)源二維碼代碼

如果僅僅是為了調(diào)通微信支付接口的話(huà),我們僅需要修改4個(gè)文件:

  1. cert文件夾中的兩個(gè)證書(shū)替換為我們公眾號(hào)自己的證書(shū)
  2. 修改WxPay.Config.php文件中的參數(shù)
  3. 修改jsapi.php文件。該文件甚至不修改也能成功調(diào)用接口,但是我們可以在該文件中設(shè)置具體支付的金額等訂單信息

證書(shū)

點(diǎn)擊證書(shū)下載公眾號(hào)相關(guān)證書(shū)。
下載下來(lái)的壓縮包內(nèi)一共包含有4個(gè)證書(shū):

cert
├── apiclient_cert.p12
├── apiclient_cert.pem
├── apiclient_key.pem
└── rootca.pem
  • apiclient_cert.p12是商戶(hù)證書(shū)文件,除PHP外的開(kāi)發(fā)均使用此證書(shū)文件。
  • 商戶(hù)如果使用.NET環(huán)境開(kāi)發(fā),請(qǐng)確認(rèn)Framework版本大于2.0,必須在操作系統(tǒng)上雙擊安裝證書(shū)apiclient_cert.p12后才能被正常調(diào)用。
  • 商戶(hù)證書(shū)調(diào)用或安裝都需要使用到密碼,該密碼的值為微信商戶(hù)號(hào)(mch_id)
  • PHP開(kāi)發(fā)環(huán)境請(qǐng)使用商戶(hù)證書(shū)文件apiclient_cert.pem和apiclient_key.pem ,rootca.pem是CA證書(shū)。

這里因?yàn)槲覀兪褂肞HP開(kāi)發(fā),所以只需要其中的兩個(gè)證書(shū)apiclient_cert.pemapiclient_key.pem。將證書(shū)復(fù)制粘貼到DEMO的cert文件夾,并替換原有文件即可

WxPay.Config.php 參數(shù)配置

代碼中的注釋寫(xiě)的非常明確,我們只需要設(shè)置基本信息中的4個(gè)常量即可,其他一般情況下保持默認(rèn)就行。

<?php
/**
*   配置賬號(hào)信息
*/

class WxPayConfig
{
    //=======【基本信息設(shè)置】=====================================
    //
    /**
     * TODO: 修改這里配置為您自己申請(qǐng)的商戶(hù)信息
     * 微信公眾號(hào)信息配置
     * 
     * APPID:綁定支付的APPID(必須配置,開(kāi)戶(hù)郵件中可查看)
     * 
     * MCHID:商戶(hù)號(hào)(必須配置,開(kāi)戶(hù)郵件中可查看)
     * 
     * KEY:商戶(hù)支付密鑰,參考開(kāi)戶(hù)郵件設(shè)置(必須配置,登錄商戶(hù)平臺(tái)自行設(shè)置)
     * 設(shè)置地址:https://pay.weixin.qq.com/index.php/account/api_cert
     * 
     * APPSECRET:公眾帳號(hào)secert(僅JSAPI支付的時(shí)候需要配置, 登錄公眾平臺(tái),進(jìn)入開(kāi)發(fā)者中心可設(shè)置),
     * 獲取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
     * @var string
     */
    const APPID = 'wx426b3015555a46be';
    const MCHID = '1225312702';
    const KEY = 'e10adc3949ba59abbe56e057f20f883e';
    const APPSECRET = '01c6d59a3f9024db6336662ac95c8e74';
    
    //=======【證書(shū)路徑設(shè)置】=====================================
    /**
     * TODO:設(shè)置商戶(hù)證書(shū)路徑
     * 證書(shū)路徑,注意應(yīng)該填寫(xiě)絕對(duì)路徑(僅退款、撤銷(xiāo)訂單時(shí)需要,可登錄商戶(hù)平臺(tái)下載,
     * API證書(shū)下載地址:https://pay.weixin.qq.com/index.php/account/api_cert,下載之前需要安裝商戶(hù)操作證書(shū))
     * @var path
     */
    const SSLCERT_PATH = '../cert/apiclient_cert.pem';
    const SSLKEY_PATH = '../cert/apiclient_key.pem';
    
    //=======【curl代理設(shè)置】===================================
    /**
     * TODO:這里設(shè)置代理機(jī)器,只有需要代理的時(shí)候才設(shè)置,不需要代理,請(qǐng)?jiān)O(shè)置為0.0.0.0和0
     * 本例程通過(guò)curl使用HTTP POST方法,此處可修改代理服務(wù)器,
     * 默認(rèn)CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此時(shí)不開(kāi)啟代理(如有需要才設(shè)置)
     * @var unknown_type
     */
    const CURL_PROXY_HOST = "0.0.0.0";//"10.152.18.220";
    const CURL_PROXY_PORT = 0;//8080;
    
    //=======【上報(bào)信息配置】===================================
    /**
     * TODO:接口調(diào)用上報(bào)等級(jí),默認(rèn)緊錯(cuò)誤上報(bào)(注意:上報(bào)超時(shí)間為【1s】,上報(bào)無(wú)論成敗【永不拋出異常】,
     * 不會(huì)影響接口調(diào)用流程),開(kāi)啟上報(bào)之后,方便微信監(jiān)控請(qǐng)求調(diào)用的質(zhì)量,建議至少
     * 開(kāi)啟錯(cuò)誤上報(bào)。
     * 上報(bào)等級(jí),0.關(guān)閉上報(bào); 1.僅錯(cuò)誤出錯(cuò)上報(bào); 2.全量上報(bào)
     * @var int
     */
    const REPORT_LEVENL = 1;
}

修改 jsapi.php文件

jsapi.php中代碼的工作順序:

  1. 頁(yè)面加載后通過(guò)window.onload = function()會(huì)自動(dòng)跳轉(zhuǎn)到地址選擇頁(yè)面,并觸發(fā)editAddress()事件
  2. 選擇住址后頁(yè)面返回支付頁(yè)面,同時(shí)彈出警告框顯示剛才選擇的地址
  3. 點(diǎn)擊支付,觸發(fā)callpay()方法。如果當(dāng)前瀏覽器為微信APP,則觸發(fā)jsApiCall()方法調(diào)用微信支付接口
  4. 最后是在notify.php處理回調(diào)通知

注意1:jsapi.php原文件中調(diào)用的是官方網(wǎng)址的notify.php文件。你需要改為調(diào)用自己服務(wù)器上的notify.php文件,不然無(wú)法再log文件夾中生成相應(yīng)的日志。而日志會(huì)包含兩部分:第一條是訂單信息,第二條是訂單信息加一個(gè)額外的trade_state參數(shù)。trade_state參數(shù)如果是success則表示訂單支付成功,其他則失敗

注意2:$input->SetTotal_fee("1")可以用來(lái)設(shè)置支付的金額。但是該金額必須為整數(shù)。這里的數(shù)字1,代表的是金額1分。如果想將金額設(shè)置為1元,則需要$input->SetTotal_fee("100")

<?php 
ini_set('date.timezone','Asia/Shanghai');
//error_reporting(E_ERROR);
require_once "../lib/WxPay.Api.php";
require_once "WxPay.JsApiPay.php";
require_once 'log.php';

//初始化日志
$logHandler= new CLogFileHandler("../logs/".date('Y-m-d').'.log');
$log = Log::Init($logHandler, 15);

//打印輸出數(shù)組信息
function printf_info($data)
{
    foreach($data as $key=>$value){
        echo "<font color='#00ff55;'>$key</font> : $value <br/>";
    }
}

//①、獲取用戶(hù)openid
$tools = new JsApiPay();
$openId = $tools->GetOpenid();

//②、統(tǒng)一下單
$input = new WxPayUnifiedOrder();
$input->SetBody("創(chuàng)源測(cè)試");
$input->SetAttach("測(cè)試attach");
$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
$input->SetTotal_fee("1");
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag("立減優(yōu)惠");
$input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php");
$input->SetTrade_type("JSAPI");
$input->SetOpenid($openId);
$order = WxPayApi::unifiedOrder($input);
echo '<font color="#f00"><b>統(tǒng)一下單支付單信息</b></font><br/>';
printf_info($order);
$jsApiParameters = $tools->GetJsApiParameters($order);

//獲取共享收貨地址js函數(shù)參數(shù)
$editAddress = $tools->GetEditAddressParameters();

//③、在支持成功回調(diào)通知中處理成功之后的事宜,見(jiàn) notify.php
/**
 * 注意:
 * 1、當(dāng)你的回調(diào)地址不可訪(fǎng)問(wèn)的時(shí)候,回調(diào)通知會(huì)失敗,可以通過(guò)查詢(xún)訂單來(lái)確認(rèn)支付是否成功
 * 2、jsapi支付時(shí)需要填入用戶(hù)openid,WxPay.JsApiPay.php中有獲取openid流程 (文檔可以參考微信公眾平臺(tái)“網(wǎng)頁(yè)授權(quán)接口”,
 * 參考http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html)
 */
?>

<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/> 
    <title>微信支付樣例-支付</title>
    <script type="text/javascript">
    //調(diào)用微信JS api 支付
    function jsApiCall()
    {
        WeixinJSBridge.invoke(
            'getBrandWCPayRequest',
            <?php echo $jsApiParameters; ?>,
            function(res){
                WeixinJSBridge.log(res.err_msg);
                alert(res.err_code+res.err_desc+res.err_msg);
            }
        );
    }

    function callpay()
    {
        if (typeof WeixinJSBridge == "undefined"){
            if( document.addEventListener ){
                //從事件冒泡開(kāi)始執(zhí)行,也就是從內(nèi)到外,從小到大開(kāi)始執(zhí)行
                document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
            }else if (document.attachEvent){
                document.attachEvent('WeixinJSBridgeReady', jsApiCall); 
                document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
            }
        }else{
            jsApiCall();
        }
    }
    </script>
    <script type="text/javascript">
    //獲取共享地址
    function editAddress()
    {
        WeixinJSBridge.invoke(
            'editAddress',
            <?php echo $editAddress; ?>,
            function(res){
                var value1 = res.proviceFirstStageName;
                var value2 = res.addressCitySecondStageName;
                var value3 = res.addressCountiesThirdStageName;
                var value4 = res.addressDetailInfo;
                var tel = res.telNumber;
                //返回所選地址
                alert(value1 + value2 + value3 + value4 + ":" + tel);
            }
        );
    }
    //進(jìn)入支付頁(yè)面后,直接跳轉(zhuǎn)地址選擇頁(yè)面
    window.onload = function(){
        if (typeof WeixinJSBridge == "undefined"){
            if( document.addEventListener ){
                document.addEventListener('WeixinJSBridgeReady', editAddress, false);
            }else if (document.attachEvent){
                document.attachEvent('WeixinJSBridgeReady', editAddress); 
                document.attachEvent('onWeixinJSBridgeReady', editAddress);
            }
        }else{
            editAddress();
        }
    };
    
    </script>
</head>
<body>
    <br/>
    <font color="#9ACD32"><b>該筆訂單支付金額為<span style="color:#f00;font-size:50px">1分</span>錢(qián)</b></font><br/><br/>
    <div align="center">
        <button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="callpay()" >立即支付</button>
    </div>
</body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.登錄微信商戶(hù)平臺(tái) 復(fù)制這兩個(gè)簽名文件,準(zhǔn)備替換DEMO中去 微信官網(wǎng)下載PHP微信支付DEMO 替換掉原來(lái)微信...
    townfish閱讀 1,176評(píng)論 1 4
  • 最近要做一個(gè)公眾號(hào)開(kāi)發(fā),里面還涉及到微信支付,對(duì)著微信支付接口文檔擼了個(gè)大概,現(xiàn)在分享出來(lái),希望對(duì)大家有所幫助。其...
    大大大浣熊閱讀 1,569評(píng)論 0 7
  • 簡(jiǎn)單介紹了微信公眾號(hào)支付的申請(qǐng)、接入、使用、確認(rèn)支付結(jié)果等相關(guān)流程 0 系列文章 系列一 微信App支付全解析系列...
    Tsy遠(yuǎn)閱讀 17,809評(píng)論 2 61
  • 時(shí)間: 2016年8月11日 說(shuō)明: 文檔主要描述微信公眾號(hào)支付開(kāi)發(fā)過(guò)程中處理流程和一些遇到的問(wèn)題。 1 準(zhǔn)備工作...
    JulyXing閱讀 6,557評(píng)論 0 6
  • 依稀記起你年輕的臉龐 如今已經(jīng)消散的青春容光 歲月在你的眼角刻出風(fēng)霜 每條皺紋都應(yīng)該有故事流淌 耳邊響起似曾熟悉的...
    天涯孤旅背包客閱讀 307評(píng)論 1 6

友情鏈接更多精彩內(nèi)容