Ver Fonte

商城订单退款

lizhen_gitee há 11 meses atrás
pai
commit
d70bfab6d0

+ 74 - 0
addons/epay/library/Service.php

@@ -23,6 +23,80 @@ class Service
     public const SDK_VERSION_V3 = 'v3';
 
     /**
+     * 提交退款订单
+     * @param array|float $amount    订单金额
+     * @param array|float $refund_money    退款金额
+     * @param string      $orderid   订单号
+     * @param string      $refund_sn   退款订单号
+     * @param string      $type      支付类型,可选alipay或wechat
+     * @param string      $remark     退款原因
+     * @param string      $notifyurl 通知回调URL
+     * @param string      $returnurl 跳转返回URL
+     * @param string      $method    支付方式
+     * @return Response|RedirectResponse|Collection
+     * @throws Exception
+     */
+    public static function submitRefund($amount=null,$refund_money,$orderid,$refund_sn,$type,$remark = null,$notifyurl = null,$returnurl = null,$method = 'app'){
+        if (!is_array($amount)) {
+            $params = [
+                'amount'    => $amount,
+                'type'      => $type,
+                'notifyurl' => $notifyurl,
+                'returnurl' => $returnurl,
+                'method'    => $method,
+            ];
+        } else {
+            $params = $amount;
+        }
+        $type = isset($params['type']) && in_array($params['type'], ['alipay', 'wechat']) ? $params['type'] : 'wechat';
+        $request = request();
+        $notifyurl = isset($params['notifyurl']) ? $params['notifyurl'] : $request->root(true) . '/addons/epay/index/' . $type . 'notify';
+        // $returnurl = isset($params['returnurl']) ? $params['returnurl'] : $request->root(true) . '/addons/epay/index/' . $type . 'return/out_trade_no/' . $orderid;
+        $config = Service::getConfig($type);
+        $config['notify_url'] = $notifyurl;
+        $config['return_url'] = $returnurl;
+        $result = null;
+        //退款参数
+        $order_data = [
+            'out_trade_no' => $orderid//原订单号
+        ];
+        if ($type == 'wechat') {
+            //创建支付对象
+            $pay = Pay::wechat($config);
+            $total_fee = $amount * 100;
+            $refund_fee = $refund_money * 100;
+            $order_data = array_merge($order_data, [
+                'out_refund_no' => $refund_sn,//退款订单号
+                'total_fee' => $total_fee,//支付金额
+                'refund_fee' => $refund_fee,//退款金额
+                'refund_desc' => $remark,//退款原因
+                //'type' => $method  //支付方式
+            ]);
+        } else {
+            $pay = Pay::alipay($config);
+            $order_data = array_merge($order_data, [
+                'out_request_no' => $refund_sn,//退款订单号
+                'refund_amount' => $refund_money,
+            ]);
+        }
+
+        $result = $pay->refund($order_data);
+
+        //使用重写的Response类、RedirectResponse、Collection类
+        if ($result instanceof \Symfony\Component\HttpFoundation\RedirectResponse) {
+            $result = new RedirectResponse($result->getTargetUrl());
+        } elseif ($result instanceof \Symfony\Component\HttpFoundation\Response) {
+            $result = new Response($result->getContent());
+        } elseif ($result instanceof \Yansongda\Supports\Collection) {
+            $result = Collection::make($result->all());
+        } elseif ($result instanceof \GuzzleHttp\Psr7\Response) {
+            $result = new Response($result->getBody());
+        }
+
+        return $result;
+    }
+
+    /**
      * 提交订单
      * @param array|float $amount    订单金额
      * @param string      $orderid   订单号

+ 187 - 33
application/admin/controller/unishop/Order.php

@@ -414,45 +414,67 @@ class Order extends Backend
             $this->error(__('This order is not returned'));
         }
         if ($this->request->isPost()) {
-            $params = $this->request->post("row/a");
-            if ($params) {
-                $params = $this->preExcludeFields($params);
-                $result = false;
-                Db::startTrans();
-                try {
 
-                    // 退款
-                    if($params['refund_action'] == 1) {
-                        $params['had_refund'] = time();
-                        Hook::add('order_refund', 'addons\\unishop\\behavior\\Order');
-                    }
+            Db::startTrans();
+            try {
 
-                    $updatetime = $this->request->post('updatetime');
-                    // 乐观锁
-                    $result = $this->model->allowField(true)->save($params, ['id' => $ids, 'updatetime' => $updatetime]);
-                    if (!$result) {
-                        throw new Exception(__('Data had been update before saved, close windows and do it again'));
-                    }
+                $updatetime = $this->request->post('updatetime');
+                $refund_amount = $this->request->post('refund_amount');
+                $refund_status = $this->request->post('refund_status');
 
-                    Db::commit();
-                } catch (ValidateException $e) {
-                    Db::rollback();
-                    $this->error($e->getMessage());
-                } catch (PDOException $e) {
-                    Db::rollback();
-                    $this->error($e->getMessage());
-                } catch (Exception $e) {
-                    Db::rollback();
-                    $this->error($e->getMessage());
+                if ($refund_amount > $row['total_price']) {
+                    $this->error('退款金额不能大于实际支付金额');
                 }
-                if ($result !== false) {
-                    Hook::listen('order_refund', $row);
-                    $this->success();
-                } else {
-                    $this->error(__('No rows were updated'));
+
+                // 退款
+                $params = [
+                    'refund_status' => $refund_status,
+                ];
+                if($refund_status == 3) {
+                    $params['had_refund'] = time();
                 }
+                // 乐观锁
+                $result = Db::name('unishop_order')->where(['id' => $ids, 'updatetime' => $updatetime])->update($params);
+
+                //修改退款金额
+                $rs2 = Db::name('unishop_order_refund')->where('order_id',$ids)->update(['amount'=>$refund_amount]);
+
+                if (!$result || !$rs2) {
+                    throw new Exception(__('Data had been update before saved, close windows and do it again'));
+                }
+
+                //执行退款
+                if($refund_amount > 0){
+                    $order = Db::name('unishop_order')->where('id',$ids)->find();
+
+                    if($order['pay_type'] == 2){
+                        $wallet_rs = model('wallet')->lockChangeAccountRemain($order['user_id'],'money',$refund_amount,32,$remark='商城订单退款','unishop_order',$ids);
+                        if($wallet_rs['status'] === false){
+                            throw new Exception($wallet_rs['msg']);
+                        }
+                    }elseif($order['pay_type'] == 3 || $order['pay_type'] == 4){
+                        $refund_result = $this->old_refund($order,$refund_amount);
+                        if($refund_result !== true){
+                            throw new Exception($refund_result);
+                        }
+                    }
+
+                }
+
+                Db::commit();
+            } catch (ValidateException $e) {
+                Db::rollback();
+                $this->error($e->getMessage());
+            } catch (PDOException $e) {
+                Db::rollback();
+                $this->error($e->getMessage());
+            } catch (Exception $e) {
+                Db::rollback();
+                $this->error($e->getMessage());
             }
-            $this->error(__('Parameter %s can not be empty', ''));
+
+            $this->success();
+
         }
 
         $products = $row->product;
@@ -485,6 +507,138 @@ class Order extends Backend
         return $this->view->fetch();
     }
 
+    // 退款
+    public function old_refund($order, $refund_price)
+    {
+
+        $table = 'unishop_order';
+        $remark = '订单退款';
+
+        if($order['pay_type'] == 3){
+            $order['pay_type'] == 'wechat';
+        }
+        if($order['pay_type'] == 4){
+            $order['pay_type'] == 'alipay';
+        }
+
+        // 生成退款单
+        $refund_data = [
+            'order_id' => $order['id'],
+            'out_refund_no'=> createUniqueNo('R',$order['id']),
+            'pay_fee'  => $order['total_price'],
+            'refund_price' => $refund_price,
+            'pay_type' => $order['pay_type'],
+            'status' => 0,
+            'createtime' => time(),
+            'updatetime' => time(),
+            'table' => $table,
+            'table_id' => $order['id'],
+        ];
+        $refund_log_id = Db::name('pay_order_refund_log')->insertGetId($refund_data);
+        if(!$refund_log_id){
+            return '退款失败';
+        }
+
+        if ($order['pay_type'] == 'wechat' || $order['pay_type'] == 'alipay') {
+            // 微信|支付宝退款
+
+            // 退款数据
+            $order_data = [
+                'out_trade_no' => $order['pay_out_trade_no']
+            ];
+
+            if ($order['pay_type'] == 'wechat') {
+                $total_fee = $order['total_price'] * 100;
+                $refund_fee = $refund_price * 100;
+
+                $order_data = array_merge($order_data, [
+                    'out_refund_no' => $refund_data['out_refund_no'],
+                    'total_fee' => $total_fee,
+                    'refund_fee' => $refund_fee,
+                    'refund_desc' => $remark,
+                ]);
+            } else {
+                $order_data = array_merge($order_data, [
+                    'out_request_no' => $refund_data['out_refund_no'],
+                    'refund_amount' => $refund_price,
+                ]);
+            }
+
+            //
+            if ($order['pay_type'] == 'wechat') {
+                $wxpay = new \app\common\library\Wxpay;
+                $result = $wxpay->WxPayRefund($order_data);
+                // 微信通知回调 pay->notifyr
+                if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
+                    Db::name('pay_order_refund_log')->where('id',$refund_log_id)->update(['status'=>1]);
+                    return true;
+                } else {
+                    return $result['return_msg'];
+                }
+            } else {
+
+                $result = Service::submitRefund($order['total_price'],$refund_price,$order['pay_out_trade_no'],$refund_data['out_refund_no'],$order['pay_type'],$remark,'');
+
+                if($result['code'] == '10000'){
+                    Db::name('pay_order_refund_log')->where('id',$refund_log_id)->update(['status'=>1]);
+                    return true;
+                }else{
+                    return $result['msg'];
+                }
+
+
+
+                /* return 'alipay wrong way';
+                 $alipay = new \app\common\library\AliPay;
+                 $result = $alipay->AliPayRefund($order_data);
+                 // 支付宝通知回调 pay->notifyx
+                 return $result;*/
+
+                /*if ($result['code'] == "10000") {
+                    return true;
+                } else {
+                    throw new \Exception($result['msg']);
+                }*/
+            }
+
+            // {        // 微信返回结果
+            //     "return_code":"SUCCESS",
+            //     "return_msg":"OK",
+            //     "appid":"wx39cd0799d4567dd0",
+            //     "mch_id":"1481069012",
+            //     "nonce_str":"huW9eIAb5BDPn0Ma",
+            //     "sign":"250316740B263FE53F5DFF50AF5A8FA1",
+            //     "result_code":"SUCCESS",
+            //     "transaction_id":"4200000497202004072822298902",
+            //     "out_trade_no":"202010300857029180027000",
+            //     "out_refund_no":"1586241595",
+            //     "refund_id":"50300603862020040700031444448",
+            //     "refund_channel":[],
+            //     "refund_fee":"1",
+            //     "coupon_refund_fee":"0",
+            //     "total_fee":"1",
+            //     "cash_fee":"1",
+            //     "coupon_refund_count":"0",
+            //     "cash_refund_fee":"1
+            // }
+
+            // {        // 支付宝返回结果
+            //     "code": "10000",
+            //     "msg": "Success",
+            //     "buyer_logon_id": "157***@163.com",
+            //     "buyer_user_id": "2088902485164146",
+            //     "fund_change": "Y",
+            //     "gmt_refund_pay": "2020-08-15 16:11:45",
+            //     "out_trade_no": "202002460317545607015300",
+            //     "refund_fee": "0.01",
+            //     "send_back_fee": "0.00",
+            //     "trade_no": "2020081522001464141438570535"
+            // }
+        }
+
+        return true;
+    }
+
     /**
      * 回收站
      */

