PaymentController.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Components\Helpers;
  4. use App\Components\Yzy;
  5. use App\Http\Models\Coupon;
  6. use App\Http\Models\Goods;
  7. use App\Http\Models\Order;
  8. use App\Http\Models\Payment;
  9. use App\Http\Models\PaymentCallback;
  10. use Illuminate\Http\Request;
  11. use Response;
  12. use Redirect;
  13. use Log;
  14. use DB;
  15. use Auth;
  16. /**
  17. * 支付控制器
  18. *
  19. * Class PaymentController
  20. *
  21. * @package App\Http\Controllers
  22. */
  23. class PaymentController extends Controller
  24. {
  25. protected static $systemConfig;
  26. function __construct()
  27. {
  28. self::$systemConfig = Helpers::systemConfig();
  29. }
  30. // 创建支付单
  31. public function create(Request $request)
  32. {
  33. $goods_id = intval($request->get('goods_id'));
  34. $coupon_sn = $request->get('coupon_sn');
  35. $goods = Goods::query()->where('is_del', 0)->where('status', 1)->where('id', $goods_id)->first();
  36. if (!$goods) {
  37. return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:商品或服务已下架']);
  38. }
  39. // 判断是否开启有赞云支付
  40. if (!self::$systemConfig['is_youzan']) {
  41. return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:系统并未开启在线支付功能']);
  42. }
  43. // 判断是否存在同个商品的未支付订单
  44. $existsOrder = Order::query()->where('status', 0)->where('user_id', Auth::user()->id)->where('goods_id', $goods_id)->exists();
  45. if ($existsOrder) {
  46. return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:尚有未支付的订单,请先去支付']);
  47. }
  48. // 限购控制
  49. $strategy = self::$systemConfig['goods_purchase_limit_strategy'];
  50. if ($strategy == 'all' || ($strategy == 'package' && $goods->type == 2) || ($strategy == 'free' && $goods->price == 0) || ($strategy == 'package&free' && ($goods->type == 2 || $goods->price == 0))) {
  51. $noneExpireOrderExist = Order::query()->where('status', '>=', 0)->where('is_expire', 0)->where('user_id', Auth::user()->id)->where('goods_id', $goods_id)->exists();
  52. if ($noneExpireOrderExist) {
  53. return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:商品不可重复购买']);
  54. }
  55. }
  56. // 单个商品限购
  57. if ($goods->is_limit == 1) {
  58. $noneExpireOrderExist = Order::query()->where('status', '>=', 0)->where('user_id', Auth::user()->id)->where('goods_id', $goods_id)->exists();
  59. if ($noneExpireOrderExist) {
  60. return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:此商品每人限购1次']);
  61. }
  62. }
  63. // 使用优惠券
  64. if ($coupon_sn) {
  65. $coupon = Coupon::query()->where('status', 0)->where('is_del', 0)->whereIn('type', [1, 2])->where('sn', $coupon_sn)->first();
  66. if (!$coupon) {
  67. return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:优惠券不存在']);
  68. }
  69. // 计算实际应支付总价
  70. $amount = $coupon->type == 2 ? $goods->price * $coupon->discount / 10 : $goods->price - $coupon->amount;
  71. $amount = $amount > 0 ? $amount : 0;
  72. } else {
  73. $amount = $goods->price;
  74. }
  75. // 价格异常判断
  76. if ($amount < 0) {
  77. return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:订单总价异常']);
  78. } elseif ($amount == 0) {
  79. return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:订单总价为0,无需使用在线支付']);
  80. }
  81. // 验证账号是否存在有效期更长的套餐
  82. if ($goods->type == 2) {
  83. $existOrderList = Order::query()
  84. ->with(['goods'])
  85. ->whereHas('goods', function ($q) {
  86. $q->where('type', 2);
  87. })
  88. ->where('user_id', Auth::user()->id)
  89. ->where('is_expire', 0)
  90. ->where('status', 2)
  91. ->get();
  92. foreach ($existOrderList as $vo) {
  93. if ($vo->goods->days > $goods->days) {
  94. return Response::json(['status' => 'fail', 'data' => '', 'message' => '支付失败:您已存在有效期更长的套餐,只能购买流量包']);
  95. }
  96. }
  97. }
  98. DB::beginTransaction();
  99. try {
  100. $orderSn = date('ymdHis') . mt_rand(100000, 999999);
  101. $sn = makeRandStr(12);
  102. // 生成订单
  103. $order = new Order();
  104. $order->order_sn = $orderSn;
  105. $order->user_id = Auth::user()->id;
  106. $order->goods_id = $goods_id;
  107. $order->coupon_id = !empty($coupon) ? $coupon->id : 0;
  108. $order->origin_amount = $goods->price;
  109. $order->amount = $amount;
  110. $order->expire_at = date("Y-m-d H:i:s", strtotime("+" . $goods->days . " days"));
  111. $order->is_expire = 0;
  112. $order->pay_way = 2;
  113. $order->status = 0;
  114. $order->save();
  115. // 生成支付单
  116. $yzy = new Yzy();
  117. $result = $yzy->createQrCode($goods->name, $amount * 100, $orderSn);
  118. if (isset($result['error_response'])) {
  119. Log::error('【有赞云】创建二维码失败:' . $result['error_response']['msg']);
  120. throw new \Exception($result['error_response']['msg']);
  121. }
  122. $payment = new Payment();
  123. $payment->sn = $sn;
  124. $payment->user_id = Auth::user()->id;
  125. $payment->oid = $order->oid;
  126. $payment->order_sn = $orderSn;
  127. $payment->pay_way = 1;
  128. $payment->amount = $amount;
  129. $payment->qr_id = $result['response']['qr_id'];
  130. $payment->qr_url = $result['response']['qr_url'];
  131. $payment->qr_code = $result['response']['qr_code'];
  132. $payment->qr_local_url = $this->base64ImageSaver($result['response']['qr_code']);
  133. $payment->status = 0;
  134. $payment->save();
  135. // 优惠券置为已使用
  136. if (!empty($coupon)) {
  137. if ($coupon->usage == 1) {
  138. $coupon->status = 1;
  139. $coupon->save();
  140. }
  141. Helpers::addCouponLog($coupon->id, $goods_id, $order->oid, '在线支付使用');
  142. }
  143. DB::commit();
  144. return Response::json(['status' => 'success', 'data' => $sn, 'message' => '创建订单成功,正在转到付款页面,请稍后']);
  145. } catch (\Exception $e) {
  146. DB::rollBack();
  147. Log::error('创建支付订单失败:' . $e->getMessage());
  148. return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建订单失败:' . $e->getMessage()]);
  149. }
  150. }
  151. // 支付单详情
  152. public function detail(Request $request, $sn)
  153. {
  154. if (empty($sn)) {
  155. return Redirect::to('services');
  156. }
  157. $payment = Payment::query()->with(['order', 'order.goods'])->where('sn', $sn)->where('user_id', Auth::user()->id)->first();
  158. if (!$payment) {
  159. return Redirect::to('services');
  160. }
  161. $order = Order::query()->where('oid', $payment->oid)->first();
  162. if (!$order) {
  163. \Session::flash('errorMsg', '订单不存在');
  164. return Response::view('payment/' . $sn);
  165. }
  166. $view['payment'] = $payment;
  167. $view['website_logo'] = self::$systemConfig['website_logo'];
  168. $view['website_analytics'] = self::$systemConfig['website_analytics'];
  169. $view['website_customer_service'] = self::$systemConfig['website_customer_service'];
  170. return Response::view('payment.detail', $view);
  171. }
  172. // 获取订单支付状态
  173. public function getStatus(Request $request)
  174. {
  175. $sn = $request->get('sn');
  176. if (empty($sn)) {
  177. return Response::json(['status' => 'fail', 'data' => '', 'message' => '请求失败']);
  178. }
  179. $payment = Payment::query()->where('sn', $sn)->where('user_id', Auth::user()->id)->first();
  180. if (!$payment) {
  181. return Response::json(['status' => 'error', 'data' => '', 'message' => '支付失败']);
  182. } elseif ($payment->status > 0) {
  183. return Response::json(['status' => 'success', 'data' => '', 'message' => '支付成功']);
  184. } elseif ($payment->status < 0) {
  185. return Response::json(['status' => 'error', 'data' => '', 'message' => '订单超时未支付,已自动关闭']);
  186. } else {
  187. return Response::json(['status' => 'fail', 'data' => '', 'message' => '等待支付']);
  188. }
  189. }
  190. // 有赞云回调日志
  191. public function callbackList(Request $request)
  192. {
  193. $status = $request->get('status', 0);
  194. $query = PaymentCallback::query();
  195. if ($status) {
  196. $query->where('status', $status);
  197. }
  198. $view['list'] = $query->orderBy('id', 'desc')->paginate(10);
  199. return Response::view('payment.callbackList', $view);
  200. }
  201. }