115 lines
3.4 KiB
PHP
115 lines
3.4 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\{User, Vip, UserVip, PayLog};
|
|
use App\Exceptions\BizException;
|
|
use App\Enums\{PayWay, SocialiteType, WxpayTradeType};
|
|
use App\Services\Payment\WxpayService;
|
|
use Carbon\Carbon;
|
|
|
|
class VipService
|
|
{
|
|
public function buy(User $user, Vip $vip)
|
|
{
|
|
if (!$vip->status) {
|
|
throw new BizException('该会员卡已关闭');
|
|
}
|
|
$user_vip = $user->vips()->create([
|
|
'vip_id' => $vip->id,
|
|
'name' => $vip->name,
|
|
'price' => $vip->price,
|
|
'times' => $vip->times,
|
|
'gift' => $vip->gift,
|
|
]);
|
|
|
|
return $user_vip;
|
|
}
|
|
|
|
public function pay(UserVip $userVip, $pay_way = '')
|
|
{
|
|
if (!$pay_way) {
|
|
$pay_way = PayWay::WxpayMiniProgram->value;
|
|
}
|
|
if ($userVip->status == 2) {
|
|
throw new BizException('支付处理中,请勿重复操作');
|
|
}
|
|
$userVip->update([
|
|
'status' => 2
|
|
]);
|
|
$pay_log = PayLog::create([
|
|
'payable_type' => UserVip::class,
|
|
'payable_id' => $userVip->id,
|
|
'pay_sn' => serial_number(),
|
|
'pay_way' => $pay_way
|
|
]);
|
|
$money = $userVip->price;
|
|
$debug = config('app.debug');
|
|
if ($debug) {
|
|
$money = 0.01;
|
|
}
|
|
$user = $userVip->user;
|
|
// 微信小程序支付
|
|
if ($pay_log->pay_way === PayWay::WxpayMiniProgram) {
|
|
$openid = $user->socialites()->where('socialite_type', SocialiteType::WechatMiniProgram)->value('socialite_id');
|
|
if (!$openid && $debug) {
|
|
$openid = 'oU7xS5UspzVvpPEBqKZuW6N9WXDg';
|
|
}
|
|
if (!$openid) {
|
|
throw new BizException('未找到用户的微信授权信息, 无法使用微信支付');
|
|
}
|
|
$params = [
|
|
'body' => app_settings('app.app_name').'-会员-' . $userVip->name,
|
|
'out_trade_no' => $pay_log->pay_sn,
|
|
'total_fee' => $money * 100,
|
|
'trade_type' => WxpayTradeType::JSAPI->value,
|
|
'openid' => $openid,
|
|
];
|
|
return (new WxpayService())->pay($params);
|
|
}
|
|
throw new BizException('未知的支付方式');
|
|
}
|
|
|
|
public function success(UserVip $userVip, array $params = null)
|
|
{
|
|
$userVip->update([
|
|
'status' => 1,
|
|
'success_time' => data_get($params, 'pay_at', now())
|
|
]);
|
|
$user = $userVip->user;
|
|
$vip_expired = $this->convertTimes(data_get($userVip->times, 'num'), data_get($userVip->times, 'unit'), $user->vip_expired);
|
|
$userVip->user->update([
|
|
'vip_expired' => $vip_expired
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 时间转换
|
|
*
|
|
* @param int $num 数量
|
|
* @param string $unit 单位
|
|
* @return Carbon
|
|
*/
|
|
public function convertTimes(int $num, string $unit, Carbon $start = null)
|
|
{
|
|
if (!$start) {
|
|
$start = now();
|
|
}
|
|
switch ($unit) {
|
|
case Vip::TIME_YEAR:
|
|
$start->addYears($num);
|
|
break;
|
|
case Vip::TIME_MONTH:
|
|
$start->addYears($num);
|
|
break;
|
|
case TIME_DAY:
|
|
$start->addDays($num);
|
|
break;
|
|
default:
|
|
throw new BizException('未知的时间单位');
|
|
}
|
|
|
|
return $start;
|
|
}
|
|
}
|