1. 程式人生 > >微信支付退款(PHP後端)

微信支付退款(PHP後端)

應用場景

當交易發生之後一段時間內,由於買家或者賣家的原因需要退款時,賣家可以通過退款介面將支付款退還給買家,微信支付將在收到退款請求並且驗證成功之後,按照退款規則將支付款按原路退到買家帳號上。

微信官方退款文件

其實微信退款呢,也就是你沒做過,感覺挺難的,其實跟其他介面一樣,都是調介面,只是請求的時候呼叫了證書

獲取商戶證書 (第3項)

按照一步步流程,很容易就生成證書了,最後放入專案中,供請求的時候使用

微信使用證書demo

<?php
//向外暴露的微信退款介面
public function refund()
{
     $result = $this->weChatrefund();
     
return $result; /* * <xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> <appid><![CDATA[wx2421b1c4370ec43b]]></appid> <mch_id><![CDATA[10000100]]></mch_id> <nonce_str><![CDATA[NfsMFbUFpdbEhPXP]]></nonce_str> <sign><![CDATA[B7274EB9F8925EB93100DD2085FA56C0]]></sign> <result_code><![CDATA[SUCCESS]]></result_code> <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id> <out_trade_no><![CDATA[1415757673]]></out_trade_no> <out_refund_no><![CDATA[1415701182]]></out_refund_no> <refund_id><![CDATA[2008450740201411110000174436]]></refund_id> <refund_channel><![CDATA[]]></refund_channel> <refund_fee>1</refund_fee> </xml>
*/ if($result['return_code'] =='SUCCESS'){ //退款申請成功 } } private function weChatrefund() { $param = array( 'appid'=> $this->APPID, 'mch_id'=> $this->MCHID, 'nonce_str'=> $this->createNoncestr(), 'out_refund_no'=> $this
->outRefundNo, 'transaction_id'=> $this->transactionId,//微信訂單號 'total_fee'=> $this->totalFee, 'refund_fee'=> $this->refundFee, ); $parma['sign'] = $this->getSign($parma); $xmldata = $this->arrayToXml($parma); $xmlresult = $this->postXmlSSLCurl($xmldata,'https://api.mch.weixin.qq.com/secapi/pay/refund'); $result = $this->xmlToArray($xmlresult); return $result; } /* * 對要傳送到微信統一下單介面的資料進行簽名 */ protected function getSign($Obj){ foreach ($Obj as $k => $v){ $Parameters[$k] = $v; } //簽名步驟一:按字典序排序引數 ksort($Parameters); $String = $this->formatBizQueryParaMap($Parameters, false); //簽名步驟二:在string後加入KEY $String = $String."&key=".$this->KEY; //簽名步驟三:MD5加密 $String = md5($String); //簽名步驟四:所有字元轉為大寫 $result_ = strtoupper($String); return $result_; } /* *排序並格式化引數方法,簽名時需要使用 */ protected function formatBizQueryParaMap($paraMap, $urlencode) { $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v) { if($urlencode) { $v = urlencode($v); } //$buff .= strtolower($k) . "=" . $v . "&"; $buff .= $k . "=" . $v . "&"; } $reqPar = ""; if (strlen($buff) > 0) { $reqPar = substr($buff, 0, strlen($buff)-1); } return $reqPar; } /* * 生成隨機字串方法 */ protected function createNoncestr($length = 32 ){ $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; $str =""; for ( $i = 0; $i < $length; $i++ ) { $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1); } return $str; } //陣列轉字串方法 protected function arrayToXml($arr){ $xml = "<xml>"; foreach ($arr as $key=>$val) { if (is_numeric($val)){ $xml.="<".$key.">".$val."</".$key.">"; }else{ $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } } $xml.="</xml>"; return $xml; } protected static function xmlToArray($xml){ $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $array_data; } //需要使用證書的請求 private function postXmlSSLCurl($xml,$url,$second=30) { $ch = curl_init(); //超時時間 curl_setopt($ch,CURLOPT_TIMEOUT,$second); //這裡設定代理,如果有的話 //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8'); //curl_setopt($ch,CURLOPT_PROXYPORT, 8080); curl_setopt($ch,CURLOPT_URL, $url); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE); //設定header curl_setopt($ch,CURLOPT_HEADER,FALSE); //要求結果為字串且輸出到螢幕上 curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE); //設定證書 //使用證書:cert 與 key 分別屬於兩個.pem檔案 //預設格式為PEM,可以註釋 curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLCERT, '../../'.$this->SSLCERT_PATH); //預設格式為PEM,可以註釋 curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLKEY,'../../'. $this->SSLKEY_PATH); //post提交方式 curl_setopt($ch,CURLOPT_POST, true); curl_setopt($ch,CURLOPT_POSTFIELDS,$xml); $data = curl_exec($ch); //返回結果 if($data){ curl_close($ch); return $data; } else { $error = curl_errno($ch); echo "curl出錯,錯誤碼:$error"."<br>"; curl_close($ch); return false; } }

  使用本程式碼,建議使用單個方法拼接,最終來組成邏輯程式碼