支付介面的注意事項
阿新 • • 發佈:2019-01-28
1、php的ini檔案要開啟php_openssl的支援
2、微信支付回撥成功後要先向微信發起查詢訂單介面,確保訂單是付款的,而不是惡意模擬請求,查詢微信後臺存在該訂單的時候,再處理自己的邏輯
3、支付寶支付成功回撥的時候,要判斷支付的金額是否和資料庫的金額一致,一致才能認為付款成功,避免模擬請求的
4、微信支付的呼叫方法
(1) 微信api生成隨機字串
function wechatRandomStr()
{
return md5(time().mt_rand(0,1000));
}
(2)生成微信sign簽名
function createWechatSign($arr) { ksort($arr); return strtoupper(md5(urldecode(http_build_query($arr) . '&key='.WECHAT_PARTNER_KEY))); }
(3)生成xml陣列
function createXml($arr)
{
$xml="<xml>\n";
foreach ($arr as $key => $value) {
$xml.="<".$key."><![CDATA[".trim($value)."]]></".$key.">\n";
}
$xml.="</xml>";
return $xml;
}
(4) 資料生成xml格式,返回xml格式的資料
function curlWechatApi($uri,$xmlData) { $ch = curl_init(); $header = array('Content-type: text/xml'); curl_setopt($ch, CURLOPT_URL, $uri); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlData); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 0); $res = simplexml_load_string(curl_exec($ch),null, LIBXML_NOCDATA); curl_close($ch); return $res; }
(5)微信查詢訂單
function orderQuery($wechatOrderID,$orderID) { $arr = array( 'appid' => WECHAT_APP_ID,//appid微信開放平臺稽核通過的應用APPID 'mch_id'=> WECHAT_MCH_ID,//mch_id微信支付分配的商戶號 'transaction_id' =>sprintf('%s',$wechatOrderID), 'out_trade_no' =>sprintf('%s',$orderID), 'nonce_str' =>wechatRandomStr() ); $arr['sign'] = createWechatSign($arr); $dataStr = createXml($arr); return curlWechatApi(WECHAT_ORDERQUERY_URI,$dataStr); }
(6)統一下單的介面
function prepayOrder($out_trade_no){
$out_trade_no = $_REQUEST['out_trade_no']; //接收訂單號
訂單號的合法合理性判斷
//構造一個微信訂單
$order=array(
"body" => 商品描述,
"appid" => WECHAT_APP_ID,
'attach'=> 附加資料(店鋪名稱),
"device_info" => 裝置號(APP-001),
"mch_id" => WECHAT_MCH_ID,
"nonce_str" => wechatRandomStr(),
"notify_url" => WECHAT_NOTIFY_URL,
"out_trade_no" => $out_trade_no,
// "spbill_create_ip" => $this->input->ip_address(), //APP傳過來
"spbill_create_ip" => $_SERVER["REMOTE_ADDR"],
"total_fee" => intval(商品價格*100),//注意:前方有坑!!!最小單位是分,跟支付寶不一樣。1表示1分錢。只能是整形。
"trade_type" => 'APP'
);
$order['sign'] = createWechatSign($order);
$xml = createXml($order);
$result = curlWechatApi(WECHAT_UNIFIEDORDER_URL,$xml);
//判斷是否在微信後臺成功生成一個訂單
if($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){
$prepay=array(
"noncestr" => $result->nonce_str,
"prepayid" => $result->prepay_id,//上一步請求微信伺服器得到nonce_str和prepay_id引數。
"appid"=>WECHAT_APP_ID,
"package"=>"Sign=WXPay",
"partnerid"=>WECHAT_MCH_ID,
"timestamp"=>sprintf('%s',time()),
);
$prepay['sign'] = createWechatSign($prepay);
$prepay['success'] = true;
}
else{
$prepay=array(
"success" => false,
"noncestr"=>"",
"prepayid"=>"",
"appid"=>WECHAT_APP_ID,
"package"=>"Sign=WXPay",
"partnerid"=>WECHAT_MCH_ID,
"timestamp"=>"".time(),
"sign" => "",
"return_msg"=>sprintf('%s',$result->return_msg)
);
}
return $prepay;
}
(7)微信支付通知回撥
function notify(){
$xml = file_get_contents('php://input');
$result = simplexml_load_string($xml,null,LIBXML_NOCDATA);
//判斷引數是否合理,微信訂單是否存在
if(is_object($result) && property_exits($result,'transaction_id') && property_exists($result,'out_trade_no')
{
$wechatOrderInfo = orderOquery($result->transaction_id,$result->out_trade_no);
//微信訂單不存在,終止執行,並進行日誌記錄
if($wechatOrderInfo->return_code != 'SUCCESS' || $wechatChatOrderInfo->trade_state != 'SUCCESS')
{
addLog($xml,'微信訂單不存在',json_encode($wechetOrderInfo));
$str = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
echo $str;
exit();
}
}
//判斷訂單在資料庫中是否已經付款,付款終止(省略)
if($wechatOrderInfo->return_code == 'SUCCESS' && $wechatOrderInfo->result_code == 'SUCCESS'){
//處理業務邏輯
}
//失敗處理
}