/**
* 處理退款
* @param $out_trade_no
* @param $total_fee
* @param $refund_fee
* @param $from 1余額 2未結算
* @return array
* @throws Exception
* 策略一:當天支付的錢,從未結算中退;非當天支付的錢,從余額中退(結算的錢到余額中有個緩沖期1-3天,結算到余額要收千分之一的手續費)。確保退款正常,需要在余額中留有備用金。
* 策略二:優先從未結算中退,未結算中余額不足,再從余額中退。(需要查詢兩次,比較消耗網絡。好處就是可以節省被騰訊收取的千分之一的費用。)
*/
public static function refundOrder($out_trade_no,$total_fee,$refund_fee,$from = 1) {
$refund_no = $out_trade_no.$total_fee;
if ((int)$from === 1) {
$refund_account = 'REFUND_SOURCE_RECHARGE_FUNDS';
} else {
$refund_account = 'REFUND_SOURCE_UNSETTLED_FUNDS';
}
// $refund_account = 'REFUND_SOURCE_UNSETTLED_FUNDS';
$param = array(
'appid' => C('APPID'),
'mch_id' => C('MCHID'),
'nonce_str' => self::createNonceStr(),
'out_refund_no' => $refund_no, //由后端生成的退款單號,需要保證唯一,因為多個同樣的退款單號只會退款一次。
'out_trade_no' => $out_trade_no, //退款訂單在支付時生成的訂單號
'total_fee' => $total_fee,
'refund_fee' => $refund_fee,
'refund_account'=> $refund_account, // REFUND_SOURCE_RECHARGE_FUNDS 從余額退,REFUND_SOURCE_UNSETTLED_FUNDS 從未結算退
'op_user_id' => C('MCHID'), //操作員 op_user_id .與商戶號相同即可
);
$param['sign'] = self::MakeSign($param);
$xml_data = self::ToXml($param);
$xml_result = self::postXmlSSLCurl($xml_data,'https://api.mch.weixin.qq.com/secapi/pay/refund');
$result = self::FromXml($xml_result);
self::setlog($param,$result,__METHOD__);
if (!$result){
$result_arr = [
'num' => '0',
'desc' => '接口錯誤',
];
return $result_arr;
}
if ($result['result_code'] != 'SUCCESS'){
$result_arr = [
'num' => '-1',
'desc' => $result['err_code_des'],
'err_code' => $result['err_code'], // NOTENOUGH 余額不足
];
} else {
$result_arr = [
'num' => '1',
'desc' => '退款成功',
'refund_id' => $result['refund_id'],
'refund_no' => $refund_no,
];
}
return $result_arr;
}
經驗之談!
