diff --git a/app/Constants/LogLabel.php b/app/Constants/LogLabel.php index 072a6f7..8807da4 100644 --- a/app/Constants/LogLabel.php +++ b/app/Constants/LogLabel.php @@ -54,4 +54,9 @@ class LogLabel extends AbstractConstants */ const OFFLINE_PAID_LOG = 'offline_paid_log'; + /** + * @Message("Pay refund Log Label") + */ + const PAY_NOTIFY_REFUND = 'notify_refund'; + } diff --git a/app/Controller/NotifyPayRefundController.php b/app/Controller/NotifyPayRefundController.php new file mode 100644 index 0000000..1f1cb76 --- /dev/null +++ b/app/Controller/NotifyPayRefundController.php @@ -0,0 +1,107 @@ +request->getQueryParams(); + $post = $this->request->getParsedBody(); + $cookie = $this->request->getCookieParams(); + $files = $this->request->getUploadedFiles(); + $server = $this->request->getServerParams(); + $xml = $this->request->getBody()->getContents(); + + $app['request'] = new Request($get,$post,[],$cookie,$files,$server,$xml); + + /* 通知回调,进行业务处理 */ + $response = $app->handleRefundedNotify(function ($message, $fail) use ($app) { + + try { + /* --- 退款失败 --- */ + if ( + empty($message) + || !isset($message['result_code']) + || $message['result_code'] != 'SUCCESS' + ) { + // 错误日志 + $this->log->event( + LogLabel::PAY_NOTIFY_REFUND, + $message + ); + $fail('Unknown error but FAIL'); + } + + /* --- 退款成功 --- */ + // 退款返还优惠券 + $this->couponService->orderRefundCoupon($message['out_trade_no']); + // 添加用户的流水 + $orderMain = OrderMain::select('id','global_order_id')->where('code',$message['out_trade_no'])->first(); + + + } catch (Exception $e) { + + $this->log->event( + LogLabel::PAY_NOTIFY_REFUND, + ['exception_fail' => $e->getMessage()] + ); + $fail('Exception'); + } + }); + + return $this->response + ->withHeader('Content-Type', 'text/xml') + ->withStatus(200) + ->withBody(new SwooleStream($response->getContent())); + } +} \ No newline at end of file diff --git a/app/Model/CouponRec.php b/app/Model/CouponRec.php index 9e6e3e4..3a9cc62 100644 --- a/app/Model/CouponRec.php +++ b/app/Model/CouponRec.php @@ -6,8 +6,15 @@ use App\Model\Model; class CouponRec extends Model { - protected $table = 'ims_system_coupon_user_receive'; + /* 状态 */ + // 未使用 + const STATE_UNUSED = 0; + // 使用部分 + const STATE_SOME = 1; + // 已用完 + const STATE_FINISH = 2; + protected $table = 'ims_system_coupon_user_receive'; public function coupon() { diff --git a/app/Model/CouponUserRec.php b/app/Model/CouponUserRec.php deleted file mode 100644 index 25afd2f..0000000 --- a/app/Model/CouponUserRec.php +++ /dev/null @@ -1,18 +0,0 @@ -select('id','system_coupon_id','user_id','number','user_receive_id') + ->where('global_order_id',$global_order_id) + ->where('status',CouponUserUse::COUPON_USE_STATE_USED) + ->select(); + if(!empty($couponUse)){ + foreach($couponUses as $use){ + $use->status = CouponUserUse::COUPON_USE_STATE_USED; + $use->return_time = $time; + $use->update_time = $time; + $res = $use->save(); + + $couponReceive = CouponRec::query() + ->where('id',$use->user_receive_id) + ->whereRaw('number >= number_remain+'.$use->number) + ->update([ + 'number_remain' => Db::raw('number_remain+'.$use->number), + 'status' => Db::raw('IF(number=number_remain,' . CouponRec::STATE_UNUSED . ',' . CouponRec::STATE_SOME . ')'), + 'update_time' => $time + ]); + + $clearUseRedis = $this->clearTodayCouponUsed($use->user_id,$use->system_coupon_id); + } + } + + Db::commit(); + return true; + } catch (Exception $e) { + + $this->log->event(LogLabel::ORDER_LOG, ['msg'=> '订单退款','exception' => $e->getMessage()]); + Db::rollBack(); + return false; + } + return true; } } \ No newline at end of file diff --git a/app/Service/CouponServiceInterface.php b/app/Service/CouponServiceInterface.php index e4155d7..e3224f4 100644 --- a/app/Service/CouponServiceInterface.php +++ b/app/Service/CouponServiceInterface.php @@ -29,4 +29,5 @@ interface CouponServiceInterface public function refundOrderCoupons($order_id,$user_id); public function clearTodayCouponUsed($userId, $couponId); + public function orderRefundCoupon($global_order_id); } diff --git a/app/Service/OrderService.php b/app/Service/OrderService.php index 8d76e7c..99c7311 100644 --- a/app/Service/OrderService.php +++ b/app/Service/OrderService.php @@ -5,7 +5,7 @@ namespace App\Service; use App\Commons\Log; use App\Constants\LogLabel; use App\Model\Coupon; -use App\Model\CouponUserRec; +use App\Model\CouponRec; use App\Model\CouponUserUse; use App\Model\Goods; use App\Model\Order; @@ -19,6 +19,7 @@ use Hyperf\DbConnection\Db; use Hyperf\Snowflake\IdGeneratorInterface; use Hyperf\Utils\ApplicationContext; use Hyperf\Di\Annotation\Inject; +use App\Service\WxRefundServiceInterface; class OrderService implements OrderServiceInterface { @@ -34,6 +35,12 @@ class OrderService implements OrderServiceInterface */ protected $couponService; + /** + * @Inject + * @var WxRefundServiceInterface + */ + protected $wxRefundService; + /** * @inheritDoc */ @@ -280,7 +287,7 @@ class OrderService implements OrderServiceInterface } // 处理红包的使用 - $canUseCoupons = CouponUserRec::select(['id', 'user_id', 'number', 'number_remain', 'system_coupon_user_id']) + $canUseCoupons = CouponRec::select(['id', 'user_id', 'number', 'number_remain', 'system_coupon_user_id']) ->whereIn('id', $receiveCouponIds) ->get()->toArray(); if (is_array($canUseCoupons)&&!empty($canUseCoupons)) { @@ -312,7 +319,7 @@ class OrderService implements OrderServiceInterface $status = 0; } - $upRes = CouponUserRec::query()->where(['id' => $coupon['id']])->update(['number_remain' => $numberRemain, 'status' => $status]); + $upRes = CouponRec::query()->where(['id' => $coupon['id']])->update(['number_remain' => $numberRemain, 'status' => $status]); if (!$upRes) { Db::rollBack(); @@ -716,14 +723,16 @@ class OrderService implements OrderServiceInterface /** * @inheritDoc */ - public function onlineRefund($global_order_id){ + public function onlineRefund($global_order_id) + { Db::beginTransaction(); try { $time = time(); // 主订单状态更新 $orderMain = OrderMain::query() - ->where(['global_order_id' => $global_order_id, 'state' => OrderMain::ORDER_STATE_DELIVERY]) + ->select('id','global_order_id','state','pay_type') + ->where(['global_order_id' => $global_order_id, 'state' => OrderMain::ORDER_STATE_REFUNDING]) ->first(); if (empty($orderMain)) { @@ -736,40 +745,26 @@ class OrderService implements OrderServiceInterface // 子订单状态更新 $upChild = Order::query() - ->where(['order_main_id' => $orderMain->id]) + ->where('order_main_id' , $orderMain->id) + ->where('state',OrderMain::ORDER_STATE_REFUNDING) ->update(['state' => OrderMain::ORDER_STATE_REFUNDED]); - - /* 退还优惠券 */ - // 先查询是否正常使用优惠券 - // 修改状态,退还领取记录库存,删除ssdb缓存 - $couponUses = CouponUserUse::query() - ->select('id','system_coupon_id','user_id','number','user_receive_id') - ->where('order_main_id',$orderMain->id) - ->where('status',CouponUserUse::COUPON_USE_STATE_USED) - ->select(); - if(!empty($couponUse)){ - foreach($couponUses as $use){ - $use->status = CouponUserUse::COUPON_USE_STATE_USED; - $use->return_time = $time; - $use->update_time = $time; - $use->save(); - - $couponReceive = CouponUserRec::query() - ->where('id',$use->user_receive_id) - ->whereRaw('number >= number_remain+'.$use->number) - ->update([ - 'number_remain' => Db::raw('number_remain+'.$use->number), - 'status' => Db::raw('IF(number=number_remain,' . CouponUserRec::STATE_UNUSED . ',' . CouponUserRec::STATE_SOME . ')'), - 'update_time' => $time - ]); - - $clearUseRedis = $this->couponService->clearTodayCouponUsed($use->user_id,$use->system_coupon_id); - } + if(empty($upChild)){ + Db::rollBack(); + return false; } - // 退还订单金额到用户微信余额 + if($orderMain->pay_type == OrderMain::ORDER_PAY_WX){ + // 微信支付 微信退款 + $refundRes = $this->wxRefundService->wxPayRefund($global_order_id); + }else if($orderMain->pay_type == OrderMain::ORDER_PAY_BALANCE){ + // 余额支付 退款到用户余额 + // 返还优惠券 + $this->couponService->orderRefundCoupon($global_order_id); + // 添加用户流水 + } + Db::commit(); return true; } catch (Exception $e) { @@ -780,4 +775,47 @@ class OrderService implements OrderServiceInterface } } + /** + * 订单退款失败 + * 回退订单状态 + */ + public function onlineRefundFail($global_order_id) + { + Db::beginTransaction(); + try { + + $time = time(); + // 主订单状态更新 + $orderMain = OrderMain::query() + ->select('id','global_order_id','state','pay_type') + ->where(['global_order_id' => $global_order_id, 'state' => OrderMain::ORDER_STATE_REFUNDED]) + ->first(); + + if (empty($orderMain)) { + Db::rollBack(); + return false; + } + + $orderMain->state = OrderMain::ORDER_STATE_REFUNDING; + $upOrderMain = $orderMain->save(); + + // 子订单状态更新 + $upChild = Order::query() + ->where('order_main_id' , $orderMain->id) + ->where('state',OrderMain::ORDER_STATE_REFUNDED) + ->update(['state' => OrderMain::ORDER_STATE_REFUNDING]); + if(empty($upChild)){ + Db::rollBack(); + return false; + } + + Db::commit(); + return true; + } catch (Exception $e) { + + $this->log->event(LogLabel::ORDER_LOG, ['msg'=> '订单退款失败时处理状态9->8','exception' => $e->getMessage()]); + Db::rollBack(); + return false; + } + } } \ No newline at end of file diff --git a/app/Service/PayRefundService.php b/app/Service/WxRefundService.php similarity index 64% rename from app/Service/PayRefundService.php rename to app/Service/WxRefundService.php index 27bd0d4..b7e5c40 100644 --- a/app/Service/PayRefundService.php +++ b/app/Service/WxRefundService.php @@ -7,7 +7,7 @@ use EasyWeChat\Factory; use Hyperf\DbConnection\Db; use App\Constants\ErrorCode; -class PayRefundService implements PayRefundServiceInterface +class WxRefundService implements WxRefundServiceInterface { /** * 微信支付退款 @@ -18,29 +18,24 @@ class PayRefundService implements PayRefundServiceInterface $app = Factory::payment($config); $app['guzzle_handler'] = CoroutineHandler::class; - $result = [ - 'status' => 0, - 'msg' => '退款成功' - ]; - // 查询订单 $orderMain = OrderMain::query() - ->select('id','code','order_num','money','state') + ->select('id','global_order_id','order_num','money','state') ->where('global_order_id',$global_order_id) ->where('pay_type',OrderMain::ORDER_PAY_WX) ->where(Db::raw('refund_time is null')) ->first(); if(empty($orderMain)){ - return ['status'=>1, 'msg'=>'订单不存在或已退款']; + return false; } - $optional = []; + ; $result = $app->refund->byOutTradeNumber( - $orderMain->code, - $orderMain->code, - $orderMain->money * 100, + $orderMain->global_order_id, + $orderMain->global_order_id, $orderMain->money * 100, - $optional + $orderMain->money * 100 ); + return $result; } diff --git a/app/Service/PayRefundServiceInterface.php b/app/Service/WxRefundServiceInterface.php similarity index 68% rename from app/Service/PayRefundServiceInterface.php rename to app/Service/WxRefundServiceInterface.php index 7ca1de1..096c055 100644 --- a/app/Service/PayRefundServiceInterface.php +++ b/app/Service/WxRefundServiceInterface.php @@ -2,7 +2,7 @@ namespace App\Service; -interface PayRefundServiceInterface +interface WxRefundServiceInterface { public function wxPayRefund($global_order_id); } \ No newline at end of file