UserRechargeRepository.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\common\repositories\user;
  12. use app\common\dao\user\UserRechargeDao;
  13. use app\common\model\user\User;
  14. use app\common\model\user\UserRecharge;
  15. use app\common\repositories\BaseRepository;
  16. use crmeb\jobs\SendSmsJob;
  17. use crmeb\services\PayService;
  18. use think\facade\Db;
  19. use think\facade\Queue;
  20. /**
  21. * Class UserRechargeRepository
  22. * @package app\common\repositories\user
  23. * @author xaboy
  24. * @day 2020/6/2
  25. * @mixin UserRechargeDao
  26. */
  27. class UserRechargeRepository extends BaseRepository
  28. {
  29. const TYPE_WECHAT = 'weixin';
  30. const TYPE_ROUTINE = 'routine';
  31. /**
  32. * UserRechargeRepository constructor.
  33. * @param UserRechargeDao $dao
  34. */
  35. public function __construct(UserRechargeDao $dao)
  36. {
  37. $this->dao = $dao;
  38. }
  39. /**
  40. * 创建充值订单
  41. *
  42. * 本函数用于生成一个新的充值订单。它根据传入的用户ID、充值金额、赠送金额和充值类型,
  43. * 创建一个订单并返回订单数据。订单初始状态为未支付。
  44. *
  45. * @param int $uid 用户ID,用于关联订单和用户。
  46. * @param float $price 充值金额,单位为元,精确到小数点后两位。
  47. * @param float $givePrice 赠送金额,单位为元,精确到小数点后两位。
  48. * @param string $type 充值类型,用于区分不同的充值方式,如:支付宝、微信等。
  49. * @return array 返回新创建的订单数据。
  50. */
  51. public function create($uid, float $price, float $givePrice, string $type)
  52. {
  53. // 生成订单数据数组,包含用户ID、充值金额、赠送金额、充值类型、初始支付状态和订单ID。
  54. $orderData = [
  55. 'uid' => $uid,
  56. 'price' => $price,
  57. 'give_price' => $givePrice,
  58. 'recharge_type' => $type,
  59. 'paid' => 0, // 订单初始支付状态为未支付。
  60. 'order_id' => $this->dao->createOrderId($uid) // 生成唯一的订单ID。
  61. ];
  62. // 调用DAO层的方法创建订单,并返回创建的订单数据。
  63. return $this->dao->create($orderData);
  64. }
  65. /**
  66. * 获取列表数据
  67. * 通过此方法可以从数据库中检索满足特定条件的列表数据。它支持分页查询,以优化大型数据集的处理。
  68. *
  69. * @param string $where 查询条件,用于筛选数据。这是一个字符串,可能包含SQL的WHERE子句条件。
  70. * @param int $page 当前页码,用于分页查询。
  71. * @param int $limit 每页的数据条数,用于分页查询。
  72. * @return array 返回一个包含两个元素的数组,'count'表示数据总数,'list'表示当前页的数据列表。
  73. */
  74. public function getList($where, $page, $limit)
  75. {
  76. // 构建查询语句,包括JOIN操作和排序规则
  77. $query = $this->dao->searchJoinQuery($where)->order('a.pay_time DESC,a.create_time DESC');
  78. // 计算满足条件的数据总数
  79. $count = $query->count();
  80. // 执行分页查询,并获取当前页的数据列表
  81. $list = $query->page($page, $limit)->select();
  82. // 将数据总数和数据列表打包成数组返回
  83. return compact('count', 'list');
  84. }
  85. /**
  86. * 根据充值金额获取赠送金额。
  87. *
  88. * 本函数用于根据用户充值的金额,确定相应的赠送金额。系统预设了不同充值金额区间的赠送规则,
  89. * 本函数通过查询这些规则,找到适用的赠送金额。
  90. *
  91. * @param float $price 充值金额。
  92. * @return float 返回应赠送的金额。
  93. */
  94. public function priceByGive($price)
  95. {
  96. // 获取系统设置的充值额度和赠送额度规则
  97. $quota = systemGroupData('user_recharge_quota');
  98. $give = 0.0; // 初始化赠送金额为0
  99. // 遍历规则数组,找出适用的赠送规则
  100. foreach ($quota as $item) {
  101. $min = floatval($item['price']); // 当前规则的最低充值金额
  102. $_give = floatval($item['give']); // 当前规则的赠送金额
  103. // 如果当前充值金额大于等于当前规则的最低充值金额,更新赠送金额
  104. if ($price >= $min) {
  105. $give = $_give;
  106. }
  107. }
  108. return $give; // 返回计算出的赠送金额
  109. }
  110. /**
  111. * 处理用户充值支付逻辑。
  112. *
  113. * 根据支付类型和是否为APP环境,生成相应的支付配置。支持微信和支付宝两种支付方式,
  114. * 当在APP环境中支付时,支付类型会相应地加上App后缀。在支付前,会触发一个before充值事件,
  115. * 允许其他功能模块在充值前进行额外的操作或校验。最终,返回包含支付配置和充值ID等信息的数组。
  116. *
  117. * @param string $type 支付方式,支持'weixin'和'alipay'。
  118. * @param User $user 进行充值的用户对象。
  119. * @param UserRecharge $recharge 用户充值记录对象。
  120. * @param string $return_url 支付宝充值成功后的回调URL,可选。
  121. * @param bool $isApp 是否在APP环境中支付,默认为false。
  122. * @return array 包含支付配置和充值ID等信息的数组。
  123. */
  124. public function pay(string $type, User $user, UserRecharge $recharge, $return_url = '', $isApp = false)
  125. {
  126. // 根据支付方式和是否为APP环境,调整支付类型
  127. if (in_array($type, ['weixin', 'alipay'], true) && $isApp) {
  128. $type .= 'App';
  129. }
  130. // 触发用户充值前的事件,允许其他功能模块介入
  131. event('user.recharge.before', compact('user', 'recharge', 'type', 'isApp'));
  132. // 根据支付类型创建支付服务对象,并初始化支付参数
  133. $service = new PayService($type, $recharge->getPayParams($type === 'alipay' ? $return_url : ''), 'user_recharge');
  134. // 生成支付配置
  135. $config = $service->pay($user);
  136. // 返回支付配置,加上充值ID和支付类型,供前端进行支付操作
  137. return $config + ['recharge_id' => $recharge['recharge_id'], 'type' => $type];
  138. }
  139. /**
  140. * //TODO 余额充值成功
  141. *
  142. * @param $orderId
  143. * @throws \think\db\exception\DataNotFoundException
  144. * @throws \think\db\exception\DbException
  145. * @throws \think\db\exception\ModelNotFoundException
  146. * @author xaboy
  147. * @day 2020/6/19
  148. */
  149. public function paySuccess($orderId)
  150. {
  151. $recharge = $this->dao->getWhere(['order_id' => $orderId]);
  152. if ($recharge->paid == 1) return;
  153. $recharge->paid = 1;
  154. $recharge->pay_time = date('Y-m-d H:i:s');
  155. Db::transaction(function () use ($recharge) {
  156. $price = bcadd($recharge->price, $recharge->give_price, 2);
  157. $mark = '成功充值余额' . floatval($recharge->price) . '元' . ($recharge->give_price > 0 ? ',赠送' . $recharge->give_price . '元' : '');
  158. app()->make(UserBillRepository::class)->incBill($recharge->user->uid, 'now_money', 'recharge', [
  159. 'link_id' => $recharge->recharge_id,
  160. 'status' => 1,
  161. 'title' => '余额充值',
  162. 'number' => $price,
  163. 'mark' => $mark,
  164. 'balance' => bcadd($recharge->user->now_money, $price, 2)
  165. ]);
  166. $recharge->user->now_money = bcadd($recharge->user->now_money, $price, 2);
  167. $recharge->user->save();
  168. $recharge->save();
  169. });
  170. Queue::push(SendSmsJob::class,['tempId' => 'USER_BALANCE_CHANGE', 'id' =>$orderId]);
  171. //小程序发货管理
  172. event('mini_order_shipping', ['recharge', $recharge, 3, '', '']);
  173. event('user.recharge',compact('recharge'));
  174. }
  175. }