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


前言

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

Paste_Image.png

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


開發(fā)步驟

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

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

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


    Paste_Image.png

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

  4. 登錄商戶平臺(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)的證書,證書也是微信支付的必要條件之一给郊,這一點(diǎn)之后會(huì)詳細(xì)說明牡肉。

    Paste_Image.png

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


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

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

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

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

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


DEMO

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

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

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

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

證書

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

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

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

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

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

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

class WxPayConfig
{
    //=======【基本信息設(shè)置】=====================================
    //
    /**
     * TODO: 修改這里配置為您自己申請(qǐng)的商戶信息
     * 微信公眾號(hào)信息配置
     * 
     * APPID:綁定支付的APPID(必須配置澳泵,開戶郵件中可查看)
     * 
     * MCHID:商戶號(hào)(必須配置,開戶郵件中可查看)
     * 
     * KEY:商戶支付密鑰兼呵,參考開戶郵件設(shè)置(必須配置兔辅,登錄商戶平臺(tái)自行設(shè)置)
     * 設(shè)置地址:https://pay.weixin.qq.com/index.php/account/api_cert
     * 
     * APPSECRET:公眾帳號(hào)secert(僅JSAPI支付的時(shí)候需要配置, 登錄公眾平臺(tái)击喂,進(jìn)入開發(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è)置】=====================================
    /**
     * TODO:設(shè)置商戶證書路徑
     * 證書路徑,注意應(yīng)該填寫絕對(duì)路徑(僅退款、撤銷訂單時(shí)需要懂昂,可登錄商戶平臺(tái)下載介时,
     * API證書下載地址:https://pay.weixin.qq.com/index.php/account/api_cert,下載之前需要安裝商戶操作證書)
     * @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
     * 本例程通過curl使用HTTP POST方法,此處可修改代理服務(wù)器褐澎,
     * 默認(rèn)CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0会钝,此時(shí)不開啟代理(如有需要才設(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)無論成敗【永不拋出異城ㄋ幔】,
     * 不會(huì)影響接口調(diào)用流程)俭正,開啟上報(bào)之后奸鬓,方便微信監(jiān)控請(qǐng)求調(diào)用的質(zhì)量,建議至少
     * 開啟錯(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. 頁面加載后通過window.onload = function()會(huì)自動(dòng)跳轉(zhuǎn)到地址選擇頁面,并觸發(fā)editAddress()事件
  2. 選擇住址后頁面返回支付頁面儿惫,同時(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文件砌烁,不然無法再log文件夾中生成相應(yīng)的日志筐喳。而日志會(huì)包含兩部分:第一條是訂單信息,第二條是訂單信息加一個(gè)額外的trade_state參數(shù)函喉。trade_state參數(shù)如果是success則表示訂單支付成功避归,其他則失敗

注意2:$input->SetTotal_fee("1")可以用來設(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/>";
    }
}

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

//②、統(tǒng)一下單
$input = new WxPayUnifiedOrder();
$input->SetBody("創(chuàng)源測試");
$input->SetAttach("測試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)通知中處理成功之后的事宜奸柬,見 notify.php
/**
 * 注意:
 * 1、當(dāng)你的回調(diào)地址不可訪問的時(shí)候婴程,回調(diào)通知會(huì)失敗廓奕,可以通過查詢訂單來確認(rèn)支付是否成功
 * 2、jsapi支付時(shí)需要填入用戶openid,WxPay.JsApiPay.php中有獲取openid流程 (文檔可以參考微信公眾平臺(tái)“網(wǎng)頁授權(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 ){
                //從事件冒泡開始執(zhí)行蒸绩,也就是從內(nè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)入支付頁面后铃肯,直接跳轉(zhuǎn)地址選擇頁面
    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>錢</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)系作者
  • 序言:七十年代末患亿,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子缘薛,更是在濱河造成了極大的恐慌窍育,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,002評(píng)論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宴胧,死亡現(xiàn)場離奇詭異漱抓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)恕齐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門乞娄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人显歧,你說我怎么就攤上這事仪或。” “怎么了士骤?”我有些...
    開封第一講書人閱讀 169,787評(píng)論 0 365
  • 文/不壞的土叔 我叫張陵范删,是天一觀的道長。 經(jīng)常有香客問我拷肌,道長到旦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,237評(píng)論 1 300
  • 正文 為了忘掉前任巨缘,我火速辦了婚禮添忘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘若锁。我一直安慰自己搁骑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,237評(píng)論 6 398
  • 文/花漫 我一把揭開白布又固。 她就那樣靜靜地躺著仲器,像睡著了一般。 火紅的嫁衣襯著肌膚如雪仰冠。 梳的紋絲不亂的頭發(fā)上娄周,一...
    開封第一講書人閱讀 52,821評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音沪停,去河邊找鬼煤辨。 笑死裳涛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的众辨。 我是一名探鬼主播端三,決...
    沈念sama閱讀 41,236評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鹃彻!你這毒婦竟也來了郊闯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,196評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤蛛株,失蹤者是張志新(化名)和其女友劉穎团赁,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谨履,經(jīng)...
    沈念sama閱讀 46,716評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡欢摄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,794評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了笋粟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怀挠。...
    茶點(diǎn)故事閱讀 40,928評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖害捕,靈堂內(nèi)的尸體忽然破棺而出绿淋,到底是詐尸還是另有隱情,我是刑警寧澤尝盼,帶...
    沈念sama閱讀 36,583評(píng)論 5 351
  • 正文 年R本政府宣布吞滞,位于F島的核電站,受9級(jí)特大地震影響盾沫,放射性物質(zhì)發(fā)生泄漏裁赠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,264評(píng)論 3 336
  • 文/蒙蒙 一疮跑、第九天 我趴在偏房一處隱蔽的房頂上張望组贺。 院中可真熱鬧凸舵,春花似錦祖娘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至菇夸,卻和暖如春琼富,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背庄新。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評(píng)論 1 274
  • 我被黑心中介騙來泰國打工鞠眉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留薯鼠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,378評(píng)論 3 379
  • 正文 我出身青樓械蹋,卻偏偏與公主長得像出皇,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哗戈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,937評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

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