From 1bc12ba559983c14a1d10eebf0636489c7769559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=9D=99?= Date: Mon, 20 Dec 2021 18:13:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E6=94=AF=E4=BB=98=E9=80=80?= =?UTF-8?q?=E6=AC=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Console/Commands/OrderRefundCommand.php | 26 ++++-- .../Http/Controllers/WeChatPayController.php | 62 +++++++------- app/Endpoint/Callback/routes.php | 3 +- app/Models/OrderRefundTask.php | 6 +- app/Services/OrderService.php | 81 +++++++++---------- app/Services/WeChatPayService.php | 11 +++ 6 files changed, 111 insertions(+), 78 deletions(-) diff --git a/app/Console/Commands/OrderRefundCommand.php b/app/Console/Commands/OrderRefundCommand.php index b99ba2bd..15111060 100644 --- a/app/Console/Commands/OrderRefundCommand.php +++ b/app/Console/Commands/OrderRefundCommand.php @@ -42,11 +42,6 @@ class OrderRefundCommand extends Command } $this->{$method}($task); - - $task->update([ - 'status' => OrderRefundTask::STATUS_SUCCESS, - 'failed_reason' => null, - ]); } catch (Throwable $e) { report($e); @@ -62,7 +57,7 @@ class OrderRefundCommand extends Command } /** - * 微信退款 + * 微信支付退款 * * @param \App\Models\OrderRefundTask $orderRefundTask * @return void @@ -78,7 +73,26 @@ class OrderRefundCommand extends Command $orderRefundTask->amount, [ 'refund_desc' => $orderRefundTask->reason, + 'notify_url' => url(route('wxpay.order_refund_notify', [], false), [], true), ] ); + + $orderRefundTask->update([ + 'status' => OrderRefundTask::STATUS_SUCCESS, + 'failed_reason' => null, + ]); + } + + /** + * 现金支付退款 + * + * @param \App\Models\OrderRefundTask $orderRefundTask + * @return void + */ + protected function refundByOffline(OrderRefundTask $orderRefundTask) + { + $orderRefundTask->update([ + 'status' => OrderRefundTask::STATUS_SUCCESS, + ]); } } diff --git a/app/Endpoint/Callback/Http/Controllers/WeChatPayController.php b/app/Endpoint/Callback/Http/Controllers/WeChatPayController.php index 9e39addd..c903169b 100644 --- a/app/Endpoint/Callback/Http/Controllers/WeChatPayController.php +++ b/app/Endpoint/Callback/Http/Controllers/WeChatPayController.php @@ -4,6 +4,7 @@ namespace App\Endpoint\Callback\Http\Controllers; use App\Exceptions\BizException; use App\Models\Order; +use App\Models\OrderRefundTask; use App\Services\OrderService; use App\Services\WeChatPayService; use Illuminate\Database\Eloquent\ModelNotFoundException; @@ -14,12 +15,12 @@ use Throwable; class WeChatPayController extends Controller { /** - * 支付结果通知 + * 订单支付结果通知 * * @param \App\Services\WeChatPayService $weChatPayService * @return \Illuminate\Http\Response */ - public function paidNotify(WeChatPayService $weChatPayService) + public function orderPaidNotify(WeChatPayService $weChatPayService) { return $weChatPayService->handlePaidNotify(function ($message, $fail) { // 通信失败 @@ -32,16 +33,17 @@ class WeChatPayController extends Controller return true; } - $attach = json_decode($message['attach'], true); - - if (! isset($attach['pay_target'])) { - return true; - } - - switch ($attach['pay_target']) { - case 'order': - $this->handlePaidNotifyForOrder($message); - break; + try { + DB::transaction(function () use ($message) { + (new OrderService())->paySuccess($message['out_trade_no'], [ + 'pay_sn' => $message['transaction_id'], + 'pay_way' => Order::PAY_WAY_WXPAY, + 'pay_at' => Carbon::parse($message['time_end']), + ]); + }); + } catch (ModelNotFoundException | BizException $e) { + } catch (Throwable $e) { + throw $e; } return true; @@ -49,24 +51,30 @@ class WeChatPayController extends Controller } /** - * 处理订单支付结果通知 + * 订单退款结果通知 * - * @param array $message - * @return void + * @param \App\Services\WeChatPayService $weChatPayService + * @return \Illuminate\Http\Response */ - protected function handlePaidNotifyForOrder(array $message): void + public function orderRefundedNotify(WeChatPayService $weChatPayService) { - try { - DB::transaction(function () use ($message) { - (new OrderService())->paySuccess($message['out_trade_no'], [ - 'pay_sn' => $message['transaction_id'], - 'pay_way' => Order::PAY_WAY_WXPAY, - 'pay_at' => Carbon::parse($message['time_end']), + return $weChatPayService->handleRefundedNotify(function ($message, $reqInfo, $fail) { + // 通信失败 + if (data_get($message, 'return_code') !== 'SUCCESS') { + return $fail('通信失败'); + } + + // 退款失败 + if ($reqInfo['refund_status'] !== 'SUCCESS') { + $orderRefundTask = OrderRefundTask::where('sn', $reqInfo['out_refund_no'])->first(); + + $orderRefundTask?->update([ + 'status' => OrderRefundTask::STATUS_FAILED, + 'failed_reason' => $reqInfo['refund_status'] === 'CHANGE' ? '退款异常' : '退款关闭', ]); - }); - } catch (ModelNotFoundException|BizException $e) { - } catch (Throwable $e) { - throw $e; - } + } + + return true; + }); } } diff --git a/app/Endpoint/Callback/routes.php b/app/Endpoint/Callback/routes.php index 2fef46bf..d9207f14 100644 --- a/app/Endpoint/Callback/routes.php +++ b/app/Endpoint/Callback/routes.php @@ -7,4 +7,5 @@ use Illuminate\Support\Facades\Route; //快递100物流推送 Route::post('kuaidi100', [Kuaidi100Controller::class, 'notify']); // 微信支付通知 -Route::post('wxpay/paid-notify', [WeChatPayController::class, 'paidNotify'])->name('wxpay.paid_notify'); +Route::post('wxpay/order-paid-notify', [WeChatPayController::class, 'orderPaidNotify'])->name('wxpay.order_paid_notify'); +Route::post('wxpay/order-refund-notify', [WeChatPayController::class, 'orderRefundedNotify'])->name('wxpay.order_refund_notify'); diff --git a/app/Models/OrderRefundTask.php b/app/Models/OrderRefundTask.php index 617da9c0..0506cd6e 100644 --- a/app/Models/OrderRefundTask.php +++ b/app/Models/OrderRefundTask.php @@ -6,9 +6,9 @@ use Illuminate\Database\Eloquent\Model; class OrderRefundTask extends Model { - public const STATUS_PENDING = 0; - public const STATUS_SUCCESS = 5; - public const STATUS_FAILED = 6; + public const STATUS_PENDING = 0; // 待处理 + public const STATUS_SUCCESS = 5; // 退款成功 + public const STATUS_FAILED = 6; // 退款失败 /** * @var array diff --git a/app/Services/OrderService.php b/app/Services/OrderService.php index 744133b1..21e1223e 100644 --- a/app/Services/OrderService.php +++ b/app/Services/OrderService.php @@ -90,45 +90,6 @@ class OrderService return $order; } - /** - * 确认快速下单 - * - * @param \App\Models\User $user - * @param int $skuId - * @param int $quantity - * @param int|null $shippingAddressId - * @param int|null $couponId - * @return array - */ - public function verifyQuickOrder(User $user, int $skuId, int $quantity, ?int $shippingAddressId = null, ?int $couponId = null) - { - $sku = ProductSku::online()->findOrFail($skuId); - - $product = [ - 'sku' => $sku, - 'quantity' => $quantity, - ]; - - return $this->verifyOrder($user, [$product], $shippingAddressId, $couponId); - } - - /** - * 确认购物车订单 - * - * @param \App\Models\User $user - * @param array $shoppingCartItemIds - * @param int|null $shippingAddressId - * @param int|null $couponId - * @return array - */ - public function verifyShoppingCartOrder(User $user, array $shoppingCartItemIds, ?int $shippingAddressId = null, ?int $couponId = null) - { - // 获取购买商品 - $products = $this->getProductsByShoppingCart($user, $shoppingCartItemIds); - - return $this->verifyOrder($user, $products, $shippingAddressId, $couponId); - } - /** * 创建订单 * @@ -254,6 +215,45 @@ class OrderService ]); } + /** + * 确认快速下单 + * + * @param \App\Models\User $user + * @param int $skuId + * @param int $quantity + * @param int|null $shippingAddressId + * @param int|null $couponId + * @return array + */ + public function verifyQuickOrder(User $user, int $skuId, int $quantity, ?int $shippingAddressId = null, ?int $couponId = null) + { + $sku = ProductSku::online()->findOrFail($skuId); + + $product = [ + 'sku' => $sku, + 'quantity' => $quantity, + ]; + + return $this->verifyOrder($user, [$product], $shippingAddressId, $couponId); + } + + /** + * 确认购物车订单 + * + * @param \App\Models\User $user + * @param array $shoppingCartItemIds + * @param int|null $shippingAddressId + * @param int|null $couponId + * @return array + */ + public function verifyShoppingCartOrder(User $user, array $shoppingCartItemIds, ?int $shippingAddressId = null, ?int $couponId = null) + { + // 获取购买商品 + $products = $this->getProductsByShoppingCart($user, $shoppingCartItemIds); + + return $this->verifyOrder($user, $products, $shippingAddressId, $couponId); + } + /** * 确认订单 * @@ -599,13 +599,12 @@ class OrderService if (in_array($payWay, $this->wxpayWays)) { return (new WeChatPayService())->pay([ 'attach' => json_encode([ - 'pay_target' => 'order', 'pay_way' => $payWay, ]), 'body' => config('settings.app_name').'-商城订单', 'out_trade_no' => $order->sn, 'total_fee' => $order->total_amount, - 'notify_url' => url(route('wxpay.paid_notify', [], false), [], true), + 'notify_url' => url(route('wxpay.order_paid_notify', [], false), [], true), 'trade_type' => PayWay::$wxpayTradeTypes[$payWay], ]); } diff --git a/app/Services/WeChatPayService.php b/app/Services/WeChatPayService.php index 601a6f4a..e1bbea40 100644 --- a/app/Services/WeChatPayService.php +++ b/app/Services/WeChatPayService.php @@ -167,4 +167,15 @@ class WeChatPayService return $result; } + + /** + * 退款结果通知 + * + * @param \Closure $closure + * @return \Symfony\Component\HttpFoundation\Response + */ + public function handleRefundedNotify(Closure $closure) + { + return $this->app->handleRefundedNotify($closure); + } }