Files
water-back/modules/Withdraw/Models/Traits/WithdrawActions.php
2023-01-12 14:47:38 +08:00

326 lines
10 KiB
PHP

<?php
namespace Modules\Withdraw\Models\Traits;
use App\Models\DayDataChain;
use Illuminate\Support\Facades\DB;
use Jason\Chain33;
use Modules\Chain\Models\Address;
use Modules\Payment\Facades\Pay;
use Modules\Payment\Models\Traits\WithConfig;
use Modules\Withdraw\Events\WithdrawAuditPass;
use Modules\Withdraw\Events\WithdrawAuditReject;
use Modules\Withdraw\Models\Account;
use Modules\Withdraw\Models\Config;
use Modules\Withdraw\Models\Withdraw;
use Yansongda\Pay\Plugin\Alipay\Fund\TransUniTransferPlugin;
trait WithdrawActions
{
use WithConfig;
/**
* Notes: 通过
*
* @Author: 玄尘
* @Date : 2021/9/26 15:20
* @param string $remark
* @return bool
* @throws \Exception
*/
public function pass(string $remark = ''): bool
{
if (! $this->canAudit()) {
throw new \Exception('该提现记录已经被审核');
}
try {
if ($this->type == self::TYPE_ALIPAY) {
if (! $this->alipayAccount) {
throw new \Exception('未找到支付宝账户');
}
$allPlugins = Pay::alipay()
->mergeCommonPlugins([TransUniTransferPlugin::class]);
$params = [
'out_biz_no' => $this->withdraw_no,
'trans_amount' => $this->take,
'payee_info' => [
'identity' => $this->alipayAccount->identity,
'identity_type' => $this->alipayAccount->identity_type,
'name' => $this->alipayAccount->name,
],
];
$res = Pay::alipay($this->getPayConfig('alipay'))->pay($allPlugins, $params);
if ($res->code != 10000) {
throw new \Exception($res->sub_msg);
}
}
DB::transaction(function () use ($remark) {
$this->status = Withdraw::STATUS_PASS;
$this->paid_at = now();
$this->save();
});
$this->addLog(Withdraw::STATUS_INIT, $remark);
event(new WithdrawAuditPass($this));
return true;
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
/**
* Notes: 驳回
*
* @Author: 玄尘
* @Date : 2021/9/26 15:21
* @param string $remark
* @return bool
* @throws \Exception
*/
public function reject(string $remark = ''): bool
{
if (! $this->canAudit()) {
throw new \Exception('该提现记录已经被审核');
}
try {
DB::transaction(function () use ($remark) {
$this->status = Withdraw::STATUS_REJECT;
$this->paid_at = now();
$this->save();
$is_chain = config('withdraw.is_chain', false);
if (! $is_chain) {
$this->user->account->rule('withdraw_in', $this->amount, false, [
'withdraw_id' => $this->id,
]);
} else {
$hash = $this->rejectPick();
$source = [
'reject_hash' => $hash,
];
$this->update(['source' => $source]);
}
$this->addLog(Withdraw::STATUS_REJECT, $remark);
event(new WithdrawAuditReject($this));
});
return true;
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
/**
* Notes: 添加记录
*
* @Author: 玄尘
* @Date : 2021/9/27 8:56
* @param $status
* @param string $remark
* @return bool
*/
public function addLog($status, string $remark = ''): bool
{
$this->logs()->create([
'status' => $status,
'remark' => $remark,
]);
return true;
}
/**
* Notes: 创建提现信息
*
* @Author: 玄尘
* @Date : 2021/9/27 10:14
*/
public static function createInfo($user, $params): bool
{
try {
DB::transaction(function () use ($user, $params) {
$type = $params->type ?? 0;
$bank_account_id = $params->bank_account_id ?? 0;
$amount = $params->amount;
$account_name = config('withdraw.account');
$source = [
$account_name => $amount,
];
$cash = $amount;
$is_chain = config('withdraw.is_chain', false);
$balance = $is_chain ? $user->getStoneBalance() : $user->account->{$account_name};
if ($amount > $balance) {
throw new \Exception('提现失败,余额不足');
}
if ($is_chain) {
$cost = (new DayDataChain())->getStoneValue();
$cash = bcmul($cost, $amount, 2);
$source = array_merge($source, ['cost' => $cost,]);
}
$withdraw_min = Config::getValue('min', 1);
if ($withdraw_min > 0 && $cash < $withdraw_min) {
throw new \Exception("提现失败,提现金额必须大于等于{$withdraw_min}");
}
$tax_value = Config::getValue('tax', 0);
$tax = $tax_value ? round($cash * $tax_value / 100, 2) : 0;
$take = $cash - $tax;
if ($type == Withdraw::TYPE_BANK) {
$bank_account = Account::find($bank_account_id);
if (! $bank_account) {
throw new \Exception('提现失败,未找到提现账户信息');
}
if ($bank_account->user->isNot($user)) {
throw new \Exception('提现失败,您不可使用此提现账户');
}
$info = $user->withdraws()->create([
'bank_account_id' => $bank_account_id,
'amount' => $cash,
'tax' => $tax, //手续费
'take' => $take, //实到金额
'source' => $source,
'type' => Withdraw::TYPE_BANK,
]);
} else {
$alipay_account = $user->alipayAccounts()->create([
'name' => $params->name,
'identity' => $params->identity,
'identity_type' => 'ALIPAY_LOGON_ID',
]);
$info = $user->withdraws()->create([
'alipay_account_id' => $alipay_account->id,
'amount' => $cash,
'tax' => $tax, //手续费
'take' => $take, //实到金额
'source' => $source,
'type' => Withdraw::TYPE_ALIPAY,
]);
}
if (! $is_chain) {
$user->account->rule('withdraw_out', -$cash, false, [
'withdraw_id' => $info->id,
]);
} else {
$hash = $info->pick();//转到代持账户
$source = array_merge($source, ['hash' => $hash,]);
$info->update(['source' => $source]);
}
});
return true;
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
/**
* Notes: 申请提现时将提现金额转入代持账户
*
* @Author: 玄尘
* @Date : 2021/9/27 10:34
* @return string
* @throws \Exception
*/
public function pick(): string
{
$to_address = Config::getValue('withdraw_addr', '');
if (! $to_address) {
throw new \Exception('提现失败,缺少代持账户信息,请管理人员配置代持账户。');
}
$number = $this->source['coins'] ?? 0;
if (! $number) {
throw new \Exception('提现数据错误');
}
$from_address = $this->user->blockChain->address;
$balance = coinsFormat(Chain33::Balance()->get($from_address)['balance']);
if ($number > $balance) {
throw new \Exception('提现失败,数量不足');
}
try {
$fromAddr = Address::where('address', $from_address)->first();
return Chain33::Transaction()
->coins($to_address, $number * 1e8, $fromAddr->private_key, 0, '用户提现');
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
/**
* Notes: description
*
* @Author: 玄尘
* @Date : 2021/9/27 14:45
* @return string
* @throws \Exception
*/
public function rejectPick(): string
{
$from_address = Config::getValue('withdraw_addr', '');
if (! $from_address) {
throw new \Exception('提现失败,缺少代持账户信息,请管理人员配置代持账户。');
}
$number = $this->source['coins'] ?? 0;
if (! $number) {
throw new \Exception('提现数据错误');
}
$to_address = $this->user->blockChain->address;
$balance = coinsFormat(Chain33::Balance()->get($from_address)['balance']);
if ($number > $balance) {
throw new \Exception('驳回失败,代持账户数量不足');
}
try {
$fromAddr = Address::where('address', $from_address)->first();
return Chain33::Transaction()
->coins($to_address, $number * 1e8, $fromAddr->private_key, 0, '驳回提现');
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
}