微信公眾號支付全解析

簡單介紹了微信公眾號支付的申請母剥、接入、使用形导、確認支付結果等相關流程

0 系列文章

系列一 微信App支付全解析
系列二 支付寶App支付全解析
系列三 微信公眾號支付全解析
系列四 微信掃碼支付全解析
系列五 支付寶即時到賬支付全解析
系列六 微信退款全解析
系列七 支付寶退款全解析
系列八 支付寶開放平臺支付更新升級全解析

1 申請

申請步驟直接參考官方文檔

主要2個大塊:

  1. 申請開通公眾平臺环疼,創(chuàng)建應用
  2. 申請支付開通商戶平臺

全部申請通過后,獲取支付必須的參數(shù)如下:

1.1 AppID和AppSecret

公眾平臺創(chuàng)建的應用唯一標識朵耕。
登錄微信公眾平臺炫隶,進入應用詳情可查看AppID和AppSecret。

Paste_Image.png

1.2 mch_id

微信支付申請完成之后阎曹,微信商戶平臺會給你的郵箱發(fā)通知郵件伪阶,里面包含開通支付的商戶信息

Paste_Image.png

1.3 API秘鑰

即商戶支付秘鑰,主要負責處理通信相關參數(shù)加密处嫌。登陸微信商戶平臺(賬號密碼在微信商戶平臺發(fā)來的郵件里)
點擊左側的「賬戶設置 - API 安全」(第一次登陸會讓你安裝操作證書栅贴,請先安裝操作證書)。點擊設置密鑰锰霜,設置自己的密鑰筹误。

Paste_Image.png

1.4 商戶證書

用于退款等一些需要證書驗證的接口使用。在微信商戶平臺點擊「賬戶中心 - API 安全」癣缅,點擊「下載證書」

Paste_Image.png

證書下載后厨剪,打開壓縮包會看到「apiclient_cert.pem」和「apiclient_key.pem」和rootca.pem證書。

2 接入流程

參考接入文檔

主要幾個步驟:

  1. 統(tǒng)一下單(放在服務端友存,需要加密參數(shù))
  2. 生成支付參數(shù)(放在服務端,需要生成簽名)
  3. 調用客戶端SDK發(fā)起支付
  4. 服務端異步接收支付結果

2.1 統(tǒng)一下單

$appid = "";  //你的appid
$mch_id = "";  //商戶id
$wx_api_key = "";    //商戶api秘鑰
$out_trade_no = "";  //自己業(yè)務系統(tǒng)生成的交易no屡立,可以唯一標識
$client_ip = "";  //客戶端ip
$notify_url = "";    //接收支付結果通知url
$openid = "";    //微信授權獲得的openid

$UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";  //統(tǒng)一下單地址

$data = array();
$data['appid'] = $appid; 
$data['mch_id'] =$mch_id;
$data['nonce_str'] = randomStr(20);  //隨機20位字符串
$data['body'] = "微信公眾號支付測試";
$data['detail'] = "微信公眾號支付測試detail";
$data['out_trade_no'] = $out_trade_no;    
$data['total_fee'] = 1;  //注意 單位是分
$data['spbill_create_ip'] = $client_ip;
$data['openid'] = $openid;
$data['notify_url'] = $notify_url;
$data['trade_type'] = "JSAPI";  //交易類型
$data['sign'] =sign($data, $wx_api_key);    //簽名

//轉為xml格式
$xml_str = arrayToXmlStr($data); 

//發(fā)送請求 使用封裝好的curl_post
$result = curl_post($UNIFIED_ORDER_URL, $xml_str);

//解析得到的值
$get_data = simplexml_load_string($raw_data, 'SimpleXMLElement', LIBXML_NOCDATA);
$get_para = array();
$get_sign = "";
foreach ($get_data->children() as $child) 
{    
  if($child->getName() == 'sign') {        
    $get_sign = strval($child);    
  } else {        
    $get_para[strval($child->getName())] = strval($child);    
   }
}

if($get_para['return_code'] !== "SUCCESS") {
    //return code fail
}

//驗證簽名
if(!verifySign($get_sign, $get_para, $wx_api_key)) {
    //驗證簽名非法
}

//可以自行處理解析獲得的參數(shù)
//todo...

一些函數(shù):

/**
 * array轉成xml str
 * @param $arr
 */
public static function arrayToXmlStr($arr) {    
  $xml_data = new \SimpleXMLElement("<xml></xml>");    
  Func::arrayToXml($arr, $xml_data);    
  return $xml_data->asXML();
}

