* @date: 2019/3/28 */ namespace payment\wechat; /** * 关于微信退款的说明 * 1.微信退款要求必传证书,需要到https://pay.weixin.qq.com 账户中心->账户设置->API安全->下载证书,证书路径在第119行和122行修改 * 2.参考 :https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4 * * 使用方法: * $wechatRefund = new WechatRefund($config); * $info = $wechatRefund->doRefund($param); * $info = $wechatRefund->queryRefund($outTradeNo); * $info['return_code'] == 'FAIL' && json_error($info['return_msg'], -2); * $info['result_code'] == 'FAIL' && json_error($info['err_code_des'], -2); * * Class WechatRefund * @package app\common\extend\wechat */ class WechatRefund extends BaseWechat { const REFUND_URL = '/secapi/pay/refund'; //申请退款 const REFUND_QUERY_URL = '/pay/refundquery'; //退款查询 public function __construct($config) { parent::__construct($config); isset($config['sslcert_path']) && $this->sslcertPath = $config['sslcert_path']; isset($config['sslkey_path']) && $this->sslkeyPath = $config['sslkey_path']; } private function checkSsl() { $this->sslcertPath || json_error('缺少参数:sslcert_path'); //证书必传 $this->sslkeyPath || json_error('缺少参数:sslkey_path'); } //退款参数检测 private function check($param) { $this->checkSsl(); isset($param['out_trade_no']) || json_error('缺少参数:out_trade_no'); isset($param['out_refund_no']) || json_error('缺少参数:out_refund_no'); isset($param['total_fee']) || json_error('缺少参数:total_fee'); isset($param['refund_fee']) || json_error('缺少参数:refund_fee'); isset($param['refund_desc']) || json_error('缺少参数:refund_desc'); isset($param['notify_url']) || json_error('缺少参数:notify_url'); $this->notifyUrl = $param['notify_url']; } //申请退款 public function doRefund($param) { $this->check($param); $data['appid'] = $this->appId; $data['mch_id'] = $this->mchId; $data['notify_url'] = $this->notifyUrl; $data['out_trade_no'] = $param['out_trade_no']; //商户系统内部订单号 $data['out_refund_no'] = $param['out_refund_no']; //商户系统内部的退款单号 $data['total_fee'] = $param['total_fee']; //订单总金额,单位为分,只能为整数 $data['refund_fee'] = $param['refund_fee']; //退款总金额,订单总金额,单位为分,只能为整数 $data['refund_desc'] = $param['refund_desc']; //若商户传入,会在下发给用户的退款消息中体现退款原因,注意:若订单退款金额≤1元且属于部分退款,则不会在退款消息中体现退款原因 $data['nonce_str'] = $this->getRandomString(); $data['sign_type'] = $this->signType; $data['sign'] = $this->makeSign($data); $xml = $this->dataToXml($data); $response = $this->postXmlCurl($xml, self::REFUND_URL, true); if (!$response) return false; $result = $this->xmlToArray($response); return $result; } //退款查询 public function queryRefund($outTradeNo, $offset = 0) { $data['appid'] = $this->appId; $data['mch_id'] = $this->mchId; $data['nonce_str'] = $this->getRandomString(); $data['out_trade_no'] = $outTradeNo; $data['sign_type'] = $this->signType; $offset > 10 && $data['offset'] = $offset; //偏移量,当部分退款次数超过10次时可使用,表示返回的查询结果从这个偏移量开始取记录 $data['sign'] = $this->makeSign($data); $xml = $this->dataToXml($data); $response = $this->postXmlCurl($xml, self::REFUND_QUERY_URL); if (!$response) return false; $result = $this->xmlToArray($response); return $result; } }