微信小程序退款 处理类

<?php
/**
 * 微信小程序退款 处理类
参考
https://www.cnblogs.com/afei-qwerty/p/7922982.html *
*/ class WeixinRefundModel extends Model { protected $SSLCERT_PATH = './apiclient_cert.pem';//证书路径 protected $SSLKEY_PATH = './apiclient_key.pem';//证书路径 // function __construct($openid,$outTradeNo,$totalFee,$outRefundNo,$refundFee){ // //初始化退款类需要的变量 // $this->openid = $openid; // $this->outTradeNo = $outTradeNo; // $this->totalFee = $totalFee; // $this->outRefundNo = $outRefundNo; // $this->refundFee = $refundFee; // } /* * array(9) { ["return_code"] => string(7) "SUCCESS" ["return_msg"] => string(2) "OK" ["appid"] => string(18) "****************" ["mch_id"] => string(10) "8888888" ["nonce_str"] => string(16) "V5BUsFl4ikNVwfWz" ["sign"] => string(32) "4DD91513B5CDA88C43B9D91DE6CE0C2B" ["result_code"] => string(4) "FAIL" ["err_code"] => string(13) "ORDERNOTEXIST" ["err_code_des"] => string(15) "订单不存在" } * * * array(18) { ["return_code"] => string(7) "SUCCESS" ["return_msg"] => string(2) "OK" ["appid"] => string(18) "***************" ["mch_id"] => string(10) "****************" ["nonce_str"] => string(16) "hYCjvz62vDdPfh3q" ["sign"] => string(32) "438E05D357B9090EBA0ED1A11A046B71" ["result_code"] => string(7) "SUCCESS" ["transaction_id"] => string(28) "4200000288201901186053870346" ["out_trade_no"] => string(15) "qs2878042616316" ["out_refund_no"] => string(15) "ceshi1547811669" ["refund_id"] => string(29) "**************************" ["refund_channel"] => array(0) {} ["refund_fee"] => string(1) "1" ["coupon_refund_fee"] => string(1) "0" ["total_fee"] => string(1) "1" ["cash_fee"] => string(1) "1" ["coupon_refund_count"] => string(1) "0" ["cash_refund_fee"] => string(1) "1" } * * */ //通过微信api进行退款流程 public function wxrefundapi($out_trade_no,$total_fee,$refund_fee){ $parma = array( 'appid' => C('APPID'), 'mch_id' => C('MCHID'), 'nonce_str' => $this->createNoncestr(), 'out_refund_no' => $out_trade_no.rand('1111,9999'), //由后端生成的退款单号,需要保证唯一,因为多个同样的退款单号只会退款一次。 'out_trade_no' => $out_trade_no, //退款订单在支付时生成的订单号 'total_fee' => $total_fee, 'refund_fee' => $refund_fee, 'op_user_id' => C('MCHID'), //操作员 op_user_id .与商户号相同即可 ); $parma['sign'] = $this->getSign($parma); $xmldata = $this->arrayToXml($parma); $xmlresult = $this->postXmlSSLCurl($xmldata,'https://api.mch.weixin.qq.com/secapi/pay/refund'); $result = $this->xmlToArray($xmlresult); setlog($parma,$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'] ]; } else { $result_arr = [ 'num' => '1', 'desc' => '退款成功', 'data' => $result['refund_id'] ]; } return $result_arr; } /* * 生成随机字符串方法 */ protected function createNoncestr($length = 32 ){ $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; $str =""; for ( $i = 0; $i < $length; $i++ ) { $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1); } return $str; } /* * 对要发送到微信统一下单接口的数据进行签名 */ protected function getSign($Obj){ foreach ($Obj as $k => $v){ $Parameters[$k] = $v; } //签名步骤一:按字典序排序参数 ksort($Parameters); $String = $this->formatBizQueryParaMap($Parameters, false); //签名步骤二:在string后加入KEY $String = $String."&key=".C('WEIXIN_PAY_KEY'); //签名步骤三:MD5加密 $String = md5($String); //签名步骤四:所有字符转为大写 $result_ = strtoupper($String); return $result_; } /* *排序并格式化参数方法,签名时需要使用 */ protected function formatBizQueryParaMap($paraMap, $urlencode) { $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v) { if($urlencode) { $v = urlencode($v); } //$buff .= strtolower($k) . "=" . $v . "&"; $buff .= $k . "=" . $v . "&"; } $reqPar = ''; if (strlen($buff) > 0) { $reqPar = substr($buff, 0, strlen($buff)-1); } return $reqPar; } //数组转字符串方法 protected function arrayToXml($arr){ $xml = "<xml>"; foreach ($arr as $key=>$val) { if (is_numeric($val)){ $xml.="<".$key.">".$val."</".$key.">"; }else{ $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } } $xml.="</xml>"; return $xml; } protected function xmlToArray($xml){ $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $array_data; } //需要使用证书的请求 function postXmlSSLCurl($xml,$url,$second=30) { $ch = curl_init(); //超时时间 curl_setopt($ch, CURLOPT_TIMEOUT, $second); //这里设置代理,如果有的话 //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); //要求结果为字符串且输出到屏幕上 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); //设置证书 //使用证书:cert 与 key 分别属于两个.pem文件 //默认格式为PEM,可以注释 curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLCERT, $this->SSLCERT_PATH); //默认格式为PEM,可以注释 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 = curl_exec($ch); //返回结果 if ($data) { curl_close($ch); return $data; } else { $error = curl_errno($ch); echo "curl出错,错误码:$error" . "<br>"; curl_close($ch); return false; } } }
原文地址:https://www.cnblogs.com/pansidong/p/10289759.html