牛肉社团后端
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.
cow/addons/shopro/model/UserWalletApply.php

379 lines
11 KiB

2 years ago
<?php
namespace addons\shopro\model;
use think\Db;
use think\Model;
use traits\model\SoftDelete;
use addons\shopro\exception\Exception;
/**
* 钱包
*/
class UserWalletApply extends Model
{
use SoftDelete;
// 表名,不含前缀
protected $name = 'shopro_user_wallet_apply';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
protected $deleteTime = false;
protected $hidden = ['actual_money', 'log', 'payment_json', 'updatetime'];
// 追加属性
protected $append = [
'status_text',
'apply_type_text',
];
/**
* 获取提现单号
*
* @param int $user_id
* @return string
*/
public static function getSn($user_id)
{
$rand = $user_id < 9999 ? mt_rand(100000, 99999999) : mt_rand(100, 99999);
$order_sn = date('Yhis') . $rand;
$id = str_pad($user_id, (24 - strlen($order_sn)), '0', STR_PAD_BOTH);
return 'W' . $order_sn . $id;
}
// 提现记录
public static function getList()
{
$user = User::info();
$walletApplys = self::where(['user_id' => $user->id])->order('id desc')->paginate(10);
return $walletApplys;
}
/**
* 申请提现
*
* @param int $type 提现方式 wechat|alipay|bank
* @param int $money 提现金额
*/
public static function apply($type, $money)
{
$user = User::info();
$config = self::getWithdrawConfig();
if (!in_array($type, $config['methods'])) {
throw new \Exception('暂不支持该提现方式');
}
$min = round(floatval($config['min']), 2);
$max = round(floatval($config['max']), 2);
$service_fee = round(floatval($config['service_fee']), 3); // 三位小数
// 检查最小提现金额
if (bccomp($money, $min) === -1 || $money <= 0) {
throw new \Exception('提现金额不能少于 ' . $min . '元');
}
// 检查最大提现金额
if ($max && bccomp($money, $max) === 1 ) {
throw new \Exception('提现金额不能大于 ' . $max . '元');
}
// 计算手续费
$charge = bcmul($money, $service_fee, 2);
if (bccomp($user->money, $charge + $money) === -1) {
throw new \Exception('可提现余额不足');
}
// 检查每日最大提现次数
if (isset($config['perday_num']) && $config['perday_num'] > 0) {
$num = self::where(['user_id' => $user->id, 'createtime' => ['egt', strtotime(date("Y-m-d", time()))]])->count();
if ($num >= $config['perday_num']) {
throw new \Exception('每日提现次数不能大于 ' . $config['perday_num'] . '次');
}
}
// 检查每日最大提现金额
if (isset($config['perday_amount']) && $config['perday_num'] > 0) {
$amount = self::where(['user_id' => $user->id, 'createtime' => ['egt', strtotime(date("Y-m-d", time()))]])->sum('money');
if ($amount >= $config['perday_amount']) {
throw new \Exception('每日提现金额不能大于 ' . $config['perday_amount'] . '元');
}
}
// 检查提现账户信息
$bank = \addons\shopro\model\UserBank::info($type, false);
// 添加提现记录
$platform = request()->header('platform');
$apply = new self();
$apply->apply_sn = self::getSn($user->id);
$apply->user_id = $user->id;
$apply->money = $money;
$apply->charge_money = $charge;
$apply->service_fee = $service_fee;
$apply->apply_type = $type;
$apply->platform = $platform;
switch ($type) {
case 'wechat':
$applyInfo = [
'微信用户' => $bank['real_name'],
'微信ID' => $bank['card_no'],
];
break;
case 'alipay':
$applyInfo = [
'真实姓名' => $bank['real_name'],
'支付宝账户' => $bank['card_no']
];
break;
case 'bank':
$applyInfo = [
'真实姓名' => $bank['real_name'],
'开户行' => $bank['bank_name'],
'银行卡号' => $bank['card_no']
];
break;
}
if (!isset($applyInfo)) {
throw new \Exception('您的提现信息有误');
}
$apply->apply_info = $applyInfo;
$apply->status = 0;
$apply->save();
self::handleLog($apply, '用户发起提现申请');
// 扣除用户余额
User::money(- ($money + $charge), $user->id, 'cash', $apply->id);
// 检查是否执行自动打款
$autoCheck = false;
if ($type !== 'bank' && $config['wechat_alipay_auto']) {
$autoCheck = true;
}
if ($autoCheck) {
$apply = self::handleAgree($apply);
$apply = self::handleWithdraw($apply);
}
return $apply;
}
public static function handleLog($apply, $oper_info)
{
$log = $apply->log;
$oper = \addons\shopro\library\Oper::set();
$log[] = [
'oper_type' => $oper['oper_type'],
'oper_id' => $oper['oper_id'],
'oper_info' => $oper_info,
'oper_time' => time()
];
$apply->log = $log;
$apply->save();
return $apply;
}
// 同意
public static function handleAgree($apply)
{
if ($apply->status != 0) {
throw new \Exception('请勿重复操作');
}
$apply->status = 1;
$apply->save();
return self::handleLog($apply, '同意提现申请');
}
// 处理打款
public static function handleWithdraw($apply)
{
$withDrawStatus = false;
if ($apply->status != 1) {
throw new \Exception('请勿重复操作');
}
if ($apply->apply_type !== 'bank') {
$withDrawStatus = self::handleTransfer($apply);
} else {
$withDrawStatus = true;
}
if ($withDrawStatus) {
$apply->status = 2;
$apply->actual_money = $apply->money;
$apply->save();
return self::handleLog($apply, '已打款');
}
return $apply;
}
// 拒绝
public static function handleReject($apply, $rejectInfo)
{
if ($apply->status != 0 && $apply->status != 1) {
throw new \Exception('请勿重复操作');
}
$apply->status = -1;
$apply->save();
User::money($apply->money + $apply->charge_money, $apply->user_id, 'cash_error', $apply->id);
return self::handleLog($apply, '拒绝:' . $rejectInfo);
}
// 企业付款提现
private static function handleTransfer($apply)
{
$type = $apply->apply_type;
$platform = $apply->platform;
try {
if ($type == 'wechat') {
$payload = [
'partner_trade_no' => $apply->apply_sn,
'openid' => $apply->apply_info['微信ID'],
'check_name' => 'NO_CHECK',
'amount' => $apply->money,
'desc' => "用户[{$apply->apply_info['微信用户']}]提现"
];
} elseif ($type == 'alipay') {
$payload = [
'out_biz_no' => $apply->apply_sn,
'trans_amount' => $apply->money,
'product_code' => 'TRANS_ACCOUNT_NO_PWD',
'biz_scene' => 'DIRECT_TRANSFER',
// 'order_title' => '余额提现到',
'remark' => '用户提现',
'payee_info' => [
'identity' => $apply->apply_info['支付宝账户'],
'identity_type' => 'ALIPAY_LOGON_ID',
'name' => $apply->apply_info['真实姓名'],
]
];
}
} catch (\Exception $e) {
throw new \Exception('提现信息不正确');
}
try {
$pay_version = pay_version();
if ($pay_version == 'v3') {
$payService = new \addons\shopro\library\payv3\PayServiceV3($type, $platform);
list($code, $response) = $payService->transfer($payload);
} else {
$pay = new \addons\shopro\library\PayService($type, $platform, '', 'transfer');
list($code, $response) = $pay->transfer($payload);
}
if ($code === 1) {
$apply->payment_json = json_encode($response, JSON_UNESCAPED_UNICODE);
$apply->save();
return true;
} else {
// 提现失败
throw new \Exception(json_encode($response, JSON_UNESCAPED_UNICODE));
}
} catch (\Exception $e) {
\think\Log::error('提现失败:' . ' 行号:' . $e->getLine() . '文件:' . $e->getFile() . '错误信息:' . $e->getMessage());
throw new \Exception($e->getMessage());
}
return false;
}
/**
* 提现类型列表
*/
public function getApplyTypeList()
{
return ['bank' => '银行卡', 'wechat' => '微信零钱', 'alipay' => '支付宝账户'];
}
/**
* 提现类型中文
*/
public function getApplyTypeTextAttr($value, $data)
{
$value = isset($data['apply_type']) ? $data['apply_type'] : '';
$list = $this->getApplyTypeList();
return isset($list[$value]) ? $list[$value] : '';
}
/**
* 提现信息
*/
public function getApplyInfoAttr($value, $data)
{
$value = isset($data['apply_info']) ? $data['apply_info'] : $value;
return json_decode($value, true);
}
/**
* 提现信息 格式转换
*/
public function setApplyInfoAttr($value, $data)
{
$value = isset($data['apply_info']) ? $data['apply_info'] : $value;
$applyInfo = json_encode($value, JSON_UNESCAPED_UNICODE);
return $applyInfo;
}
public function getStatusTextAttr($value, $data)
{
switch ($data['status']) {
case 0:
$status_name = '审核中';
break;
case 1:
$status_name = '处理中';
break;
case 2:
$status_name = '已处理';
break;
case -1:
$status_name = '已拒绝';
break;
default:
$status_name = '';
}
return $status_name;
}
public static function getWithdrawConfig()
{
$config = \addons\shopro\model\Config::where('name', 'withdraw')->find();
return json_decode($config['value'], true);
}
/**
* 获取日志字段数组
*/
public function getLogAttr($value, $data)
{
$value = array_filter((array)json_decode($value, true));
return (array)$value;
}
/**
* 设置日志字段
* @param mixed $value
* @return string
*/
public function setLogAttr($value)
{
$value = is_object($value) || is_array($value) ? json_encode($value, JSON_UNESCAPED_UNICODE) : $value;
return $value;
}
}