Sfoglia il codice sorgente

增加支付和退款

jun 1 mese fa
parent
commit
cedb443197

+ 1 - 0
.gitignore

@@ -11,6 +11,7 @@
 /public/uploads/score_product/*
 /public/uploads/company/*
 /public/uploads/topic/*
+/public/uploads/*
 /vendor
 *.DS_Store
 *.log

+ 65 - 1
app/Http/Controllers/Admin/Orders.php

@@ -12,10 +12,12 @@ use App\Models\Orders\Receipt;
 use App\Models\OrdersAddr;
 use App\Models\OrdersProduct;
 use App\Models\Business;
+use App\Servers\WechatPay\Payment;
 use Illuminate\Support\Facades\DB;
 use Intervention\Image\Facades\Image;
 use Intervention\Image\Gd\Font;
 use App\Models\Custom\Shoptype;
+use Kra8\Snowflake\Snowflake;
 
 /**
  * 订单管理
@@ -610,5 +612,67 @@ class Orders extends Auth{
 			return 			'';
 		}
 	}
-
+    /**
+     * 退款
+     *
+     * */
+    public function refund( Request $request, Model $Model,OrdersProduct $OrdersProduct,Payment $Payment){
+        // 验证参数
+        $request->scene('refund')->validate();
+        // 接收参数
+        $id									= request('id',0);
+        // 查询数据
+        $orderInfo							= $Model->query()->find($id);
+        // 数据信息
+        if (!$orderInfo)    				return json_send(['code'=>'error','msg'=>'订单不存在']);
+        // 订单编号
+        $params['out_trade_no']   			= (string)$orderInfo['snowflake_id'];
+        $out_refund_no 						= (new Snowflake())->next();
+        $params['out_refund_no']    		= (string)$out_refund_no;
+        // 组合数据,写入订单表,子表
+        DB::beginTransaction();
+        // 尝试
+        try {
+            //修改订单状态
+            $res                        	= $Model->query()->where('snowflake_id','=',$orderInfo['snowflake_id'])->update(['out_refund_no'=>$out_refund_no,'status'=>5]);
+            // 错误提醒
+            if (!$res)                  	{
+                // 回退数据
+                DB::rollBack();
+                // 返回结果
+                return json_send(['code'=>'error','msg'=>'退款失败']);
+            }
+            //修改订单产品状态
+            $res                        	= $OrdersProduct->query()->where('order_id','=',$id)->update(['status'=>5]);
+            // 错误提醒
+            if (!$res)                  	{
+                // 回退数据
+                DB::rollBack();
+                // 返回结果
+                return json_send(['code'=>'error','msg'=>'退款失败']);
+            }
+            // 组合参数
+            $params['refund']           	=  $orderInfo['pay_total'];
+            $params['total']            	=  $orderInfo['pay_total'];
+            $params['reason']           	=  '用户退款';
+            $res                        	=  $Payment->refund($params);
+            if (!$res)                  	{
+                // 回退数据
+                DB::rollBack();
+                // 返回结果
+                return json_send(['code'=>'error','msg'=>'退款失败']);
+            }
+            // 记录行为
+            $this->addAdminHistory(admin('uid'),$Model->getTable(),$id,2,$orderInfo,['status'=>5]);
+            // 提交数据
+            DB::commit();
+            // 告知结果
+            return							json_send(['code'=>'success','msg'=>'退款成功','path'=>'']);
+        } catch (\Throwable $th) {
+            // 回退数据
+            DB::rollBack();
+            // 下单失败提示
+            return							json_send(['code'=>'error','msg'=>'退款失败','data'=>['error'=>$th->getMessage().$th->getLine()]]);
+        }
+    }
 }

+ 22 - 3
app/Http/Controllers/Api/Orders.php

@@ -1,6 +1,5 @@
 <?php namespace App\Http\Controllers\Api;
 
-use App\Http\Controllers\Api\Api;
 use App\Models\Orders as Model;
 use App\Models\Product;
 use App\Models\Product\Skus as ProductSkus;
