完整的PHP 微信 退款类操作,详细如下,完整页面下载在底部:
use think\Config; //微信申请退款类 class Refund{ protected $config = null; private $appid;//公众账号appid private $mch_id;//商户号 private $nonce_str;//随机字符串,不长于32位 private $sign; // 签名 private $transaction_id;//微信生成的订单号,在支付通知中有返回 private $out_refund_no;//商户退款单号商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ private $total_fee;//total_fee订单总金额,单位为分,只能为整数 private $refund_fee;//退款金额 private $refund_desc='接单员暂时都没有空,麻烦您提价,或稍后再发一次';//退款原因; private $api_password; //商户平台设置的密钥key private $refundurl = "https://api.mch.weixin.qq.com/secapi/pay/refund"; /** 公钥*/ private $apiclient_cert; /** 私钥*/ private $apiclient_key; /** ca证书*/ private $rootca; public function __construct(){ $this->config = Config::get(); //初始化红包设置信息 $this->appid = $this->config["wechat"]["app_id"]; $this->mch_id = $this->config["wechat"]["payment"]["mch_id"]; $this->api_password = $this->config["wechat"]["payment"]["key"]; $this->nonce_str = $this->create_nonce_str(32); $this->apiclient_cert = EXTEND_PATH . 'wxcert' . DS . 'apiclient_cert.pem'; $this->apiclient_key = EXTEND_PATH . 'wxcert' . DS . 'apiclient_key.pem'; $this->rootca = EXTEND_PATH . 'wxcert' . DS . 'rootca.pem'; } //发出退款请求 public function send_post($transaction_id="",$out_refund_no='',$refund_fee=0,$total_fee=0){ $sign = $this->create_sign($transaction_id, $out_refund_no, $refund_fee, $total_fee); $send_array = array( 'appid' => $this->appid, 'mch_id' => $this->mch_id, 'nonce_str' => $this->nonce_str, 'out_refund_no' => $out_refund_no, 'refund_desc' => $this->refund_desc, 'refund_fee' => $refund_fee, 'total_fee' => $total_fee, 'transaction_id'=> $transaction_id , 'sign' => $sign, ); $send_xml = $this->toxml($send_array); $result = $this->get_curl_contents($this->refundurl, $send_xml); if($result){ $data = $this->xmlToArray($result); return $data; } else{ return null; } } //生成随机字符串 public function create_nonce_str($length){ $str = null; $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; $max = strlen($strPol)-1; for($i=0;$i<$length;$i++){ $str.=$strPol[rand(0,$max)];//rand($min,$max)生成介于min和max两个数
之间的一个随机整数 } return $str; } /** 创建签名 例如: appid: wxd111665abv58f4f mch_id: 10000100 device_info: 1000 Body: test nonce_str: ibuaiVcKdpRxkhJA 第一步:对参数按照 key=value 的格式,并按照参数名 ASCII 字典序排序如下: stringA="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_i d=10000100&nonce_str=ibuaiVcKdpRxkhJA"; 第二步:拼接支付密钥: stringSignTemp="stringA&key=192006250b4c09247ec02edce69f6a2d" sign=MD5(stringSignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A 9CF3B7" */ private function create_sign($transaction_id="",$out_refund_no='',$refund_fee=0,
$total_fee=0){ $string_array = array( 'appid' => $this->appid, 'mch_id' => $this->mch_id, 'nonce_str' => $this->nonce_str, 'out_refund_no' => $out_refund_no, 'refund_desc' => $this->refund_desc, 'refund_fee' => $refund_fee, 'total_fee' => $total_fee, 'transaction_id'=> $transaction_id ); $stringA = ""; foreach($string_array as $key =>$value){ if(!empty($value)){ $stringA .= "$key=$value"; if($key != 'transaction_id'){$stringA .= '&';} } } $stringSignTemp="$stringA&key=$this->api_password"; $sign = MD5($stringSignTemp); $sign = strtoupper($sign); return $sign; } public function toxml($arr){ $xml = "<xml>"; foreach ($arr as $key=>$val) { $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } $xml.="</xml>"; return $xml; } private function xmlToArray($postStr){ $msg = array(); $msg = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); return $msg; } //curl获取请求文本内容 public function get_curl_contents($url, $data = null) { $curl = curl_init(); //初始化 curl_setopt($curl, CURLOPT_URL, $url);//设置抓取的url 为 $requesturl curl_setopt($curl, CURLOPT_HEADER, 0);//设置头文件的信息作为数据流输出 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); //设置获取的信息以文件流的形式返回,而不是直接输出。 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); //跳过证书验证 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在 curl_setopt($curl,CURLOPT_SSLCERTTYPE,'PEM'); curl_setopt($curl,CURLOPT_SSLCERT,$this->apiclient_cert); curl_setopt($curl,CURLOPT_SSLKEYTYPE,'PEM'); curl_setopt($curl,CURLOPT_SSLKEY,$this->apiclient_key); curl_setopt($curl,CURLOPT_SSLKEYTYPE,'PEM'); //echo $this->rootca; curl_setopt($curl,CURLOPT_CAINFO,$this->rootca); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, 1); //POST请求 curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } $data = curl_exec($curl);//执行命令 curl_close($curl);//关闭URL请求 return $data; } public function get_server_ip(){ if('/'==DIRECTORY_SEPARATOR){ $server_ip=$_SERVER['SERVER_ADDR']; }else{ $server_ip=@gethostbyname($_SERVER['SERVER_NAME']); } return $server_ip; } }