微信小程序支付及退款流程詳解【下】
發表時(shí)間:2021-3-31
發布人(rén):融晨科技
浏覽次數:140
微信小程序支付及退款流程詳解【上(shàng)】中講了(le/liǎo)微信支付的(de)相關流程。在(zài)理清思路後,流程還是(shì)比較清晰和(hé / huò)簡單的(de)。重點在(zài)于(yú)需要(yào / yāo)注意一些細節問題,例如數據格式,加密方法等。
下面說(shuō)一下微信小程序退款的(de)具體實現
二.退款
小程序退款的(de)流程和(hé / huò)付款相似,但有一些細節上(shàng)的(de)不(bù)同。
首先退款的(de)步驟通常如下:
- 用戶前端點擊退款按鈕後,後端接收到(dào)用戶的(de)退款請求通過商城後台呈現給商戶,商戶确定允許退款後,後端再發起向微信退款接口的(de)請求來(lái)請求退款。
- 後端向微信退款接口發送請求後,得到(dào)響應信息,确定退款是(shì)否完成,根據退款是(shì)否完成再去進行改變訂單狀态等業務邏輯。
退款的(de)步驟相對微信支付來(lái)說(shuō)比較簡單。
值得注意的(de)有以(yǐ)下兩點:
1.向微信退款接口請求退款後,根據得到(dào)的(de)響應是(shì)可以(yǐ)直接确定退款是(shì)否完成的(de)。不(bù)再需要(yào / yāo)設置專門的(de)回調接口等待微信通知。當然如果需要(yào / yāo)也(yě)是(shì)可以(yǐ)在(zài)微信商戶平台設置回調接口接受從而(ér)接受微信回調的(de),但并不(bù)是(shì)必須的(de)。
2.退款請求需要(yào / yāo)在(zài)請求服務器安裝微信提供的(de)安全證書,也(yě)就(jiù)是(shì)說(shuō),發起退款請求相比較支付請求在(zài)請求時(shí)請求方法不(bù)能複用,因爲(wéi / wèi)微信退款需要(yào / yāo)攜帶證書的(de)請求,此證書可在(zài)申請微信商戶号成功後從微信商戶平台自行下載,Linux下的(de)PHP開發環境的(de)證書隻需要(yào / yāo)放在(zài)網站根目錄的(de)cert文件夾中即可。其他(tā)開發環境可能需要(yào / yāo)導入操作。
下面講解一下退款的(de)具體步驟
一. 用戶發起退款請求
用戶在(zài)前端發起退款請求,後端接收到(dào)退款請求,将相應訂單标記爲(wéi / wèi)申請退款,展示在(zài)後台.商戶查看後,如果同意退款再進行相應操作.此後才進入真正的(de)退款流程.
二. 商戶發起退款請求
商戶同意退款後,後端即向微信提供的(de)退款 API 發起請求.
同請求微信支付API一樣.退款請求也(yě)需要(yào / yāo)将需要(yào / yāo)的(de)參數進行簽名後以(yǐ)XML發送到(dào)微信的(de)退款API [https://api.mch.weixin.qq.com/pay/refund](https://api.mch.weixin.qq.com/pay/refund)
退款請求需要(yào / yāo)的(de)參數如下(多個(gè)參數在(zài)支付API請求時(shí)也(yě)有使用):
- 小程序 appid。
- 商戶号 mch_id 。申請開通微信支付商戶認證成功後微信發給你的(de)郵件裏有
- 商戶訂單号 out_trade_no 。退款訂單在(zài)支付時(shí)生成的(de)訂單号
- 退款訂單号 out_refund_no 。由後端生成的(de)退款單号,需要(yào / yāo)保證唯一,因爲(wéi / wèi)多個(gè)同樣的(de)退款單号隻會退款一次。
- 總金額 total_fee 。訂單總金額,單位爲(wéi / wèi)分。
- 退款金額 refund_fee 需要(yào / yāo)退款的(de)金額,單位同樣爲(wéi / wèi)分
- 操作員 op_user_id .與商戶号相同即可
- 随機字符串 nonce_str 。同支付請求
- 簽名 sign 。使用上(shàng)面的(de)所有參數進行相應處理加密生成簽名。(具體處理方式與支付相同,可直接複用。)
三. 退款完成
在(zài)發起退款請求後,就(jiù)可以(yǐ)直接根據請求的(de)響應XML中的(de) result_code字段來(lái)判斷退款是(shì)否成功,從而(ér)對訂單狀态進行處理和(hé / huò)後續操作。不(bù)需要(yào / yāo)像支付那樣等待另一個(gè)接口的(de)通知來(lái)确定請求狀态。當然如上(shàng)文所說(shuō),如果需要(yào / yāo)微信服務器發送通知到(dào)後端的(de)話,可以(yǐ)到(dào)微信商戶平台進行設置。
退款因爲(wéi / wèi)流程與支付大(dà)同小異,因此退款的(de)PHP類我選擇了(le/liǎo)直接繼承支付類,
代碼如下,注意區分退款請求方法postXmlSSLCurl和(hé / huò)支付請求方法postXmlCurl的(de)區别,這(zhè)也(yě)就(jiù)是(shì)上(shàng)文提到(dào)的(de)退款需要(yào / yāo)的(de)雙向證書的(de)使用。
````
class WinXinRefund extends WeiXinPay{
protected \$SSLCERT_PATH = 'cert/apiclient_cert.pem';//證書路徑
protected \$SSLKEY_PATH = 'cert/apiclient_key.pem';//證書路徑
protected \$opUserId = '1234567899';//商戶号
function __construct($openid,$outTradeNo,$totalFee,$outRefundNo,$refundFee){
//初始化退款類需要(yào / yāo)的(de)變量
$this->openid = $openid;
$this->outTradeNo = $outTradeNo;
$this->totalFee = $totalFee;
$this->outRefundNo = $outRefundNo;
$this->refundFee = $refundFee;
}
public function refund(){
//對外暴露的(de)退款接口
$result = $this->wxrefundapi();
return $result;
}
private function wxrefundapi(){
//通過微信api進行退款流程
$parma = array(
'appid'=> $this->APPID,
'mch_id'=> $this->MCHID,
'nonce_str'=> $this->createNoncestr(),
'out_refund_no'=> $this->outRefundNo,
'out_trade_no'=> $this->outTradeNo,
'total_fee'=> $this->totalFee,
'refund_fee'=> $this->refundFee,
'op_user_id' => $this->opUserId,
);
$parma['sign'] = $this->getSign($parma);
$xmldata = https://www.wxapp-union.com/$this->arrayToXml($parma);
$xmlresult = $this->postXmlSSLCurl($xmldata,'https://api.mch.weixin.qq.com/secapi/pay/refund');
$result = $this->xmlToArray($xmlresult);
return $result;
}
//需要(yào / yāo)使用證書的(de)請求
function postXmlSSLCurl($xml,$url,$second=30)
{
$ch = curl_init();
//超時(shí)時(shí)間
curl_setopt($ch,CURLOPT_TIMEOUT,$second);
//這(zhè)裏設置代理,如果有的(de)話
//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);
//要(yào / yāo)求結果爲(wéi / wèi)字符串且輸出(chū)到(dào)屏幕上(shàng)
curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
//設置證書
//使用證書:cert 與 key 分别屬于(yú)兩個(gè).pem文件
//默認格式爲(wéi / wèi)PEM,可以(yǐ)注釋
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT, $this->SSLCERT_PATH);
//默認格式爲(wéi / wèi)PEM,可以(yǐ)注釋
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 = https://www.wxapp-union.com/curl_exec($ch);
//返回結果
if($data){
curl_close($ch);
return $data;
}
else {
$error = curl_errno($ch);
echo "curl出(chū)錯,錯誤碼:$error"."<br>";
curl_close($ch);
return false;
}
}}
三. 總結
以(yǐ)上(shàng)就(jiù)是(shì)關于(yú)微信支付和(hé / huò)退款的(de)流程及相關知識的(de)介紹。文中的(de) PHP類 均封裝直接可用。
因爲(wéi / wèi)微信支付和(hé / huò)退款涉及的(de)東西較爲(wéi / wèi)繁雜,很多人(rén)直接看官方文檔可能會一頭霧水,所以(yǐ)看過此文了(le/liǎo)解流程和(hé / huò)要(yào / yāo)點後,再去看微信官方文檔。一方面可以(yǐ)更清晰的(de)了(le/liǎo)解小程序的(de)支付和(hé / huò)退款流程。另一方面,本文因爲(wéi / wèi)篇幅有限及作者能力有限,肯定有無暇顧及或有所纰漏之(zhī)處。爲(wéi / wèi)求穩妥,還是(shì)需要(yào / yāo)多看看官方開發文檔。畢竟事涉支付,出(chū)個(gè)BUG可不(bù)是(shì)小事。
最後扯點閑話吧。這(zhè)篇博客本來(lái)應該在(zài)三個(gè)月前就(jiù)發表的(de),也(yě)算當時(shí)我從一無所知到(dào)獨立完成微信小程序商城前後端的(de)總結系列的(de)第一篇。但是(shì)公司突然出(chū)現人(rén)員和(hé / huò)項目的(de)變動,導緻管理和(hé / huò)項目上(shàng)都混亂不(bù)堪,再加上(shàng)個(gè)人(rén)的(de)惰性,導緻此篇博客一直拖到(dào)三個(gè)月後的(de)今天才斷斷續續寫完。這(zhè)三個(gè)月我的(de)心态因爲(wéi / wèi)各種事起起伏伏,也(yě)頗有一番風味。
借用李志的(de)一句歌詞結束這(zhè)篇博客吧。下一篇是(shì)什麽時(shí)候也(yě)說(shuō)不(bù)定了(le/liǎo),我苦笑。
我再也(yě)不(bù)會把自己,愚蠢的(de)交給過去。我的(de)生活和(hé / huò)我的(de)想法,從此相隔萬裏。