@@ -20,6 +19,7 @@ use App\Models\ShopCart;
 use Illuminate\Support\Facades\DB;
 use App\Models\WeiBan\Tags as WeiBanTags;
 use App\Models\PromoProduct as PromoProduct;
+use Kra8\Snowflake\Snowflake;
 
 /**
  * 订单接口
@@ -97,6 +97,8 @@ class Orders extends Api{
 		$orderProduct					= [];
 		// 产品价格同级,用于优惠券计算
 		$productPrice					= [];
+        $Snowflake                      = new Snowflake();
+        $SnowflakeId                    = $Snowflake->next();
 		// 循环处理购买信息
 		foreach ($buyList as $buyInfo) 	{
 			// 如果产品不存在
@@ -232,6 +234,8 @@ class Orders extends Api{
         $promoList					    = $PromoProduct->getRebatePrice(array_column($buyList,'product_id'),$uid,$productPrice,$cityId,$tags);
         $promoProductPrice				= $promoList['product_price'];
         $promoRebateProduct				= $promoList['rebate_product'];
+        //订单支付总价
+        $orderPayTotal                  =   0;
 		// 组合订单数据
 		foreach ($orderProduct as $key => $order) {
 			// 判断哪一家的赠品
@@ -290,6 +294,7 @@ class Orders extends Api{
 			}
 			// 成交总价
 			$order['pay_total']			= $order['pay_total'] -  $order['coupon_total'];
+            $orderPayTotal              +=  $order['pay_total'];
 			// 赠送积分
 			$order['order_score']		= (config('order_score_send',0) && floor( $order['pay_total'] * 1 ) > 0 )  ? floor( $order['pay_total'] * 1 ) : 0;
 			// 成交总价
@@ -331,6 +336,7 @@ class Orders extends Api{
 				$productItem			= array_values($order['product_list']);
 				// 删除非必要数据
 				unset($order['product_list']);
+                $order['snowflake_id']  = $SnowflakeId;
 				// 创建总订单
 				$orderId				= $Model->add($order);
 				// 如果订单写入失败
@@ -381,8 +387,13 @@ class Orders extends Api{
 			$this->autoCoupon($uid);
 			// 提交数据
 			DB::commit();
+            $data = [
+                'order_id'      =>$orderId,
+                'pay_total'     =>$orderPayTotal,
+                'snowflake_id'  =>$SnowflakeId,
+            ];
 			// 返回结果
-			return						json_send(['code'=>'success','msg'=>'下单成功','data'=>['id'=>null]]);
+			return						json_send(['code'=>'success','msg'=>'下单成功','data'=>$data]);
 			// 返回结果
 		} catch (\Throwable $th) {
 			// 回退数据
@@ -646,6 +657,8 @@ class Orders extends Api{
         $regimentId					    = request('regiment_id',0);
         $regimentActiveId				= request('regiment_active_id',0);
         $btnType					    = request('btn_type',0);
+        $Snowflake                      = new Snowflake();
+        $SnowflakeId                    = $Snowflake->next();
         // 如果不存在数据
         if( !$addrId )					return json_send(['code'=>'error','msg'=>'请选择收货地址','data'=>['error'=>'请选择收货地址']]);
         // 解码购买信息
@@ -789,6 +802,7 @@ class Orders extends Api{
             'pay_total'		        => $payTotal,
             'price_total'		    => $priceTotal,
             'business_id'		    => $productList[$buyInfo['product_id']]['business_id'],
+            'snowflake_id'		    => $SnowflakeId,
         ];
         // 赠送积分
         $orderInfo['order_score']		= (config('order_score_send',0) && floor( $orderInfo['pay_total'] * 1 ) > 0 )  ? floor( $orderInfo['pay_total'] * 1 ) : 0;
@@ -926,8 +940,13 @@ class Orders extends Api{
             }
             // 提交数据
             DB::commit();
+            $data = [
+                'order_id'      =>$orderId,
+                'pay_total'     =>$orderInfo['pay_total'],
+                'snowflake_id'  =>$orderInfo['snowflake_id'],
+            ];
             // 返回结果
-            return						json_send(['code'=>'success','msg'=>'下单成功','data'=>['id'=>null]]);
+            return						json_send(['code'=>'success','msg'=>'下单成功','data'=>$data]);
             // 返回结果
         } catch (\Throwable $th) {
             // 回退数据

+ 338 - 0
app/Http/Controllers/Api/WechatPay.php

@@ -0,0 +1,338 @@
+<?php namespace App\Http\Controllers\Api;
+
+use App\Models\Custom;
+use App\Models\Orders;
+use App\Facades\Servers\Logs\Log;
+use App\Models\OrdersProduct;
+use App\Models\Regiment;
+use App\Models\RegimentActive;
+use App\Models\RegimentRecord;
+use App\Models\CustomScore;
+use EasyWeChat\Factory;
+use Illuminate\Http\Request;
+use App\Servers\WechatPay\Payment;
+use App\Facades\Servers\WechatMini\Mini;
+use Illuminate\Support\Facades\DB;
+use WeChatPay\Formatter;
+use WeChatPay\Crypto\AesGcm;
+use WeChatPay\Crypto\Rsa;
+
+/**
+ * 微信支付接口
+ *
+ * @author JUN
+ *
+ * */
+class WechatPay extends Api{
+    /**
+     * 小程序微信支付下单				/api/wechat_pay/pay
+     *
+     * */
+    public function pay(Custom $Custom)
+    {
+        // 检查登录
+        $uid				= $this->checkLogin();
+        $code				= request('code','');
+        $orderId			= request('order_id','');
+        $orderInfo          = Orders::query()->where('id','=',$orderId)->first()->toArray();
+        if (empty($orderInfo))
+            return		json_send(['code'=>'error','msg'=>'订单不存在','data'=>['id'=>null]]);
+        if ($orderInfo['custom_uid'] != $uid)
+            return		json_send(['code'=>'error','msg'=>'无权操作','data'=>['id'=>null]]);
+        if ($orderInfo['status'] != 1)
+            return		json_send(['code'=>'error','msg'=>'订单已支付或取消','data'=>['id'=>null]]);
+        //获取openid
+        $result			= Mini::jscode2session($code);
+        if (!$result['openid']) return json_send(['code'=>'error','msg'=>'获取openid失败','data'=>$result['error']]);
+        $openid = $result['openid'];
+        $description    =   '开邻智数-订单编号'.$orderInfo['snowflake_id'];
+        $payment = new Payment();
+        return $payment->pay(['out_trade_no' => $orderInfo['snowflake_id'],'openid' => $openid,'description' => $description,'total_price' => $orderInfo['pay_total']]);
+    }
+
+    /**
+     * 小程序微信支付回调				/api/wechat_pay/notify
+     *
+     * */
+    public function notify(Custom $Custom,CustomScore $CustomScore)
+    {
+        $content = file_get_contents("php://input");
+        if (!empty($content)) {
+            //直接json字符串
+            $params = $content;
+        } elseif (!empty($_POST)) {
+            //直接POST数据
+            $params = $_POST;
+        } else {
+            $params = [];
+        }
+        $post_data = $params;
+        Log::log('notify_wechat_pay', 'post_data:' . $post_data);
+        //获取headers参数
+        $headers = request()->header();
+        Log::log('notify_wechat_pay', '微信支付回调返回headers参数:' . json_encode($headers));
+
+        $inWechatpaySignature = $headers['wechatpay-signature'][0];
+        $inWechatpayTimestamp = $headers['wechatpay-timestamp'][0];
+        $inWechatpaySerial = $headers['wechatpay-serial'][0];
+        $inWechatpayNonce = $headers['wechatpay-nonce'][0];
+        $inBody = $post_data;
+        Log::log('notify_wechat_pay', 'wechatpay-timestamp:' . $inWechatpayTimestamp);
+        $apiv3Key = Config('wechatpay.APIV3');// 在商户平台上设置的APIv3密钥
+        // 根据通知的平台证书序列号,查询本地平台证书文件,
+        $platformCertificateFilePath = Config('wechatpay.platformCertificate');
+        $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
+        try {
+            // 检查通知时间偏移量,允许5分钟之内的偏移
+            $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
+            Log::log('notify_wechat_pay', '时间偏移量:' . $timeOffsetStatus);
+            $verifiedStatus = Rsa::verify(
+            // 构造验签名串
+                Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
+                $inWechatpaySignature,
+                $platformPublicKeyInstance
+            );
+        }catch (\Exception $e){
+            Log::log('notify_wechat_pay', '错误getMessage:' . $e->getMessage());
+        }
+        Log::log('notify_wechat_pay', '验签:' . $verifiedStatus.'验签inWechatpayTimestamp:' . $inWechatpayTimestamp.'验签verifiedStatus:' . $inWechatpayNonce.'验签timeOffsetStatus:' . $timeOffsetStatus);
+        if ($timeOffsetStatus && $verifiedStatus) {
+            // 转换通知的JSON文本消息为PHP Array数组
+            $inBodyArray = (array)json_decode($inBody, true);
+            // 使用PHP7的数据解构语法,从Array中解构并赋值变量
+            ['resource' => [
+                'ciphertext' => $ciphertext,
+                'nonce' => $nonce,
+                'associated_data' => $aad
+            ]] = $inBodyArray;
+            // 加密文本消息解密
+            $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
+            // 把解密后的文本转换为PHP Array数组
+            $inBodyResourceArray = (array)json_decode($inBodyResource, true);
+            Log::log('notify_wechat_pay', '打印解密后的结果:' . json_encode($inBodyResourceArray));
+            Log::log('notify_wechat_pay', '参数:' . $inBodyResourceArray['trade_state'] . '订单号' . $inBodyResourceArray['out_trade_no'] . '微信支付号' . $inBodyResourceArray['transaction_id']);
+            if ($inBodyResourceArray['trade_state'] == "SUCCESS") {
+                Log::log('notify_wechat_pay', '通知订单');
+                $orderInfo   = Orders::query()->where('snowflake_id','=',$inBodyResourceArray['out_trade_no'])->first()->toArray();
+                $status      =  2;
+                if ($orderInfo['regiment_id'] > 0){
+                    $status     =   10;
+                }
+                //更新订单支付状态
+                $orderData = [
+                    'pay_time' => time(),
+                    'transaction_id'=>$inBodyResourceArray['transaction_id'],
+                    'status'=>$status,
+                ];
+                // 组合数据,写入订单表,子表
+                DB::beginTransaction();
+                try {
+                    $res = Orders::query()->where('snowflake_id','=',$inBodyResourceArray['out_trade_no'])->update($orderData);
+                    Log::log('notify_wechat_pay', '更新订单,snowflake_id:'.$inBodyResourceArray['out_trade_no'].';'. json_encode($res));
+                    if (!$res) {
+                        // 回退数据
+                        DB::rollBack();
+                        Log::log('notify_wechat_pay', '更新订单失败' . json_encode($res));
+                        return json_send(['code'=>'FAIL']);
+                    }
+                    //更新子订单
+                    $res         =  OrdersProduct::query()->where('order_id','=',$orderInfo['id'])->update(['status'=>$status]);
+                    Log::log('notify_wechat_pay', '更新子订单,order_id:'.$orderInfo['id'].';'. json_encode($res));
+                    if (!$res) {
+                        Log::log('notify_wechat_pay', '更新子订单失败:'.$orderInfo['id'].':'.$status . json_encode($res));
+                        // 回退数据
+                        DB::rollBack();
+                        return json_send(['code'=>'FAIL']);
+                    }
+                    //更新团信息
+                    if ($orderInfo['regiment_id']){
+                        //查询团信息
+                        $regimentInfo           =   Regiment::query()->where('id','=',$orderInfo['regiment_id'])->first()->toArray();
+                        if (!$regimentInfo) {
+                            Log::log('notify_wechat_pay', '查询团信息失败' . json_encode($regimentInfo));
+                            // 回退数据
+                            DB::rollBack();
+                            return json_send(['code'=>'FAIL']);
+                        }
+                        //查询团活动
+                        $regimentActiveInfo     =   RegimentActive::query()->where('id','=',$regimentInfo['active_id'])->first();
+                        if (!$regimentActiveInfo) {
+                            Log::log('notify_wechat_pay', '查询团活动失败' . json_encode($regimentInfo));
+                            // 回退数据
+                            DB::rollBack();
+                            return json_send(['code'=>'FAIL']);
+                        }
+                        //查询团记录
+                        $regimentRecordInfo     =   RegimentRecord::query()->where('order_id','=',$orderInfo['id'])->first();
+                        if (!$regimentRecordInfo) {
+                            Log::log('notify_wechat_pay', '查询团记录失败' . json_encode($regimentInfo));
+                            // 回退数据
+                            DB::rollBack();
+                            return json_send(['code'=>'FAIL']);
+                        }
+                        $regimentId     =   $orderInfo['regiment_id'];
+                        // 拼团人数加1
+                        $inc				=   Regiment::query()->where('id','=',$regimentId)->increment('people_number',1);
+                        Log::log('notify_wechat_pay', '拼团人数加1,regiment_id:'.$regimentId.';'. json_encode($inc));
+                        if( !$inc )			{
+                            Log::log('notify_wechat_pay', '更新团人数加1失败' . json_encode($regimentInfo));
+                            // 回退数据
+                            DB::rollBack();
+                            return json_send(['code'=>'FAIL']);
+                        }
+                        //团满
+                        if ((($regimentInfo['people_number'] + 1) == $regimentActiveInfo['number']) && $regimentActiveInfo['exceed_people'] == 1) {
+                            $res            =   regiment::query()->where('id','=',$regimentId)->update(['status'=>3]);
+                            Log::log('notify_wechat_pay', '图满 团状态,regiment_id:'.$regimentId.';'. json_encode($res));
+                            if( !$res )			{
+                                Log::log('notify_wechat_pay', '更新团订单失败1' . json_encode($regimentInfo));
+                                // 回退数据
+                                DB::rollBack();
+                                return json_send(['code'=>'FAIL']);
+                            }
+                            //修改团记录状态
+                            $res            =   RegimentRecord::query()->where('order_id','=',$orderInfo['id'])->update(['status'=>3]);
+                            if( !$res )			{
+                                Log::log('notify_wechat_pay', '更新团记录状态失败' . json_encode($regimentInfo));
+                                // 回退数据
+                                DB::rollBack();
+                                return json_send(['code'=>'FAIL']);
+                            }
+                            //修改订单
+                            $orderRes       =   Orders::query()->where('regiment_id','=',$regimentId)->update(['status'=>'2']);
+                            if( !$orderRes )			{
+                                Log::log('notify_wechat_pay', '更新订单失败' . json_encode($regimentInfo));
+                                // 回退数据
+                                DB::rollBack();
+                                return json_send(['code'=>'FAIL']);
+                            }
+                            //赠送积分
+                            $orderList      =   Orders::query()->where('regiment_id','=',$regimentId)->get();
+                            foreach ($orderList as $key => $value) {
+                                if( $value['order_score'] > 0 ) $CustomScore->trade($orderInfo['custom_uid'],$value['id'],$value['order_score'],5,1);
+                            }
+                        }
+                    }
+                    // 提交数据
+                    DB::commit();
+                }catch (\Exception $e){
+                    Log::log('notify_wechat_pay', '更新订单失败' . json_encode($e));
+                    return json_send(['code'=>'FAIL']);
+                }
+                $orderInfo   = Orders::query()->where('snowflake_id','=',$inBodyResourceArray['out_trade_no'])->first()->toArray();
+                Log::log('notify_wechat_pay', '支付回调完成 通知返回' . json_encode($orderInfo));
+                return json_send(['code'=>'SUCCESS']);
+
+            }
+            return json_send(['code'=>'SUCCESS']);
+        }else{
+            return json_send(['code'=>'FAIL']);
+        }
+    }
+
+    /**
+     * 小程序微信支付 退款回调				/api/wechat_pay/refund_notify
+     *
+     * */
+    public function refund_notify(Custom $Custom,CustomScore $CustomScore)
+    {
+        $content = file_get_contents("php://input");
+        if (!empty($content)) {
+            //直接json字符串
+            $params = $content;
+        } elseif (!empty($_POST)) {
+            //直接POST数据
+            $params = $_POST;
+        } else {
+            $params = [];
+        }
+        $post_data = $params;
+        Log::log('notify_refund_wechat_pay', 'post_data:' . $post_data);
+        //获取headers参数
+        $headers = request()->header();
+        Log::log('notify_refund_wechat_pay', '微信支付回调返回headers参数:' . json_encode($headers));
+
+        $inWechatpaySignature = $headers['wechatpay-signature'][0];
+        $inWechatpayTimestamp = $headers['wechatpay-timestamp'][0];
+        $inWechatpaySerial = $headers['wechatpay-serial'][0];
+        $inWechatpayNonce = $headers['wechatpay-nonce'][0];
+        $inBody = $post_data;
+        Log::log('notify_refund_wechat_pay', 'wechatpay-timestamp:' . $inWechatpayTimestamp);
+        $apiv3Key = Config('wechatpay.APIV3');// 在商户平台上设置的APIv3密钥
+        // 根据通知的平台证书序列号,查询本地平台证书文件,
+        $platformCertificateFilePath = Config('wechatpay.platformCertificate');
+        $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
+        try {
+            // 检查通知时间偏移量,允许5分钟之内的偏移
+            $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
+            Log::log('notify_wechat_pay', '时间偏移量:' . $timeOffsetStatus);
+            $verifiedStatus = Rsa::verify(
+            // 构造验签名串
+                Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
+                $inWechatpaySignature,
+                $platformPublicKeyInstance
+            );
+        }catch (\Exception $e){
+            Log::log('notify_refund_wechat_pay', '错误getMessage:' . $e->getMessage());
+        }
+        Log::log('notify_refund_wechat_pay', '验签:' . $verifiedStatus.'验签inWechatpayTimestamp:' . $inWechatpayTimestamp.'验签verifiedStatus:' . $inWechatpayNonce.'验签timeOffsetStatus:' . $timeOffsetStatus);
+        if ($timeOffsetStatus && $verifiedStatus) {
+            // 转换通知的JSON文本消息为PHP Array数组
+            $inBodyArray = (array)json_decode($inBody, true);
+            // 使用PHP7的数据解构语法,从Array中解构并赋值变量
+            ['resource' => [
+                'ciphertext' => $ciphertext,
+                'nonce' => $nonce,
+                'associated_data' => $aad
+            ]] = $inBodyArray;
+            // 加密文本消息解密
+            $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
+            // 把解密后的文本转换为PHP Array数组
+            $inBodyResourceArray = (array)json_decode($inBodyResource, true);
+            Log::log('notify_refund_wechat_pay', '打印解密后的结果:' . json_encode($inBodyResourceArray));
+            Log::log('notify_refund_wechat_pay', '参数:' . $inBodyResourceArray['refund_status'] . '订单号' . $inBodyResourceArray['out_trade_no'] . '微信支付号' . $inBodyResourceArray['transaction_id']);
+            if ($inBodyResourceArray['refund_status'] == "SUCCESS") {
+                Log::log('notify_refund_wechat_pay', '通知订单');
+                $orderInfo   = Orders::query()->where('snowflake_id','=',$inBodyResourceArray['out_trade_no'])->first()->toArray();
+                $status      =  6;
+                //更新订单支付状态
+                $orderData = [
+                    'status'=>$status,
+                ];
+                // 组合数据,写入订单表,子表
+                DB::beginTransaction();
+                try {
+                    $res = Orders::query()->where('snowflake_id','=',$inBodyResourceArray['out_trade_no'])->update($orderData);
+                    Log::log('notify_refund_wechat_pay', '更新订单,snowflake_id:'.$inBodyResourceArray['out_trade_no'].';'. json_encode($res));
+                    if (!$res) {
+                        // 回退数据
+                        DB::rollBack();
+                        Log::log('notify_refund_wechat_pay', '更新订单失败' . json_encode($res));
+                        return json_send(['code'=>'FAIL']);
+                    }
+                    //更新子订单
+                    $res         =  OrdersProduct::query()->where('order_id','=',$orderInfo['id'])->update(['status'=>$status]);
+                    Log::log('notify_refund_wechat_pay', '更新子订单,order_id:'.$orderInfo['id'].';'. json_encode($res));
+                    if (!$res) {
+                        Log::log('notify_refund_wechat_pay', '更新子订单失败:'.$orderInfo['id'].':'.$status . json_encode($res));
+                        // 回退数据
+                        DB::rollBack();
+                        return json_send(['code'=>'FAIL']);
+                    }
+                    // 提交数据
+                    DB::commit();
+                }catch (\Exception $e){
+                    Log::log('notify_refund_wechat_pay', '更新订单失败' . json_encode($e));
+                    return json_send(['code'=>'FAIL']);
+                }
+                $orderInfo   = Orders::query()->where('snowflake_id','=',$inBodyResourceArray['out_trade_no'])->first()->toArray();
+                Log::log('notify_refund_wechat_pay', '支付回调完成 通知返回' . json_encode($orderInfo));
+                return json_send(['code'=>'SUCCESS']);
+
+            }
+            return json_send(['code'=>'SUCCESS']);
+        }else{
+            return json_send(['code'=>'FAIL']);
+        }
+    }
+}

