微信支付退款(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;
    }
}

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

參考其他案例


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM