AbstractPayment.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <?php
  2. namespace App\Http\Controllers\Gateway;
  3. use App\Components\Helpers;
  4. use App\Models\Goods;
  5. use App\Models\Order;
  6. use App\Models\Payment;
  7. use App\Models\PaymentCallback;
  8. use App\Models\ReferralLog;
  9. use App\Models\User;
  10. use Illuminate\Http\JsonResponse;
  11. use Illuminate\Http\Request;
  12. use Log;
  13. abstract class AbstractPayment {
  14. protected static $systemConfig;
  15. public function __construct() {
  16. self::$systemConfig = Helpers::systemConfig();
  17. }
  18. abstract public function purchase(Request $request): JsonResponse;
  19. abstract public function notify(Request $request): void;
  20. protected function postPayment($data, $method): int {
  21. // 获取需要的信息
  22. $payment = Payment::query()->whereTradeNo($data)->latest()->first();
  23. // 是否为余额购买套餐
  24. if($payment){
  25. if($payment->status === 1){// 已处理
  26. return 0;
  27. }
  28. Payment::query()->whereTradeNo($data)->update(['status' => 1]);
  29. $order = Order::find($payment->oid);
  30. }else{
  31. $order = Order::find($data);
  32. }
  33. $goods = Goods::find($order->goods_id);
  34. $user = User::find($order->user_id);
  35. //余额充值
  36. if($order->goods_id == 0){
  37. Order::query()->whereOid($order->oid)->update(['status' => 2]);
  38. User::query()->whereId($order->user_id)->increment('credit', $order->amount * 100);
  39. // 余额变动记录日志
  40. Helpers::addUserCreditLog($order->user_id, $order->oid, $order->user->credit,
  41. $order->user->credit + $order->amount, $order->amount, '用户'.$method.'充值余额');
  42. return 0;
  43. }
  44. // 商品为流量或者套餐
  45. switch($goods->type){
  46. case 1:
  47. Order::query()->whereOid($order->oid)->update(['status' => 2]);
  48. User::query()->whereId($order->user_id)->increment('transfer_enable', $goods->traffic * MB);
  49. Helpers::addUserTrafficModifyLog($order->user_id, $order->oid, $user->transfer_enable,
  50. $user->transfer_enable + $goods->traffic * MB, '['.$method.']加上用户购买的套餐流量');
  51. break;
  52. case 2:
  53. $activePlan = Order::query()
  54. ->whereUserId($user->id)
  55. ->with(['goods'])
  56. ->whereIsExpire(0)
  57. ->whereStatus(2)
  58. ->whereHas('goods', static function($q) {
  59. $q->whereType(2);
  60. })
  61. ->exists();
  62. // 2为开始生效,3为预支付
  63. $order->status = $activePlan? 3 : 2;
  64. $order->save();
  65. if($activePlan){
  66. // 预支付订单, 刷新账号有效时间用于流量重置判断
  67. User::query()->whereId($order->user_id)->update([
  68. 'expire_time' => date('Y-m-d',
  69. strtotime("+".$goods->days." days", strtotime($user->expire_time)))
  70. ]);
  71. }else{
  72. // 如果买的是套餐,则先将之前购买的套餐都无效化,重置用户已用、可用流量为0
  73. Order::query()->whereUserId($user->id)->with(['goods'])->whereHas('goods', static function($q) {
  74. $q->where('type', '<=', 2);
  75. })->whereIsExpire(0)->whereStatus(2)->where('oid', '<>', $order->oid)->update([
  76. 'expired_at' => date('Y-m-d H:i:s'),
  77. 'is_expire' => 1
  78. ]);
  79. User::query()->whereId($order->user_id)->update(['u' => 0, 'd' => 0, 'transfer_enable' => 0]);
  80. Helpers::addUserTrafficModifyLog($order->user_id, $order->oid, $user->transfer_enable, 0,
  81. '['.$method.']用户购买新套餐,先清空流量');
  82. $userTraffic = $goods->traffic * MB;
  83. // 添加账号有效期
  84. $expireTime = date('Y-m-d', strtotime("+".$goods->days." days"));
  85. //账号下一个重置时间
  86. $nextResetTime = date('Y-m-d', strtotime("+".$goods->period." days"));
  87. if($nextResetTime >= $expireTime){
  88. $nextResetTime = null;
  89. }
  90. User::query()->whereId($order->user_id)->increment('invite_num', $goods->invite_num?: 0, [
  91. 'transfer_enable' => $userTraffic,
  92. 'reset_time' => $nextResetTime,
  93. 'expire_time' => $expireTime,
  94. 'level' => $goods->level,
  95. 'enable' => 1
  96. ]);
  97. Helpers::addUserTrafficModifyLog($order->user_id, $order->oid, $user->transfer_enable, $userTraffic,
  98. '['.$method.']加上用户购买的套餐流量');
  99. }
  100. // 是否返利
  101. if(self::$systemConfig['referral_type'] && $order->user->referral_uid){
  102. //获取历史返利记录
  103. $referral = ReferralLog::whereUserId($order->user_id)->get();
  104. // 无记录 / 首次返利
  105. if(!$referral && self::$systemConfig['is_invite_register']){
  106. // 邀请注册功能开启时,返还邀请者邀请名额
  107. User::query()->whereId($order->user->referral_uid)->increment('invite_num', 1);
  108. }
  109. //按照返利模式进行返利判断
  110. if(self::$systemConfig['referral_type'] == 2 || (self::$systemConfig['referral_type'] == 1 && !$referral)){
  111. $this->addReferralLog($order->user_id, $order->user->referral_uid, $order->oid, $order->amount,
  112. $order->amount * self::$systemConfig['referral_percent']);
  113. }
  114. }
  115. break;
  116. default:
  117. Log::info('【处理订单】出现错误-未知套餐类型');
  118. }
  119. return 0;
  120. }
  121. /**
  122. * 添加返利日志
  123. *
  124. * @param int $userId 用户ID
  125. * @param int $refUserId 返利用户ID
  126. * @param int $oid 订单ID
  127. * @param int $amount 发生金额
  128. * @param int $refAmount 返利金额
  129. *
  130. * @return int
  131. */
  132. private function addReferralLog($userId, $refUserId, $oid, $amount, $refAmount): int {
  133. $log = new ReferralLog();
  134. $log->user_id = $userId;
  135. $log->ref_user_id = $refUserId;
  136. $log->order_id = $oid;
  137. $log->amount = $amount;
  138. $log->ref_amount = $refAmount;
  139. $log->status = 0;
  140. return $log->save();
  141. }
  142. protected function creatNewPayment($uid, $oid, $amount): Payment {
  143. $payment = new Payment();
  144. $payment->trade_no = makeRandStr(8);
  145. $payment->user_id = $uid;
  146. $payment->oid = $oid;
  147. $payment->amount = $amount;
  148. $payment->save();
  149. return $payment;
  150. }
  151. /**
  152. * @param string $trade_no 本地订单号
  153. * @param string $out_trade_no 外部订单号
  154. * @param int $amount 交易金额
  155. * @return int
  156. */
  157. protected function addPamentCallback($trade_no, $out_trade_no, $amount): int {
  158. $log = new PaymentCallback();
  159. $log->trade_no = $trade_no;
  160. $log->out_trade_no = $out_trade_no;
  161. $log->amount = $amount;
  162. return $log->save();
  163. }
  164. // MD5验签
  165. protected function verify($data, $key, $signature): bool {
  166. return hash_equals($this->aliStyleSign($data, $key), $signature);
  167. }
  168. /**
  169. * Alipay式数据MD5签名
  170. * @param array $data 需要加密的数组
  171. * @param string $key 尾部的密钥
  172. * @return string md5加密后的数据
  173. */
  174. protected function aliStyleSign($data, $key): string {
  175. // 剃离sign,sign_type,空值
  176. unset($data['sign'], $data['sign_type']);
  177. $data = array_filter($data);
  178. // 排序
  179. ksort($data, SORT_STRING);
  180. reset($data);
  181. return md5(urldecode(http_build_query($data)).$key);
  182. }
  183. }