+ 2 - 1
app/Http/Requests/Admin/Orders.php

@@ -32,7 +32,8 @@ class Orders extends BaseRequest
         'edit'                  => ['id','product_code'],
         'set_status'            => ['id','status'],
         'import_execl'          => ['order_file'],
-        'import_execl_status'   => ['order_file']
+        'import_execl_status'   => ['order_file'],
+        'refund'                => ['id']
 	];
 
     /**

+ 1 - 1
app/Models/Traits/Orders/Status.php

@@ -18,7 +18,7 @@ trait Status
                                     ],'1'=>[
                                         'id'            =>1,
                                         'name'          =>'创建订单',// 未付款,系统报单不走支付流程的状态
-                                        'state'         =>'进行中', 
+                                        'state'         =>'待付款',
                                     ],'2'=>[
                                         'id'            =>2,
                                         'name'          =>'已付款未发货',// 已付款未发货

+ 9 - 8
app/Servers/WechatPay/Payment.php

@@ -125,29 +125,30 @@ class Payment
      */
     public function refund($params)
     {
-        $notify_url = Config('wechat.course_refund_notify_url');
+        $notify_url = config('wechatpay.refund_notify_url');
         try {
             $resp = $this->instance
                 ->chain('v3/refund/domestic/refunds')
                 ->post(['json' => [
-                    'transaction_id'  => $params['transaction_id'],
+                    'out_trade_no'      => $params['out_trade_no'],
                     'out_refund_no'   => $params['out_refund_no'],
-                    'reason'          => $params['reason'] ?? '',
+                    'reason'          => $params['reason'] ?? '用户退款',
                     'notify_url'      => $notify_url,
                     'amount'          => [
-                        'refund'      => $params['refund'],
-                        'total'       => $params['total'],
+                        'refund'      => $params['refund'] * 100,
+                        'total'       => $params['total'] * 100,
                         'currency'    => 'CNY'
                     ],
                 ]]);
+            $result = json_decode($resp->getBody(),true);
         } catch (\Exception $e) {
             if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
                 $r = $e->getResponse();
-                Log::error('wechat/Payment','订单微信退款,出现错误'.$r->getBody());
+                Log::error('wechat/payment_refund','订单微信退款,出现错误'.$r->getBody());
             }
-            return response()->json(['error' => '订单微信退款失败'], 500);
+            return false;
         }
