Compare commits
					merge into: Leadfyy.co:dev
					
				
				Leadfyy.co:ccb_pay
						
							Leadfyy.co:ccb_pay2
						
							Leadfyy.co:dev
						
							Leadfyy.co:master
						
							Leadfyy.co:sf_express
						
						
						
						
					
					pull from: Leadfyy.co:sf_express
					
				
				Leadfyy.co:ccb_pay
						
							Leadfyy.co:ccb_pay2
						
							Leadfyy.co:dev
						
							Leadfyy.co:master
						
							Leadfyy.co:sf_express
						
						
						
						
					
	
		
			4 Commits 
		
	
	
		
			dev
			...
			sf_express
		
	
    | Author | SHA1 | Message | Date | 
|---|---|---|---|
| 
							
							
								
									
								
								 | 
						5a2a3efd68 | 
							
							
								
								JsonRpc退款时,同时取消顺丰配送
							
							
							
							
								
 | 
						4 years ago | 
| 
							
							
								
									
								
								 | 
						35798124e7 | 
							
							
								
								顺丰同城第一次完成
							
							
							
							
								
 | 
						4 years ago | 
| 
							
							
								
									
								
								 | 
						bfe89bba95 | 
							
							
								
								增加.user.ini到忽略文件
							
							
							
							
								
 | 
						4 years ago | 
| 
							
							
								
									
								
								 | 
						2e7e0cd81e | 
							
							
								
								增加.user.ini到忽略文件
							
							
							
							
								
 | 
						4 years ago | 
				 15 changed files with 776 additions and 32 deletions
			
			
		- 
					1.gitignore
 - 
					18MySQL_change.sql
 - 
					37app/Controller/v3/OrderOnlineController.php
 - 
					223app/Controller/v3/SfExpressController.php
 - 
					6app/Controller/v3/UserAddressController.php
 - 
					6app/JsonRpc/OrderService.php
 - 
					22app/Model/v3/Goods.php
 - 
					22app/Model/v3/GoodsActivity.php
 - 
					14app/Model/v3/SfExpressOrder.php
 - 
					108app/Service/v3/Implementations/OrderOnlineService.php
 - 
					51app/Service/v3/Implementations/UserAddressService.php
 - 
					2app/Service/v3/Interfaces/UserAddressServiceInterface.php
 - 
					262app/Service/v3/SfExpress.php
 - 
					11config/routes.php
 - 
					3小程序修改
 
@ -0,0 +1,18 @@ | 
				
			|||
# 2022-04-09 14:57 | 
				
			|||
ALTER TABLE `lanzu_order_main` | 
				
			|||
    CHANGE COLUMN `shipping_type` `shipping_type` TINYINT(1) NOT NULL DEFAULT '1' COMMENT '配送方式:1服务站配送,2达达配送,3自提,4顺丰配送' AFTER `global_order_id`, | 
				
			|||
    CHANGE COLUMN `delivery_time_note` `delivery_time_note` VARCHAR(100) NULL DEFAULT '' COMMENT '客户期望送达时间' COLLATE 'utf8mb4_general_ci' AFTER `shipping_name`; | 
				
			|||
 | 
				
			|||
# 2022-04-11 23:50 | 
				
			|||
ALTER TABLE `lanzu_goods` | 
				
			|||
    ADD COLUMN `weight` INT(11) NOT NULL DEFAULT '0' COMMENT '产品毛重,用于计算顺丰运费' AFTER `goods_unit`; | 
				
			|||
ALTER TABLE `lanzu_goods_activity` | 
				
			|||
    ADD COLUMN `weight` INT(11) NOT NULL DEFAULT '0' COMMENT '产品毛重,用于计算顺丰运费' AFTER `goods_unit`; | 
				
			|||
 | 
				
			|||
# 2022-04-17 23:41 | 
				
			|||
ALTER TABLE `lanzu_order_goods` | 
				
			|||
    ADD COLUMN `weight` INT NULL DEFAULT 0 COMMENT '一件商品的重量(多个需要*number),单位:克' AFTER `note`; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