/**
 * 生成指定長度的隨機字符串(包含大寫英文字母, 小寫英文字母, 數(shù)字)
 * @param $length int 需要生成的字符串的長度
 * @return string 包含 大小寫英文字母 和 數(shù)字 的隨機字符串
 */
public static function randomStr($length){    
  //生成一個包含 大寫英文字母, 小寫英文字母, 數(shù)字 的數(shù)組    
  $arr = array_merge(range(0, 9), range('a', 'z'), range('A', 'Z'));    
  $str = '';    
  $arr_len = count($arr);    
  for ($i = 0; $i < $length; $i++)    {        
    $rand = mt_rand(0, $arr_len-1);        
    $str.=$arr[$rand];    
  }    
  return $str;
}

/**
 * 微信簽名
 * @param $para mixed 帶簽名參數(shù)數(shù)組
 * @param $wx_key string wxkey
 */
public static function sign($para, $wx_key) {    
  $unsign_str = Func::createLinkString(Func::argSort($para)) . "&key=" . $wx_key;    
  $sign = strtoupper(md5($unsign_str));    
  return $sign;
}

/**
 * 微信簽名驗證
 * @param $sign
 * @param $para
 * @param $wx_key
 * @return false-驗證失敗 true-驗證成功
 */
public static function verifySign($sign, $para, $wx_key) {    
  $unsign_str = Func::createLinkString(Func::argSort($para)) . "&key=" . $wx_key;    
  $sign_str = strtoupper(md5($unsign_str));    
  if($sign === $sign_str) {        
    return true;    
  }    
  return false;
}

2.2 生成支付參數(shù)

客戶端需要的支付參數(shù)是帶簽名的直晨,所以最好支付參數(shù)也在服務端生成后,jsondecode后傳入客戶端即可直接調用

//生成支付參數(shù)
$data = array();
$data['appId'] = $appid;
$data['timeStamp'] = time();
$data['nonceStr'] = randomStr(20);
$data['package'] = "prepay_id=$prepay_id";
$data['signType'] = "MD5";
$data['timestamp'] = time();
$data['sign'] =sign($data, $wx_api_key);

$pay_param = json_encode($data);

3. 調用支付

注:微信公眾號發(fā)起支付的路徑必須是在公眾號支付-開發(fā)配置-公眾號支付-支付授權目錄中設置中填入的支付路徑,而且不能是多級目錄

Paste_Image.png

客戶端js調用,封裝了一個簡單的js勇皇,可以直接調用:

//調用微信JS api 支付function 
jsApiCall(pay_param, callback){ 
  var pay_param_arr = eval("(" + pay_param + ")"); 
  WeixinJSBridge.invoke( 
    'getBrandWCPayRequest',{ 
      'appId':pay_param_arr.appId,   
      'timeStamp':pay_param_arr.timeStamp+"", 
      'nonceStr':pay_param_arr.nonceStr, 
      'package':pay_param_arr.package, 
      'signType':pay_param_arr.signType, 
      'paySign':pay_param_arr.paySign 
    }, 
    function(res){ 
      if(res.err_msg == "get_brand_wcpay_request:ok") { 
        //成功 
        callback("ok"); 
      } else if(res.err_msg == "get_brand_wcpay_request:cancel") {   
        //取消 
        callback("cancel"); 
      } else { 
        //失敗 
        callback("fail", res.err_desc); 
      } 
    } );
  }

/** * 微信公眾號支付
 * @param pay_param 服務端生成的pay_param
 */
function callWxJsPay(pay_param, callback){ 
  if (typeof WeixinJSBridge == "undefined"){ 
    if( document.addEventListener ){ 
      document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); 
    }else if (document.attachEvent){ 
      document.attachEvent('WeixinJSBridgeReady', jsApiCall); 
      document.attachEvent('onWeixinJSBridgeReady', jsApiCall); 
    } 
  }else{ 
    jsApiCall(pay_param, callback); 
  }
}

調用示例:

<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" src="../pay_h5_sdk/js/wx_jspay.js"></script> 
  <script type="text/javascript"> 
    function docallpay() { 
      var pay_param = document.getElementById('pay_param').value; 
      callWxJsPay(pay_param, callback); 
    } 
    function callback(state, msg) { 
      alert(state + " " + msg); 
    } 
  </script>
</head>

