需求: 安卓,ios端集成微信支付,PHPer(我)要提供一個接口給微信調用,(支付完成後調用),如果成功,就返回success,如果失敗就返回fail,
環境說明:thinkphp 框架開發,
微信的接口說明文檔:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3
支付結果通用通知
應用場景
支付完成後,微信會把相關支付結果和用戶信息發送給商戶,商戶需要接收處理,並返回應答。
對後臺通知交互時,如果微信收到商戶的應答不是成功或超時,微信認爲通知失敗,微信會通過一定的策略定期重新發起通知,儘可能提高通知的成功率,但微信不保證通知最終能成功。 (通知頻率爲15/15/30/180/1800/1800/1800/1800/3600,單位:秒)
注意:同樣的通知可能會多次發送給商戶系統。商戶系統必須能夠正確處理重複的通知。
推薦的做法是,當收到通知進行處理時,首先檢查對應業務數據的狀態,判斷該通知是否已經處理過,如果沒有處理過再進行處理,如果處理過直接返回結果成功。在對業務數據進行狀態檢查和處理之前,要採用數據鎖進行併發控制,以避免函數重入造成的數據混亂。
特別提醒:商戶系統對於支付結果通知的內容一定要做簽名驗證,並校驗返回的訂單金額是否與商戶側的訂單金額一致,防止數據泄漏導致出現“假通知”,造成資金損失。
接口鏈接
該鏈接是通過【統一下單API】中提交的參數notify_url設置,如果鏈接無法訪問,商戶將無法接收到微信通知。
通知url必須爲直接可訪問的url,不能攜帶參數。示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action”
是否需要證書
不需要。
通知參數
字段名 | 變量名 | 必填 | 類型 | 示例值 | 描述 |
---|---|---|---|---|---|
返回狀態碼 | return_code | 是 | String(16) | SUCCESS |
SUCCESS/FAIL 此字段是通信標識,非交易標識,交易是否成功需要查看result_code來判斷 |
返回信息 | return_msg | 否 | String(128) | 簽名失敗 |
返回信息,如非空,爲錯誤原因 簽名失敗 參數格式校驗錯誤 |
以下字段在return_code爲SUCCESS的時候有返回
字段名 | 變量名 | 必填 | 類型 | 示例值 | 描述 |
---|---|---|---|---|---|
應用ID | appid | 是 | String(32) | wx8888888888888888 | 微信開放平臺審覈通過的應用APPID |
商戶號 | mch_id | 是 | String(32) | 1900000109 | 微信支付分配的商戶號 |
設備號 | device_info | 否 | String(32) | 013467007045764 | 微信支付分配的終端設備號, |
隨機字符串 | nonce_str | 是 | String(32) | 5K8264ILTKCH16CQ2502SI8ZNMTM67VS | 隨機字符串,不長於32位 |
簽名 | sign | 是 | String(32) | C380BEC2BFD727A4B6845133519F3AD6 | 簽名,詳見簽名算法 |
業務結果 | result_code | 是 | String(16) | SUCCESS | SUCCESS/FAIL |
錯誤代碼 | err_code | 否 | String(32) | SYSTEMERROR | 錯誤返回的信息描述 |
錯誤代碼描述 | err_code_des | 否 | String(128) | 系統錯誤 | 錯誤返回的信息描述 |
用戶標識 | openid | 是 | String(128) | wxd930ea5d5a258f4f | 用戶在商戶appid下的唯一標識 |
是否關注公衆賬號 | is_subscribe | 否 | String(1) | Y | 用戶是否關注公衆賬號,Y-關注,N-未關注,僅在公衆賬號類型支付有效 |
交易類型 | trade_type | 是 | String(16) | APP | APP |
付款銀行 | bank_type | 是 | String(16) | CMC | 銀行類型,採用字符串類型的銀行標識,銀行類型見銀行列表 |
總金額 | total_fee | 是 | Int | 100 | 訂單總金額,單位爲分 |
貨幣種類 | fee_type | 否 | String(8) | CNY | 貨幣類型,符合ISO4217標準的三位字母代碼,默認人民幣:CNY,其他值列表詳見貨幣類型 |
現金支付金額 | cash_fee | 是 | Int | 100 | 現金支付金額訂單現金支付金額,詳見支付金額 |
現金支付貨幣類型 | cash_fee_type | 否 | String(16) | CNY | 貨幣類型,符合ISO4217標準的三位字母代碼,默認人民幣:CNY,其他值列表詳見貨幣類型 |
代金券或立減優惠金額 | coupon_fee | 否 | Int | 10 | 代金券或立減優惠金額<=訂單總金額,訂單總金額-代金券或立減優惠金額=現金支付金額,詳見支付金額 |
代金券或立減優惠使用數量 | coupon_count | 否 | Int | 1 | 代金券或立減優惠使用數量 |
代金券或立減優惠ID | coupon_id_$n | 否 | String(20) | 10000 | 代金券或立減優惠ID,$n爲下標,從0開始編號 |
單個代金券或立減優惠支付金額 | coupon_fee_$n | 否 | Int | 100 | 單個代金券或立減優惠支付金額,$n爲下標,從0開始編號 |
微信支付訂單號 | transaction_id | 是 | String(32) | 1217752501201407033233368018 | 微信支付訂單號 |
商戶訂單號 | out_trade_no | 是 | String(32) | 1212321211201407033568112322 | 商戶系統的訂單號,與請求一致。 |
商家數據包 | attach | 否 | String(128) | 123456 | 商家數據包,原樣返回 |
支付完成時間 | time_end | 是 | String(14) | 20141030133525 | 支付完成時間,格式爲yyyyMMddHHmmss,如2009年12月25日9點10分10秒錶示爲20091225091010。其他詳見時間規則 |
舉例如下:
(這個就是微信回調的內容。要把他轉成自己要的數組,下面有代碼)
<xml>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<attach><![CDATA[支付測試]]></attach>
<bank_type><![CDATA[CFT]]></bank_type>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[Y]]></is_subscribe>
<mch_id><![CDATA[10000100]]></mch_id>
<nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str>
<openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid>
<out_trade_no><![CDATA[1409811653]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign>
<sub_mch_id><![CDATA[10000100]]></sub_mch_id>
<time_end><![CDATA[20140903131540]]></time_end>
<total_fee>1</total_fee>
<trade_type><![CDATA[JSAPI]]></trade_type>
<transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id>
</xml>
返回參數
商戶處理後同步返回給微信參數:
字段名 | 變量名 | 必填 | 類型 | 示例值 | 描述 |
---|---|---|---|---|---|
返回狀態碼 | return_code | 是 | String(16) | SUCCESS |
SUCCESS/FAIL SUCCESS表示商戶接收通知成功並校驗成功 |
返回信息 | return_msg | 否 | String(128) | OK |
返回信息,如非空,爲錯誤原因: 簽名失敗 參數格式校驗錯誤 |
舉例如下:
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>
相信很多第一次做這個開發的人都很煩。並不知道怎麼處理。
下面貼出我的代碼:
//微信支付驗證
//微信異步通知接口,如果我返回success,微信不再通知,
public function weipayverify(){
//寫支付記錄,WEB_PATH是我網站的根目錄
create_pay_log(WEB_PATH.'/Public/apilog/weipay_ajax/',date('Y-m-d').'.log');
libxml_disable_entity_loader(true);
$postStr = postdata();//接收post數據
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$arr = object2array($postObj);//對象轉成數組
ksort($arr);// 對數據進行排序
$str = ToUrlParams($arr);//對數據拼接成字符串
$user_sign = strtoupper(md5($str));
if($user_sign == $arr['sign']){//驗證成功
//寫支付記錄
// to do...
//處理購買後的業務邏輯
//to do
}
}
// 接收post數據
/*
* 微信是用$GLOBALS['HTTP_RAW_POST_DATA'];這個函數接收post數據的
*/
function postdata(){
$receipt = $_REQUEST;
if($receipt==null){
$receipt = file_get_contents("php://input");
if($receipt == null){
$receipt = $GLOBALS['HTTP_RAW_POST_DATA'];
}
}
return $receipt;
}
//把對象轉成數組
function object2array($array) {
if(is_object($array)) {
$array = (array)$array;
} if(is_array($array)) {
foreach($array as $key=>$value) {
$array[$key] = object2array($value);
}
}
return $array;
}
/**
* 格式化參數格式化成url參數
*/
private function ToUrlParams($arr)
{
$weipay_key = 'sdfasdfasdfasd';//微信的key,這個是微信支付給你的key,不要瞎填。
$buff = "";
foreach ($arr as $k => $v)
{
if($k != "sign" && $v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff.'&key='.$weipay_key;
}
代碼雖然很簡單。貼在這裏給用的到的朋友。
再次提醒一下。這個接口是給安卓ios端用的,他們把這個接口放在支付完成回調的接口。微信會回調的。