-        return response()->json($resp);
+        return true;
     }
     //Rfc3339时间日期格式
     public function timestampToRfc3339($timestamp)

+ 1 - 1
app/Servers/WechatPay/Transfer.php

@@ -77,7 +77,7 @@ class Transfer
                             'info_content'      => '预约下单得现金红包',
                         ],
                     ],
-                    'notify_url'   => Config('wechatpay.notify_url')
+                    'notify_url'   => Config('wechatpay.transfer_notify_url')
                     /*'time_expire'  => $this->timestampToRfc3339(time() + env('ORDER_OUT_TIME')*60),*/
                 ]]);
             $result = json_decode($resp->getBody(),true);

+ 3 - 1
config/wechatpay.php

@@ -4,7 +4,9 @@ return array(
     'mchid'                 => "1612111355",//微信直连商户号mchid
     'certificate'           => '68E43B250D73977F1DC0E0D0827AF25A8BFB1777', //证书序列号
     'APIV3'                 => 'iD1xB1mH6zO7pP2wD1rU4aD2nH7oL2lN',
-    'notify_url'            => 'https://kailin.dfwy.tech/api/wechat_transfer/notify',
+    'transfer_notify_url'   => env('APP_URL').'/api/wechat_transfer/notify',
+    'pay_notify_url'        => env('APP_URL').'/api/wechat_pay/notify',
+    'refund_notify_url'     => env('APP_URL').'/api/wechat_pay/refund_notify',
     'private_key'           => '-----BEGIN PRIVATE KEY-----
 MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBcmSf2j2gN8Ie
 +vx0GxqFDzxetgJX+sCju9wyxSiPiFGqNRp1dXyzmb0WMDZ4EHSuwhgMp9xdY6BE

+ 5 - 0
resources/views/admin/orders/index.blade.php

@@ -137,6 +137,11 @@ style="margin: 0 auto;width: 96%;padding: 30px 0px;"
 								取消
 							</a>
 							@endif
+							@if( $a['status'] == 2 && check_auth('admin/orders/refund') )
+								<a class="delete btn btn-sm btn-danger " data-url="{{url('admin/orders/refund?'.http_build_query(['id'=>$a['order_id']]))}}" title="退款">
+									退款
+								</a>
+							@endif
 						</td>
 					</tr>
 					@endforeach

+ 8 - 1
routes/api.php

@@ -363,4 +363,11 @@ Route::any('learn_report_share_image/get_after', [App\Http\Controllers\Api\Video
  * 获取学习后的报告图片
  */
 Route::any('exam_report_share_image/get', [App\Http\Controllers\Api\Video\ExamReportShareImage::class, 'get_share_image']);
-Route::any('exam_report_share_image/get_after', [App\Http\Controllers\Api\Video\ExamReportShareImage::class, 'get_after_study_report_image_share']);
+Route::any('exam_report_share_image/get_after', [App\Http\Controllers\Api\Video\ExamReportShareImage::class, 'get_after_study_report_image_share']);
+
+// 微信支付
+Route::any('wechat_pay/pay',[\App\Http\Controllers\Api\WechatPay::class,'pay']);
+// 微信支付回调
+Route::any('wechat_pay/notify',[\App\Http\Controllers\Api\WechatPay::class,'notify']);
+// 微信支付  退款回调
+Route::any('wechat_pay/refund_notify',[\App\Http\Controllers\Api\WechatPay::class,'refund_notify']);

+ 2 - 0
routes/web.php

@@ -185,6 +185,8 @@ Route::middleware('admin')->prefix('admin')->group(function(){
     Route::any('orders/down_excel',[App\Http\Controllers\Admin\Orders::class,'down_excel']);
     // 订单批量更新状态
     Route::any('orders/import_execl_status',[App\Http\Controllers\Admin\Orders::class,'import_execl_status']);
+    // 退款
+    Route::any('orders/refund',[App\Http\Controllers\Admin\Orders::class,'refund']);
 
     /* 订单物流-发货 */
     // 列表