6
0
Fork 0

批零提现代付

release
李静 2022-04-13 13:54:06 +08:00
parent 704287d550
commit dcdcfcbf56
10 changed files with 255 additions and 15 deletions

View File

@ -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("<a href=\"javascript:void(0)\" class=\"btn btn-sm {$this->style}\">{$this->title}</a>&nbsp;&nbsp;");
->button("<a href=\"javascript:void(0)\" class=\"btn btn-sm {$this->style}\">{$this->title}</a>");
}
}

View File

@ -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("<a href=\"javascript:void(0)\" class=\"btn btn-sm {$this->style}\">{$this->title}</a>&nbsp;&nbsp;");
->button("<a href=\"javascript:void(0)\" class=\"btn btn-sm {$this->style}\">{$this->title}</a>");
}
}

View File

@ -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());
}

View File

@ -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()

View File

@ -0,0 +1,92 @@
<?php
namespace App\Console\Commands\Dealer;
use App\Enums\Bank;
use App\Enums\DealerWalletToBankLogStatus;
use App\Exceptions\YeePayException;
use App\Models\DealerWalletToBankLog;
use App\Services\YeePayService;
use Illuminate\Console\Command;
use Throwable;
class WalletToBankCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'dealer:wallet-to-bank';
/**
* The console command description.
*
* @var string
*/
protected $description = '批零提现';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$yeePayService = new YeePayService(config('services.yeepay'));
while (true) {
DealerWalletToBankLog::where('status', DealerWalletToBankLogStatus::Passed)->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);
}
}
}

View File

@ -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,
]);
}
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Enums;
enum DealerWalletToBankLogPayWay: int {
case Offline = 1;
case Behalf = 2;
/**
* @return string
*/
public function color(): string
{
return match ($this) {
static::Offline => '#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 => '代付',
];
}
}

View File

@ -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;

View File

@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddPayColumnsToDealerWalletToBankLogsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('dealer_wallet_to_bank_logs', function (Blueprint $table) {
$table->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']);
});
}
}

View File

@ -17,6 +17,8 @@ return [
'account_amount' => '到账金额',
'status' => '状态',
'remarks' => '备注',
'failed_reason' => '失败原因',
'pay_way' => '支付方式',
],
'options' => [
],