From dcdcfcbf567b511ce3d1979fcffd903753cfbb92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=9D=99?= Date: Wed, 13 Apr 2022 13:54:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=B9=E9=9B=B6=E6=8F=90=E7=8E=B0=E4=BB=A3?= =?UTF-8?q?=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Admin/Actions/Show/DealerWalletPay.php | 4 +- app/Admin/Actions/Show/DealerWalletRefuse.php | 4 +- .../DealerWalletToBankLogController.php | 8 +- app/Admin/Forms/DealerWalletPay.php | 31 +++++-- .../Commands/Dealer/WalletToBankCommand.php | 92 +++++++++++++++++++ .../Controllers/YeePayNotifyController.php | 31 ++++++- app/Enums/DealerWalletToBankLogPayWay.php | 38 ++++++++ app/Models/DealerWalletToBankLog.php | 23 ++++- ...ns_to_dealer_wallet_to_bank_logs_table.php | 37 ++++++++ .../lang/zh_CN/dealer-wallet-to-bank-log.php | 2 + 10 files changed, 255 insertions(+), 15 deletions(-) create mode 100644 app/Console/Commands/Dealer/WalletToBankCommand.php create mode 100644 app/Enums/DealerWalletToBankLogPayWay.php create mode 100644 database/migrations/2022_04_13_104039_add_pay_columns_to_dealer_wallet_to_bank_logs_table.php diff --git a/app/Admin/Actions/Show/DealerWalletPay.php b/app/Admin/Actions/Show/DealerWalletPay.php index 32b4f7b6..8ef3873d 100644 --- a/app/Admin/Actions/Show/DealerWalletPay.php +++ b/app/Admin/Actions/Show/DealerWalletPay.php @@ -18,7 +18,7 @@ class DealerWalletPay extends AbstractTool * * @var string */ - protected $style = 'btn-danger'; + protected $style = 'btn-danger mr-1'; public function render() { @@ -27,6 +27,6 @@ class DealerWalletPay extends AbstractTool ->lg() ->title($this->title) ->body($form) - ->button("style}\">{$this->title}  "); + ->button("style}\">{$this->title}"); } } diff --git a/app/Admin/Actions/Show/DealerWalletRefuse.php b/app/Admin/Actions/Show/DealerWalletRefuse.php index 134c99c2..e3a7b6f7 100644 --- a/app/Admin/Actions/Show/DealerWalletRefuse.php +++ b/app/Admin/Actions/Show/DealerWalletRefuse.php @@ -18,7 +18,7 @@ class DealerWalletRefuse extends AbstractTool * * @var string */ - protected $style = 'btn-warning'; + protected $style = 'btn-warning mr-1'; public function render() { @@ -27,6 +27,6 @@ class DealerWalletRefuse extends AbstractTool ->lg() ->title($this->title) ->body($form) - ->button("style}\">{$this->title}  "); + ->button("style}\">{$this->title}"); } } diff --git a/app/Admin/Controllers/DealerWalletToBankLogController.php b/app/Admin/Controllers/DealerWalletToBankLogController.php index 1a145466..9be4f41f 100644 --- a/app/Admin/Controllers/DealerWalletToBankLogController.php +++ b/app/Admin/Controllers/DealerWalletToBankLogController.php @@ -84,7 +84,7 @@ class DealerWalletToBankLogController extends AdminController $show->field('rate')->append('%'); $show->field('service_amount')->prepend('¥'); $show->field('account_amount')->prepend('¥'); - $show->field('status')->as(function ($v) { + $show->field('status')->unescape()->as(function ($v) { $text = $this->status->text(); $background = $this->status->color(); @@ -92,6 +92,9 @@ class DealerWalletToBankLogController extends AdminController }); $show->field('pay_image')->image(); $show->field('remarks'); + if ($show->model()->isFailed()) { + $show->field('failed_reason'); + } $show->divider('收款信息-银行'); $show->field('bank_user_name', '银行-收款人')->as(function () { $payInfo = $this->getPayInfo(); @@ -141,7 +144,8 @@ class DealerWalletToBankLogController extends AdminController ->tools(function (Show\Tools $tools) use ($show) { $tools->disableEdit(); $tools->disableDelete(); - if ($show->model()->isPending() && Admin::user()->can('dcat.admin.dealer_wallet_to_bank_logs.verify')) { + + if (in_array($show->model()->status, [DealerWalletToBankLogStatus::Pending, DealerWalletToBankLogStatus::Failed]) && Admin::user()->can('dcat.admin.dealer_wallet_to_bank_logs.verify')) { $tools->append(new DealerWalletRefuse()); $tools->append(new DealerWalletPay()); } diff --git a/app/Admin/Forms/DealerWalletPay.php b/app/Admin/Forms/DealerWalletPay.php index e3f96381..2cb69eb5 100644 --- a/app/Admin/Forms/DealerWalletPay.php +++ b/app/Admin/Forms/DealerWalletPay.php @@ -2,7 +2,9 @@ namespace App\Admin\Forms; +use App\Enums\DealerWalletToBankLogPayWay; use App\Enums\DealerWalletToBankLogStatus; +use App\Exceptions\BizException; use App\Models\DealerWalletToBankLog; use Carbon\Carbon; use Dcat\Admin\Contracts\LazyRenderable; @@ -38,12 +40,25 @@ class DealerWalletPay extends Form implements LazyRenderable try { DB::beginTransaction(); - $log = DealerWalletToBankLog::findOrFail($id); - $log->update([ - 'pay_info' => $log->getPayInfo(), - 'pay_image' => $input['pay_image'] ?? null, - 'status' => DealerWalletToBankLogStatus::Success, - ]); + + $log = DealerWalletToBankLog::lockForUpdate()->findOrFail($id); + + if (! in_array($log->status, [DealerWalletToBankLogStatus::Pending, DealerWalletToBankLogStatus::Failed])) { + throw new BizException('提现记录状态异常'); + } + + $log->pay_info = $log->user->dealer->pay_info; + $log->pay_image = $input['pay_image'] ?? null; + $log->pay_way = $input['pay_way']; + if ($log->pay_way == DealerWalletToBankLogPayWay::Offline) { + $log->pay_at = now(); + $log->status = DealerWalletToBankLogStatus::Success; + } else { + $log->pay_sn = serial_number(); + $log->status = DealerWalletToBankLogStatus::Passed; + } + $log->save(); + DB::commit(); } catch (Throwable $th) { DB::rollBack(); @@ -61,6 +76,10 @@ class DealerWalletPay extends Form implements LazyRenderable */ public function form() { + $this->hidden('pay_way')->value(DealerWalletToBankLogPayWay::Offline->value); + // $this->select('pay_way') + // ->options(DealerWalletToBankLogPayWay::texts()) + // ->required(); $this->image('pay_image') ->move('dealer-pay/'.Carbon::now()->toDateString()) ->saveFullUrl() diff --git a/app/Console/Commands/Dealer/WalletToBankCommand.php b/app/Console/Commands/Dealer/WalletToBankCommand.php new file mode 100644 index 00000000..4feaeffb --- /dev/null +++ b/app/Console/Commands/Dealer/WalletToBankCommand.php @@ -0,0 +1,92 @@ +chunkById(1, function ($logs) use ($yeePayService) { + foreach ($logs as $log) { + try { + $result = $yeePayService->request('accountpay.behalf.Pay', [ + 'payerOutUserId' => '21102510220227100003' ?: config('services.yeepay.partner_id'), + 'merchOrderNo' => $log->pay_sn, + 'tradeName' => '批零提现', + 'payeeUserName' => data_get($log->pay_info, 'bank.user_name'), + 'bankCardNo' => data_get($log->pay_info, 'bank.bank_number'), + 'bankCode' => Bank::tryFromBankName(data_get($log->pay_info, 'bank.bank_name'))?->name, + 'bankCardType' => 'DEBIT_CARD', + 'amount' => $log->account_amount, + 'feeRole' => 'PAYER', + 'tradeMemo' => '批零提现', + 'context' => json_encode(['type' => 'dealer_wallet_to_bank']), + ]); + + // 如果交易超时,重新发起支付 + if ($result['resultCode'] === 'TIME_OUT') { + continue; + } + + if ($result['orderStatus'] === 'SUCCESS') { + $log->update([ + 'status' => DealerWalletToBankLogStatus::Success, + 'pay_at' => now(), + 'failed_reason' => null, + ]); + } elseif ($result['orderStatus'] === 'FAIL') { + $log->update([ + 'status' => DealerWalletToBankLogStatus::Failed, + 'failed_reason' => '交易失败', + ]); + } else { + $log->update([ + 'status' => DealerWalletToBankLogStatus::Paying, + 'failed_reason' => null, + ]); + } + } catch (YeePayException $e) { + $log->update([ + 'status' => DealerWalletToBankLogStatus::Failed, + 'failed_reason' => $e->getMessage(), + ]); + } catch (Throwable $e) { + throw $e; + } + } + }); + + sleep(60); + } + } +} diff --git a/app/Endpoint/Callback/Http/Controllers/YeePayNotifyController.php b/app/Endpoint/Callback/Http/Controllers/YeePayNotifyController.php index fedc181a..87739334 100644 --- a/app/Endpoint/Callback/Http/Controllers/YeePayNotifyController.php +++ b/app/Endpoint/Callback/Http/Controllers/YeePayNotifyController.php @@ -2,7 +2,9 @@ namespace App\Endpoint\Callback\Http\Controllers; +use App\Enums\DealerWalletToBankLogStatus; use App\Enums\WalletToBankLogStatus; +use App\Models\DealerWalletToBankLog; use App\Models\WalletToBankLog; use App\Services\YeePayService; use Exception; @@ -45,9 +47,11 @@ class YeePayNotifyController extends Controller $orderNo = $request->input('merchOrderNo'); $orderStatus = $request->input('orderStatus'); - $context = (array) json_decode($request->input('context'), true); - if (Arr::get($context, 'type') === 'wallet_to_bank') { + $context = (array) json_decode($request->input('context'), true); + $contextType = Arr::get($context, 'type'); + + if ($contextType === 'wallet_to_bank') { $log = WalletToBankLog::where('pay_sn', $orderNo)->first(); if ($log === null) { @@ -70,6 +74,29 @@ class YeePayNotifyController extends Controller 'failed_reason' => $request->input('resultMessage').'#'.$resultCode, ]); } + } elseif ($contextType === 'dealer_wallet_to_bank') { + $log = DealerWalletToBankLog::where('pay_sn', $orderNo)->first(); + + if ($log === null) { + return; + } + + if ($log->status !== DealerWalletToBankLogStatus::Paying) { + return; + } + + if ($orderStatus === 'SUCCESS') { + $log->update([ + 'status' => DealerWalletToBankLogStatus::Success, + 'pay_at' => Carbon::parse($request->input('finishTime')), + 'failed_reason' => null, + ]); + } elseif ($orderStatus === 'FAIL') { + $log->update([ + 'status' => DealerWalletToBankLogStatus::Failed, + 'failed_reason' => $request->input('resultMessage').'#'.$resultCode, + ]); + } } } diff --git a/app/Enums/DealerWalletToBankLogPayWay.php b/app/Enums/DealerWalletToBankLogPayWay.php new file mode 100644 index 00000000..4dc66ea3 --- /dev/null +++ b/app/Enums/DealerWalletToBankLogPayWay.php @@ -0,0 +1,38 @@ + '#5b69bc', + static::Behalf => '#21b978', + }; + } + + /** + * @return string + */ + public function text(): string + { + return static::texts()[$this->value]; + } + + /** + * @return array + */ + public static function texts(): array + { + return [ + static::Offline->value => '线下', + static::Behalf->value => '代付', + ]; + } +} diff --git a/app/Models/DealerWalletToBankLog.php b/app/Models/DealerWalletToBankLog.php index 90d3eed6..52132eed 100644 --- a/app/Models/DealerWalletToBankLog.php +++ b/app/Models/DealerWalletToBankLog.php @@ -2,6 +2,8 @@ namespace App\Models; +use App\Casts\JsonArray; +use App\Enums\DealerWalletToBankLogPayWay; use App\Enums\DealerWalletToBankLogStatus; use Dcat\Admin\Traits\HasDateTimeFormatter; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -12,7 +14,15 @@ class DealerWalletToBankLog extends Model use HasFactory; use HasDateTimeFormatter; + protected $attributes = [ + 'pay_way' => DealerWalletToBankLogPayWay::Offline, + 'status' => DealerWalletToBankLogStatus::Pending, + ]; + protected $casts = [ + 'pay_info' => JsonArray::class, + 'pay_at' => 'datetime', + 'pay_way' => DealerWalletToBankLogPayWay::class, 'status' => DealerWalletToBankLogStatus::class, ]; @@ -27,6 +37,12 @@ class DealerWalletToBankLog extends Model 'rate', 'service_amount', 'account_amount', + 'pay_info', + 'pay_image', + 'pay_sn', + 'pay_way', + 'pay_at', + 'failed_reason', ]; /** @@ -53,6 +69,11 @@ class DealerWalletToBankLog extends Model return $this->status === DealerWalletToBankLogStatus::Pending; } + public function isFailed() + { + return $this->status === DealerWalletToBankLogStatus::Failed; + } + /** * 获取用户的打款信息 * @@ -60,7 +81,7 @@ class DealerWalletToBankLog extends Model */ public function getPayInfo() { - if ($this->isPending()) {//待打款订单显示发货人收款信息 + if ($this->isPending() || $this->isFailed()) {//待打款订单显示发货人收款信息 $payInfo = $this->user->dealer->pay_info; } else { $payInfo = $this->pay_info; diff --git a/database/migrations/2022_04_13_104039_add_pay_columns_to_dealer_wallet_to_bank_logs_table.php b/database/migrations/2022_04_13_104039_add_pay_columns_to_dealer_wallet_to_bank_logs_table.php new file mode 100644 index 00000000..8bc680ae --- /dev/null +++ b/database/migrations/2022_04_13_104039_add_pay_columns_to_dealer_wallet_to_bank_logs_table.php @@ -0,0 +1,37 @@ +string('pay_sn')->nullable()->comment('支付单号'); + $table->tinyInteger('pay_way')->default(1)->comment('支付方式: 1 线下, 2 代付'); + $table->timestamp('pay_at')->nullable()->comment('支付时间'); + $table->text('failed_reason')->nullable()->comment('失败原因'); + + $table->unique('pay_sn'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('dealer_wallet_to_bank_logs', function (Blueprint $table) { + $table->dropColumn(['pay_sn', 'pay_way', 'failed_reason', 'pay_at']); + }); + } +} diff --git a/resources/lang/zh_CN/dealer-wallet-to-bank-log.php b/resources/lang/zh_CN/dealer-wallet-to-bank-log.php index 22108113..2b959ddc 100644 --- a/resources/lang/zh_CN/dealer-wallet-to-bank-log.php +++ b/resources/lang/zh_CN/dealer-wallet-to-bank-log.php @@ -17,6 +17,8 @@ return [ 'account_amount' => '到账金额', 'status' => '状态', 'remarks' => '备注', + 'failed_reason' => '失败原因', + 'pay_way' => '支付方式', ], 'options' => [ ],