# 顺丰订单记录 | 
				
			|||
create table `lanzu_sf_express_orders`; | 
				
			|||
@ -0,0 +1,223 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Controller\v3; | 
				
			|||
use App\Constants\v3\OrderState; | 
				
			|||
use App\Controller\BaseController; | 
				
			|||
use App\Model\v3\Order; | 
				
			|||
use App\Model\v3\OrderMain; | 
				
			|||
use Hyperf\DbConnection\Db; | 
				
			|||
use Psr\Http\Message\ResponseInterface; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * 顺丰同城回调 | 
				
			|||
 */ | 
				
			|||
class SfExpressController extends BaseController | 
				
			|||
{ | 
				
			|||
	private string $dev_id; | 
				
			|||
	private string $dev_key; | 
				
			|||
//	private string $shop_id;
 | 
				
			|||
 | 
				
			|||
	public function __construct() | 
				
			|||
	{ | 
				
			|||
		parent::__construct(); //此句不能少,否则$this->request和$this->response获取不到
 | 
				
			|||
		$this->dev_id = env('SF_EXPRESS_DEV_ID'); | 
				
			|||
		$this->dev_key = env('SF_EXPRESS_DEV_KEY'); | 
				
			|||
//		$this->shop_id = env('SF_EXPRESS_SHOP_ID');
 | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 配送状态更改回调 | 
				
			|||
	 */ | 
				
			|||
	public function riderStatus(): ResponseInterface | 
				
			|||
	{ | 
				
			|||
		if (!$this->checkSign($this->request->query('sign'))) { | 
				
			|||
			return $this->response->json([ | 
				
			|||
				'error_code' => 500, | 
				
			|||
				'error_msg' => '签名错误', | 
				
			|||
			]); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		$formData = $this->request->all(); | 
				
			|||
		if (empty($formData['shop_order_id'])) { | 
				
			|||
			return $this->response->json([ | 
				
			|||
				'error_code' => 500, | 
				
			|||
				'error_msg' => '无效的shop_order_id', | 
				
			|||
			]); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		# 主订单表
 | 
				
			|||
		$orderMain = OrderMain::whereIn('state', [OrderState::PAID, OrderState::DELIVERY]) | 
				
			|||
			->where('global_order_id', $formData['shop_order_id']) | 
				
			|||
			->first(); | 
				
			|||
 | 
				
			|||
		if (!$orderMain) { | 
				
			|||
			return $this->response->json([ | 
				
			|||
				'error_code' => 500, | 
				
			|||
				'error_msg' => '订单不存在', | 
				
			|||
			]); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		DB::beginTransaction(); | 
				
			|||
		try { | 
				
			|||
			# 主订单表
 | 
				
			|||
			$orderMain->state = OrderState::DELIVERY; | 
				
			|||
			//order_status 订单状态 10-配送员确认;12:配送员到店;15:配送员配送中
 | 
				
			|||
			if (!empty($formData['order_status'])) { | 
				
			|||
				if ($formData['order_status'] == 10 && $orderMain->receive_time == 0) { | 
				
			|||
					$orderMain->receive_time = time(); // 接单时间
 | 
				
			|||
				} else if ($formData['order_status'] == 12 && $orderMain->delivery_start_time == 0) { | 
				
			|||
					$orderMain->delivery_start_time = time(); // 开始配送时间
 | 
				
			|||
				} | 
				
			|||
			} | 
				
			|||
			$orderMain->save(); | 
				
			|||
 | 
				
			|||
			# 子订单表
 | 
				
			|||
			Order::where('order_main_id', $formData['shop_order_id']) | 
				
			|||
				->update(['state' => $orderMain->state]); | 
				
			|||
 | 
				
			|||
			DB::commit(); | 
				
			|||
		} catch (\Exception $exception) { | 
				
			|||
			DB::rollBack(); | 
				
			|||
			return $this->response->json([ | 
				
			|||
				'error_code' => 500, | 
				
			|||
				'error_msg' => $exception->getMessage(), | 
				
			|||
			]); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		return $this->response->json([ | 
				
			|||
			'error_code' => 0, | 
				
			|||
			'error_msg' => 'success', | 
				
			|||
		]); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 骑士撤单状态回调 | 
				
			|||
	 */ | 
				
			|||
	public function riderRecall(): ResponseInterface | 
				
			|||
	{ | 
				
			|||
		if (!$this->checkSign($this->request->query('sign'))) { | 
				
			|||
			return $this->response->json([ | 
				
			|||
				'error_code' => 500, | 
				
			|||
				'error_msg' => '签名错误', | 
				
			|||
			]); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		$formData = $this->request->all(); | 
				
			|||
		if (empty($formData['shop_order_id'])) { | 
				
			|||
			return $this->response->json([ | 
				
			|||
				'error_code' => 500, | 
				
			|||
				'error_msg' => '无效的shop_order_id', | 
				
			|||
			]); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		//order_status 22-配送员撤单
 | 
				
			|||
		//TODO 因目前订单表没有相关撤单的字段,故目前不做处理,仅仅返回成功给顺丰
 | 
				
			|||
		return $this->response->json([ | 
				
			|||
			'error_code' => 0, | 
				
			|||
			'error_msg' => 'success', | 
				
			|||
		]); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 订单完成回调 | 
				
			|||
	 */ | 
				
			|||
	public function orderComplete(): ResponseInterface | 
				
			|||
	{ | 
				
			|||
		if (!$this->checkSign($this->request->query('sign'))) { | 
				
			|||
			return $this->response->json([ | 
				
			|||
				'error_code' => 500, | 
				
			|||
				'error_msg' => '签名错误', | 
				
			|||
			]); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		$formData = $this->request->all(); | 
				
			|||
		if (empty($formData['shop_order_id'])) { | 
				
			|||
			return $this->response->json([ | 
				
			|||
				'error_code' => 500, | 
				
			|||
				'error_msg' => '无效的shop_order_id', | 
				
			|||
			]); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		# 主订单表
 | 
				
			|||
		$orderMain = OrderMain::where('state', '>', OrderState::UNPAID) | 
				
			|||
			->where('global_order_id', $formData['shop_order_id']) | 
				
			|||
			->first(); | 
				
			|||
 | 
				
			|||
		if (!$orderMain) { | 
				
			|||
			return $this->response->json([ | 
				
			|||
				'error_code' => 500, | 
				
			|||
				'error_msg' => '订单不存在', | 
				
			|||
			]); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		DB::beginTransaction(); | 
				
			|||
		try { | 
				
			|||
			# 主订单表
 | 
				
			|||
			$orderMain->state = OrderState::COMPLETED; | 
				
			|||
			$orderMain->complete_time = time(); | 
				
			|||
			$orderMain->delivery_time = time(); | 
				
			|||
			$orderMain->save(); | 
				
			|||
 | 
				
			|||
			# 子订单表
 | 
				
			|||
			Order::where('order_main_id', $formData['shop_order_id']) | 
				
			|||
				->update(['state' => $orderMain->state]); | 
				
			|||
 | 
				
			|||
			DB::commit(); | 
				
			|||
		} catch (\Exception $exception) { | 
				
			|||
			DB::rollBack(); | 
				
			|||
			return $this->response->json([ | 
				
			|||
				'error_code' => 500, | 
				
			|||
				'error_msg' => $exception->getMessage(), | 
				
			|||
			]); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		return $this->response->json([ | 
				
			|||
			'error_code' => 0, | 
				
			|||
			'error_msg' => 'success', | 
				
			|||
		]); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 顺丰原因订单取消回调 | 
				
			|||
	 */ | 
				
			|||
	public function sfCancel(): ResponseInterface | 
				
			|||
	{ | 
				
			|||
		//TODO 因目前订单表没有相关撤单的字段,故目前不做处理,仅仅返回成功给顺丰
 | 
				
			|||
		return $this->riderRecall(); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 订单异常回调 | 
				
			|||
	 */ | 
				
			|||
	public function riderException(): ResponseInterface | 
				
			|||
	{ | 
				
			|||
		/** ex_id枚举值: | 
				
			|||
			4003:托寄物丢失或损坏 | 
				
			|||
			1001:商家出货慢 | 
				
			|||
			2010:顾客拒绝实名认证 | 
				
			|||
			3004:实名认证校验失败 | 
				
			|||
			1007:更改取货地址 | 
				
			|||
			2001:顾客电话无法接通 | 
				
			|||
			2004:更改期望送达时间 | 
				
			|||
			2005:顾客拒收 | 
				
			|||
			2008:顾客不在家 | 
				
			|||
			2009:更改送货地址 | 
				
			|||
			4001:配送地址错误 | 
				
			|||
			4002:其他 | 
				
			|||
		 */ | 
				
			|||
		//TODO 因目前订单表没有相关撤单的字段,故目前不做处理,仅仅返回成功给顺丰
 | 
				
			|||
		return $this->riderRecall(); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 回调签名校验 | 
				
			|||
	 */ | 
				
			|||
	private function checkSign(?string $checkSign): bool | 
				
			|||
	{ | 
				
			|||
		$post_data = $this->request->getBody()->getContents(); | 
				
			|||
		echo PHP_EOL, '$post_data', PHP_EOL; | 
				
			|||
		print_r($post_data); | 
				
			|||
		$sign_char = $post_data . "&{$this->dev_id}&{$this->dev_key}"; | 
				
			|||
		return $checkSign == base64_encode(md5($sign_char)); | 
				
			|||
	} | 
				
			|||
} | 
				
			|||
@ -0,0 +1,14 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Model\v3; | 
				
			|||
use App\Model\Model; | 
				
			|||
use Hyperf\Database\Model\Relations\BelongsTo; | 
				
			|||
 | 
				
			|||
class SfExpressOrder extends Model | 
				
			|||
{ | 
				
			|||
	protected $table = 'lanzu_sf_express_orders'; | 
				
			|||
	public function orderMain(): BelongsTo | 
				
			|||
	{ | 
				
			|||
		return $this->belongsTo(OrderMain::class, 'shop_order_id', 'global_order_id'); | 
				
			|||
	} | 
				
			|||
} | 
				
			|||
@ -0,0 +1,262 @@ | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
namespace App\Service\v3; | 
				
			|||
 | 
				
			|||
use App\Exception\BusinessException; | 
				
			|||
use Hyperf\Guzzle\ClientFactory; | 
				
			|||
use Hyperf\Utils\ApplicationContext; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * 顺丰同城相关 | 
				
			|||
 * 文档:https://commit-openic.sf-express.com/open/api/docs/index#/apidoc
 | 
				
			|||
 */ | 
				
			|||
class SfExpress | 
				
			|||
{ | 
				
			|||
	private string $dev_id; | 
				
			|||
	private string $dev_key; | 
				
			|||
	private string $shop_id; | 
				
			|||
	private string $host = 'https://openic.sf-express.com'; | 
				
			|||
	private ClientFactory $clientFactory; | 
				
			|||
	private static ?SfExpress $_instance = NULL; | 
				
			|||
 | 
				
			|||
	public function __construct() | 
				
			|||
	{ | 
				
			|||
		$this->dev_id = env('SF_EXPRESS_DEV_ID'); | 
				
			|||
		$this->dev_key = env('SF_EXPRESS_DEV_KEY'); | 
				
			|||
		$this->shop_id = env('SF_EXPRESS_SHOP_ID'); | 
				
			|||
		$this->clientFactory = ApplicationContext::getContainer()->get(ClientFactory::class); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	public static function getInstance(): SfExpress | 
				
			|||
	{ | 
				
			|||
		if (is_null(self::$_instance)) { | 
				
			|||
			self::$_instance = new static(); | 
				
			|||
		} | 
				
			|||
		return self::$_instance; | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 创建订单 | 
				
			|||
	 */ | 
				
			|||
	public function createOrder(array $params): array | 
				
			|||
	{ | 
				
			|||
		if (!isset($params['shop_order_id'], $params['order_time'], $params['receive'], $params['order_detail'])) { | 
				
			|||
			throw new BusinessException(500, '商户订单号、用户下单时间、收货信息、订单信息不能为空'); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		$params = array_merge([ | 
				
			|||
			'dev_id' => $this->dev_id, //必填
 | 
				
			|||
			'shop_id' => $this->shop_id, //必填
 | 
				
			|||
			'shop_type' => 1, //1:顺丰店铺ID 2:接入方店铺ID
 | 
				
			|||
			'shop_order_id' => '', //商户订单号
 | 
				
			|||
			'shop_preparation_time' => 15, //商家预计备餐时长,分钟级时间 比如: 10 分钟 则传入 10
 | 
				
			|||
			'order_source' => '街链平台', //必填。订单接入来源 1:美团;2:饿了么;3:百度;4:口碑;其他请直接填写中文字符串值
 | 
				
			|||
			// 'order_sequence' => '', //取货序号 与order_source配合使用 如:饿了么10号单,表示如下:order_source=2;order_sequence=10。用于骑士快速寻找配送物
 | 
				
			|||
			// 'lbs_type' => 2, //坐标类型,1:百度坐标,2:高德坐标
 | 
				
			|||
			'pay_type' => 1, //必填,用户支付方式:1、已支付 0、货到付款
 | 
				
			|||
			'order_time' => time(), | 
				
			|||
			'is_appoint' => 0, //必填,是否是预约单,0:非预约单;1:预约单
 | 
				
			|||
			'appoint_type' => 0, //预约单类型,1:预约单送达单;2:预约单上门单,默认:0
 | 
				
			|||
			// 'expect_time' => '', //用户期望送达时间,若传入自此段且时间大于配送时效,则按照预约送达单处理,时间小于配送时效按照立即单处理;appoint_type=1时需必传,秒级时间戳
 | 
				
			|||
			// 'expect_pickup_time' => '', //用户期望上门时间,appoint_type=2时需必传,秒级时间戳
 | 
				
			|||
			// 'shop_expect_time' => 0, //商家期望送达时间 只展示给骑士,不参与时效考核;秒级时间戳
 | 
				
			|||
			'is_insured' => 0, //必填,是否保价,0:非保价;1:保价
 | 
				
			|||
			'is_person_direct' => 0, //必填,是否是专人直送订单,0:否;1:是
 | 
				
			|||
			// 'vehicle' => 0, //配送交通工具,0:否;1:电动车;2:小轿车
 | 
				
			|||
			// 'declared_value' => 0, //保价金额
 | 
				
			|||
			// 'gratuity_fee' => 0, //订单小费,不传或者传0为不加小费,单位分,加小费最低不能少于100分
 | 
				
			|||
			'remark' => '无备注', //订单备注
 | 
				
			|||
			'rider_pick_method' => 1, //物流流向,1:从门店取件送至用户;2:从用户取件送至门店
 | 
				
			|||
			'return_flag' => 511, //1:商品总价格,2:配送距离,4:物品重量,8:起送时间,16:期望送达时间,32:支付费用,64:实际支持金额,128:优惠券总金额,256:结算方式,例如全部返回为填入511
 | 
				
			|||
			'push_time' => time(), //必填,推单时间,秒级时间戳(格林尼治时间)
 | 
				
			|||
			'version' => 17, //版本号 参照文档主版本号填写 如:文档版本号1.7,version=17
 | 
				
			|||
			'receive' => [ //收货人信息 Obj,详见receive结构
 | 
				
			|||
				'user_name' => '', //必填,用户姓名
 | 
				
			|||
				'user_phone' => '', //必填,用户电话
 | 
				
			|||
				'user_address' => '', //必填,用户详细地址
 | 
				
			|||
				'user_lng' => 0, //必填,用户地址经度
 | 
				
			|||
				'user_lat' => 0, //必填,用户地址纬度
 | 
				
			|||
				// 'city_name' => '', //发单城市 用来校验是否跨城;请填写城市的中文名称,如北京市、深圳市
 | 
				
			|||
			], | 
				
			|||
			/*'shop' => [ //发货店铺信息;obj,详见shop结构,平台级开发者需要传入
 | 
				
			|||
				'shop_name' => '店铺姓名', | 
				
			|||
				'shop_phone' => '店铺电话', | 
				
			|||
				'shop_address' => '店铺地址', | 
				
			|||
				'shop_lng' => '店铺经度', | 
				
			|||
				'shop_lat' => '店铺纬度', | 
				
			|||
			],*/ | 
				
			|||
			'order_detail' => [ // 必填,订单详情
 | 
				
			|||
				'total_price' => 0, //用户订单商品总金额(单位:分)	100 表示1元(最大值为100万, 超过此值则按100万计算)
 | 
				
			|||
				'product_type' => 10, //必填,物品类型。1:快餐,2:药品,3:百货,4:脏衣服收,5:干净衣服派,6:生鲜,其它详见文档
 | 
				
			|||
				// 'user_money' => 0, // 用户实付商家金额(单位:分) 100 表示1元
 | 
				
			|||
				// 'shop_money' => 0, // 商家实收用户金额(单位:分) 100 表示1元
 | 
				
			|||
				'weight_gram' => 0, // 必填,物品重量(单位:克) 100 表示100g
 | 
				
			|||
				// 'volume_litre' => 0, // 物品体积(单位:升) 1 表示1升
 | 
				
			|||
				// 'delivery_money' => 0, // 商家收取用户的配送费(单位:分) 100 表示1元
 | 
				
			|||
				'product_num' => 1, // 必填,物品个数
 | 
				
			|||
				'product_type_num' => 1, // 必填,物品种类个数
 | 
				
			|||
				'product_detail' => [ // 必填,物品种类个数
 | 
				
			|||
					[ | 
				
			|||
						'product_name' => '', // 必填,物品名称
 | 
				
			|||
						// 'product_id' => 1, // 物品ID
 | 
				
			|||
						'product_num' => 1, // 必填,物品数量
 | 
				
			|||
						// 'product_price' => 0, // 物品价格
 | 
				
			|||
						// 'product_unit' => 0, // 物品单位
 | 
				
			|||
						// 'product_remark' => 0, // 备注
 | 
				
			|||
						// 'item_detail' => 0, // 详情
 | 
				
			|||
					], | 
				
			|||
				], | 
				
			|||
			], | 
				
			|||
			/*'multi_pickup_info' => [ //多点取货信息
 | 
				
			|||
				[ | 
				
			|||
					'pickup_shop_address' => '取货点地址', // 必填,取货点地址
 | 
				
			|||
					'pickup_shop_phone' => '取货点店铺手机号', // 必填,取货点店铺手机号
 | 
				
			|||
					'pickup_shop_name' => '取货点店铺手机号', // 必填,取货点店铺名称
 | 
				
			|||
					'pickup_lng' => '取货点经度', // 必填,取货点经度
 | 
				
			|||
					'pickup_lat' => '取货点纬度', // 必填,取货点纬度
 | 
				
			|||
					'pickup_products' => '', // 必填,取货点店铺物品信息
 | 
				
			|||
				], | 
				
			|||
			],*/ | 
				
			|||
		], $params); | 
				
			|||
 | 
				
			|||
		return $this->send('/open/api/external/createorder', $params); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 取消订单 | 
				
			|||
	 */ | 
				
			|||
	public function cancelOrder(array $params): array | 
				
			|||
	{ | 
				
			|||
		$params = array_merge([ | 
				
			|||
			'dev_id' => $this->dev_id, | 
				
			|||
			'order_id' => $params['order_id'], | 
				
			|||
			'shop_id' => $this->shop_id, // 使用商家订单号,需要传入shop_id
 | 
				
			|||
			'shop_type' => 1, // 输入shop_id,shop_type需必传
 | 
				
			|||
			'order_type' => 2, // 订单ID类型,1、顺丰订单号 2、商家订单号
 | 
				
			|||
			'cancel_code' => 300, | 
				
			|||
			'push_time' => time(), | 
				
			|||
		], $params); | 
				
			|||
 | 
				
			|||
		return $this->send('/open/api/external/cancelorder', $params); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 获取顺丰同城配送费 | 
				
			|||
	 */ | 
				
			|||
	public function getDeliveryCost(array $params): float | 
				
			|||
	{ | 
				
			|||
		$res = $this->preCreateOrder($params); | 
				
			|||
		$real_pay_money = $res['result']['real_pay_money'] ?? null; | 
				
			|||
		if ($real_pay_money === null) { | 
				
			|||
			throw new BusinessException(500, '获取配送费失败'); | 
				
			|||
		} | 
				
			|||
		return (float)bcdiv($real_pay_money, 100, 2); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 获取原始配送费 | 
				
			|||
	 */ | 
				
			|||
	public function getOriginDeliveryCost(float $deliveryCost): float | 
				
			|||
	{ | 
				
			|||
		return (float)bcadd($deliveryCost,3.50,2); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 预创建订单 | 
				
			|||
	 */ | 
				
			|||
	private function preCreateOrder(array $params): array | 
				
			|||
	{ | 
				
			|||
		if (!isset($params['user_lng'], $params['user_lat'], $params['user_address'], $params['weight'], $params['shop'])) { | 
				
			|||
			throw new BusinessException(500, '经度、纬度、收货地址、重量、发货店铺信息不能为空'); | 
				
			|||
		} | 
				
			|||
		$params = array_merge([ | 
				
			|||
			'dev_id' => $this->dev_id, //必填
 | 
				
			|||
			'shop_id' => $this->shop_id, //必填
 | 
				
			|||
			'shop_type' => 1, //1:顺丰店铺ID 2:接入方店铺ID
 | 
				
			|||
			'user_lng' => 0, //必填,用户地址经度
 | 
				
			|||
			'user_lat' => 0, //必填,用户地址纬度
 | 
				
			|||
			'user_address' => '', //必填,用户详细地址
 | 
				
			|||
			'weight' => 0, //必填,物品重量(单位:克)
 | 
				
			|||
			'product_type' => 6, //必填,物品类型。1:快餐,2:药品,3:百货,4:脏衣服收,5:干净衣服派,6:生鲜,其它详见文档
 | 
				
			|||
			// 'total_price' => 0, //用户订单总金额(单位:分)
 | 
				
			|||
			'is_appoint' => 0, //必填,是否是预约单,0:非预约单;1:预约单
 | 
				
			|||
			'appoint_type' => 0, //预约单类型,1:预约单送达单;2:预约单上门单,默认:0
 | 
				
			|||
			// 'expect_time' => '', //用户期望送达时间,若传入自此段且时间大于配送时效,则按照预约送达单处理,时间小于配送时效按照立即单处理;appoint_type=1时需必传,秒级时间戳
 | 
				
			|||
			// 'expect_pickup_time' => '', //用户期望上门时间,appoint_type=2时需必传,秒级时间戳
 | 
				
			|||
			// 'lbs_type' => 2, //坐标类型,1:百度坐标,2:高德坐标
 | 
				
			|||
			'pay_type' => 1, //必填,用户支付方式:1、已支付 0、货到付款
 | 
				
			|||
			// 'receive_user_money' => 0, //代收金额,单位:分
 | 
				
			|||
			'is_insured' => 0, //必填,是否保价,0:非保价;1:保价
 | 
				
			|||
			'is_person_direct' => 0, //必填,是否是专人直送订单,0:否;1:是
 | 
				
			|||
			// 'declared_value' => 0, //保价金额
 | 
				
			|||
			// 'gratuity_fee' => 0, //订单小费,不传或者传0为不加小费,单位分,加小费最低不能少于100分
 | 
				
			|||
			'rider_pick_method' => 1, //物流流向,1:从门店取件送至用户;2:从用户取件送至门店
 | 
				
			|||
			'return_flag' => 511, //1:商品总价格,2:配送距离,4:物品重量,8:起送时间,16:期望送达时间,32:支付费用,64:实际支持金额,128:优惠券总金额,256:结算方式,例如全部返回为填入511
 | 
				
			|||
			'push_time' => time(), //必填,推单时间,秒级时间戳(格林尼治时间)
 | 
				
			|||
			/*'shop' => [ //发货店铺信息;obj,详见shop结构,平台级开发者需要传入
 | 
				
			|||
				'shop_name' => '店铺姓名', | 
				
			|||
				'shop_phone' => '店铺电话', | 
				
			|||
				'shop_address' => '店铺地址', | 
				
			|||
				'shop_lng' => '店铺经度', | 
				
			|||
				'shop_lat' => '店铺纬度', | 
				
			|||
			], | 
				
			|||
			'multi_pickup_info' => [ //多点取货信息
 | 
				
			|||
				'pickup_shop_address' => '取货点地址', | 
				
			|||
				'pickup_lng' => '取货点经度', | 
				
			|||
				'pickup_lat' => '取货点纬度', | 
				
			|||
			],*/ | 
				
			|||
		], $params); | 
				
			|||
 | 
				
			|||
		return $this->send('/open/api/external/precreateorder', $params); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 发送请求 | 
				
			|||
	 */ | 
				
			|||
	public function send(string $url, array $params): array | 
				
			|||
	{ | 
				
			|||
		$url = $this->host . $url; | 
				
			|||
		$url = $url . (str_contains($url, '?') ? '&sign=' . $this->getSign($params) : '?sign=' . $this->getSign($params)); | 
				
			|||
 | 
				
			|||
		$res = json_decode($this->clientFactory->create()->post($url, ['json' => $params])->getBody()->getContents(), true); | 
				
			|||
		if (!$res || !isset($res['error_code']) || $res['error_code'] != 0) { | 
				
			|||
			throw new BusinessException(500, ($res['error_code'] ?? '') . ':' . ($res['error_msg'] ?? '请求异常')); | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
		return $res; | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 计算请求签名 | 
				
			|||
	 */ | 
				
			|||
	private function getSign(array $params): string | 
				
			|||
	{ | 
				
			|||
		$post_data = json_encode($params); | 
				
			|||
		$sign_char = $post_data . "&{$this->dev_id}&{$this->dev_key}"; | 
				
			|||
		return base64_encode(md5($sign_char)); | 
				
			|||
	} | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 前端传上来的送达时间(如:11:30 - 12:00)转顺丰的expect_time等预约参数 | 
				
			|||
	 */ | 
				
			|||
	public function deliveryTimeNote2expectTime(string $deliveryTimeNote): array | 
				
			|||
	{ | 
				
			|||
		if (!empty($deliveryTimeNote) && $deliveryTimeNote != '尽快送达' && strpos($deliveryTimeNote, '-') !== false) { | 
				
			|||
			$arr = array_map(function ($v) { | 
				
			|||
				return trim($v); | 
				
			|||
			}, explode('-', $deliveryTimeNote)); | 
				
			|||
 | 
				
			|||
			if ($arr[0] && $arr[1]) { | 
				
			|||
				$startTime = strtotime($arr[0]); | 
				
			|||
				$endTime = strtotime($arr[1]); | 
				
			|||
				# 判断是否是有效时间戳
 | 
				
			|||
				if ($startTime > 1650000000 && $endTime > 1650000000) { | 
				
			|||
					$sfParams['is_appoint'] = 1; | 
				
			|||
					$sfParams['appoint_type'] = 1; | 
				
			|||
					$sfParams['expect_time'] = floor(($startTime + $endTime) / 2); | 
				
			|||
				} | 
				
			|||
			} | 
				
			|||
		} | 
				
			|||
		return $sfParams ?? []; | 
				
			|||
	} | 
				
			|||
} | 
				
			|||
@ -0,0 +1,3 @@ | 
				
			|||
/pages/orderSubmit/orderSubmit.vue约490行增加 | 
				
			|||
					shopcart_ids: that.shopcart_ids, | 
				
			|||
					delivery_time_note: that.order_info.appointment_time.distribution[that.time_index].value, | 
				
			|||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue