$userSn, 'avatar' => $avatar, 'nickname' => '用户' . $userSn, 'account' => $params['account'], 'mobile' => !empty($params['mobile'])?$params['mobile']:'', 'password' => $password, 'channel' => self::$terminal, 'user_type' => $params['user_type']??0, ]); return $user; } public static function phoneLogin(array $params) { try { $where = ['mobile' => $params['mobile']]; $params['account'] = $params['mobile']; $user = User::where($where)->findOrEmpty(); if ($user->isEmpty()) { //直接注册用户 $params['channel'] = self::$terminal; $user = self::register($params); } //更新登录信息 $user->login_time = time(); $user->login_ip = request()->ip(); $user->save(); $userInfo = UserTokenService::setToken($user->id, self::$terminal); //返回登录信息 $avatar = $user->avatar ?: Config::get('project.default_image.user_avatar'); $avatar = FileService::getFileUrl($avatar); return [ 'nickname' => $userInfo['nickname'], 'sn' => $userInfo['sn'], 'mobile' => $userInfo['mobile'], 'avatar' => $avatar, 'token' => $userInfo['token'], ]; } catch (\Exception $e) { throw new \Exception($e->getMessage()); } } public static function getDouyinUserByOpenId(array $openId) { try { $user = DouyinUserAuth::where('openid',$openId)->findOrEmpty(); if ($user->isEmpty()) { //直接注册用户 $params['channel'] = self::$terminal; $user = self::register($params); } //更新登录信息 $user->login_time = time(); $user->login_ip = request()->ip(); $user->save(); $userInfo = UserTokenService::setToken($user->id, self::$terminal); //返回登录信息 $avatar = $user->avatar ?: Config::get('project.default_image.user_avatar'); $avatar = FileService::getFileUrl($avatar); return [ 'nickname' => $userInfo['nickname'], 'sn' => $userInfo['sn'], 'mobile' => $userInfo['mobile'], 'avatar' => $avatar, 'token' => $userInfo['token'], ]; } catch (\Exception $e) { throw new \Exception($e->getMessage()); } } // **************************** 商品管理 goods_category_id goods_id external_platform_id public static function addProduct($params) { $send_url = env('internal_api.api_url_host').'platf/dou_yin/addGoods'; $res = http_request($send_url,http_build_query($params)); Log::info('addProduct:' .'url:'.$send_url .'|data:'.json_encode($params,JSON_UNESCAPED_UNICODE) .'|res:'.json_encode([$res],JSON_UNESCAPED_UNICODE) ); return $res?:[]; } // ******************************** 订单业务 public static function getOrderDetail($params) { //抖音订单信息/商品信息/预约信息(地址、时间、履约状态与信息) // $params['order_number'] user_id $order = DouyinOrder::with(['goods','serviceWork','douyinRefundOrder'])->where('order_number', $params['order_number'])->where('user_id', $params['user_id'])->findOrEmpty(); if($order->isEmpty()){ return []; } $orderInfo = $order->toArray(); empty($orderInfo['goods']) && $orderInfo['goods'] = []; empty($orderInfo['serviceWork']) && $orderInfo['serviceWork'] = []; empty($orderInfo['douyinRefundOrder']) && $orderInfo['douyinRefundOrder'] = []; $orderInfo['book_info'] = json_decode($orderInfo['book_info']?:'{}',true); $work_status = $orderInfo['serviceWork']['work_status']??0; $performance = []; // tmp switch ($work_status){ case 0: $performance[] = ['status' => '待派单','title' => '待派单','time' => date('Y-m-d H:i:s',time())]; break; case 1: case 2: case 3: $performance[] = ['status' => '待派单','title' => '待派单','time' => date('Y-m-d H:i:s',time())]; $performance[] = ['status' => '已派单','title' => '已派单','time' => date('Y-m-d H:i:s',time())]; break; case 4: case 5: case 6: $performance[] = ['status' => '待派单','title' => '待派单','time' => date('Y-m-d H:i:s',time())]; $performance[] = ['status' => '已派单','title' => '已派单','time' => date('Y-m-d H:i:s',time())]; $performance[] = ['status' => '服务中','title' => '服务中','time' => date('Y-m-d H:i:s',time())]; break; case 7: case 8: $performance[] = ['status' => '待派单','title' => '待派单','time' => date('Y-m-d H:i:s',time())]; $performance[] = ['status' => '已派单','title' => '已派单','time' => date('Y-m-d H:i:s',time())]; $performance[] = ['status' => '服务中','title' => '服务中','time' => date('Y-m-d H:i:s',time())]; $performance[] = ['status' => '已完结','title' => '已完结','time' => date('Y-m-d H:i:s',time())]; break; } $orderInfo['performance'] = $performance; return $orderInfo; } public static function createOrder($params) { try { $goods_id = $params['goods_id']??0; $open_id = '_000o7ntqTR--_hCTBOBCSR_NJkyp_hiqlEK'; $goods = Goods::where('id',$goods_id)->findOrEmpty(); if($goods->isEmpty()){ throw new \Exception('商品不存在!'); } $goods = $goods->toArray(); $platformGoods = ExternalPlatformGoods::where('goods_id', $goods_id)->where('external_platform_id', self::EXTERNAL_PLATFORM_ID)->findOrEmpty(); if($platformGoods->isEmpty()){ throw new \Exception('外部商品不存在!'); } $platformGoods = $platformGoods->toArray(); $quantity = $params['quantity']?:1; $appointment_time = strtotime($params['appointment_time']??date('Y-m-d H:i:s',time())); $bookStartTime = $appointment_time * 1000; $bookEndTime = ($appointment_time + (2 * 86400)) * 1000; $order_number = self::submitOrder([ 'open_id'=>$open_id, 'goods_id'=>$goods_id, 'user_id'=>$params['user_id']??0, 'mobile'=>$params['user_info']['mobile']??'', 'quantity'=>$quantity ]); $data = [ "total_amount" => $platformGoods['service_fee'] * $quantity * 100, "open_id" => $open_id, "out_order_no" => $order_number, "order_entry_schema" => ['path'=>'pages/detail','params'=>json_encode(['goods_id'=>$goods['id']??0])], "cp_extra" => json_encode([ "outShopId" => self::EXTERNAL_PLATFORM_ID, "skuId" => (string)$platformGoods['external_goods_sn'], "quantity" => $quantity, "user_id" => $params['user_id'], "user_address" => $params['user_address'], "lon" => $params['lon'], "lat" => $params['lat'], "appointment_time" => $params['appointment_time'] ]), "goods_list" => [ [ "goods_id_type" => 1, "goods_id" => (string)$platformGoods['external_goods_sn'], "quantity" => 1 ] ], "goods_book_info" => [ "book_type" => 2, "cancel_policy" => 3, "cancel_advance_hour" => 5 ], ]; // 服务器向抖音发起创建订单 $url = 'api/apps/trade/v2/order/create_order'; $resData = self::toDyRequestUrl($url,$data); return $resData; } catch (\Exception $e) { throw new \Exception($e->getMessage()); } } // 预下单接口 - 前端 首次/尾款 public static function getPluginCreateOrderData($goods_id, $quantity, $douyinOrderId,$params) { try { $goods = Goods::where('id',$goods_id)->findOrEmpty(); if($goods->isEmpty()){ throw new \Exception('商品不存在!'); } $goods = $goods->toArray(); $platformGoods = ExternalPlatformGoods::where('goods_id', $goods_id)->where('external_platform_id', self::EXTERNAL_PLATFORM_ID)->findOrEmpty(); if($platformGoods->isEmpty()){ throw new \Exception('外部商品不存在!'); } $platformGoods = $platformGoods->toArray(); $quantity = $quantity?:1; $appointment_time = strtotime($params['appointment_time']??date('Y-m-d H:i:s',time())); $bookStartTime = $appointment_time * 1000; $bookEndTime = ($appointment_time + (2 * 86400)) * 1000; $data = [ /*"goodsList" => [ "quantity" => $quantity, "price" => $platformGoods['service_fee'] * 100, "goodsName" => $goods['goods_name'], "goodsPhoto" => $goods['goods_image']??'', "goodsId" => '', "goodsType" => 1 ],*/ "skuList" => [ [ "quantity" => (int)$quantity, "skuId" => (string)$platformGoods['external_goods_sn'], "skuType" => 1, // 1:商品库商品 2:非商品库商品(融合预约品走加价时,固定传2) "price" => $platformGoods['service_fee'] * 100, ] ], // "bookInfo" => [ // "itemBookInfoList"=>[ // [ // "poiId" => '7511543640776017961', // "shopName" => '亿蜂快修·武汉市', // "outShopId" => (string)self::EXTERNAL_PLATFORM_ID, // "skuId" => (string)$platformGoods['external_goods_sn'], // "bookStartTime" => $bookStartTime?:'', // "bookEndTime" => $bookEndTime?:'', // ] // ] // ], "payment" => [ "totalAmount" => $quantity * $platformGoods['service_fee'] * 100, ], //"callbackUrl" => $callbackUrl?:'', "callbackData" => [ "outShopId" => self::EXTERNAL_PLATFORM_ID, "skuId" => (string)$platformGoods['external_goods_sn'], "quantity" => $quantity, "user_id" => $params['user_id'], "douyinOrderId" => $douyinOrderId?:0, "user_name" => $params['user_name']??'', "mobile" => $params['mobile']??'', "user_address" => $params['user_address']??'', "lon" => $params['lon']??'', "lat" => $params['lat']??'', "appointment_time" => $params['appointment_time']??'' ], /*"tradeOption" => json_encode([ "life_trade_flag" => 1, "order_relation_info" => [ "related_order_id" => 0, // 加价时上个订单号 "relation_type" => 'multi_buy_as_one' ] ])*/ ]; if($douyinOrderId){ // 说明是来自首单订单即要创建尾款 $data['callbackUrl'] = env('douyin.pay_tail_notify_url')??''; $data['tradeOption'] = [ "life_trade_flag" => 1, "order_relation_info" => [ "related_order_id" => $douyinOrderId?:0, // 加价时上个订单号 "relation_type" => 'multi_buy_as_one' ] ]; } /*else{ // 创建首单订单 $data['callbackUrl'] = ''; }*/ return $data; } catch (\Exception $e) { throw new \Exception($e->getMessage()); } } // ++++++++++++++++++++ 首次/尾款 扩展点 /** * 预下单扩展点 * @param $params * @throws \Exception * @author liugc <466014217@qq.com> * @date 2025/6/4 14:03 */ public static function submitOrderNotify($params = []) { try { $params['external_platform_id'] = self::EXTERNAL_PLATFORM_ID; // order_id goods total_amount discount cp_extra create_order_time phone_num contact_name open_id $params['cp_extra'] = json_decode($params['cp_extra'], true); $user_id = $params['cp_extra']['user_id']; $user = User::where('id',$user_id)->findOrEmpty(); if($params['cp_extra']['douyinOrderId']>0){ // 说明是尾款单 // 创建尾款单 $order_number = self::tailOrder([ 'douyinOrderId'=>$params['cp_extra']['douyinOrderId'], 'user_id'=>$user_id??0, 'total_amount'=>$params['total_amount'], 'discount_amount'=>$params['discount_amount'], ]); $payNotifyUrl = 'https://weixiudev.kyjlkj.com/api/dou_yin/payTailNotify'; }else{ // 创建首单 goods_id user_info.mobile user_id quantity $order_number = self::submitOrder([ 'open_id'=>$params['open_id'], 'order_id'=>$params['order_id'], // 抖音订单号 'goods_id'=>$params['cp_extra']['skuId'], 'user_id'=>$user_id??0, 'mobile'=>$user['mobile']??'', 'quantity'=>$params['cp_extra']['quantity'], 'book_info'=>$params['cp_extra'], ]); $payNotifyUrl = 'https://weixiudev.kyjlkj.com/api/dou_yin/payNotify'; } return [ "out_order_no" => $order_number, "order_entry_schema" => [ "path" => "pages/order/detail", "params" => json_encode(['order_number' => $order_number]) ], "payNotifyUrl" => $payNotifyUrl ]; } catch (\Exception $e) { throw new \Exception($e->getMessage()); } } // ++++++++++++++++++++ 首次创单 /** * 预下单扩展点-子 * @param array $params goods_id user_info.mobile user_id quantity * @return array|false */ public static function submitOrder($params) { Db::startTrans(); try { $platformGoods = ExternalPlatformGoods::where('external_goods_sn', $params['goods_id'])->where('external_platform_id', self::EXTERNAL_PLATFORM_ID)->findOrEmpty(); if($platformGoods->isEmpty()){ throw new \Exception('产品不存在!'); } $goods = Goods::findOrEmpty($platformGoods['goods_id']); if($goods->isEmpty()){ throw new \Exception('产品不存在!'); } if(empty($params['mobile'])){ throw new \Exception('请先补充您的联系方式后在提交订单'); } // TODO tmp防抖1m $isExist = DouyinOrder::where(['user_id'=>$params['user_id'],'goods_id'=>$goods['id']])->where('create_time','>',(time() - 60))->findOrEmpty(); if(!$isExist->isEmpty()){ //throw new \Exception('请勿重复下单!'); } $quantity = $params['quantity']??1; //生成订单 $create_data = [ 'user_id' => $params['user_id'], 'mobile' => $params['mobile'], 'open_id' => $params['open_id'], 'goods_id'=>$goods['id'], 'title' => $goods['goods_name'], 'book_info' => json_encode($params['book_info']??[]), 'unit_price' => $platformGoods['service_fee'], 'quantity' => $quantity, 'total_amount' => $platformGoods['service_fee'] * $quantity, 'dy_order_id' => $params['order_id']??'', 'order_number' => generate_sn(DouyinOrder::class, 'order_number'), ]; $order = DouyinOrder::create($create_data); Db::commit(); return $create_data['order_number']; } catch (\Exception $e) { Db::rollback(); throw new \Exception($e->getMessage()); } } // 支付成功回调 public static function payNotify($params) { Log::write(json_encode($params)); // 查询抖音订单是否完成支付 if ($params['status'] === 'SUCCESS') { $params['cp_extra'] = json_decode($params['cp_extra'], true); $transaction_id = $params['order_id']??''; $paid_amount = bcdiv(bcsub($params['total_amount'] ,$params['discount_amount']), '100', 2)??0; $out_order_no = $params['out_order_no']; $pay_time = time(); $order = DouyinOrder::where('order_number', $out_order_no)->findOrEmpty(); if(!$order->isEmpty()){ // 更新充值订单状态 $order->transaction_id = $transaction_id; $order->order_status = 2; $order->pay_time = $pay_time; $order->paid_amount = $paid_amount; $user = User::where('id',$order->user_id)->findOrEmpty()->toArray(); $form_detail = [ 'user_name' => $user['real_name']??'', 'mobile' => $user['mobile'], 'transaction_id' => $transaction_id, 'out_trade_no' => $out_order_no, 'paid_amount' => $paid_amount, 'params' => $params, ]; $consultation = ExternalConsultation::create([ 'external_platform_id' => self::EXTERNAL_PLATFORM_ID, 'form_detail' => json_encode($form_detail), 'user_name' => $user['real_name']??'', 'mobile' => $user['mobile'], 'goods_id' => $order->goods_id, 'amount' => $paid_amount ]); $order->consultation_id = $consultation->id; $order->save(); //order_number user_address lon lat appointment_time self::reservation([ 'order_number' => $out_order_no, 'user_address' => $params['cp_extra']['user_address'], 'lon' => $params['cp_extra']['lon'], 'lat' => $params['cp_extra']['lat'], 'appointment_time' => $params['cp_extra']['appointment_time'], ]); return true; } }elseif ($params['status'] === 'CANCEL' && $params['message'] == 'TIME_OUT'){ // 超时取消支付 Log::info('支付超时取消:order_id'.$params['order_id']."--out_order_no:" .$params['out_order_no']); return true; } return false; } // ++++++++++++++++++++ 首次创单 end // ++++++++++++++++++++ 尾款创单 /** * 预下单扩展点-子 * @param array $params goods_id user_info.mobile user_id quantity * @return array|false */ public static function tailOrder($params) { Db::startTrans(); try { $amount = bcdiv(bcsub($params['total_amount'] ,$params['discount_amount']), '100', 2)??0; $work_id = DouyinOrder::where(['id'=>$params['douyinOrderId']])->value('work_id')??0; $sn = ''; $rechargeOrder = RechargeOrder::where(['work_id'=>$work_id,'payment_type'=>2])->findOrEmpty(); if($work_id && $rechargeOrder->isEmpty()){ //新增待支付尾款 $sn = generate_sn(RechargeOrder::class, 'sn'); $order_data = [ 'order_type' => 0, 'sn' => $sn, 'order_terminal' => 1, 'work_id' => $work_id, 'user_id' => $params['user_id'], 'payment_type' => 2, 'order_total' => $amount, 'order_amount' => $amount, 'pay_status' => 0, 'paid_amount' => 0, 'pay_way' => 4 ]; RechargeOrder::create($order_data); } Db::commit(); return $sn; } catch (\Exception $e) { Db::rollback(); throw new \Exception($e->getMessage()); } } // 尾款支付成功回调 public static function payTailNotify($params) { Log::write(json_encode($params)); // 查询抖音订单是否完成支付 if ($params['status'] === 'SUCCESS') { $transaction_id = $params['order_id']??''; $paid_amount = bcdiv(bcsub($params['total_amount'] ,$params['discount_amount']), '100', 2)??0; $out_order_no = $params['out_order_no']; $pay_time = time(); $params['cp_extra'] = json_decode($params['cp_extra'], true); $work_id = DouyinOrder::where(['id'=>$params['cp_extra']['douyinOrderId']])->value('work_id')??0; $rechargeOrder = RechargeOrder::where(['work_id'=>$work_id,'sn'=>$out_order_no,'payment_type'=>2])->findOrEmpty(); if(!$rechargeOrder->isEmpty()){ // 更新充值订单状态 $rechargeOrder->transaction_id = $transaction_id; $rechargeOrder->pay_status = 1; $rechargeOrder->pay_time = $pay_time; $rechargeOrder->paid_amount = $paid_amount; $rechargeOrder->save(); // 尾款订单支付成功后续操作 fun return true; } }elseif ($params['status'] === 'CANCEL' && $params['message'] == 'TIME_OUT'){ // 超时取消支付 Log::info('支付超时取消:order_id'.$params['order_id']."--out_order_no:" .$params['out_order_no']); return true; } return false; } // ++++++++++++++++++++ 尾款创单 end // ******************************** 订单预约/改约 // 创建预约单 public static function reservation($params) { /*$lon_lat = get_address_lat_lng($params['user_address']); $params['lon'] = $lon_lat['lon']; $params['lat'] = $lon_lat['lat'];*/ // $params['order_number'] user_address lon lat appointment_time Db::startTrans(); try { $order = DouyinOrder::where('order_number', $params['order_number'])->findOrEmpty(); if(!$order->isEmpty()){ $consultation = ExternalConsultation::where('id', $order->consultation_id)->findOrEmpty()->toArray(); $consultation['user_name'] = $params['user_name']??$consultation['user_name']; $consultation['mobile'] = $params['mobile']??$consultation['mobile']; $consultation['user_address'] = $params['user_address']; $consultation['lon'] = $params['lon']; $consultation['lat'] = $params['lat']; $consultation['appointment_time'] = $params['appointment_time']; $consultationOrderId = ExternalConsultationLogic::order($consultation); if (false === $consultationOrderId) { throw new \Exception('预约失败'); } if(!empty($consultationOrderId)){ $consultationOrder = ExternalConsultationOrder::where('id', $consultationOrderId)->findOrEmpty()->toArray(); $work_status = ServiceWork::where('id', $consultationOrder['work_id'])->value('work_status'); $order->work_id = $consultationOrder['work_id']; $order->fulfillment_status = $work_status; $order->save(); } $params['dy_order_id'] = $order->dy_order_id; $params['consultationOrderId'] = $consultationOrderId; $params['open_id'] = $order->open_id; $params['goods_id'] = $order->goods_id; } Db::commit(); // 抖音创建预约单 //$url = 'api/apps/trade/v2/book/create_book'; //$resData = self::toDyRequestUrl($url,self::getCreateBookParams($params)); //book_id result // 抖音预约接单结果回调 $bookurl = 'api/apps/trade/v2/book/book_result_callback'; $res = self::toDyRequestUrl($bookurl,[ 'book_id' => $resData['book_id']??$params['dy_order_id'], 'result' => 1, ]); return $order['id']??0; } catch (\Exception $e) { Db::rollback(); throw new \Exception($e->getMessage()); } } public static function getCreateBookParams($params) { try { $platformGoods = ExternalPlatformGoods::where('goods_id', $params['goods_id'])->where('external_platform_id', self::EXTERNAL_PLATFORM_ID)->findOrEmpty(); if($platformGoods->isEmpty()){ throw new \Exception('产品不存在!'); } $appointment_time = strtotime($params['appointment_time']); $book_start_time = $appointment_time * 1000; $book_end_time = ($appointment_time + (2 * 86400)) * 1000; $data = [ "order_id"=> (string)$params['dy_order_id']??'', "out_book_no"=> (string)$params['consultationOrderId']??'', "open_id"=> (string)$params['open_id']??'', "item_book_info_list" => [ [ "poi_id" => '7511543640776017961', "shop_name" => '亿蜂快修·武汉市', "ext_shop_id" => (string)self::EXTERNAL_PLATFORM_ID, "goods_id" => (string)$platformGoods->external_goods_sn, "book_start_time" => (int)$book_start_time??0, "book_end_time" => (int)$book_end_time??0, ] ] ]; return $data; } catch (\Exception $e) { return []; } } public static function upReservation($params) { // $params['order_number'] Db::startTrans(); try { $order = DouyinOrder::where('order_number', $params['order_number'])->findOrEmpty(); if(!$order->isEmpty()){ // sn appointment_time $result = ServiceOrderLogic::approvalChangeAppointment(['sn'=>RechargeOrder::where('work_id', $order->work_id)->value('sn'),'appointment_time'=>$params['appointment_time']]); if (false === $result) { throw new \Exception(ServiceOrderLogic::getError()); } $order->fulfillment_status = ServiceWork::where('id', $order->work_id)->value('work_status'); $order->save(); } Db::commit(); return $order['id']; } catch (\Exception $e) { Db::rollback(); throw new \Exception($e->getMessage()); } } // ******************************** 订单退款 public static function cancelOrder($params) { // $params['order_number'] Db::startTrans(); try { $order = DouyinOrder::where('order_number', $params['order_number'])->findOrEmpty(); if(!$order->isEmpty()){ if($order->order_status == 1 && $order->pay_status == 0){ $order->order_status = 4; $order->save(); }else{ throw new \Exception('订单状态不可取消!'); } } Db::commit(); return $order['id']; } catch (\Exception $e) { Db::rollback(); throw new \Exception($e->getMessage()); } } public static function refund($params) { Db::startTrans(); try { // $params['order_number'] user_id $order = DouyinOrder::with(['goods','serviceWork'])->where('order_number', $params['order_number'])->where('user_id', $params['user_id'])->findOrEmpty(); if($order->isEmpty()){ throw new \Exception('订单不存在'); } $orderInfo = $order->toArray(); $work_status = $orderInfo['serviceWork']['work_status']??0; if(3 < $work_status){ throw new \Exception('该订单禁止退款'); } DouyinRefundOrder::create([ 'refund_number' => generate_sn(DouyinRefundOrder::class, 'refund_number'), 'order_number' => $orderInfo['order_number'], 'transaction_id' => $orderInfo['transaction_id'], 'reason' => $params['reason']??'', 'refund_status' => 0, 'user_id' => $orderInfo['user_id'], 'refund_amount' => $orderInfo['paid_amount'], ]); Db::commit(); return true; } catch (\Exception $e) { Db::rollback(); throw new \Exception($e->getMessage()); } } public static function refundExamine($params) { Db::startTrans(); try { // $params['order_number'] $order = DouyinOrder::with(['goods','serviceWork'])->where('order_number', $params['order_number'])->findOrEmpty(); if($order->isEmpty()){ throw new \Exception('订单不存在'); } $orderInfo = $order->toArray(); //$refund_number = $params['refund_number']??''; $douyinRefundOrder = DouyinRefundOrder::where('order_number', $params['order_number'])->order('id', 'desc')->findOrEmpty(); if($params['is_examine_ok'] === 'pass'){ $douyinRefundOrder->refund_status = 2; RechargeOrder::where('work_id', $orderInfo['work_id'])->update([ 'pay_status' => 2, 'pay_time' => 0, 'paid_amount' => 0, ]); ServiceWork::where('id', $orderInfo['work_id'])->update([ 'work_status' => 0, 'user_confirm_status' => 0, 'service_status' => 4, 'work_pay_status' => 0 ]); }else{ $douyinRefundOrder->refund_status = 1; } $douyinRefundOrder->save(); Db::commit(); if($params['is_examine_ok'] === 'pass'){ //通过后向抖音申请退款 self::sendRefundCreate($params['order_number']); } return true; } catch (\Exception $e) { Db::rollback(); throw new \Exception($e->getMessage()); } } public static function sendRefundCreate($order_number) { try { // $params['order_number'] $order = DouyinOrder::with(['goods','serviceWork'])->where('order_number', $order_number)->findOrEmpty(); if($order->isEmpty()){ throw new \Exception('订单不存在'); } $orderInfo = $order->toArray(); $douyinRefundOrder = DouyinRefundOrder::where('order_number', $order_number)->order('id', 'desc')->findOrEmpty(); //通过后向抖音申请退款 $url = 'api/trade_basic/v1/developer/refund_create/'; $data = [ "order_id" => $orderInfo['transaction_id'], "out_refund_no" => $douyinRefundOrder->refund_number, "cp_extra" => $orderInfo['id'].'|'.$douyinRefundOrder->id, "order_entry_schema" => [ "path" => "page/index/index", "params" => json_encode(['refund_number'=>$douyinRefundOrder->refund_number]) ], "refund_total_amount " => $douyinRefundOrder->refund_amount * 100, //"notify_url" => config('douyin.refundNotifyUrl'), "refund_reason" => [ [ "code" => 101, "text" => "不想要了" ] ] ]; $resData = self::toDyRequestUrl($url,$data); if(isset($resData['data']) && $resData['data']){ $douyinRefundOrder->transaction_id = $resData['data']['refund_id']; $douyinRefundOrder->save(); } return true; } catch (\Exception $e) { Log::info($e->getMessage()); return false; } } public static function refundNotify($params) { Db::startTrans(); try { $douyinRefundOrder = DouyinRefundOrder::where('refund_number', $params['out_refund_no'])->findOrEmpty(); if($douyinRefundOrder->isEmpty()){ throw new \Exception('退款订单不存在'); } if($douyinRefundOrder->refund_status == 0){ if($params['status'] === 'SUCCESS'){ $douyinRefundOrder->refund_status = 3; DouyinOrder::where('order_number', $douyinRefundOrder->order_number)->update([ 'order_status' => 4, 'pay_status' => 3, ]); }elseif($params['status'] === 'FAIL'){ $douyinRefundOrder->refund_status = 4; }else{ throw new \Exception('退款状态未知'); } $douyinRefundOrder->save(); } Db::commit(); return true; } catch (\Exception $e) { Db::rollback(); throw new \Exception($e->getMessage()); } } public static function toDyRequestUrl($url,$data,$headers = [],$resFunction = 'extraErrorCodeReturn',$isHost = 0) { $toData = [ 'url' => $url, 'data' => $data, 'headers' => $headers, 'resFunction' => $resFunction, 'isHost' => $isHost ]; $res = commonHttpClient(env('internal_api.api_url_host').'platf/dou_yin/toDyRequestUrl', $toData, 'post', 'json', ['Content-Type' => 'application/json']); Log::info(json_encode($res)); if(isset($res['code']) && $res['code'] === 0){ Log::info("toDyRequestUrl:".json_encode($res)); return $res['data']; }else{ Log::info("toDyRequestUrl:".$res['msg']); throw new \Exception($res['msg']); } } }