| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520 |
- <?php
- /**
- * VIP套餐仓库.
- * @author jim <jim458734573@gmail.com>
- * @date 2020-01-29 10:10:06
- */
- declare(strict_types=1);
- namespace App\Repositories;
- use App\Constants\ChangeLogConstant;
- use App\Constants\CommonConstant;
- use App\Exception\ApiException;
- use App\Model\CoinsLogModel;
- use App\Model\CollectionsModel;
- use App\Model\UserModel;
- use App\Model\VipCardModel;
- use App\Model\VipOrderModel;
- use App\Repositories\Service\CommonService;
- use App\Repositories\Service\PaymentService;
- use App\Repositories\Service\QueueService;
- use App\Repositories\UserRepository;
- use Carbon\Carbon;
- use Hyperf\DbConnection\Db;
- use KZ2\Repositories\Model\Repository;
- use Psr\SimpleCache\CacheInterface;
- use App\Repositories\Utils\M3u8CacheRepository;
- class VipRepository extends Repository
- {
- public function model()
- {
- return VipCardModel::class;
- }
- /**
- * 获取vip套餐信息
- * @return array
- */
- public function getCanUseVipList($id = 0)
- {
- $list = make(CacheInterface::class)
- ->remember(
- 'vip_list',
- 60 * 60,
- function () {
- $arrItems = [];
- $items = VipCardModel::query()
- ->where('status', 1)
- ->orderByDesc('sort')
- ->get()->keyBy('id');
- if ($items->count()) {
- $arrItems = $items->toArray();
- foreach ($arrItems as $k => $v) {
- $arrJson = [];
- if (!empty($v['jdata'])) {
- $arrJson = json_decode($v['jdata'], true);
- }
- $arrItems[$k]['jdata'] = $arrJson;
- }
- }
- return $arrItems;
- }
- );
- if ($id) {
- return isset($list[$id]) ? $list[$id] : [];
- } else {
- return $list;
- }
- }
- /**
- * 删除vip套餐缓存 后台相关操作的时候调用此方法
- * @return bool
- */
- public function delUserVipCache()
- {
- return make(CacheInterface::class)->delete('vip_list');
- }
- /**
- * 获取vip套餐信息
- * @return array
- */
- public function getVipPackageData()
- {
- $result = array();
- $vipList = $this->getCanUseVipList();
- if ($vipList) {
- foreach ($vipList as $item) {
- $item['true_price'] = floatval($item['true_price']);
- $payment = make(PaymentService::class)
- ->getPayGatewayByAmount($item['true_price']);
- $tempItem = array(
- 'id' => $item['id'],
- 'title' => $item['title'],
- 'remark' => $item['remark'],
- 'day' => $item['day'] >= 9999 ? '永久无限' : $item['day'] . '天',
- 'price' => round($item['true_price']) . '',
- 'payment' => $payment,
- 'color' => $item['color'] ?? '',
- 'jdata' => $item['jdata'],
- 'intro' => $item['intro'] ?? '',
- 'mark' => $item['mark'] ?? '',
- 'is_super' => $item['is_super'] ?? 0,
- 'send_type' => $item['send_type'] ?? 0,
- 'send_num' => $item['send_num'] ?? 0,
- 'send_remark' => $item['send_remark'] ?? '',
- );
- $result [] = $tempItem;
- }
- }
- return $result;
- }
- /**
- * 获取vip套餐信息(大鲨鱼版)
- * @return array
- */
- public function getVipPackage($coins = 0, $deviceType = '')
- {
- $result = array();
- $vipList = $this->getCanUseVipList();
- $paymentList = make(PaymentService::class)->getAllPayments();
- if ($vipList) {
- $price_array = [];
- foreach ($vipList as $item) {
- $item['true_price'] = floatval($item['true_price']);
- $price_array[] = $item['true_price'];
- $truePrice = (float)$item['true_price'];
- $price = (float)$item['price'];
- $payment = make(PaymentService::class)
- ->getPayGatewayByAmount($item['true_price'], $deviceType, $paymentList);
- if ($coins >= $item['true_price']) {
- $cotnType = [
- 'id' => 1,
- 'name' => '金币',
- 'img' => M3u8CacheRepository::getImageUrl('f2|/'. env('STATIC_DIR_NAME', 'doukui') . '/pay_type/4_144x144.ceb'),
- 'pay_type' => 4
- ];
- array_push($payment, $cotnType);
- }
- $tempItem = array(
- 'id' => $item['id'],
- 'title' => $item['title'],
- 'remark' => $item['remark'],
- 'day' => $item['day'] >= 9999 ? '永久无限' : $item['day'] . '天',
- 'price' => $price,
- 'true_price' => $truePrice,
- 'payment' => $payment,
- 'color' => $item['color'] ?? '',
- 'jdata' => $item['jdata'],
- 'intro' => $item['intro'] ?? '',
- 'mark' => $item['mark'] ?? '',
- 'is_super' => $item['is_super'] ?? 0,
- 'send_type' => $item['send_type'] ?? 0,
- 'send_num' => $item['send_num'] ?? 0,
- 'send_remark' => $item['send_remark'] ?? '',
- 'coins' => $item['coins'] ?? 0,
- 'coin_remark' => $item['coin_remark'] ?? '', // 花金币购买促销描述,例如文案:金币支付优惠20元
- );
- $result[] = $tempItem;
- }
- /*$payment = [
- [
- 'pay_type' => 'ali',
- 'gatway' => 'ali:ys',
- 'pay_name' => '支付宝',
- 'img' => 'f2|/'. env('STATIC_DIR_NAME', 'doukui') . '/pay_type/ali_144x144.ceb',
- ],
- [
- 'pay_type' => 'wx',
- 'gatway' => 'wx:hf',
- 'pay_name' => '微信',
- 'img' => 'f2|/'. env('STATIC_DIR_NAME', 'doukui') . '/pay_type/wx_144x144.ceb',
- ],
- [
- 'pay_type' => 'union',
- 'gatway' => 'union:ys',
- 'pay_name' => '银联',
- 'img' => 'f2|/'. env('STATIC_DIR_NAME', 'doukui') . '/pay_type/union_144x144.ceb',
- ],
- [
- 'pay_type' => 'coin',
- 'gatway' => 'coin:coin',
- 'pay_name' => '金币',
- 'img' => 'f2|/'. env('STATIC_DIR_NAME', 'doukui') . '/pay_type/coin_144x144.ceb',
- ],
- ];*/
- }
- return $result;
- }
- /**
- * 创建vip订单
- * @param array $requestData 请求参数
- * @return mixed
- */
- public function createVipOrder($requestData)
- {
- $userInfo = make(UserRepository::class)
- ->getUserInfoFromCache($requestData['user_id']);
- if (!$userInfo) {
- throw new ApiException('账号异常');
- }
- $vipItem = $this->getCanUseVipList($requestData['vip_id']);
- if (!$vipItem) {
- throw new ApiException('vip套餐不存在');
- }
- $vipItem['true_price'] = floatval($vipItem['true_price']);
- //次数控制 十秒钟内同支付方式只允许一单
- $queryTime = Carbon::now()->modify('-10 second')->toDateTimeString();
- $orderNum = VipOrderModel::query()
- ->where('user_id', '=', $userInfo['id'])
- ->where('created_at', '>', $queryTime)->count();
- if ($orderNum > 0) {
- throw new ApiException('亲,麻烦歇一会呢');
- }
- //生成订单
- $orderSn = make(CommonService::class)->createOrderSn(CommonConstant::APP_SHORT_NAME);
- $insertData = array(
- 'order_sn' => $orderSn,
- 'order_type' => $requestData['order_type'],
- 'user_id' => $userInfo['id'],
- 'user_code' => $userInfo['code'],
- 'user_parent_id' => $userInfo['parent_uid'] ?: 0,
- 'user_channel_id' => $userInfo['channel_id'],
- 'vip_title' => $vipItem['title'],
- 'vip_id' => $requestData['vip_id'],
- 'vip_days' => $vipItem['day'],
- 'pay_type' => $requestData['pay_type'],
- 'device_type' => $userInfo['device_type'],
- 'order_amount' => $vipItem['true_price'],
- 'real_amount' => $vipItem['true_price'],
- 'package_info' => json_encode($vipItem),
- 'trade_no' => $orderSn,
- 'status'=>3,
- );
- $result = VipOrderModel::query()->create($insertData);
- $jobData = clone $result;
- if (empty($result)) {
- return [];
- }
- $jobData = $jobData->toArray();
- $jobData['user_info'] = $userInfo;
- // 代理系统异步订单
- make(QueueService::class)->agentOrderIncJob($jobData);
- return $result;
- }
- /**
- * 金币购买vip
- *
- * @param $requestData
- * @return bool
- */
- public function createCoinVipOrder($requestData)
- {
- $userInfo = make(UserRepository::class)->findBy('code', $requestData['user_id']);
- if (!$userInfo) {
- throw new ApiException('账号异常');
- }
- $vipItem = $this->getCanUseVipList($requestData['vip_id']);
- if (!$vipItem) {
- throw new ApiException('vip套餐不存在');
- }
- if ($userInfo->coins < $vipItem['coins']) {
- throw new ApiException('金币不足,请充值金币后购买会员');
- }
- //次数控制 一分钟内同支付方式只允许一单
- $queryTime = Carbon::now()->modify('-1 minute')->toDateTimeString();
- $orderNum = VipOrderModel::query()
- ->where('user_id', '=', $userInfo['id'])
- ->where('created_at', '>', $queryTime)->count();
- if ($orderNum > 0) {
- throw new ApiException('亲,麻烦歇一会呢');
- }
- Db::beginTransaction();
- //订单号
- $orderSn = make(CommonService::class)->createOrderSn(CommonConstant::APP_SHORT_NAME);
- $orderData = [
- 'order_sn' => $orderSn,
- 'order_type' => $requestData['order_type'],
- 'user_id' => $userInfo['id'],
- 'user_code' => $userInfo['code'],
- 'user_parent_id' => $userInfo['parent_uid'] ?: 0,
- 'user_channel_id' => $userInfo['channel_id'],
- 'vip_title' => $vipItem['title'],
- 'vip_id' => $requestData['vip_id'],
- 'vip_days' => $vipItem['day'],
- 'pay_type' => $requestData['pay_type'], //4 金币类型
- 'device_type' => $userInfo['device_type'],
- 'order_amount' => $vipItem['true_price'],
- 'real_amount' => $vipItem['true_price'],
- 'status' => 1,
- 'pay_time' => Carbon::now()->toDateTimeString(),
- 'trade_no' => $orderSn,
- 'package_info' => json_encode($vipItem),
- ];
- $result = VipOrderModel::query()->create($orderData);
- if (!$result) {
- Db::rollBack();
- throw new ApiException('亲,麻烦歇一会呢');
- }
- //写收款单
- // $collectionsData = [
- // 'user_id' => $userInfo['id'],
- // 'user_code' => $userInfo['code'],
- // 'order_sn' => $orderSn,
- // 'type' => $requestData['order_type'],
- // 'pay_type' => $requestData['pay_type'],
- // 'device_type' => $userInfo['device_type'],
- // 'channel' => $userInfo['channel_id'],
- // 'trade_sn' => $orderSn,
- // 'order_amount' => $vipItem['true_price'],
- // 'real_amount' => $vipItem['true_price'],
- // ];
- // $result1 = CollectionsModel::query()->create($collectionsData);
- //加会员天数
- $userInfoCache = make(UserRepository::class)
- ->getUserInfoFromCache($userInfo['code']);
- if ($userInfoCache['is_vip'] == 'y') {
- $vipTime = Carbon::parse($userInfoCache['vip_expired'])
- ->addDays($vipItem['day'])
- ->toDateTimeString();
- } else {
- $vipTime = Carbon::now()
- ->addDays($vipItem['day'])
- ->toDateTimeString();
- }
- $houseCount = 0;
- $userCoins = 0;
- foreach ($vipItem['jdata']['feature'] as $packVal) {
- switch ($packVal['type']) {
- case 'house':
- $houseCount = $packVal['count'];
- break;
- }
- }
- if ($vipItem['send_type'] == 2) {
- $userCoins = $vipItem['send_num'];
- }
- //扣除金币 todo 这个地方不用考虑并发问题,加金币和买会员不会同时进行
- $coin = $userInfo->coins - $vipItem['coins'] + $userCoins;
- $houseCount = $userInfo['max_open_house'] + $houseCount;
- $result2 = UserModel::query()
- ->where('id', $userInfo['id'])
- ->update(['vip_expired' => $vipTime, 'vip_level' => $vipItem['id'], 'coins' => $coin, 'max_open_house' => $houseCount]);
- if ($result2) {
- Db::commit();
- // 送金币帐变记录
- if ($userCoins > 0) {
- $changeData = [
- 'user_uid' => $userInfo->code,
- 'currency_type' => ChangeLogConstant::CHANGE_COIN,
- 'amount' => $userCoins,
- 'way' => ChangeLogConstant::WAY_1,
- 'type' => ChangeLogConstant::TYPE_23,
- ];
- make(QueueService::class)->saveChangeLogJob($changeData);
- }
- // 帐变记录
- $changeData = [
- 'user_uid' => $userInfo->code,
- 'currency_type' => ChangeLogConstant::CHANGE_COIN,
- 'amount' => $vipItem['coins'],
- 'way' => ChangeLogConstant::WAY_2,
- 'type' => ChangeLogConstant::TYPE_2,
- ];
- make(QueueService::class)->saveChangeLogJob($changeData);
- make(UserRepository::class)->delUserCache($userInfo['code']);
- return true;
- }
- Db::rollBack();
- return false;
- }
- /**
- * 处理支付回调
- * @param int $orderId
- * @param string $tradeNo
- * @param float $payMoney
- * @param int $orderType
- * @return bool
- */
- public function doBuy($orderId, $tradeNo, $payMoney, $orderType)
- {
- if (!$orderId || !$tradeNo || !$payMoney || !$orderType) {
- return false;
- }
- Db::beginTransaction();
- try {
- $orderItem = VipOrderModel::query()->where('id', $orderId)
- ->first();
- if (!$orderItem || $orderItem['status'] == 1) {
- logger('订单状态异常:', [$orderItem['status']]);
- Db::rollBack();
- return false;
- }
- $orderItem = $orderItem->toArray();
- //金额校验
- $orderMoney = floatval($orderItem['order_amount']);
- $payMoney = floatval($payMoney);
- $minusMoney = $orderMoney - $payMoney;
- $minusMoney = abs(round($minusMoney, 2));
- if ($minusMoney > 2) {
- //只允许订单金额和付款金额相差2元内
- Db::rollBack();
- return false;
- }
- //修改订单状态
- $updateData = array(
- 'real_amount' => $payMoney,
- 'status' => 1,
- 'pay_time' => Carbon::now()->toDateTimeString(),
- 'trade_no' => $tradeNo,
- );
- $result1 = VipOrderModel::query()
- ->where('id', $orderId)
- ->update($updateData);
- //写收款单
- $collectionsData = array(
- 'user_id' => $orderItem['user_id'],
- 'user_code' => $orderItem['user_code'],
- 'order_sn' => $orderItem['order_sn'],
- 'type' => $orderType,
- 'pay_type' => $orderItem['pay_type'],
- 'device_type' => $orderItem['device_type'],
- 'channel' => $orderItem['user_channel_id'],
- 'trade_sn' => $tradeNo,
- 'order_amount' => $orderMoney,
- 'real_amount' => $payMoney,
- );
- $result2 = CollectionsModel::query()->create($collectionsData);
- //加会员天数
- $userInfo = make(UserRepository::class)
- ->getUserInfoFromCache($orderItem['user_code']);
- if ($userInfo['is_vip'] == 'y') {
- $vipTime = Carbon::parse($userInfo['vip_expired'])
- ->addDays($orderItem['vip_days'])
- ->toDateTimeString();
- } else {
- $vipTime = Carbon::now()
- ->addDays($orderItem['vip_days'])
- ->toDateTimeString();
- }
- $package = json_decode($orderItem['package_info'], true);
- $houseCount = 0;
- $userCoins = 0;
- foreach ($package['jdata']['feature'] as $packVal) {
- switch ($packVal['type']) {
- case 'house':
- $houseCount = $packVal['count'];
- break;
- }
- }
- if ($package['send_type'] == 2) {
- $userCoins = $package['send_num'];
- }
- $houseCount = $userInfo['max_open_house'] + $houseCount;
- $coins = $userInfo['coins'] + $userCoins;
- $result3 = UserModel::query()
- ->where('id', $orderItem['user_id'])
- ->update(['vip_expired' => $vipTime, 'vip_level' => $orderItem['vip_id'], 'max_open_house' => $houseCount, 'coins' => $coins]);
- if ($result1 && $result2 && $result3) {
- Db::commit();
- $queue = make(QueueService::class);
- //返佣计算 异步
- $queue->rebateTwoUserJob(['amount' => $orderMoney, 'user_id' =>$orderItem['user_code']]);
- // 帐变记录
- if ($userCoins > 0) {
- // 帐变记录
- $changeData = [
- 'user_uid' => $orderItem['user_code'],
- 'currency_type' => ChangeLogConstant::CHANGE_COIN,
- 'amount' => $userCoins,
- 'way' => ChangeLogConstant::WAY_1,
- 'type' => ChangeLogConstant::TYPE_23,
- ];
- $queue->saveChangeLogJob($changeData);
- }
- // 代理系统异步订单
- $jobData = VipOrderModel::query()->where('id', $orderId)->first()->toArray();
- $jobData['user_info'] = UserModel::query()->find($orderItem['user_id'])->toArray();
- $queue->agentOrderIncJob($jobData);
- make(UserRepository::class)->delUserCache($orderItem['user_code']);
- return true;
- }
- } catch (\Exception $e) {
- logger('支付回调失败:', [$e->getMessage()]);
- }
- Db::rollBack();
- return false;
- }
- }
|