|
|
@@ -25,6 +25,7 @@ class DouYinService
|
|
|
{
|
|
|
protected static int $terminal = \app\common\enum\user\UserTerminalEnum::DOUYIN;
|
|
|
protected static int $external_platform_id = 6;
|
|
|
+ protected CONST EXTERNAL_PLATFORM_ID = 6;
|
|
|
|
|
|
// ********************************* 注册登录
|
|
|
public static function register(array $params)
|
|
|
@@ -82,7 +83,6 @@ class DouYinService
|
|
|
}
|
|
|
|
|
|
// **************************** 商品管理 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';
|
|
|
@@ -95,170 +95,186 @@ class DouYinService
|
|
|
return $res?:[];
|
|
|
}
|
|
|
|
|
|
- public static function addSku($params)
|
|
|
+ // ******************************** 订单业务
|
|
|
+ public static function getOrderDetail($params)
|
|
|
{
|
|
|
- $sku_url = config('douyin.host').'goodlife/v1/goods/sku/batch_save/';
|
|
|
- $res = http_request($sku_url,self::getSkuParams($params),['Content-Type' => 'application/json;charset=utf-8','access-token' => self::getClientToken()]);
|
|
|
- Log::info('addSku:'.json_encode($res));
|
|
|
- // 根据返回后更新本地库对应关系 $res['data']['sku_id_list']
|
|
|
- if(isset($res['data']['sku_id_list']) && !empty($res['data']['sku_id_list'])){
|
|
|
- foreach ($res['data']['sku_id_list'] as $item) {
|
|
|
- ExternalPlatformGoods::where('goods_id', $item['out_sku_id'])->where('external_platform_id', $params['external_platform_id'])->update([
|
|
|
- 'external_goods_sn' => $item['sku_id']
|
|
|
- ]);
|
|
|
- }
|
|
|
+ //抖音订单信息/商品信息/预约信息(地址、时间、履约状态与信息)
|
|
|
+ // $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'] = [];
|
|
|
+
|
|
|
+ $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;
|
|
|
}
|
|
|
- return [];
|
|
|
+ $orderInfo['performance'] = $performance;
|
|
|
+
|
|
|
+ return $orderInfo;
|
|
|
}
|
|
|
|
|
|
- public static function getProductParams($params)
|
|
|
+ // 预下单接口 - 前端 首次/尾款
|
|
|
+ public static function getPluginCreateOrderData($goods_id, $quantity, $douyinOrderId)
|
|
|
{
|
|
|
- $goods = Goods::where('id',$params['goods_id']??0)->findOrEmpty();
|
|
|
- if($goods->isEmpty()){
|
|
|
- return [];
|
|
|
- }
|
|
|
- $goods = $goods->toArray();
|
|
|
- return [
|
|
|
- "account_id" => '7511543640776017961',
|
|
|
- "product" => [
|
|
|
- "out_id" => $params['goods_id']??0,
|
|
|
- "product_name" => $goods['goods_name']??'无',
|
|
|
- "product_type" => 22,
|
|
|
- "category_id" => 6004003,
|
|
|
- "category_full_name" => "其他维修服务",
|
|
|
- "biz_line" => 5,
|
|
|
- "account_name" => "亿蜂快修·武汉市",
|
|
|
- //{\"params\":\"{\"spuId\":\"xxxxx\",\"skuId\":\"xxxxxx\"}\",\"path\":\"pages/any/path\",\"app_id\":\"xxxxx\"}
|
|
|
- "out_url" => json_encode(['app_id'=>config('douyin.appId'),'path'=>'pages/detail','params'=>json_encode(['goods_id'=>$params['goods_id']??0])]),
|
|
|
- "pois" =>[
|
|
|
+ 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;
|
|
|
+ $data = [
|
|
|
+ /*"goodsList" => [
|
|
|
+ "quantity" => $quantity,
|
|
|
+ "price" => $platformGoods['service_fee'] * 100,
|
|
|
+ "goodsName" => $goods['goods_name'],
|
|
|
+ "goodsPhoto" => $goods['goods_image']??'',
|
|
|
+ "goodsId" => '',
|
|
|
+ "goodsType" => 1
|
|
|
+ ],*/
|
|
|
+ "skuList" => [
|
|
|
[
|
|
|
- "poi_id" => "7511543640776017961"
|
|
|
+ "quantity" => $quantity,
|
|
|
+ "skuId" => (string)$platformGoods['external_goods_sn'],
|
|
|
+ "skuType" => 2,
|
|
|
+ "price" => $platformGoods['service_fee'] * 100,
|
|
|
]
|
|
|
],
|
|
|
- "product_ext" => [
|
|
|
- "auto_online" => true,
|
|
|
- "display_price"=> ["low_price" => 30,"high_price" => 300],
|
|
|
- "test_extra"=> ["test_flag" => true,"uids" => ["15482888"]]
|
|
|
+ /*"bookInfo" => [
|
|
|
+ "itemBookInfoList"=>[
|
|
|
+ [
|
|
|
+ "poiId" => '7511543640776017961',
|
|
|
+ "shopName" => '亿蜂快修·武汉市',
|
|
|
+ "outShopId" => self::EXTERNAL_PLATFORM_ID,
|
|
|
+ "skuId" => (string)$platformGoods['external_goods_sn'],
|
|
|
+ "bookStartTime" => $bookStartTime?:'',
|
|
|
+ "bookEndTime" => $bookEndTime?:'',
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ],*/
|
|
|
+ "payment" => [
|
|
|
+ "totalAmount" => $quantity * $platformGoods['service_fee'] * 100,
|
|
|
],
|
|
|
- "attr_key_value_map" => self::getAttrKeyValueMapParams('product',$goods),
|
|
|
- "sold_end_time" => time() + 180 * 86400,
|
|
|
- "sold_start_time" => time()
|
|
|
- ]
|
|
|
- ];
|
|
|
- }
|
|
|
- public static function getSkuParams($params)
|
|
|
- {
|
|
|
- $goods = Goods::where('id',$params['goods_id']??0)->findOrEmpty();
|
|
|
- if ($goods->isEmpty()) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- $goods = $goods->toArray();
|
|
|
- // 查询商品信息
|
|
|
- return [
|
|
|
- "account_id" => '7511543640776017961',
|
|
|
- "product_out_id" => $params['goods_category_id']??0,
|
|
|
- "sku" => [
|
|
|
- [
|
|
|
- "out_sku_id"=> $goods['id'],
|
|
|
- "sku_name"=> $goods['name'],
|
|
|
- "origin_amount"=> $goods['service_total'] * 100,
|
|
|
- "actual_amount"=> $goods['service_fee'] * 100,
|
|
|
- "stock"=> [
|
|
|
- "limit_type"=> 2,
|
|
|
- "stock_qty"=> 9999
|
|
|
- ],
|
|
|
- "status"=> 1,
|
|
|
- "attr_key_value_map"=> self::getAttrKeyValueMapParams('sku',$goods)
|
|
|
- ]
|
|
|
- ]
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- public static function getAttrKeyValueMapParams($type,$params)
|
|
|
- {
|
|
|
- $res = [];
|
|
|
- if($type === 'product'){
|
|
|
- $res = [
|
|
|
- "appointment"=>json_encode([
|
|
|
- "need_appointment"=>true,
|
|
|
- "ahead_time_type"=>2,
|
|
|
- "ahead_hour_num"=> 5,
|
|
|
- "external_link"=>"pages/detail",
|
|
|
- "order_appointment_time_url"=>"pages/order"
|
|
|
- ]),
|
|
|
- "auto_renew"=>true,
|
|
|
- "can_no_use_date" => json_encode(["enable"=>false]),
|
|
|
- "Description" => json_encode([]),
|
|
|
- "image_list" => json_encode([["url"=>$params['goods_image']??'']]),
|
|
|
- "limit_use_rule" => json_encode(["is_limit_use"=>true, "use_num_per_consume"=>1]),
|
|
|
- "Notification" => json_encode([["title"=>$params['goods_name']??'',"content"=>$params['goods_name']??'']]),
|
|
|
- "RefundPolicy"=> "2",
|
|
|
- "refund_need_merchant_confirm"=> true,
|
|
|
- "show_channel"=> 1,
|
|
|
- "superimposed_discounts"=> false,
|
|
|
- "trade_url"=> json_encode(['app_id'=>config('douyin.appId'),'path'=>'pages/detail','params'=>json_encode(['goods_id'=>$params['id']??0])]),
|
|
|
- "use_date"=> json_encode(["use_date_type"=>2, "day_duration"=>15]),
|
|
|
- "use_time"=> json_encode(["use_time_type"=>1]),
|
|
|
- //"user_num_limit"=> ,
|
|
|
- "code_source_type"=> 3,
|
|
|
- "settle_type"=> 1,
|
|
|
- "use_type"=> 1,
|
|
|
- "limit_rule"=> json_encode(["is_limit"=>false]),
|
|
|
- "out_id"=> $params['id']??0
|
|
|
- ];
|
|
|
- }
|
|
|
- if($type === 'sku'){
|
|
|
- $res = [
|
|
|
- "code_source_type"=> 3,
|
|
|
- "limit_rule"=> json_encode(["is_limit"=>false]),
|
|
|
- "settle_type"=> 1
|
|
|
+ //"callbackUrl" => $callbackUrl?:'',
|
|
|
+ "callbackData" => [
|
|
|
+ "outShopId" => self::EXTERNAL_PLATFORM_ID,
|
|
|
+ "skuId" => (string)$platformGoods['external_goods_sn'],
|
|
|
+ "quantity" => $quantity,
|
|
|
+ "douyinOrderId" => $douyinOrderId?:0,
|
|
|
+ ],
|
|
|
+ /*"tradeOption" => json_encode([
|
|
|
+ "life_trade_flag" => 1,
|
|
|
+ "order_relation_info" => [
|
|
|
+ "related_order_id" => 0, // 加价时上个订单号
|
|
|
+ "relation_type" => 'multi_buy_as_one'
|
|
|
+ ]
|
|
|
+ ])*/
|
|
|
];
|
|
|
+
|
|
|
+ if($douyinOrderId){ // 说明是来自首单订单即要创建尾款
|
|
|
+ $data['callbackUrl'] = '';
|
|
|
+ $data['tradeOption'] = [
|
|
|
+ "life_trade_flag" => 1,
|
|
|
+ "order_relation_info" => [
|
|
|
+ "related_order_id" => '', // 加价时上个订单号
|
|
|
+ "relation_type" => 'multi_buy_as_one'
|
|
|
+ ]
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ /*else{ // 创建首单订单
|
|
|
+ $data['callbackUrl'] = '';
|
|
|
+ }*/
|
|
|
+ return $data;
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ throw new \Exception($e->getMessage());
|
|
|
}
|
|
|
- return $res;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- // ******************************** 订单
|
|
|
-
|
|
|
+ // ++++++++++++++++++++ 首次/尾款 扩展点
|
|
|
/**
|
|
|
- * 扩展点回调提交订单
|
|
|
+ * 预下单扩展点
|
|
|
* @param $params
|
|
|
* @throws \Exception
|
|
|
* @author liugc <466014217@qq.com>
|
|
|
* @date 2025/6/4 14:03
|
|
|
*/
|
|
|
- public static function submitOrderNotify($params)
|
|
|
+ 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
|
|
|
- if(empty($params['user_info']['mobile'])){
|
|
|
+ if(empty($params['phone_num'])){
|
|
|
throw new \Exception('手机号不能为空!');
|
|
|
}
|
|
|
- // goods_id user_info.mobile user_id quantity
|
|
|
- $order_number = self::submitOrder([
|
|
|
- 'goods_id'=>$params['goods'][0]['goods_id'],
|
|
|
- 'user_id'=>$params['user_id'],
|
|
|
- 'user_info'=>$params['user_info'],
|
|
|
- 'quantity'=>$params['goods'][0]['quantity']
|
|
|
- ]);
|
|
|
+ $user_id = $params['user_id'];
|
|
|
+
|
|
|
+ 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 = 'payTailNotify';
|
|
|
+ }else{
|
|
|
+ // 创建首单 goods_id user_info.mobile user_id quantity
|
|
|
+ $order_number = self::submitOrder([
|
|
|
+ 'goods_id'=>$params['cp_extra']['skuId'],
|
|
|
+ 'user_id'=>$user_id??0,
|
|
|
+ 'mobile'=>$params['phone_num'],
|
|
|
+ 'quantity'=>$params['cp_extra']['quantity']
|
|
|
+ ]);
|
|
|
+ }
|
|
|
return [
|
|
|
"outOrderNo" => $order_number,
|
|
|
"orderEntrySchema" => [
|
|
|
"path" => "page/index/index",
|
|
|
"params" => json_encode(['order_number' => $order_number])
|
|
|
],
|
|
|
- "payNotifyUrl" => config('douyin.payNotifyUrl')
|
|
|
+ "payNotifyUrl" => $payNotifyUrl??''
|
|
|
];
|
|
|
} catch (\Exception $e) {
|
|
|
throw new \Exception($e->getMessage());
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+ // ++++++++++++++++++++ 首次创单
|
|
|
/**
|
|
|
- * 提交订单
|
|
|
+ * 预下单扩展点-子
|
|
|
* @param array $params goods_id user_info.mobile user_id quantity
|
|
|
* @return array|false
|
|
|
*/
|
|
|
@@ -271,7 +287,7 @@ class DouYinService
|
|
|
if($goods->isEmpty()){
|
|
|
throw new \Exception('产品不存在!');
|
|
|
}
|
|
|
- if(empty($params['user_info']['mobile'])){
|
|
|
+ if(empty($params['mobile'])){
|
|
|
throw new \Exception('请先补充您的联系方式后在提交订单');
|
|
|
}
|
|
|
// TODO tmp防抖1m
|
|
|
@@ -283,7 +299,7 @@ class DouYinService
|
|
|
//生成订单
|
|
|
$create_data = [
|
|
|
'user_id' => $params['user_id'],
|
|
|
- 'mobile' => $params['user_info']['mobile'],
|
|
|
+ 'mobile' => $params['mobile'],
|
|
|
'title' => $goods['goods_name'],
|
|
|
|
|
|
'goods_id'=>$goods['id'],
|
|
|
@@ -300,125 +316,120 @@ class DouYinService
|
|
|
throw new \Exception($e->getMessage());
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- public static function getByteAuthorization($order_number)
|
|
|
+ // 支付成功回调
|
|
|
+ public static function payNotify($params)
|
|
|
{
|
|
|
- /*{
|
|
|
- "skuList": [{
|
|
|
- "skuId": "商品ID",
|
|
|
- "price": 100,//单价-分
|
|
|
- "quantity": 1,
|
|
|
- "title": "商品标题",
|
|
|
- "imageList": ["https://cdn.weixiu.kyjlkj.com/uploads/images/20240914/202409141528015aeaa2357.png"],
|
|
|
- "type": 701,
|
|
|
- "tagGroupId": "tag_group_7272625659887960076"
|
|
|
- }],
|
|
|
- "outOrderNo": "202411121413333930",
|
|
|
- "totalAmount": 100,//分
|
|
|
- "orderEntrySchema": {
|
|
|
- "path": "page/path/index",
|
|
|
- "params": '{"id":1234, "name":"hello"}'
|
|
|
- },
|
|
|
- "payNotifyUrl": "https://weixiudev.kyjlkj.com/api/dou_yin/payNotify"
|
|
|
- }*/
|
|
|
- try {
|
|
|
- $douyinOrder = DouyinOrder::where('order_number',$order_number)->findOrEmpty();
|
|
|
- if($douyinOrder->isEmpty()){
|
|
|
- throw new \Exception('订单不存在!');
|
|
|
+ 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 = $params['event_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();
|
|
|
+ return true;
|
|
|
}
|
|
|
- $order = $douyinOrder->toArray();
|
|
|
- $goods_image = Goods::where('id',$order['goods_id'])->value('goods_image')??'';
|
|
|
-
|
|
|
- $data = [
|
|
|
- "skuList" => [
|
|
|
- [
|
|
|
- "skuId" => (string)$order['goods_id'],
|
|
|
- "price" => $order['unit_price'] * 100,
|
|
|
- "quantity" => $order['quantity'],
|
|
|
- "title" => $order['title'],
|
|
|
- "imageList" => [$goods_image],
|
|
|
- "type" => 701,
|
|
|
- "tagGroupId" => "tag_group_7272625659887960076"
|
|
|
- ]
|
|
|
- ],
|
|
|
- "outOrderNo" => $order['order_number'],
|
|
|
- "totalAmount" => $order['total_amount'] * 100,
|
|
|
- "orderEntrySchema" => [
|
|
|
- "path" => "page/index/index",
|
|
|
- "params" => json_encode(['order_number' => $order['order_number']])
|
|
|
- ],
|
|
|
- "payNotifyUrl" => config('douyin.payNotifyUrl'),
|
|
|
- ];
|
|
|
- $byteAuthorization = self::byteAuthorization(config('douyin.privateKeyStr'), json_encode($data), config('douyin.appId'), self::randStr(10), time(), 1);
|
|
|
- return ['byteAuthorization'=>$byteAuthorization,'data'=>json_encode($data)];
|
|
|
- } catch (\Exception $e) {
|
|
|
- throw new \Exception($e->getMessage());
|
|
|
}
|
|
|
+ return false;
|
|
|
}
|
|
|
-
|
|
|
- public static function cancelOrder($params)
|
|
|
+ // ++++++++++++++++++++ 首次创单 end
|
|
|
+ // ++++++++++++++++++++ 尾款创单
|
|
|
+ /**
|
|
|
+ * 预下单扩展点-子
|
|
|
+ * @param array $params goods_id user_info.mobile user_id quantity
|
|
|
+ * @return array|false
|
|
|
+ */
|
|
|
+ public static function tailOrder($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('订单状态不可取消!');
|
|
|
- }
|
|
|
+ $amount = bcdiv(bcsub($params['total_amount'] ,$params['discount_amount']), '100', 2)??0;
|
|
|
+ $work_id = DouyinOrder::where(['id'=>$params['douyinOrderId']])->value('work_id');
|
|
|
+ $sn = '';
|
|
|
+ $rechargeOrder = RechargeOrder::where(['work_id'=>$work_id,'payment_type'=>2])->findOrEmpty();
|
|
|
+ if($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 $order['id'];
|
|
|
+ return $sn;
|
|
|
} catch (\Exception $e) {
|
|
|
Db::rollback();
|
|
|
throw new \Exception($e->getMessage());
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- public static function payNotify($params)
|
|
|
+ // 尾款支付成功回调
|
|
|
+ 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 = $params['event_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();
|
|
|
- return true;
|
|
|
- }
|
|
|
+ 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 = $params['event_time']??time();
|
|
|
+
|
|
|
+ $rechargeOrder = RechargeOrder::where(['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();
|
|
|
+ return true;
|
|
|
}
|
|
|
- return false;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
}
|
|
|
+
|
|
|
+ // ++++++++++++++++++++ 尾款创单 end
|
|
|
+
|
|
|
+
|
|
|
+ // ******************************** 订单预约/改约
|
|
|
+ // 创建预约单
|
|
|
public static function reservation($params)
|
|
|
{
|
|
|
/*$lon_lat = get_address_lat_lng($params['user_address']);
|
|
|
@@ -441,20 +452,58 @@ class DouYinService
|
|
|
if (false === $result) {
|
|
|
throw new \Exception('预约失败');
|
|
|
}
|
|
|
- $consultationOrder = ExternalConsultationOrder::where('consultation_id', $order->consultation_id)->where('goods_id', $order->goods_id)->where('amount', $order->paid_amount)
|
|
|
- ->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();
|
|
|
+ if(!empty($result)){
|
|
|
+ $consultationOrder = ExternalConsultationOrder::where('consultation_id', $order->consultation_id)->where('goods_id', $order->goods_id)->where('amount', $order->paid_amount)
|
|
|
+ ->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();
|
|
|
+ }
|
|
|
}
|
|
|
Db::commit();
|
|
|
- return $order['id'];
|
|
|
+
|
|
|
+ // 抖音创建预约单
|
|
|
+ $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']??'',
|
|
|
+ 'result' => 1,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return $order['id']??0;
|
|
|
} catch (\Exception $e) {
|
|
|
Db::rollback();
|
|
|
throw new \Exception($e->getMessage());
|
|
|
}
|
|
|
}
|
|
|
+ public static function getCreateBookParams($params)
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ $data = [
|
|
|
+ "order_id"=> $params['order_number']??'',
|
|
|
+ "out_book_no"=> time()??'',
|
|
|
+ "open_id"=> $params['open_id']??'',
|
|
|
+ "item_book_info_list" => [
|
|
|
+ [
|
|
|
+ "poi_id" => '7511543640776017961',
|
|
|
+ "shop_name" => '亿蜂快修·武汉市',
|
|
|
+ "ext_shop_id" => self::EXTERNAL_PLATFORM_ID,
|
|
|
+ "goods_id" => (string)$params['external_goods_sn'],
|
|
|
+ "book_start_time" => $params['book_start_time']??'',
|
|
|
+ "book_end_time" => $params['book_end_time']??'',
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ];
|
|
|
+ return $data;
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ }
|
|
|
public static function upReservation($params)
|
|
|
{
|
|
|
// $params['order_number']
|
|
|
@@ -478,52 +527,28 @@ class DouYinService
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public static function getOrderDetail($params)
|
|
|
+ // ******************************** 订单退款
|
|
|
+ public static function cancelOrder($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'] = [];
|
|
|
-
|
|
|
- $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;
|
|
|
+ // $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());
|
|
|
}
|
|
|
- $orderInfo['performance'] = $performance;
|
|
|
-
|
|
|
- return $orderInfo;
|
|
|
}
|
|
|
-
|
|
|
public static function refund($params)
|
|
|
{
|
|
|
Db::startTrans();
|
|
|
@@ -557,7 +582,6 @@ class DouYinService
|
|
|
throw new \Exception($e->getMessage());
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
public static function refundExamine($params)
|
|
|
{
|
|
|
Db::startTrans();
|
|
|
@@ -612,8 +636,7 @@ class DouYinService
|
|
|
$douyinRefundOrder = DouyinRefundOrder::where('order_number', $order_number)->order('id', 'desc')->findOrEmpty();
|
|
|
|
|
|
//通过后向抖音申请退款
|
|
|
- //getClientToken()
|
|
|
- $url = config('douyin.host').'api/trade_basic/v1/developer/refund_create/';
|
|
|
+ $url = 'api/trade_basic/v1/developer/refund_create/';
|
|
|
$data = [
|
|
|
"order_id" => $orderInfo['transaction_id'],
|
|
|
"out_refund_no" => $douyinRefundOrder->refund_number,
|
|
|
@@ -623,7 +646,7 @@ class DouYinService
|
|
|
"params" => json_encode(['refund_number'=>$douyinRefundOrder->refund_number])
|
|
|
],
|
|
|
"refund_total_amount " => $douyinRefundOrder->refund_amount * 100,
|
|
|
- "notify_url" => config('douyin.refundNotifyUrl'),
|
|
|
+ //"notify_url" => config('douyin.refundNotifyUrl'),
|
|
|
"refund_reason" => [
|
|
|
[
|
|
|
"code" => 101,
|
|
|
@@ -631,9 +654,9 @@ class DouYinService
|
|
|
]
|
|
|
]
|
|
|
];
|
|
|
- $res = http_request($url,$data,['Content-Type' => 'application/json;charset=utf-8','access_token' => self::getClientToken()]);
|
|
|
- if(isset($res['err_msg']) && $res['err_msg'] === 'success'){
|
|
|
- $douyinRefundOrder->transaction_id = $res['data']['refund_id'];
|
|
|
+ $resData = self::toDyRequestUrl($url,$data);
|
|
|
+ if(isset($resData['data']) && $resData['data']){
|
|
|
+ $douyinRefundOrder->transaction_id = $resData['data']['refund_id'];
|
|
|
$douyinRefundOrder->save();
|
|
|
}
|
|
|
return true;
|
|
|
@@ -673,63 +696,21 @@ class DouYinService
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- public static function byteAuthorization($privateKeyStr, $data, $appId, $nonceStr, $timestamp, $keyVersion) {
|
|
|
- $byteAuthorization = '';
|
|
|
- // 读取私钥
|
|
|
- $privateKey = openssl_pkey_get_private($privateKeyStr);
|
|
|
- if (!$privateKey) {
|
|
|
- throw new \Exception("Invalid private key");
|
|
|
- }
|
|
|
- // 生成签名
|
|
|
- $signature = self::getSignature("POST", "/requestOrder", $timestamp, $nonceStr, $data, $privateKey);
|
|
|
- if ($signature === false) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- // 构造 byteAuthorization
|
|
|
- $byteAuthorization = sprintf("SHA256-RSA2048 appid=%s,nonce_str=%s,timestamp=%s,key_version=%s,signature=%s", $appId, $nonceStr, $timestamp, $keyVersion, $signature);
|
|
|
- return $byteAuthorization;
|
|
|
- }
|
|
|
-
|
|
|
- public static function getSignature($method, $url, $timestamp, $nonce, $data, $privateKey) {
|
|
|
- Log::info("method:{$method}\n url:{$url}\n timestamp:{$timestamp}\n nonce:{$nonce}\n data:{$data}");
|
|
|
- $targetStr = $method. "\n" . $url. "\n" . $timestamp. "\n" . $nonce. "\n" . $data. "\n";
|
|
|
- openssl_sign($targetStr, $sign, $privateKey, OPENSSL_ALGO_SHA256);
|
|
|
- $sign = base64_encode($sign);
|
|
|
- return $sign;
|
|
|
- }
|
|
|
-
|
|
|
- public static function randStr($length = 8) {
|
|
|
- $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
|
- $str = '';
|
|
|
- for ($i = 0; $i < $length; $i++) {
|
|
|
- $str .= $chars[mt_rand(0, strlen($chars) - 1)];
|
|
|
- }
|
|
|
- return $str;
|
|
|
- }
|
|
|
- public static function getClientToken($isRefresh = false) {
|
|
|
- $url = config('douyin.host').'oauth/client_token/';
|
|
|
- $cache_name = 'dy_client_token';
|
|
|
- $cache_data = cache($cache_name);
|
|
|
- if(empty($cache_data) || $cache_data == null || $isRefresh){
|
|
|
- $data = [
|
|
|
- 'client_key'=> config('douyin.appId'),
|
|
|
- 'client_secret'=> config('douyin.appSecret'),
|
|
|
- 'grant_type'=> "client_credential"
|
|
|
- ];
|
|
|
- $res = http_request($url,$data,['Content-Type' => 'application/json;charset=utf-8']);
|
|
|
- Log::info(json_encode($res));
|
|
|
- if($res['message'] === 'success'){
|
|
|
- cache($cache_name, json_encode($res['data']), (time()+$res['data']['expires_in']-1));
|
|
|
- $cache_data = $res['data'];
|
|
|
- }
|
|
|
+ public static function toDyRequestUrl($url,$data)
|
|
|
+ {
|
|
|
+ $toData = [
|
|
|
+ 'url' => $url,
|
|
|
+ 'data' => $data
|
|
|
+ ];
|
|
|
+ $res = http_request(env('internal_api.api_url_host').'platf/dou_yin/toDyRequestUrl',$toData,['Content-Type' => 'application/json;charset=utf-8']);
|
|
|
+ Log::info(json_encode($res));
|
|
|
+ if($res['code'] === 0){
|
|
|
+ Log::info("toDyRequestUrl:".json_encode($res));
|
|
|
+ return $res['data'];
|
|
|
+ }else{
|
|
|
+ Log::info("toDyRequestUrl:".$res['msg']);
|
|
|
+ throw new \Exception($res['msg']);
|
|
|
}
|
|
|
- return $cache_data['access_token'];
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
}
|