You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

201 lines
6.7 KiB

<?php
namespace App\Controller\v3;
use App\Commons\Log;
use App\Constants\v3\ErrorCode;
use App\Constants\v3\LogLabel;
use App\Constants\v3\UserType;
use App\Controller\BaseController;
use App\Exception\ErrorCodeException;
use App\Model\v3\FinancialRecord;
use App\Model\v3\Store;
use App\Model\v3\StoreWithdrawal;
use App\Model\v3\User;
use App\Model\v3\UserBalance;
use App\Service\v3\Interfaces\FinancialRecordServiceInterface;
use App\Service\v3\Interfaces\PaymentServiceInterface;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Snowflake\IdGeneratorInterface;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Validation\ValidationException;
class WithdrawController extends BaseController
{
/**
* @Inject
* @var Log
*/
protected $log;
/**
* @Inject
* @var FinancialRecordServiceInterface
*/
protected $financialService;
/**
* @Inject
* @var PaymentServiceInterface
*/
protected $paymentService;
/**
* 商户提现页数据
* 1、可提现金额
* 2、获得的奖励金额(历史总奖励金额)
* 3、用户须知
* 4、提现须知
*/
public function pageByStore()
{
$validator = $this->validationFactory->make(
$this->request->all(),
[
'user_id' => 'required|nonempty|integer',
'store_id' => 'required|nonempty|integer',
],
['*.*' => ':attribute 参数不正确']
);
if ($validator->fails()) {
throw new ValidationException($validator);
}
$userId = $this->request->input('user_id');
$storeId = $this->request->input('store_id');
$store = Store::query()->where(['user_id' => $userId, 'id' => $storeId])->first();
if (empty($store)) {
throw new ErrorCodeException(ErrorCode::STORE_NOT_AVAILABLE);
}
$data['balance'] = UserBalance::query()
->where(['source_id' => $store->user_id, 'user_type' => UserType::STORE])
->value('balance');
$data['award'] = $this->financialService->sumAmount(
$store->user_id,
UserType::STORE,
[FinancialRecord::MONEY_TYPE_STORE_PLAT_NEW_USER, FinancialRecord::MONEY_TYPE_STORE_FIRST_ORDER]
);
$data['notice'] = [
[
'title' => '用户须知',
'content' => '<p>请仔细填写相关信息,如果由于您填写的信息有误导致资金流失,平台概不负责。</p><p>注意:因微信限制当前用户账户余额满<span style="color:red;">1</span>元后才可提现</p>'
],
[
'title' => '提现须知',
'content' => '<p>一次提现金额最低为<span style="color:red;">1</span>元</p>'
.'<p>一次提现金额最高为<span style="color:red;">5000</span>元</p>'
.'<p>每天可提现<span style="color:red;">10</span>次</p>'
],
];
return $this->success($data);
}
/**
* 商户提现申请
* 1、商户提现参数校验
* 2、商户提现是否超过可提现金额
* 3、提现是否秒到账,秒到账则打款并且做流水,否则就打到后台审核
*/
public function applyByStore()
{
$isDirect = config('wechat.withdrawal.is_direct');
$min = config('wechat.withdrawal.min_amount');
$max = config('wechat.withdrawal.max_amount');
$validator = $this->validationFactory->make(
$this->request->all(),
[
'user_id' => 'required|nonempty|integer',
'store_id' => 'required|nonempty|integer',
'money' => "required|nonempty|numeric|between:{$min}, {$max}",
]
);
if ($validator->fails()) {
throw new ValidationException($validator);
}
$money = $this->request->input('money');
$userId = $this->request->input('user_id');
$storeId = $this->request->input('store_id');
$store = Store::query()->where(['user_id' => $userId, 'id' => $storeId])->first();
if (empty($store)) {
throw new ErrorCodeException(ErrorCode::STORE_NOT_AVAILABLE, '[稍后重试]');
}
// 校验余额
$balance = UserBalance::query()
->where(['source_id' => $store->user_id, 'user_type' => UserType::STORE])
->first();
if ($money > $balance->balance) {
throw new ErrorCodeException(ErrorCode::STORE_WITHDRAW_INSUFFICIENT_BALANCE);
}
Db::beginTransaction();
try {
$storeUser = User::query()->find($store->user_id);
$currentTime = time();
// 获取分布式全局ID
$generator = ApplicationContext::getContainer()->get(IdGeneratorInterface::class);
$globalOrderId = $generator->generate();
// 记录提现申请记录
$withdraw = new StoreWithdrawal();
$withdraw->trade_no = $globalOrderId;
$withdraw->store_id = $store->id;
$withdraw->name = $storeUser->nick_name ?: '';
$withdraw->tel = $storeUser->tel;
$withdraw->apply_cash = $money;
$withdraw->save();
// 先扣除余额
$balance->balance = bcsub($balance->balance, $money, 2);
$balance->save();
// 如果秒到账无需审核的话
if ($isDirect) {
// 打款
$res = $this->paymentService->payToWx(
bcmul($withdraw->apply_cash, 100 , 0),
$withdraw->trade_no,
$storeUser->openid,
$withdraw->name,
'商户提现打款'
);
// 更新打款金额,审核时间等
$withdraw->check_time = time();
$withdraw->real_cash = $money;
$withdraw->state = 2;
$withdraw->save();
// 打款成功,写流水
if ($res === true) {
$this->financialService->storeWithdrawByWx($store->user_id, $withdraw->id, $withdraw->real_cash);
}
}
Db::commit();
return $this->success([]);
} catch (\Exception $e) {
Db::rollBack();
$this->log->event(LogLabel::STORE_WITHDRAW_FAIL_LOG, [
'msg' => $e->getMessage(),
'withdraw' => json_encode($withdraw),
'params' => json_encode(['balance' => $balance->balance, 'user_id' => $userId, 'store_id' => $storeId]),
]);
throw new ErrorCodeException(ErrorCode::STORE_WITHDRAW_FAIL, '-'.$e->getMessage());
}
}
}