getOrderInfo($order_id,$order_type); if(empty($orderInfo)){ $this->resultError('订单不存在'); } else if($orderInfo['pay_status'] == 1){ $this->resultError('订单已支付'); } else { $cashResult = $this->createCash($orderInfo,$order_type); if(false !== $cashResult){ if($pay_type == 0){ $result = $this->freePay($orderInfo); } elseif ($pay_type == 1){ $result = $this->getMemberCardPay($orderInfo); } else { $result = $this->getWechatPay($orderInfo,$order_type); } return $result; } else { $this->resultError('支付发起失败'); } } } /** * 创建支付流水记录 * @param object $orderInfo 订单详情 * @param int $order_type 订单类型 */ private function createCash(object $orderInfo, int $order_type){ $cashModel = new \addons\xilufitness\model\CashFlow; $cashInfo = $cashModel ->where(['user_id' => $orderInfo->user_id, 'order_no' => $orderInfo->order_no, 'order_type' => $order_type]) ->field(['id','user_id','order_no','updatetime','createtime']) ->find(); if(!empty($cashInfo)){ $result = $cashInfo->save(['updatetime' => time(), 'createtime' => time()]); } else { $result = $cashModel->save([ 'brand_id' => $orderInfo->brand_id, 'user_id' => $orderInfo->user_id, 'order_type' => $order_type, 'order_no' => $orderInfo->order_no, 'pay_amount' => $orderInfo->pay_amount, 'pay_type' => $orderInfo->pay_type, ]); } return $result; } /** * 获取订单详情 * @param int $order_id 订单id * @param int $order_type 订单类型 0 充值订单 1 团课 2 私教课 3 活动 * @param string $order_no 订单号 */ public function getOrderInfo(int $order_id, int $order_type,string $order_no='') { $orderModel = new \addons\xilufitness\model\Order; if(!empty($this->getUserId())){ $where['user_id'] = $this->getUserId(); } if(!empty($order_id)){ $where['id'] = $order_id; } if(!empty($order_no)){ $where['order_no'] = $order_no; } $info = $orderModel ->where($where) ->find(); return $info; } /** * 获取用户小程序openid */ public function getOpenid(){ $model = new \addons\xilufitness\model\UserConnect; $openid = $model ->where(['brand_id' => $this->brand_id, 'account_user_id' => $this->getUserId()]) ->value('openid'); return $openid; } /** * 微信支付发起 * @param object $orderInfo 订单详情 * @param int $order_type 订单类型 */ public function getWechatPay(object $orderInfo,int $order_type){ try { $test_pay_uids = array_filter(explode(',',config('site.wechar_pay_user_ids'))); $wechat = \WeChat\Pay::instance($this->data['mini_config']); // 4. 组装参数,可以参考官方商户文档 $options = [ 'body' => $orderInfo['pay_body'] ?? '健身小程序商品支付', 'out_trade_no' => $orderInfo['order_no'], 'total_fee' => !empty($test_pay_uids) && in_array($orderInfo['user_id'],$test_pay_uids) ? 1 : $orderInfo['pay_amount']*100, 'openid' => $this->getOpenid(), 'trade_type' => 'JSAPI', 'notify_url' => url('/addons/xilufitness/pay/notify',['order_type' => $order_type, 'brand_id' => $orderInfo['brand_id'] ?? 0],true,true), 'spbill_create_ip' => get_client_ip(), ]; // 生成预支付码 $result = $wechat->createOrder($options); // 创建JSAPI参数签名 $options = $wechat->createParamsForJsApi($result['prepay_id']); return $options; } catch (\Exception $e){ $this->resultError($e->getMessage()); } } /** * 会员卡支付 * @param object $orderInfo 订单详情 */ public function getMemberCardPay(object $orderInfo){ return $orderInfo->payAfter($orderInfo,time(),1); } /** * 免支付 * @param object $orderInfo 订单详情 */ public function freePay(object $orderInfo){ return $orderInfo->payAfter($orderInfo,time(),0); } /** * 支付异步通知 */ public function notify($order_type){ try { $wechat = \WeChat\Pay::instance($this->data['mini_config']); // 4. 获取通知参数 $data = $wechat->getNotify(); // Db::name('xilufitness_logs')->insertGetId(['content' => json_encode($data)]); // $data = json_decode(Db::name('xilufitness_logs')->where(['id' => 37])->value('content'),true); $orderInfo = $this->getOrderInfo(0,$order_type,$data['out_trade_no']); if ($data['return_code'] === 'SUCCESS' && $data['result_code'] === 'SUCCESS') { if(!empty($orderInfo) && $orderInfo['pay_status'] == 0){ $orderInfo->payAfter($orderInfo,$data['transaction_id'] ?? '',$orderInfo['pay_type']); } // 返回接收成功的回复 ob_clean(); echo $wechat->getNotifySuccessReply(); } } catch (\Exception $e){ echo $e->getMessage() . PHP_EOL; } } /** * 退款申请 * @param int $order_id 订单id * @param int $brand_id 品牌商id * @return bool */ public function refundOrder(int $order_id,int $brand_id = 0){ $model = new \addons\xilufitness\model\Order; $where['id'] = $order_id; if(!empty($this->getUserId())){ $where['user_id'] = $this->getUserId(); } $where['brand_id'] = !empty($brand_id) ? $brand_id : $this->brand_id; $orderInfo = $model->where($where)->find(); $cancel_able_time = $orderInfo['starttime'] - 300; if(empty($orderInfo)){ throw new Exception('订单不存在'); } else if($cancel_able_time < time()){ throw new Exception('离开课不到5分钟,暂时不能取消'); } else if($orderInfo['pay_type'] == 0){ throw new Exception('免支付订单,暂时不能取消'); } else { if($orderInfo['pay_type'] == 1){ //会员卡 return $this->refundCard($orderInfo); } elseif($orderInfo['pay_type'] == 2) { //微信支付 return $this->refundWechat($orderInfo); } } } /** * 会员卡原路退回 */ private function refundCard($orderInfo){ $title = $this->getRefundTitle($orderInfo); return UserService::getInstance()->userAccountChange($title,$orderInfo->user_id,xilufitness_get_id_value($orderInfo->id),$orderInfo['pay_amount'],1,$orderInfo['order_type']); } /** * 微信原路退回 */ private function refundWechat($orderInfo){ $wechat = \WeChat\Pay::instance($this->data['mini_config']); $return_no = 'R'.xilufitness_build_order_no(); $test_pay_uids = array_filter(explode(',',config('site.wechar_pay_user_ids'))); // 4. 组装参数,可以参考官方商户文档 $options = [ 'transaction_id' => $orderInfo['trade_no'], 'out_refund_no' => $return_no, 'total_fee' => !empty($test_pay_uids) && in_array($orderInfo['user_id'],$test_pay_uids) ? 1 : $orderInfo['pay_amount'] * 100, 'refund_fee' => !empty($test_pay_uids) && in_array($orderInfo['user_id'],$test_pay_uids) ? 1 : $orderInfo['pay_amount'] * 100, ]; $result = $wechat->createRefund($options); if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){ $orderInfo->allowField(true)->save(['re_no' => $return_no ?? '']); return true; } else { throw new Exception($result['err_code_des'] ?? '微信退款申请失败'); } } /** * 获取退款标题 */ private function getRefundTitle($orderInfo){ if($orderInfo['order_type'] == 1){ $title = '团课取消退款:'.$orderInfo['order_no']; } elseif ($orderInfo['order_type'] == 2){ $title = '私教课取消退款:'.$orderInfo['order_no']; } else { $title = '活动取消退款:'.$orderInfo['order_no']; } return $title; } /** * 排队释放 * @param int $num 释放人数 * @param int $data_id 排课id * @param int $course_type 课程类型 1 团课 2 私教课 3 活动 * @return bool */ public function orderQueue(int $num = 0,int $data_id,int $course_type,int $brand_id=0){ if($num == 0) return false; $model = new \addons\xilufitness\model\Order; $queueList = $model ->where(['brand_id' => $brand_id, 'data_id' => $data_id, 'order_type' => $course_type, 'order_status' => 10]) ->order("pay_time asc") ->limit($num) ->select(); if(empty($queueList)) return false; foreach ($queueList as $key => $val){ $val->save(['order_status' => 1]); } return true; } }