+ 1 - 1
application/admin/view/unishop/order/refund.html

@@ -121,7 +121,7 @@
             <div class="radio">
                 {foreach name="refundStatusList" item="vo"}
                 {if $key > 0}
-                <label for="row[refund_status]-{$key}"><input id="row[refund_status]-{$key}" name="row[refund_status]" type="radio" value="{$key}" {in name="key" value="$row.refund_status"}checked{/in} /> {$vo}</label>
+                <label for="row[refund_status]-{$key}"><input id="row[refund_status]-{$key}" name="refund_status" type="radio" value="{$key}" {in name="key" value="$row.refund_status"}checked{/in} /> {$vo}</label>
                 {/if}
                 {/foreach}
             </div>

+ 2 - 1
application/api/controller/Unishop.php

@@ -190,7 +190,8 @@ class Unishop extends Api
         //订单改为已支付
         $update = [
             'have_paid'=>$nowtime,
-            'pay_type' =>$paytype_enum[$paytype]
+            'pay_type' =>$paytype_enum[$paytype],
+            'pay_out_trade_no' =>$out_trade_no,
         ];
         $rs_order = Db::name('unishop_order')->where('id',$orderInfo['table_id'])->update($update);
         if($rs_order === false){

+ 333 - 0
application/common/library/Wxpay.php

@@ -0,0 +1,333 @@
+<?php
+namespace app\common\library;
+
+class WxPay {
+
+    /**
+     * 初始化参数
+     *
+     * @param array $options
+     * @param $options ['app_id']  APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
+     * @param $options ['mch_id'] MCHID:商户号(必须配置,开户邮件中可查看)
+     * @param $options ['key'] KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置)
+     * @param $options ['appsecret'] 公众帐号secert(仅JSAPI支付的时候需要配置),
+     * @param $options ['notify_url'] 支付宝回调地址
+     */
+    public function __construct($options = array()) {
+        $this->config = !empty($options) ? $options : config('wechatpay');
+    }
+
+    /**
+     * 微信支付App
+     * @param string $data 业务参数 body out_trade_no total_fee
+     * @param string $data ['out_trade_no'] 订单号  必填
+     * @param string $data ['total_fee'] 订单金额  必填
+     * @param string $data ['body'] 订单详情  必填
+     * @return $response 返回app所需字符串
+     */
+    public function WxPayApp($d) {
+        $wxConfig = $this->config;
+
+        $out_trade_no = $d['out_trade_no'];
+        $total_fee = abs(floatval($d['total_fee'])) * 100;// 微信支付 单位为分
+        $nonce_str = $this->getRandChar(32);
+        $ip = $this->get_client_ip();
+        if ($ip == '::1')
+            $ip = '1.1.1.1';
+        $data ["appid"] = $wxConfig["app_id"];
+        $data ["body"] = $d['body'];
+        $data ["mch_id"] = $wxConfig['mch_id'];
+        $data ["nonce_str"] = $nonce_str;
+        $data ["notify_url"] = $wxConfig["notify_url"];
+        $data ["out_trade_no"] = $out_trade_no;
+        $data ["spbill_create_ip"] = $ip;
+        $data ["total_fee"] = $total_fee;
+        $data ["trade_type"] = "APP";
+        $data['time_expire'] = date('YmdHis', time() + 120);
+        $s = $this->getSign($data);
+        $data ["sign"] = $s;
+        $xml = $this->arrayToXml($data);
+        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
+        $response = $this->postXmlCurl($xml, $url);
+
+        $re = $this->xmlstr_to_array($response);
+        if ($re ['return_code'] == 'FAIL') {
+            return $re['return_msg'];
+        }
+        // 二次签名
+        $reapp = $this->getOrder($re['prepay_id']);
+        return $reapp;
+    }
+
+    /**
+     * 微信App支付退款申请
+     * @param array $d 业务参数 body out_trade_no total_fee
+     * @param string $data ['out_trade_no'] 订单号  必填
+     * @param string $data ['total_fee'] 订单金额  必填
+     * @return $response 返回app所需字符串
+     */
+    public function WxPayRefund($order_data) {
+        $wxConfig = config('wechatpay');
+
+        $data['appid'] = $wxConfig['app_id'];
+        $data['mch_id'] = $wxConfig['mch_id'];
+        $data['nonce_str'] = $this->getRandChar(32);;
+        if ($wxConfig['refund_notify']) {
+            $data['notify_url'] = $wxConfig['refund_notify'];
+        }
+        $data['out_trade_no']  = $order_data['out_trade_no'];
+        $data['out_refund_no'] = $order_data['out_refund_no'];
+        $data['total_fee']     = $order_data['total_fee'];
+        $data['refund_fee']    = $order_data['refund_fee'];
+        $data['refund_desc']   = $order_data['refund_desc'];
+        $data['sign'] = $this->getSign($data);
+        $xml = $this->arrayToXml($data);
+        $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
+        $response = $this->postXmlCurl($xml, $url);
+        $re = $this->xmlstr_to_array($response);
+        /*if ($re ['return_code'] == 'FAIL') {
+            return $re['return_msg'];
+        }*/
+        return $re;
+    }
+
+
+    /**
+     * 微信退款通知
+     * @return array 验证正确返回状态及订单数据
+     */
+    public function WxPayRefundNotifyCheck() {
+        $postStr = $GLOBALS['HTTP_RAW_POST_DATA'];
+        if (!$postStr) {
+            $postStr = file_get_contents("php://input");
+        }
+        $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
+        if ($postObj === false) {
+            error_log('parse xml error', 3, './wechat_errorlog.txt');
+        }
+        if ($postObj->return_code != 'SUCCESS') {
+            error_log($postObj->return_msg, 3, './wechat_errorlog.txt');
+        }
+        $arr = (array)$postObj;
+        file_put_contents('wx_refund_error_logs.txt', date('Y-m-d H:i:s').'退款数据1!'.json_encode($arr), FILE_APPEND);
+
+        if($arr['return_code'] == 'SUCCESS') {
+            $wxConfig = $this->config;
+            //解密信息
+            require_once("Plugins/WxPay/OpenSSLAES.php");
+            $aes = new \OpenSSLAES(md5($wxConfig['key']));
+            $decrypted = $aes->decrypt($arr['req_info']);
+            $reqObj = simplexml_load_string($decrypted, 'SimpleXMLElement', LIBXML_NOCDATA);
+            $arr['req_info'] = (array)$reqObj;
+            file_put_contents('wx_refund_error_logs.txt', date('Y-m-d H:i:s').'退款数据2!'.json_encode($arr), FILE_APPEND);
+            return array('status' => true, 'data' => $arr);
+        }
+        return array('status' => false);
+    }
+
+    /**
+     * 微信签名验证
+     * @param string $data 业务参数
+     * @return array
+     */
+    public function WxPayNotifyCheck() {
+        $postStr = $GLOBALS['HTTP_RAW_POST_DATA'];
+        if(!$postStr){
+            $postStr = file_get_contents("php://input");
+        }
+
+        $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
+        if ($postObj === false) {
+            error_log('parse xml error', 3, './wechat_errorlog.txt');
+        }
+        if ($postObj->return_code != 'SUCCESS') {
+            error_log($postObj->return_msg, 3, './wechat_errorlog.txt');
+        }
+
+        $arr = (array)$postObj;
+        unset($arr['sign']);
+        if ($this->getSign($arr) == $postObj->sign) {
+            return array('status' => true, 'data' => $arr);
+        } else
+            return array('status' => false);
+    }
+
+    /**
+     * 以下为微信所需相关方法,请勿修改
+     */
+
+
+    // 执行第二次签名,才能返回给客户端使用
+    public function getOrder($prepayId) {
+        $data ["appid"] = $this->config ["app_id"];
+        $data ["noncestr"] = $this->getRandChar(32);;
+        $data ["package"] = "Sign=WXPay";
+        $data ["partnerid"] = $this->config ['mch_id'];
+        $data ["prepayid"] = $prepayId;
+        $data ["timestamp"] = time();
+        $s = $this->getSign($data);
+        $data ["sign"] = $s;
+
+        return $data;
+    }
+
+    //生成签名
+    function getSign($Obj) {
+        foreach ($Obj as $k => $v) {
+            $Parameters [strtolower($k)] = $v;
+        }
+        // 签名步骤一:按字典序排序参数
+        ksort($Parameters);
+        $String = $this->formatBizQueryParaMap($Parameters, false);
+        // echo "【string】 =".$String."</br>";
+        // 签名步骤二:在string后加入KEY
+        $String = $String . "&key=" . $this->config ['key'];
+        // echo "<textarea style='width: 50%; height: 150px;'>$String</textarea> <br />";
+        // 签名步骤三:MD5加密
+        $result_ = strtoupper(md5($String));
+        return $result_;
+    }
+
+    // 获取指定长度的随机字符串
+    function getRandChar($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;
+    }
+
+    // 数组转xml
+    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;
+    }
+
+    // post https请求,CURLOPT_POSTFIELDS xml格式
+    function postXmlCurl($xml, $url, $second = 30) {
+        // 初始化curl
+        $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);
+        // post提交方式
+        curl_setopt($ch, CURLOPT_POST, TRUE);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+        // 证书
+        curl_setopt($ch, CURLOPT_SSLKEY, APP_PATH . '../addons/epay/certs/apiclient_key.pem');
+        curl_setopt($ch, CURLOPT_SSLCERT, APP_PATH . '../addons/epay/certs/apiclient_cert.pem');
+        // 运行curl
+        $data = curl_exec($ch);
+        // 返回结果
+        if ($data) {
+            curl_close($ch);
+            return $data;
+        } else {
+            $error = curl_errno($ch);
+            echo "curl出错,错误码:$error" . "<br>";
+            echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
+            curl_close($ch);
+            return false;
+        }
+    }
+
+    //获取当前服务器的IP
+    function get_client_ip() {
+        if ($_SERVER ['REMOTE_ADDR']) {
+            $cip = $_SERVER ['REMOTE_ADDR'];
+        } elseif (getenv("REMOTE_ADDR")) {
+            $cip = getenv("REMOTE_ADDR");
+        } elseif (getenv("HTTP_CLIENT_IP")) {
+            $cip = getenv("HTTP_CLIENT_IP");
+        } else {
+            $cip = "unknown";
+        }
+        return $cip;
+    }
+
+    // 将数组转成uri字符串
+    function formatBizQueryParaMap($paraMap, $urlencode) {
+        $buff = "";
+        ksort($paraMap);
+        foreach ($paraMap as $k => $v) {
+            if ($urlencode) {
+                $v = urlencode($v);
+            }
+            $buff .= strtolower($k) . "=" . $v . "&";
+        }
+
+        if (strlen($buff) > 0) {
+            $reqPar = substr($buff, 0, strlen($buff) - 1);
+        }
+        return $reqPar;
+    }
+
+    //xml转成数组
+    function xmlstr_to_array($xmlstr) {
+        $doc = new \DOMDocument ();
+        $doc->loadXML($xmlstr);
+        return $this->domnode_to_array($doc->documentElement);
+    }
+
+    //dom转成数组
+    function domnode_to_array($node) {
+        $output = array();
+        switch ($node->nodeType) {
+            case XML_CDATA_SECTION_NODE :
+            case XML_TEXT_NODE :
+                $output = trim($node->textContent);
+                break;
+            case XML_ELEMENT_NODE :
+                for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) {
+                    $child = $node->childNodes->item($i);
+                    $v = $this->domnode_to_array($child);
+                    if (isset ($child->tagName)) {
+                        $t = $child->tagName;
+                        if (!isset ($output [$t])) {
+                            $output [$t] = array();
+                        }
+                        $output [$t] [] = $v;
+                    } elseif ($v) {
+                        $output = ( string )$v;
+                    }
+                }
+                if (is_array($output)) {
+                    if ($node->attributes->length) {
+                        $a = array();
+                        foreach ($node->attributes as $attrName => $attrNode) {
+                            $a [$attrName] = ( string )$attrNode->value;
+                        }
+                        $output ['@attributes'] = $a;
+                    }
+                    foreach ($output as $t => $v) {
+                        if (is_array($v) && count($v) == 1 && $t != '@attributes') {
+                            $output [$t] = $v [0];
+                        }
+                    }
+                }
+                break;
+        }
+        return $output;
+    }
+
+}

+ 9 - 0
application/config.php

@@ -392,6 +392,15 @@ return [
         'secret' => '5c56f3d50113caf5d105279305a2ca44',
     ],
 
+    //微信支付退款用,和epay保持一直
+    'wechatpay' => [
+        'app_id' => 'wxbe5585d53a9b5062',  //小程序appid
+        //'app_app_id' => 'wx6844c1575498710e',  //APP appid ,暂时用不到
+        'mch_id' => '1636573418',
+        'key'    => '0Ed5rUZWDF80Bt2gzneL6lVq7wf6Sl8l',//v2密钥
+        'refund_notify' => '',
+    ],
+
     //各种url
     'pay_notify_url' => 'https://jiankangyijia.huxiukeji.cn',  //支付异步回调域名
 ];

+ 1 - 0
application/extra/wallet.php

@@ -20,6 +20,7 @@ return [
         22 => '提现拒绝返回',//money +
 
         31 => '商城购物',//money -
+        32 => '商城退款',//money +
 
 /////////////////医生//////////////////