orderModel = new OrderModel(); } // 商品信息 public const GOODS = [ 1 => [ 'goods_id' => 1, 'desc' => '金fa充值', 'total_fee' => 100, 'gold_flower' => 1, 'red_flower' => 0, 'body' => '卖室友充值', 'notify_url' => "/api/core/pay/notify" ], 2 => [ 'goods_id' => 2, 'desc' => '卖室友表白', 'total_fee' => 100, 'gold_flower' => 0, 'red_flower' => 0, 'body' => '卖室友表白', 'notify_url' => "/api/core/pay/notify" ], 3 => [ 'goods_id' => 3, 'desc' => '72小时恋爱体验入场券', 'total_fee' => 990, 'gold_flower' => 0, 'red_flower' => 0, 'body' => '72小时入场券', 'notify_url' => "/api/core/pay/notify" ], 9 => [ 'goods_id' => 9, 'desc' => '购买小fa充值', 'total_fee' => 900, 'gold_flower' => 10, 'red_flower' => 0, 'body' => '卖室友充值', 'notify_url' => "/api/core/pay/notify" ], 10 => [ 'goods_id' => 10, 'desc' => '购买小fa充值', 'total_fee' => 8800, 'gold_flower' => 100, 'red_flower' => 0, 'body' => '卖室友充值', 'notify_url' => "/api/core/pay/notify" ], 12 => [ 'goods_id' => 12, 'desc' => "「1个月」超级会员充值", 'total_fee' => 2990, 'gold_flower' => 0, 'red_flower' => 0, 'body' => '分配对象「1个月」超级会员充值', 'notify_url' => "/api/pay/notify/supervip" ], 13 => [ 'goods_id' => 13, 'desc' => "「3个月」超级会员充值", 'total_fee' => 7200, 'gold_flower' => 0, 'red_flower' => 0, 'body' => '分配对象「3个月」超级会员充值', 'notify_url' => "/api/pay/notify/supervip" ], 14 => [ 'goods_id' => 14, 'desc' => "「12个月」超级会员充值", 'total_fee' => 25200, 'gold_flower' => 0, 'red_flower' => 0, 'body' => '分配对象「12个月」超级会员充值', 'notify_url' => "/api/pay/notify/supervip" ], ]; /** * 超级会员充值 * @param Request $request * @param int $goods_type * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response * @throws AlertException * @throws \App\Exceptions\ApiException */ public function unifyBySuperVip(Request $request, int $goods_type) { $uid = Auth::auth(); if (!in_array($goods_type, [1, 3, 9, 10, 12, 13, 14])) { throw new AlertException("商品类型不存在", 404001); } $agent = $request->header('user-agent'); $os = 'other'; if ( strpos($agent, 'macintosh') || strpos($agent, 'iPod') || strpos($agent, 'iPhone') || strpos($agent, 'iPad') ) { $os = "ios"; } if (strpos($agent, 'Android')) { $os = 'android'; } $goods = self::GOODS[$goods_type]; $total_fee = $goods['total_fee']; $coupon_id = $request->input('coupon_id', 0); if ($coupon_id) { $couponService = new CouponService(); $total_fee = $couponService->setUid($uid) ->setCouponId($coupon_id) ->setGoodsId($goods['goods_id']) ->use(); } $params = [ 'uid' => $uid, 'body' => $goods['body'], 'total_fee' => $total_fee, 'notify_url' => config('api.msy_url') . $goods['notify_url'] ]; $url = config('api.pay_url') . "/payments/unify"; $result = Curl::to($url)->withContentType("application/x-www-form-urlencoded")->withData($params)->asJsonResponse()->post(); if (isset($result->code) && $result->code == 200) { $fill = [ 'flower' => $goods['gold_flower'], 'out_trade_no' => $result->data->order_id, 'total_amount' => $goods['total_fee'], 'total_fee' => $total_fee, 'uid' => $uid, 'type' => $goods['goods_id'], 'coupon_id' => $coupon_id, 'device' => $os, 'create_at' => time(), ]; $media_id = $request->get('media_id', null); if (!is_null($media_id)) { $fill['attach_data'] = json_encode(['media_id' => $media_id]); } $order = $this->orderModel->fill($fill); if ($order->save()) { OrderCloseJob::dispatch($order->id)->onQueue('{order:close}')->delay(now()->addMinute(5)); return response([ 'code' => 200, 'message' => 'OK', 'data' => [ 'order_id' => $order->id ], ]); } else { throw new AlertException("系统异常", 505); } } else { throw new AlertException("系统异常", 505); } } /** * 用户充值任意小fa下单 * @param Request $request * @param float $gold_flower * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response */ public function unifyByFlower(Request $request, $gold_flower = 1.00) { $uid = Auth::auth(); // 支付设备 $agent = $request->header('user-agent'); $os = 'other'; if ( strpos($agent, 'macintosh') || strpos($agent, 'iPod') || strpos($agent, 'iPhone') || strpos($agent, 'iPad') ) { $os = "ios"; } if (strpos($agent, 'Android')) { $os = 'android'; } $goods = self::GOODS[1]; $params = [ 'uid' => $uid, 'body' => $goods['body'], 'total_fee' => $gold_flower * 100, 'notify_url' => config('api.msy_url') . "/api/core/pay/notify" ]; $url = config('api.pay_url') . "/payments/unify"; $result = \Curl::to($url)->withContentType("application/x-www-form-urlencoded")->withData($params)->asJsonResponse()->post(); if (isset($result->code) && $result->code == 200) { $order = $this->orderModel->fill([ 'flower' => $gold_flower, 'out_trade_no' => $result->data->order_id, 'total_amount' => $gold_flower * 100, 'total_fee' => $gold_flower * 100, 'uid' => $uid, 'type' => $goods['goods_id'], 'device' => $os, 'create_at' => time(), ]); if ($order->save()) { return response([ 'code' => 200, 'message' => 'OK', 'data' => [ 'order_id' => $order->id ], ]); } else { return response([ 'code' => 505, 'message' => '数据库异常' ]); } } else { return response([ 'code' => $result->code ?? 505, 'message' => $result->message ?? "系统异常" ]); } } /** * 分配对象下单 * @param int $total_fee 费用 * @param array $attach 附加数据包 * @param Request $request * @return int * @throws AlertException */ public function unifyByFpdx(int $total_fee, array $attach, Request $request) { $uid = Auth::auth(); // 支付设备 $agent = $request->header('user-agent'); $os = 'other'; if ( strpos($agent, 'macintosh') || strpos($agent, 'iPod') || strpos($agent, 'iPhone') || strpos($agent, 'iPad') ) { $os = "ios"; } if (strpos($agent, 'Android')) { $os = 'android'; } $goods = self::GOODS[3]; // 使用优惠券 $coupon_id = $request->input('coupon_id', 0); if ($coupon_id) { $couponService = new CouponService(); $total_fee = $couponService->setUid($uid) ->setCouponId($coupon_id) ->setGoodsId($goods['goods_id']) ->use(); } $params = [ 'uid' => $uid, 'body' => "72小时恋爱体验报名", 'total_fee' => $total_fee, 'notify_url' => config('api.msy_url') . "/api/core/pay/notify/fpdx", 'attach' => json_encode($attach) ]; $url = config('api.pay_url') . "/payments/unify"; $result = \Curl::to($url)->withData($params)->asJsonResponse()->post(); if (isset($result->code) && $result->code == 200) { $order = $this->orderModel->fill([ 'out_trade_no' => $result->data->order_id, 'total_amount' => $goods['total_fee'], 'total_fee' => $total_fee, 'uid' => $uid, 'type' => $goods['goods_id'], 'type_id' => $attach['stage_id'] ?? 0, 'coupon_id' => $coupon_id, 'attach_data' => json_encode($attach), 'device' => $os, 'create_at' => time(), ]); if ($order->save()) { OrderCloseJob::dispatch($order->id)->onQueue('{order:close}')->delay(now()->addMinute(5)); if ($total_fee == 0) { $params = [ 'out_trade_no' => $result->data->order_id, ]; $url = config('api.pay_url') . "/payments/notify/koudai"; \Curl::to($url)->withContentType("application/x-www-form-urlencoded")->withData($params)->post(); return 0; } return $order->id; } else { throw new AlertException("数据库异常", 505); } } else { throw new AlertException(isset($result->message) ? $result->message : "发起支付失败", $result->code ?? 505); } } /** * 表白下单 * @param int $total_fee 表白费用 * @param int $confess_id 表白记录id * @param Request $request * @return mixed * @throws AlertException */ public function unifyByConfess(int $total_fee, int $confess_id, Request $request) { $uid = Auth::auth(); // 支付设备 $agent = $request->header('user-agent'); $os = 'other'; if ( strpos($agent, 'macintosh') || strpos($agent, 'iPod') || strpos($agent, 'iPhone') || strpos($agent, 'iPad') ) { $os = "ios"; } if (strpos($agent, 'Android')) { $os = 'android'; } $goods = self::GOODS[2]; $params = [ 'uid' => $uid, 'body' => '卖室友表白', 'total_fee' => $total_fee, 'notify_url' => config('api.msy_url') . "/api/core/pay/notify/confess" ]; $pay_url = config('api.pay_url') . "/payments/unify"; $result = \Curl::to($pay_url)->withContentType("application/x-www-form-urlencoded")->withData($params)->asJsonResponse()->post(); if (isset($result->code) && $result->code == 200) { $order = $this->orderModel->fill([ 'out_trade_no' => $result->data->order_id, 'total_amount' => $total_fee, 'total_fee' => $total_fee, 'uid' => $uid, 'type' => $goods['goods_id'], 'type_id' => $confess_id, 'device' => $os, 'create_at' => time(), ]); if ($order->save()) { OrderCloseJob::dispatch($order->id)->onQueue('{order:close}')->delay(now()->addMinute(5)); return $order->id; } else { throw new AlertException("数据库异常", 505); } } else { throw new AlertException($result->message ?? "系统异常", $result->code ?? 505); } } /** * 小程序支付jssdk * @param int $order_id * @return array * @throws \Tymon\JWTAuth\Exceptions\JWTException */ public function miniProgram(int $order_id) { $uid = MiniAuth::auth(); $order = $this->orderModel->find($order_id); if (collect($order)->isEmpty()) { return response([ 'code' => 404, 'message' => '订单号错误或者不存在' ]); } if ($order->trade_state != 0) { return response([ 'code' => 102, 'message' => '订单失效' . json_encode($order->toArray()) ]); } if ($uid != $order->uid) { return response([ 'code' => 403, 'message' => '用户标识不一致' ]); } $public_id = config('miniprogram.public_id'); $pay_url = config('api.pay_url') . "/payments/miniProgram/{$order->out_trade_no}"; $result = \Curl::to($pay_url)->withHeader("app:{$public_id}")->asJsonResponse()->get(); if (isset($result->code) && $result->code == 200) { return response([ 'code' => 200, 'message' => 'Success', 'data' => $result->data, ]); } else { return response([ 'code' => $result->code ?? 505, 'message' => $result->message ?? "系统异常", 'data' => $result ]); } } /** * 公众号支付jssdk * @param int $order_id * @return array */ public function jssdk(int $order_id) { $uid = Auth::auth(); $order = $this->orderModel->find($order_id); if (collect($order)->isEmpty()) { return response([ 'code' => 404, 'message' => '订单号错误或不存在' ]); } if ($order->trade_state != 0) { return response([ 'code' => 102, 'message' => '订单失效' ]); } if ($uid != $order->uid) { return response([ 'code' => 403, 'message' => '用户标识不一致' ]); } $url = config('api.pay_url') . "/payments/jssdk/{$order->out_trade_no}"; $result = \Curl::to($url)->asJsonResponse()->get(); if (isset($result->code) && $result->code == 200) { return response([ 'code' => 200, 'message' => 'Success', 'data' => $result->data, ]); } else { return response([ 'code' => $result->code ?? 505, 'message' => $result->message ?? "系统异常" ]); } } /** * app支付jssdk * @param int $order_id * @return array */ public function app(int $order_id) { $uid = Auth::auth(); $order = $this->orderModel->find($order_id); if (collect($order)->isEmpty()) { return response([ 'code' => 404, 'message' => '订单号错误或者不存在' ]); } if ($order->trade_state != 0) { return response([ 'code' => 102, 'message' => '订单失效' . json_encode($order->toArray()) ]); } if ($uid != $order->uid) { return response([ 'code' => 403, 'message' => '用户标识不一致' ]); } $pay_url = config('api.pay_url') . "/payments/app/{$order->out_trade_no}"; $result = \Curl::to($pay_url)->asJsonResponse()->get(); if (isset($result->code) && $result->code == 200) { return response([ 'code' => 200, 'message' => 'Success', 'data' => $result->data, ]); } else { return response([ 'code' => $result->code ?? 505, 'message' => $result->message ?? "系统异常", 'data' => $result ]); } } /** * 订单退款 * @param int $order_id * @param int $refund_fee 退款金额:分 * @param string $refund_desc * @param bool $all * @return array|bool * @throws AlertException */ public function refund(int $order_id, int $refund_fee, $refund_desc = "", $all = false) { $order = $this->orderModel->find($order_id); if (collect($order)->isEmpty()) { throw new AlertException('订单错误或不存在', 101); } if (0 == $order->order_state) { throw new AlertException('订单未支付不可退款', 102); } if ($all && $order->create_at < 1533114000) { throw new AlertException("过期订单,请联系小向导微信:fpdxkf", 103); $pay_url = config('api.pay_url') . '/payments/transfer'; $data = [ 'uid' => $order->uid, 'amount' => $refund_fee, 'app_order_id' => "fpdx_refund_" . uniqid(), 'desc' => $refund_desc ]; } else { $pay_url = config('api.pay_url') . "/payments/order/{$order->out_trade_no}/refund"; $data = [ 'refund_fee' => $refund_fee, 'refund_desc' => $refund_desc ]; } $result = \Curl::to($pay_url)->withContentType("application/x-www-form-urlencoded")->asJsonResponse()->withData($data)->post(); if (isset($result->code) && $result->code == 200) { // 使用优惠券逻辑 if ($order->coupon_id) { $couponService = new CouponService(); $couponService->setUid($order->uid) ->setCouponId($order->coupon_id) ->unUse(); } return true; } else { throw new AlertException("退款失败", 500); } } /** * 支付结果核销处理 * @param Request $request * @param array $callback * @return string */ private function handlePaidNotify(Request $request, array $callback) { $orderModel = new OrderModel(); /** @var OrderModel|null $order */ $order = $orderModel->where('out_trade_no', $request->input('order_id'))->first(); if (!$order) { return "fail"; } if ($order->order_state != 0) { return "success"; } else { $order->cash_fee = $request->input('cash_fee', 0); if ($request->input('trade_state') == 'SUCCESS') { $order->order_state = 1; } if ($order->save()) { dispatch_now(new ActivateSvipReportJob($order)); call_user_func($callback, $order); return "success"; } else { return "fail"; } } } /** * 普通支付成功业务处理 * @param OrderModel $order * @return bool * @throws \Exception */ protected function payment(OrderModel $order) { DB::beginTransaction(); try { // 增加花 DB::table('kdgx_partner_charge_user')->where('uid', $order->uid)->increment( 'red_flower', self::GOODS[$order->type]['red_flower'] ); DB::table('kdgx_partner_charge_user')->where('uid', $order->uid)->increment('gold_flower', $order->flower); // 日志 DB::table('kdgx_partner_charge_pay_logs')->insert([ 'uid' => $order->uid, 'create_at' => time(), 'type' => 3, 'gold_flower' => $order->flower, 'red_flower' => self::GOODS[$order->type]['red_flower'], 'type_id' => $order->total_fee, 'remark' => "微信充值 {$order->total_fee}" ]); DB::commit(); return true; } catch (\Exception $e) { DB::rollBack(); return false; } } /** * 普通支付结果通知 * @param Request $request * @return string * @throws \Exception */ public function notify(Request $request) { return $this->handlePaidNotify($request, [$this, 'payment']); } // 超级VIP支付结果通知 public function notifyBySuperVip(Request $request) { $vs = new VipService(); return $this->handlePaidNotify($request, [$vs, 'payment']); } /** * 表白支付结果通知 * @param Request $request * @return string */ public function notifyByconfess(Request $request) { $confess = new Confess(); return $this->handlePaidNotify($request, [$confess, 'payment']); } /** * 分配对象报名支付结果通知 * @param Request $request * @return string */ public function notifyByfpdx(Request $request) { $pairObj = new PairController(); return $this->handlePaidNotify($request, [$pairObj, 'payment']); } /** * 后台退款接口 * @param int $order_id * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response * @throws AlertException * @throws \App\Exceptions\ApiException */ public function requestRefund(int $order_id) { $order = $this->orderModel->find($order_id); $orderService = new OrderService(); $result = $orderService->refund($order_id, $order->cash_fee, '测试退款'); return response([ 'code' => 200, 'message' => 'OK', 'data' => $result ]); } /** * 订单关闭 * @param $id * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response * @throws \App\Exceptions\ApiException */ public function closeOrder($id) { $orderService = new OrderService(); $orderService->closeOrder($id); return response([ 'code' => 200, 'message' => 'OK' ]); } }