關於微信支付,退款操作,原路返回


有這樣的場景,用戶購買商品。但是退款的時候要去除運費。
或者,用戶購買多個商家的商品,統一支付。但是用戶只退其中一個商家的商品。
又或者,用戶一個訂單購買多個商品。只退其中一個商品。

微信退款接口可以滿足這些需求,前提是總的退款金額不能超過總的支付金額。
支付的時候,不需要證書。
但是退款的時候,需要提供證書。

下面看看實際的情況。

從上圖可以看出,我支付2分錢,可以一次性退。

也可以,一次退1分,分兩次退還。

而且,用銀行卡就退到銀行卡,用信用卡就退到信用卡。

這些支付,退款相關的信息,可以在管理后台中統一管理。或者寫到配置文件中。


退款需要證書,需要到微信商戶平台進行下載。(開放平台【app】,公眾平台【微信,pc,小程序】)分別有一個商戶號。

退款的時候,需要提供支付的訂單號或者微信提供的transaction_id。每一個退款都有自己的退款號(確保不要相同)。

一筆退款失敗后重新提交,請不要更換退款單號,請使用原商戶退款單號。

private function refundWx($data)
    {
        Clog::setLog($data);
        vendor('Wxpay.WxPay');

        $input = new WxPayRefund();
        $input->SetOut_trade_no($data['out_trade_no']);
        $input->SetAppid($data['app_id']);
        $input->SetMch_id($data['mch_id']);
        $input->SetOut_refund_no($data['out_trade_no'] . 'R');
        $input->SetTotal_fee($data['price']);
        $input->SetRefund_fee($data['price']);
        $input->SetOp_user_id($data['mch_id']);
        $input->key = $data['key'];
        $path = C('WX_KEY_PATH');
        switch ($data['type']) {
            case 1:
                $path = $path . 'open/';
                break;
            case 2:
                $path = $path . 'public/';
                break;
        }
        $response = WxPayApi::refund($input, $path);

        if ($response['return_code'] == 'SUCCESS' && $response['result_code'] == 'SUCCESS') {
            return true;
        } else {
            return false;
        }
}
/**
	 * 
	 * 申請退款,WxPayRefund中out_trade_no、transaction_id至少填一個且
	 * out_refund_no、total_fee、refund_fee、op_user_id為必填參數
	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
	 * @param WxPayRefund $inputObj
	 * @param int $timeOut
	 * @throws WxPayException
	 * @return 成功時返回,其他拋異常
	 */
	public static function refund($inputObj, $path, $timeOut = 6)
	{
		$url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
		//檢測必填參數
		if(!$inputObj->IsOut_trade_noSet() && !$inputObj->IsTransaction_idSet()) {
			throw new WxPayException("退款申請接口中,out_trade_no、transaction_id至少填一個!");
		}else if(!$inputObj->IsOut_refund_noSet()){
			throw new WxPayException("退款申請接口中,缺少必填參數out_refund_no!");
		}else if(!$inputObj->IsTotal_feeSet()){
			throw new WxPayException("退款申請接口中,缺少必填參數total_fee!");
		}else if(!$inputObj->IsRefund_feeSet()){
			throw new WxPayException("退款申請接口中,缺少必填參數refund_fee!");
		}else if(!$inputObj->IsOp_user_idSet()){
			throw new WxPayException("退款申請接口中,缺少必填參數op_user_id!");
		}

  
		$inputObj->SetNonce_str(self::getNonceStr());//隨機字符串
		
		$inputObj->SetSign();//簽名
		$xml = $inputObj->ToXml();
		$startTimeStamp = self::getMillisecond();//請求開始時間
		$response = self::postXmlCurl($xml, $url, true, $timeOut, $path);
		$result = WxPayResults::Init($response);
		self::reportCostTime($url, $startTimeStamp, $result);//上報請求花費時間
		
		return $result;
}
	
/**
	 * 以post方式提交xml到對應的接口url
	 * 
	 * @param string $xml  需要post的xml數據
	 * @param string $url  url
	 * @param bool $useCert 是否需要證書,默認不需要
	 * @param int $second   url執行超時時間,默認30s
	 * @throws WxPayException
	 */
	private static function postXmlCurl($xml, $url, $useCert = false, $second = 30, $certPath = '')
	{		
		$ch = curl_init();
		//設置超時
		curl_setopt($ch, CURLOPT_TIMEOUT, $second);
		
		//如果有配置代理這里就設置代理
		if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0" 
			&& WxPayConfig::CURL_PROXY_PORT != 0){
			curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
			curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
		}
		curl_setopt($ch,CURLOPT_URL, $url);
		curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
		curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//嚴格校驗
		//設置header
		curl_setopt($ch, CURLOPT_HEADER, FALSE);
		//要求結果為字符串且輸出到屏幕上
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
	
		if($useCert == true){
			//設置證書
			//使用證書:cert 與 key 分別屬於兩個.pem文件
			curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
			curl_setopt($ch,CURLOPT_SSLCERT, $certPath . 'apiclient_cert.pem');
			curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
			curl_setopt($ch,CURLOPT_SSLKEY, $certPath . 'apiclient_key.pem');
		}
		//post提交方式
		curl_setopt($ch, CURLOPT_POST, TRUE);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
		//運行curl
		$data = curl_exec($ch);
		//返回結果
		if($data){
			curl_close($ch);
			return $data;
		} else { 
			$error = curl_errno($ch);
			curl_close($ch);
			throw new WxPayException("curl出錯,錯誤碼:$error");
		}
}

具體的參考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4


免責聲明!

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



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