| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- <?php
- /**
- * 金币仓库.
- * @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\OrderConstrant;
- use App\Model\CoinsLogModel;
- use App\Model\CoinsModel;
- use App\Model\CoinsOrderModel;
- use App\Model\CollectionsModel;
- use App\Model\UserModel;
- use App\Repositories\Service\CommonService;
- use App\Repositories\Service\PaymentService;
- use App\Repositories\Service\QueueService;
- use Carbon\Carbon;
- use Hyperf\Database\Model\Builder;
- use Hyperf\DbConnection\Db;
- use KZ2\Repositories\Model\Repository;
- use Psr\SimpleCache\CacheInterface;
- use App\Constants\CommonConstant;
- class CoinsRepository extends Repository
- {
- /**
- * @return Builder|mixed
- */
- public function model()
- {
- return CoinsModel::class;
- }
- /**
- * 定义金币记录类型
- * @return array
- */
- public function getCoinsTypeArr()
- {
- return array(
- 1 => '购买金币',
- 2 => '购买会员', //金币购买会员
- );
- }
- /**
- * 增加用户金币,在外层调用业务中使用事物、否则会存在事物套事物的情况
- * @param array|int $user 用户 数组 or 用户id
- * @param float $amount 金额 大于0
- * @param int $type 类型
- * @param string $orderSn 流水号 如果是因为订单之类的、可以传订单流水号进来、方便后期查询
- * @return bool
- */
- public function addCoins($userCode, $amount, $type, $collectionsData = [], $orderId = '')
- {
- if (!$userCode || !$amount || !$type || $amount <= 0) {
- return false;
- }
- $user = UserModel::where('code', $userCode)->first();
- if (!$user) {
- return false;
- }
- $user = $user->toArray();
- //增加用户金币
- $result1 = UserModel::where('id', $user['id'])->increment('coins', $amount);
- if ($result1) {
- // 帐变记录
- $changeData = [
- 'user_uid' => $userCode,
- 'currency_type' => ChangeLogConstant::CHANGE_COIN,
- 'amount' => $amount,
- 'way' => ChangeLogConstant::WAY_1,
- 'type' => ChangeLogConstant::TYPE_1,
- ];
- make(QueueService::class)->saveChangeLogJob($changeData);
- // 写收款单据
- $collectionsData['device_type'] = $user['device_type'];
- CollectionsModel::create($collectionsData);
- $jobData = CoinsOrderModel::query()->where('id', $orderId)->first()->toArray();
- $jobData['user_info'] = $user;
- make(QueueService::class)->agentOrderIncJob($jobData);
- return true;
- }
- return false;
- }
- /**
- * 减少用户金币,在外层调用业务中使用事物、否则会存在事物套事物的情况
- * @param array|int $user 用户 数组 or 用户id
- * @param float $amount 金额 小于0
- * @param int $type 类型
- * @param string $orderSn 流水号 如果是因为订单之类的、可以传订单流水号进来、方便后期查询
- * @return bool
- */
- public function reduceCoins($user, $amount, $type, $orderSn = '')
- {
- if (!$user || !$amount || !$type || $amount >= 0) {
- return false;
- }
- if (is_numeric($user)) {
- $user = UserModel::where('id', $user)->first()->toArray();
- }
- if (!$user) {
- return false;
- }
- if (empty($orderSn)) {
- $orderSn = make(CommonService::class)->createOrderSn('C');
- }
- //增加用户金币
- $result1 = UserModel::where('id', $user['id'])->increment('coins', $amount);
- //写金币日志
- $amountLog = $user['coins'] + $amount;
- $logData = array(
- 'user_id' => $user['id'],
- 'user_code' => $user['code'],
- 'amount' => $amount,
- 'amount_log' => $amountLog,
- 'coin_type' => $type,
- 'order_sn' => $orderSn,
- );
- $result2 = CoinsLogModel::create($logData);
- if ($result1 && $result2) {
- return true;
- }
- return false;
- }
- /**
- * 获取所有能使用的金币套餐
- * @return array
- */
- public function getCanUseCoinsList()
- {
- $result = make(CacheInterface::class)->remember(
- 'user_coins_list',
- 60 * 60,
- function () {
- $tempData = array();
- $tempResult = CoinsModel::query()
- ->where('status', 1)
- ->orderBy('sort', 'DESC')
- ->get()
- ->toArray();
- if ($tempResult) {
- foreach ($tempResult as $tempItem) {
- $tempData[$tempItem['id']] = $tempItem;
- }
- }
- return $tempData;
- }
- );
- return $result;
- }
- /**
- * 删除金币套餐缓存 后台相关操作的时候调用此方法
- * @return bool
- */
- public function delUserCoinsCache()
- {
- make(CacheInterface::class)
- ->deleteMultiple(array('user_coins_list'));
- return true;
- }
- /**
- * 获取用户金币套餐信息
- * @return array
- */
- public function getUserCoinsPackageData($deviceType = '')
- {
- $result = array();
- $vipList = $this->getCanUseCoinsList();
- $paymentList = make(PaymentService::class)->getAllPayments();
- if ($vipList) {
- $buyNotice = make(ConfigRepoistory::class)->get('coins_intro', 'rule', '');
- foreach ($vipList as $item) {
- $payment = make(PaymentService::class)->getPayGatewayByAmount($item['real_price'], $deviceType, $paymentList);
- $tempItem = array(
- 'id'=>$item['id'],
- 'coins'=>$item['coins'].'',
- 'price'=>round(floatval($item['price'])).'',
- 'real_price' => round(floatval($item['real_price'])).'',
- 'intro'=>$item['title_desc'],
- 'buy_notice'=>$buyNotice,
- 'payment'=>$payment,
- );
- $result []= $tempItem;
- }
- }
- return $result;
- }
- /**
- * 生成金币订单
- * @param array $requestData
- * @return int
- */
- public function createCoinsOrder($requestData)
- {
- if (empty($requestData['pay_id']) || empty($requestData['user_id']) || empty($requestData['coin_id'])) {
- throw new \App\Exception\ApiException('参数错误');
- }
- $userInfo = make(UserRepository::class)->getUserInfoFromCache($requestData['user_id']);
- if (!$userInfo) {
- throw new \App\Exception\ApiException('账号异常');
- }
- $coinList = $this->getCanUseCoinsList();
- if (!isset($coinList[$requestData['coin_id']])) {
- throw new \App\Exception\ApiException('套餐不存在');
- }
- $coinItem = $coinList[$requestData['coin_id']];
- //次数控制 一分钟内同支付方式只允许一单
- $queryTime = Carbon::now()->modify('-1 minute')->toDateTimeString();
- $orderNum = make(CoinsOrderModel::class)
- ->where('user_id', '=', $userInfo['id'])
- // ->where('payment_id', '=', $payment['id'])
- ->where('created_at', '>', $queryTime)
- ->count();
- if ($orderNum > 0) {
- throw new \App\Exception\ApiException('亲,麻烦歇一会呢');
- }
- //生成订单
- Db::beginTransaction();
- try {
- $orderSn = make(CommonService::class)->createOrderSn(CommonConstant::APP_SHORT_NAME);
- $insertData = array(
- 'order_sn' => $orderSn,
- 'user_id' => $userInfo['id'],
- 'user_code' => $userInfo['code'],
- 'user_parent_id' => $userInfo['parent_uid'] ?: 0,
- 'user_channel_id' => $userInfo['channel_id'],
- 'coins_id' => $requestData['coin_id'],
- 'coins' => $coinItem['coins'],
- 'order_amount' => $coinItem['price'],
- 'real_amount' => $coinItem['real_price'],
- 'payment_name' => OrderConstrant::$messages[$requestData['pay_type']] ?? '官方通道',
- 'status' => 3,
- 'trade_no' => $orderSn,
- 'package_info' => json_encode($coinItem),
- );
- $result = CoinsOrderModel::create($insertData);
- if ($result) {
- Db::commit();
- $jobData = clone $result;
- $jobData = $jobData->toArray();
- $jobData['user_info'] = $userInfo;
- // 代理系统异步订单
- make(QueueService::class)->agentOrderIncJob($jobData);
- return $result;
- }
- } catch (\Exception $e) {
- logger($e->getMessage());
- }
- Db::rollBack();
- return 0;
- }
- /**
- * 金额回调
- * @param int $orderId 订单id
- * @param string $tradeNo 交易单号
- * @param float $payMoney 支付金额
- * @return bool
- */
- public function doBuy($orderId, $tradeNo, $payMoney)
- {
- if (!$orderId || !$tradeNo || !$payMoney) {
- return false;
- }
- Db::beginTransaction();
- try {
- $orderItem = CoinsOrderModel::where('id', $orderId)->first()->toArray();
- if (!$orderItem || $orderItem['status'] == 1) {
- Db::rollBack();
- return false;
- }
- //金额校验
- $orderMoney = floatval($orderItem['real_amount']);
- $payMoney = floatval($payMoney);
- $minusMoney = floatval($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 = CoinsOrderModel::where('id', $orderId)->update($updateData);
- //写收款单
- $collectionsData = array(
- 'user_id' => $orderItem['user_id'],
- 'user_code' => $orderItem['user_code'],
- 'order_sn' => $orderItem['order_sn'],
- 'trade_sn' => $tradeNo,
- 'order_amount' => $orderMoney,
- 'real_amount' => $payMoney,
- 'type' => 2,
- );
- //加金币
- $result3 = $this->addCoins($orderItem['user_code'], $orderItem['coins'], 2, $collectionsData, $orderId);
- if ($result1 && $result3) {
- Db::commit();
- make(UserRepository::class)->delUserCache($orderItem['user_code']);
- return true;
- }
- } catch (\Exception $e) {
- Db::rollBack();
- return false;
- }
- Db::rollBack();
- return false;
- }
- }
|