From 07fd87fcd1f59305550f82a49082890974818e46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=9D=99?= Date: Mon, 20 Dec 2021 14:33:22 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E9=80=80=E6=AC=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Console/Commands/OrderRefundCommand.php | 84 +++++++++++++++++++ .../Controllers/Order/OrderController.php | 1 + app/Models/OrderRefundTask.php | 3 + app/Services/WeChatPayService.php | 66 +++++++++++++++ ...113756_create_order_refund_tasks_table.php | 1 + 5 files changed, 155 insertions(+) create mode 100644 app/Console/Commands/OrderRefundCommand.php diff --git a/app/Console/Commands/OrderRefundCommand.php b/app/Console/Commands/OrderRefundCommand.php new file mode 100644 index 00000000..b99ba2bd --- /dev/null +++ b/app/Console/Commands/OrderRefundCommand.php @@ -0,0 +1,84 @@ +chunkById(200, function ($tasks) { + foreach ($tasks as $task) { + try { + $method = 'refundBy'.Str::studly($task->order->pay_way); + + if (! method_exists($this, $method)) { + throw new BizException('退款方式暂不支持'); + } + + $this->{$method}($task); + + $task->update([ + 'status' => OrderRefundTask::STATUS_SUCCESS, + 'failed_reason' => null, + ]); + } catch (Throwable $e) { + report($e); + + $task->update([ + 'status' => OrderRefundTask::STATUS_FAILED, + 'failed_reason' => $e->getMessage(), + ]); + } + } + }); + + return 0; + } + + /** + * 微信退款 + * + * @param \App\Models\OrderRefundTask $orderRefundTask + * @return void + */ + protected function refundByWxpay(OrderRefundTask $orderRefundTask) + { + $order = $orderRefundTask->order; + + (new WeChatPayService())->refundByOutTradeNumber( + $order->sn, + $orderRefundTask->sn, + $order->total_amount, + $orderRefundTask->amount, + [ + 'refund_desc' => $orderRefundTask->reason, + ] + ); + } +} diff --git a/app/Endpoint/Api/Http/Controllers/Order/OrderController.php b/app/Endpoint/Api/Http/Controllers/Order/OrderController.php index fae9b3d0..c2eb3787 100644 --- a/app/Endpoint/Api/Http/Controllers/Order/OrderController.php +++ b/app/Endpoint/Api/Http/Controllers/Order/OrderController.php @@ -158,6 +158,7 @@ class OrderController extends Controller $order->refundTasks()->create([ 'sn' => OrderHelper::serialNumber(), 'amount' => $order->total_amount, + 'reason' => '取消订单', ]); } diff --git a/app/Models/OrderRefundTask.php b/app/Models/OrderRefundTask.php index 486253a5..617da9c0 100644 --- a/app/Models/OrderRefundTask.php +++ b/app/Models/OrderRefundTask.php @@ -7,6 +7,8 @@ use Illuminate\Database\Eloquent\Model; class OrderRefundTask extends Model { public const STATUS_PENDING = 0; + public const STATUS_SUCCESS = 5; + public const STATUS_FAILED = 6; /** * @var array @@ -24,6 +26,7 @@ class OrderRefundTask extends Model 'after_sale_id', 'amount', 'status', + 'reason', 'failed_reason', ]; diff --git a/app/Services/WeChatPayService.php b/app/Services/WeChatPayService.php index 0f9b22c5..601a6f4a 100644 --- a/app/Services/WeChatPayService.php +++ b/app/Services/WeChatPayService.php @@ -101,4 +101,70 @@ class WeChatPayService { return $this->app->handlePaidNotify($closure); } + + /** + * 根据微信订单号退款 + * + * @param string $transactionId + * @param string $refundNumber + * @param int $totalFee + * @param int $refundFee + * @param array $optional + * @return array + */ + public function refundByTransactionId(string $transactionId, string $refundNumber, int $totalFee, int $refundFee, array $optional = []) + { + $result = $this->app->refund->byTransactionId($transactionId, $refundNumber, $totalFee, $refundFee, $optional); + + if (data_get($result, 'return_code') !== 'SUCCESS') { + throw new WeChatPayException( + data_get($result, 'return_msg', '请求失败') + ); + } + + if (data_get($result, 'result_code') !== 'SUCCESS') { + throw new WeChatPayException( + sprintf( + '[%s] %s', + data_get($result, 'err_code', '-1'), + data_get($result, 'err_code_des', '退款失败') + ) + ); + } + + return $result; + } + + /** + * 根据商户订单号退款 + * + * @param string $number + * @param string $refundNumber + * @param int $totalFee + * @param int $refundFee + * @param array $optional + * @return array + */ + public function refundByOutTradeNumber(string $number, string $refundNumber, int $totalFee, int $refundFee, array $optional = []) + { + $result = $this->app->refund->byOutTradeNumber($number, $refundNumber, $totalFee, $refundFee, $optional); + + if (data_get($result, 'return_code') !== 'SUCCESS') { + throw new WeChatPayException( + data_get($result, 'return_msg', '请求失败') + ); + } + + if (data_get($result, 'result_code') !== 'SUCCESS') { + throw new WeChatPayException( + sprintf( + '[%s] %s', + data_get($result, 'err_code', '-1'), + data_get($result, 'err_code_des', '退款失败') + ) + ); + } + + return $result; + } } diff --git a/database/migrations/2021_12_20_113756_create_order_refund_tasks_table.php b/database/migrations/2021_12_20_113756_create_order_refund_tasks_table.php index ea67b41b..a31c3846 100644 --- a/database/migrations/2021_12_20_113756_create_order_refund_tasks_table.php +++ b/database/migrations/2021_12_20_113756_create_order_refund_tasks_table.php @@ -20,6 +20,7 @@ class CreateOrderRefundTasksTable extends Migration $table->unsignedBigInteger('after_sale_id')->nullable()->comment('售后ID'); $table->unsignedBigInteger('amount')->comment('退款金额'); $table->tinyInteger('status')->default(0)->comment('状态'); + $table->string('reason')->nullable()->comment('退款原因'); $table->string('failed_reason')->nullable()->comment('失败原因'); $table->timestamps();