<body>
<br/>
<div align="center"> 
  輸入支付參數(shù):<br /><br /> 
  <textarea id="pay_param"></textarea> <br/><br />   
  <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="docallpay()" >立即支付</button>
</div>
</body>
</html>

4 異步結果通知

注:尤其要注意通知結果驗證成功后要能正確處理重復通知罩句,放置多次發(fā)貨造成資金損失

$raw_data = $GLOBALS["HTTP_RAW_POST_DATA"];

$get_data = simplexml_load_string($raw_data, 'SimpleXMLElement', LIBXML_NOCDATA);
$get_para = array();
$get_sign = "";
foreach ($get_data->children() as $child) 
{    
  if($child->getName() == 'sign') {        
    $get_sign = strval($child);    
  } else {        
    $get_para[strval($child->getName())] = strval($child);    
   }
}

if($get_para['return_code'] !== "SUCCESS") {
    //return code fail
    die("<xml><return_code><![CDATA[FAIL]]></return_code></xml>");
}

//驗證簽名
if(!verifySign($get_sign, $get_para, $wx_api_key)) {
    //驗證簽名非法
    //todo
    die("<xml><return_code><![CDATA[FAIL]]></return_code></xml>");
}

//在這其實通知已經接受成功 可以返回成功告訴微信不用再次通知了
echo("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");

//業(yè)務狀態(tài)碼判斷
if ($get_para['result_code'] !== 'SUCCESS') {       //狀態(tài)碼錯誤
  //支付錯誤 更改訂單狀態(tài) 記錄log等 
  //...
}

//支付成功 更改訂單狀態(tài) 記錄log等 
//todo

5 其他

  1. 客戶端收到同步支付結果后建議一段時間內輪詢檢查服務端,獲取服務端的結果敛摘,支付最終狀態(tài)以服務端為準

結尾

更多文章關注我的公眾號


我的公眾號
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末门烂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子兄淫,更是在濱河造成了極大的恐慌屯远,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捕虽,死亡現(xiàn)場離奇詭異慨丐,居然都是意外死亡,警方通過查閱死者的電腦和手機泄私,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門房揭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人晌端,你說我怎么就攤上這事崩溪。” “怎么了斩松?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵伶唯,是天一觀的道長。 經常有香客問我惧盹,道長乳幸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任钧椰,我火速辦了婚禮粹断,結果婚禮上,老公的妹妹穿的比我還像新娘嫡霞。我一直安慰自己瓶埋,他們只是感情好,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布诊沪。 她就那樣靜靜地躺著养筒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪端姚。 梳的紋絲不亂的頭發(fā)上晕粪,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機與錄音渐裸,去河邊找鬼巫湘。 笑死装悲,一個胖子當著我的面吹牛,可吹牛的內容都是我干的尚氛。 我是一名探鬼主播诀诊,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼阅嘶!你這毒婦竟也來了畏梆?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤奈懒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后宪巨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體磷杏,經...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年捏卓,在試婚紗的時候發(fā)現(xiàn)自己被綠了极祸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡怠晴,死狀恐怖遥金,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情蒜田,我是刑警寧澤稿械,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站冲粤,受9級特大地震影響美莫,放射性物質發(fā)生泄漏。R本人自食惡果不足惜梯捕,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一厢呵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧傀顾,春花似錦襟铭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嫉拐,卻和暖如春入撒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背椭岩。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工茅逮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留璃赡,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓献雅,卻偏偏與公主長得像碉考,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子挺身,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內容

  • 微信公眾號支付全解析:http://www.reibang.com/p/f1df7ed364c6 公眾號支付筆記:...
    yuzhan550閱讀 383評論 0 2
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,777評論 25 707
  • 選擇恐懼癥章钾,密集恐懼癥墙贱,社交恐懼癥。 此時還有一種交作業(yè)恐懼癥贱傀。 看圖作文惨撇。隨之而來的是考試恐懼癥。曾經夜夜夢到考...
    槿篁閱讀 241評論 0 0
  • 企業(yè)名稱:深圳市慧友冠源科技有限公司府寒。 組別:272期樂觀四組 【日精進打卡82天】 【知~學習】 巜六項精進》讀...
    江陽水閱讀 226評論 0 0
  • 輕分享是AA組織的一場線上社群分享活動魁衙,旨在讓創(chuàng)業(yè)者之間相互傳遞分享創(chuàng)業(yè)經驗。采訪100位獨立創(chuàng)業(yè)者株搔,將他們最拿手...
    洞天水月閱讀 401評論 0 0