You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
6.8 KiB
186 lines
6.8 KiB
11 months ago
|
<?php
|
||
|
// +----------------------------------------------------------------------
|
||
|
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
|
||
|
// +----------------------------------------------------------------------
|
||
|
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
|
||
|
// +----------------------------------------------------------------------
|
||
|
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
|
||
|
// +----------------------------------------------------------------------
|
||
|
// | Author: 萤火科技 <admin@yiovo.com>
|
||
|
// +----------------------------------------------------------------------
|
||
|
declare (strict_types=1);
|
||
|
|
||
|
namespace app\common\service\order;
|
||
|
|
||
|
use app\common\library\helper;
|
||
|
use app\common\model\Express as ExpressModel;
|
||
|
use app\common\model\UserOauth as UserOauthModel;
|
||
|
use app\common\model\wxapp\Setting as WxappSettingModel;
|
||
|
use app\common\enum\Client as ClientEnum;
|
||
|
use app\common\enum\order\OrderType as OrderTypeEnum;
|
||
|
use app\common\enum\payment\Method as PaymentMethodEnum;
|
||
|
use app\common\enum\order\DeliveryStatus as DeliveryStatusEnum;
|
||
|
use app\common\library\wechat\Shipping as WechatShippingApi;
|
||
|
use app\common\service\BaseService;
|
||
|
use cores\exception\BaseException;
|
||
|
|
||
|
/**
|
||
|
* 微信小程序-发货信息管理
|
||
|
* Class Shipping
|
||
|
* @package app\common\service\order
|
||
|
*/
|
||
|
class Shipping extends BaseService
|
||
|
{
|
||
|
// 物流配送
|
||
|
const DELIVERY_EXPRESS = 1;
|
||
|
|
||
|
// 虚拟商品
|
||
|
const DELIVERY_VIRTUAL = 3;
|
||
|
|
||
|
// 用户自提
|
||
|
const DELIVERY_EXTRACT = 4;
|
||
|
|
||
|
/**
|
||
|
* 发货信息同步微信平台
|
||
|
* @param mixed $completed 订单详情
|
||
|
* @param array $param 发货信息参数
|
||
|
* @return bool
|
||
|
* @throws BaseException
|
||
|
* @throws \think\db\exception\DataNotFoundException
|
||
|
* @throws \think\db\exception\DbException
|
||
|
* @throws \think\db\exception\ModelNotFoundException
|
||
|
*/
|
||
|
public function syncMpWeixinShipping($completed, array $param): bool
|
||
|
{
|
||
|
// 构建发货信息参数
|
||
|
$param = $this->buildParam($completed, $param);
|
||
|
// 仅微信小程序端并且使用微信支付的订单才可以同步
|
||
|
if (
|
||
|
!$param['syncMpWeixinShipping']
|
||
|
|| $completed['pay_method'] !== PaymentMethodEnum::WECHAT
|
||
|
|| $completed['platform'] !== ClientEnum::MP_WEIXIN
|
||
|
) {
|
||
|
return false;
|
||
|
}
|
||
|
// 订单全部发货时再同步, 分包发货时不同步
|
||
|
if ($completed['delivery_status'] !== DeliveryStatusEnum::DELIVERED) {
|
||
|
return false;
|
||
|
}
|
||
|
if (empty($completed['trade'])) {
|
||
|
throwError('很抱歉,该订单不存在微信支付交易记录');
|
||
|
}
|
||
|
// 请求微信API接口
|
||
|
return $this->request($this->buildApiParam($completed, $param));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 请求微信API接口
|
||
|
* @param array $apiParam
|
||
|
* @return true
|
||
|
* @throws BaseException
|
||
|
* @throws \think\db\exception\DataNotFoundException
|
||
|
* @throws \think\db\exception\DbException
|
||
|
* @throws \think\db\exception\ModelNotFoundException
|
||
|
*/
|
||
|
private function request(array $apiParam): bool
|
||
|
{
|
||
|
// 小程序配置信息
|
||
|
$wxConfig = WxappSettingModel::getConfigBasic();
|
||
|
// 请求API数据
|
||
|
$WechatShippingApi = new WechatShippingApi($wxConfig['app_id'], $wxConfig['app_secret']);
|
||
|
// 处理返回结果
|
||
|
$response = $WechatShippingApi->uploadShippingInfo($apiParam);
|
||
|
empty($response) && throwError('微信API请求失败:' . $WechatShippingApi->getError());
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 构建发货信息参数
|
||
|
* @param $completed
|
||
|
* @param array $param
|
||
|
* @return array
|
||
|
*/
|
||
|
private function buildParam($completed, array $param): array
|
||
|
{
|
||
|
// 设置默认的参数
|
||
|
$param = helper::setQueryDefaultValue($param, [
|
||
|
// 同步至微信小程序《发货信息录入》
|
||
|
'syncMpWeixinShipping' => 1,
|
||
|
// 物流模式:1物流配送 3虚拟商品 4用户自提
|
||
|
'logisticsType' => self::DELIVERY_EXPRESS,
|
||
|
// 物流公司ID
|
||
|
'expressId' => '',
|
||
|
// 物流单号
|
||
|
'expressNo' => '',
|
||
|
]);
|
||
|
// 虚拟订单发货方式强制为无需物流
|
||
|
if ($completed['order_type'] == OrderTypeEnum::VIRTUAL) {
|
||
|
$param['logisticsType'] = self::DELIVERY_VIRTUAL;
|
||
|
}
|
||
|
return $param;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 构建API参数
|
||
|
* @param $completed
|
||
|
* @param array $param
|
||
|
* @return array
|
||
|
* @throws BaseException
|
||
|
*/
|
||
|
private function buildApiParam($completed, array $param): array
|
||
|
{
|
||
|
// 获取物流公司编码
|
||
|
$param['expressId'] > 0 && $expressCode = $this->getExpressCode($param['expressId']);
|
||
|
return [
|
||
|
'order_key' => [
|
||
|
// 订单单号类型:1使用下单商户号和商户侧单号 2使用微信支付单号
|
||
|
'order_number_type' => 2,
|
||
|
// 支付交易对应的微信订单号
|
||
|
'transaction_id' => $completed['trade']['trade_no'],
|
||
|
],
|
||
|
// 物流模式:1物流配送 3虚拟商品 4用户自提
|
||
|
'logistics_type' => $param['logisticsType'],
|
||
|
// 发货模式:1、UNIFIED_DELIVERY(统一发货)2、SPLIT_DELIVERY(分拆发货)
|
||
|
'delivery_mode' => 1,
|
||
|
// 用于标识分拆发货模式下是否已全部发货完成 示例值: true/false
|
||
|
'is_all_delivered' => true,
|
||
|
'shipping_list' => [
|
||
|
[
|
||
|
'express_company' => $expressCode ?? '', // 物流公司编码
|
||
|
'tracking_no' => $param['expressNo'], // 物流单号
|
||
|
'item_desc' => $completed['goods'][0]['goods_name'], // 商品信息
|
||
|
]
|
||
|
],
|
||
|
// 上传时间 (RFC3339格式)
|
||
|
'upload_time' => \date(DATE_RFC3339),
|
||
|
// 微信用户openid
|
||
|
'payer' => ['openid' => $this->getUserOpenId($completed['user_id'])],
|
||
|
];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取物流公司编码 [这里用快递鸟编码格式]
|
||
|
* @param int $expressId
|
||
|
* @return mixed
|
||
|
* @throws BaseException
|
||
|
*/
|
||
|
private function getExpressCode(int $expressId)
|
||
|
{
|
||
|
$detail = ExpressModel::detail($expressId);
|
||
|
empty($detail) && throwError('很抱歉,未找到指定的物流公司');
|
||
|
return $detail['kdniao_code'];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取微信小程序用户openid
|
||
|
* @param int $userId
|
||
|
* @return mixed
|
||
|
* @throws BaseException
|
||
|
*/
|
||
|
private function getUserOpenId(int $userId)
|
||
|
{
|
||
|
$openid = UserOauthModel::getOauthIdByUserId($userId, ClientEnum::MP_WEIXIN);
|
||
|
empty($openid) && throwError('很抱歉,未找到当前用户的openid');
|
||
|
return $openid;
|
||
|
}
|
||
|
}
|