当前位置:首页 > PHP教程 > php高级应用 > 列表

php实现微信支付之退款功能

发布:smiling 来源: PHP粉丝网  添加日期:2021-09-21 19:54:05 浏览: 评论:0 

网上的很多PHP微信支付接入教程都颇为复杂,且需要配置和引入较多的文件,本人通过整理后给出一个单文件版的,希望可以给各位想接入微信支付的带来些许帮助和借鉴意义。

直接运行该文件即可给指定的微信用户退款。

需要注意的事项:

1.微信退款到零钱要求必传证书,需要到这里账户中心->账户设置->API安全->下载证书,然后修改代码中的证书路径

2.该文件需放到支付授权目录下,可以在微信支付商户平台->产品中心->开发配置中设置。

3.如提示签名错误可以通过微信支付签名验证工具进行验证:微信公众平台支付接口调试工具

4.错误码参照:参照地址代码如下:

  1. <?php 
  2. /** 
  3.  * 关于微信退款的说明 
  4.  * 1.微信退款要求必传证书,需要到https://pay.weixin.qq.com 账户中心->账户设置->API安全->下载证书,证书路径在第119行和122行修改 
  5.  * 2.错误码参照 :https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4 
  6.  */ 
  7. header('Content-type:text/html; Charset=utf-8'); 
  8. $mchid = 'xxxxx';     //微信支付商户号 PartnerID 通过微信支付商户资料审核后邮件发送 
  9. $appid = 'xxxxx'; //微信支付申请对应的公众号的APPID 
  10. $apiKey = 'xxxxx';  //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥 
  11. $orderNo = '';           //商户订单号(商户订单号与微信订单号二选一,至少填一个) 
  12. $wxOrderNo = '';           //微信订单号(商户订单号与微信订单号二选一,至少填一个) 
  13. $totalFee = 0.01;          //订单金额,单位:元 
  14. $refundFee = 0.01;         //退款金额,单位:元 
  15. $refundNo = 'refund_'.uniqid();    //退款订单号(可随机生成) 
  16. $wxPay = new WxpayService($mchid,$appid,$apiKey); 
  17. $result = $wxPay->doRefund($totalFee, $refundFee, $refundNo, $wxOrderNo,$orderNo); 
  18. if($result===true){ 
  19.   echo 'refund success';exit(); 
  20. } 
  21. echo 'refund fail'; 
  22. class WxpayService 
  23. { 
  24.   protected $mchid; 
  25.   protected $appid; 
  26.   protected $apiKey; 
  27.   public $data = null; 
  28.   public function __construct($mchid, $appid, $key) 
  29.   { 
  30.     $this->mchid = $mchid; //https://pay.weixin.qq.com 产品中心-开发配置-商户号 
  31.     $this->appid = $appid; //微信支付申请对应的公众号的APPID 
  32.     $this->apiKey = $key;  //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥 
  33.   } 
  34.   /** 
  35.    * 退款 
  36.    * @param float $totalFee 订单金额 单位元 
  37.    * @param float $refundFee 退款金额 单位元 
  38.    * @param string $refundNo 退款单号 
  39.    * @param string $wxOrderNo 微信订单号 
  40.    * @param string $orderNo 商户订单号 
  41.    * @return string 
  42.    */ 
  43.   public function doRefund($totalFee, $refundFee, $refundNo, $wxOrderNo='',$orderNo='') 
  44.   { 
  45.     $config = array( 
  46.       'mch_id' => $this->mchid, 
  47.       'appid' => $this->appid, 
  48.       'key' => $this->apiKey, 
  49.     ); 
  50.     $unified = array( 
  51.       'appid' => $config['appid'], 
  52.       'mch_id' => $config['mch_id'], 
  53.       'nonce_str' => self::createNonceStr(), 
  54.       'total_fee' => intval($totalFee * 100),    //订单金额  单位 转为分 
  55.       'refund_fee' => intval($refundFee * 100),    //退款金额 单位 转为分 
  56.       'sign_type' => 'MD5',      //签名类型 支持HMAC-SHA256和MD5,默认为MD5 
  57.       'transaction_id'=>$wxOrderNo,        //微信订单号 
  58.       'out_trade_no'=>$orderNo,    //商户订单号 
  59.       'out_refund_no'=>$refundNo,    //商户退款单号 
  60.       'refund_desc'=>'商品已售完',   //退款原因(选填) 
  61.     ); 
  62.     $unified['sign'] = self::getSign($unified, $config['key']); 
  63.     $responseXml = $this->curlPost('https://api.mch.weixin.qq.com/secapi/pay/refund', self::arrayToXml($unified)); 
  64.     $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA); 
  65.     if ($unifiedOrder === false) { 
  66.       die('parse xml error'); 
  67.     } 
  68.     if ($unifiedOrder->return_code != 'SUCCESS') { 
  69.       die($unifiedOrder->return_msg); 
  70.     } 
  71.     if ($unifiedOrder->result_code != 'SUCCESS') { 
  72.       die($unifiedOrder->err_code); 
  73.     } 
  74.     return true; 
  75.   } 
  76.   public static function curlGet($url = '', $options = array()) 
  77.   { 
  78.     $ch = curl_init($url); 
  79.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
  80.     curl_setopt($ch, CURLOPT_TIMEOUT, 30); 
  81.     if (!emptyempty($options)) { 
  82.       curl_setopt_array($ch, $options); 
  83.     } 
  84.     //https请求 不验证证书和host 
  85.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
  86.     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 
  87.     $data = curl_exec($ch); 
  88.     curl_close($ch); 
  89.     return $data; 
  90.   } 
  91.   public function curlPost($url = '', $postData = '', $options = array()) 
  92.   { 
  93.     if (is_array($postData)) { 
  94.       $postData = http_build_query($postData); 
  95.     } 
  96.     $ch = curl_init(); 
  97.     curl_setopt($ch, CURLOPT_URL, $url); 
  98.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
  99.     curl_setopt($ch, CURLOPT_POST, 1); 
  100.     curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); 
  101.     curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数 
  102.     if (!emptyempty($options)) { 
  103.       curl_setopt_array($ch, $options); 
  104.     } 
  105.     //https请求 不验证证书和host 
  106.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
  107.     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 
  108.     //第一种方法,cert 与 key 分别属于两个.pem文件 
  109.     //默认格式为PEM,可以注释 
  110.     curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM'); 
  111.     curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/cert/apiclient_cert.pem'); 
  112.     //默认格式为PEM,可以注释 
  113.     curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM'); 
  114.     curl_setopt($ch,CURLOPT_SSLKEY,getcwd().'/cert/apiclient_key.pem'); 
  115.     //第二种方式,两个文件合成一个.pem文件 
  116. //    curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/all.pem'); 
  117.     $data = curl_exec($ch); 
  118.     curl_close($ch); 
  119.     return $data; 
  120.   } 
  121.   public static function createNonceStr($length = 16) 
  122.   { 
  123.     $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; 
  124.     $str = ''; 
  125.     for ($i = 0; $i < $length; $i++) { 
  126.       $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); 
  127.     } 
  128.     return $str; 
  129.   } 
  130.   public static function arrayToXml($arr) 
  131.   { 
  132.     $xml = "<xml>"; 
  133.     foreach ($arr as $key => $val) { 
  134.       if (is_numeric($val)) { 
  135.         $xml .= "<" . $key . ">" . $val . "</" . $key . ">"; 
  136.       } else 
  137.         $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">"; 
  138.     } 
  139.     $xml .= "</xml>"; 
  140.     return $xml; 
  141.   } 
  142.   public static function getSign($params, $key) 
  143.   { 
  144.     ksort($params, SORT_STRING); 
  145.     $unSignParaString = self::formatQueryParaMap($params, false); 
  146.     $signStr = strtoupper(md5($unSignParaString . "&key=" . $key)); 
  147.     return $signStr; 
  148.   } 
  149.   protected static function formatQueryParaMap($paraMap, $urlEncode = false) 
  150.   { 
  151.     $buff = ""; 
  152.     ksort($paraMap); 
  153.     foreach ($paraMap as $k => $v) { 
  154.       if (null != $v && "null" != $v) { 
  155.         if ($urlEncode) { 
  156.           $v = urlencode($v); 
  157.         } 
  158.         $buff .= $k . "=" . $v . "&"; 
  159.       } 
  160.     } 
  161.     $reqPar = ''; 
  162.     if (strlen($buff) > 0) { 
  163.       $reqPar = substr($buff, 0, strlen($buff) - 1); 
  164.     } 
  165.     return $reqPar; 
  166.   } 
  167. } 
  168. ?>

Tags: php微信支付 php微信退款

分享到: