Преглед изворни кода

feat: 添加小程序订单

Gosowong пре 2 година
родитељ
комит
8f316ee2aa

+ 4 - 0
crmeb/crmeb/services/easywechat/Application.php

@@ -14,10 +14,12 @@ namespace crmeb\services\easywechat;
 
 
 use crmeb\services\easywechat\miniPayment\ServiceProvider;
 use crmeb\services\easywechat\miniPayment\ServiceProvider;
 use crmeb\services\easywechat\oauth2\wechat\WechatOauth2Provider;
 use crmeb\services\easywechat\oauth2\wechat\WechatOauth2Provider;
+use crmeb\services\easywechat\orderShipping\OrderClient;
 use crmeb\services\easywechat\subscribe\ProgramProvider;
 use crmeb\services\easywechat\subscribe\ProgramProvider;
 use crmeb\services\easywechat\v3pay\PayClient;
 use crmeb\services\easywechat\v3pay\PayClient;
 use crmeb\services\easywechat\wechatlive\ProgramProvider as LiveProgramProvider;
 use crmeb\services\easywechat\wechatlive\ProgramProvider as LiveProgramProvider;
 use crmeb\services\easywechat\v3pay\ServiceProvider as V3PayServiceProvider;
 use crmeb\services\easywechat\v3pay\ServiceProvider as V3PayServiceProvider;
+use crmeb\services\easywechat\orderShipping\ServiceProvider as OrderServiceProvider;
 
 
 
 
 /**
 /**
@@ -26,6 +28,7 @@ use crmeb\services\easywechat\v3pay\ServiceProvider as V3PayServiceProvider;
  * @property LiveProgramProvider $wechat_live
  * @property LiveProgramProvider $wechat_live
  * @property WechatOauth2Provider $oauth2
  * @property WechatOauth2Provider $oauth2
  * @property PayClient $v3pay
  * @property PayClient $v3pay
+ * @property OrderClient $order_ship
  */
  */
 class Application extends \EasyWeChat\Foundation\Application
 class Application extends \EasyWeChat\Foundation\Application
 {
 {
@@ -40,6 +43,7 @@ class Application extends \EasyWeChat\Foundation\Application
         ProgramProvider::class,
         ProgramProvider::class,
         V3PayServiceProvider::class,
         V3PayServiceProvider::class,
         \crmeb\services\easywechat\Open3rd\ProgramProvider::class,
         \crmeb\services\easywechat\Open3rd\ProgramProvider::class,
+        OrderServiceProvider::class
     ];
     ];
 
 
     /**
     /**

+ 131 - 0
crmeb/crmeb/services/easywechat/orderShipping/BaseOrder.php

@@ -0,0 +1,131 @@
+<?php
+
+namespace crmeb\services\easywechat\orderShipping;
+
+use crmeb\exceptions\AdminException;
+use EasyWeChat\Core\AbstractAPI;
+use EasyWeChat\Core\AccessToken;
+use EasyWeChat\Support\Collection;
+
+
+class BaseOrder extends AbstractAPI
+{
+
+    public $config;
+
+    const BASE_API = 'https://api.weixin.qq.com/';
+
+    const ORDER = 'wxa/sec/order/';
+    const EXPRESS = 'cgi-bin/express/delivery/open_msg/';
+
+
+    public function __construct(AccessToken $accessToken, $config)
+    {
+        parent::__construct($accessToken);
+        $this->config = $config;
+    }
+
+    private function resultHandle(Collection $result)
+    {
+        if (empty($result)) {
+            throw new AdminException('微信接口返回异常');
+        }
+        $res = $result->toArray();
+        if ($res['errcode'] == 0) {
+            return $res;
+        } else {
+            throw  new AdminException("微信接口异常:code = {$res['errcode']} msg = {$res['errmsg']}");
+        }
+    }
+
+    /**
+     * 发货
+     * @param $params
+     * @return array
+     * @throws \EasyWeChat\Core\Exceptions\HttpException
+     *
+     * @date 2023/05/09
+     * @author yyw
+     */
+    public function shipping($params)
+    {
+        return $this->resultHandle($this->parseJSON('POST', [self::BASE_API . self::ORDER . 'upload_shipping_info', json_encode($params)]));
+
+    }
+
+    /**
+     * 合单
+     * @param $params
+     * @return array
+     * @throws \EasyWeChat\Core\Exceptions\HttpException
+     *
+     * @date 2023/05/09
+     * @author yyw
+     */
+    public function combinedShipping($params)
+    {
+        return $this->resultHandle($this->parseJSON('POST', [self::BASE_API . self::ORDER . 'upload_combined_shipping_info', json_encode($params)]));
+    }
+
+
+    /**
+     * 签收消息提醒
+     * @param $params
+     * @return array
+     * @throws \EasyWeChat\Core\Exceptions\HttpException
+     *
+     * @date 2023/05/09
+     * @author yyw
+     */
+    public function notifyConfirm($params)
+    {
+        return $this->resultHandle($this->parseJSON('POST', [self::BASE_API . self::ORDER . 'notify_confirm_receive', json_encode($params)]));
+    }
+
+
+    /**
+     * 查询小程序是否已开通发货信息管理服务
+     * @return array
+     * @throws \EasyWeChat\Core\Exceptions\HttpException
+     *
+     * @date 2023/05/09
+     * @author yyw
+     */
+    public function isManaged()
+    {
+        $params = [
+            'appid' => $this->config['order_shipping']['appid']
+        ];
+        return $this->resultHandle($this->parseJSON('POST', [self::BASE_API . self::ORDER . 'notify_confirm_receive', json_encode($params)]));
+    }
+
+    /**
+     * 设置跳转连接
+     * @param $path
+     * @return array
+     * @throws \EasyWeChat\Core\Exceptions\HttpException
+     *
+     * @date 2023/05/10
+     * @author yyw
+     */
+    public function setMesJumpPath($path)
+    {
+        $params = [
+            'path' => $path
+        ];
+        return $this->resultHandle($this->parseJSON('POST', [self::BASE_API . self::ORDER . 'set_msg_jump_path', json_encode($params)]));
+    }
+
+    /**
+     * 获取运力id列表get_delivery_list
+     * @return array
+     * @throws \EasyWeChat\Core\Exceptions\HttpException
+     *
+     * @date 2023/05/09
+     * @author yyw
+     */
+    public function getDeliveryList()
+    {
+        return $this->resultHandle($this->parseJSON('POST', [self::BASE_API . self::EXPRESS . 'get_delivery_list']));
+    }
+}

+ 130 - 0
crmeb/crmeb/services/easywechat/orderShipping/MiniOrderService.php

@@ -0,0 +1,130 @@
+<?php
+
+namespace crmeb\services\easywechat\orderShipping;
+
+use crmeb\services\easywechat\Application;
+
+class MiniOrderService
+{
+
+    /**
+     * @var Application
+     */
+    protected static $instance;
+
+    /**
+     * @param array $config
+     * @return array[]
+     *
+     * @date 2023/05/09
+     * @author yyw
+     */
+    protected static function options(array $config = [])
+    {
+        return [
+            'order_shipping' => [
+                'appid' => sys_config('routine_appId'),
+                'merchant_id' => sys_config('pay_new_weixin_open') ? sys_config('pay_weixin_mchid') : sys_config('pay_new_weixin_mchid'),
+            ]
+        ];
+    }
+
+    /**
+     * 初始化
+     * @param bool $cache
+     * @return Application
+     */
+    protected static function application($cache = false)
+    {
+        (self::$instance === null || $cache === true) && (self::$instance = new Application(self::options()));
+        return self::$instance;
+    }
+
+    protected static function order()
+    {
+        return self::application()->order_ship;
+    }
+
+
+    /**
+     * 上传订单
+     * @param string $out_trade_no
+     * @param int $logistics_type
+     * @param array $shipping_list
+     * @param string $payer_openid
+     * @param int $delivery_mode
+     * @param bool $is_all_delivered
+     * @return array
+     *
+     * @date 2023/05/09
+     * @author yyw
+     */
+    public static function shippingByTradeNo(string $out_trade_no, int $logistics_type, array $shipping_list, string $payer_openid, int $delivery_mode = 1, bool $is_all_delivered = true)
+    {
+        return self::order()->shippingByTradeNo($out_trade_no, $logistics_type, $shipping_list, $payer_openid, $delivery_mode, $is_all_delivered);
+    }
+
+    /**
+     * 合单
+     * @param string $out_trade_no
+     * @param int $logistics_type
+     * @param array $sub_orders
+     * @param string $payer_openid
+     * @param int $delivery_mode
+     * @param bool $is_all_delivered
+     * @return array
+     * @throws \EasyWeChat\Core\Exceptions\HttpException
+     *
+     * @date 2023/05/10
+     * @author yyw
+     */
+    public static function combinedShippingByTradeNo(string $out_trade_no, int $logistics_type, array $sub_orders, string $payer_openid, int $delivery_mode = 2, bool $is_all_delivered = false)
+    {
+        return self::order()->combinedShippingByTradeNo($out_trade_no, $logistics_type, $sub_orders, $payer_openid, $delivery_mode, $is_all_delivered);
+    }
+
+    /**
+     * 签收通知
+     * @param string $merchant_trade_no
+     * @param string $received_time
+     * @return array
+     *
+     * @date 2023/05/09
+     * @author yyw
+     */
+    public static function notifyConfirmByTradeNo(string $merchant_trade_no, string $received_time)
+    {
+        return self::order()->notifyConfirmByTradeNo($merchant_trade_no, $received_time);
+    }
+
+    /**
+     * 判断是否开通
+     * @return bool
+     * @throws \EasyWeChat\Core\Exceptions\HttpException
+     * @throws \Psr\SimpleCache\InvalidArgumentException
+     *
+     * @date 2023/05/09
+     * @author yyw
+     */
+    public static function isManaged()
+    {
+        return self::order()->checkManaged();
+    }
+
+
+    /**
+     * 设置小修跳转路径
+     * @param $path
+     * @return array
+     * @throws \EasyWeChat\Core\Exceptions\HttpException
+     *
+     * @date 2023/05/10
+     * @author yyw
+     */
+    public static function setMesJumpPath($path)
+    {
+        return self::order()->setMesJumpPath($path);
+    }
+
+
+}

+ 257 - 0
crmeb/crmeb/services/easywechat/orderShipping/OrderClient.php

@@ -0,0 +1,257 @@
+<?php
+
+namespace crmeb\services\easywechat\orderShipping;
+
+use crmeb\exceptions\AdminException;
+use crmeb\services\CacheService;
+use EasyWeChat\Core\Exceptions\HttpException;
+use think\facade\Cache;
+
+
+class OrderClient extends BaseOrder
+{
+    const redis_prefix = 'mimi_order';
+
+
+    /**
+     * @var \Redis
+     */
+    protected $redis;
+
+    /**
+     * @return object|\Redis|null
+     *
+     * @date 2023/05/10
+     * @author yyw
+     */
+    protected function getRedis()
+    {
+        if (empty($this->redis)) {
+            $this->redis = Cache::store('redis')->handler();
+        }
+        return $this->redis;
+    }
+
+    /**
+     * 发货
+     * @param string $out_trade_no
+     * @param int $logistics_type
+     * @param array $shipping_list
+     * @param string $payer_openid
+     * @param int $delivery_mode
+     * @param bool $is_all_delivered
+     * @return array
+     * @throws HttpException
+     *
+     * @date 2023/05/10
+     * @author yyw
+     */
+    public function shippingByTradeNo(string $out_trade_no, int $logistics_type, array $shipping_list, string $payer_openid, int $delivery_mode = 1, bool $is_all_delivered = true)
+    {
+        if (!$this->checkManaged()) {
+            throw new AdminException('开通小程序订单管理服务后重试');
+        }
+
+
+        $params = [
+            'order_key' => [
+                'order_number_type' => 1,
+                'mchid' => $this->config['order_shipping']['merchant_id'],
+                'out_trade_no' => $out_trade_no,
+            ],
+            'logistics_type' => $logistics_type,
+            'delivery_mode' => $delivery_mode,
+            'upload_time' => date(DATE_RFC3339),
+            'payer' => [
+                'openid' => $payer_openid
+            ]
+        ];
+        if ($delivery_mode == 2) {
+            $params['is_all_delivered'] = $is_all_delivered;
+        }
+
+        foreach ($shipping_list as $shipping) {
+            $params['shipping_list'][] = [
+                'tracking_no' => $shipping['tracking_no'],
+                'express_company' => $this->getDelivery($shipping['express_company']),
+                'item_desc' => $shipping['item_desc'],
+                'contact' => $shipping['contact'] ?? []
+            ];
+        }
+        return $this->shipping($params);
+    }
+
+
+    /**
+     * 合单
+     * @param string $out_trade_no
+     * @param int $logistics_type
+     * @param array $sub_orders
+     * @param string $payer_openid
+     * @param int $delivery_mode
+     * @param bool $is_all_delivered
+     * @return array
+     * @throws HttpException
+     *
+     * @date 2023/05/10
+     * @author yyw
+     */
+    public function combinedShippingByTradeNo(string $out_trade_no, int $logistics_type, array $sub_orders, string $payer_openid, int $delivery_mode = 2, bool $is_all_delivered = false)
+    {
+        if (!$this->checkManaged()) {
+            throw new AdminException('开通小程序订单管理服务后重试');
+        }
+        $params = [
+            'order_key' => [
+                'order_number_type' => 1,
+                'mchid' => $this->config['order_shipping']['merchant_id'],
+                'out_trade_no' => $out_trade_no,
+            ],
+            'sub_orders' => [
+                'order_key' => [
+                    'order_number_type' => 1,
+                    'mchid' => $this->config['order_shipping']['merchant_id'],
+                    'out_trade_no' => '',
+                    'logistics_type' => '',
+                ],
+                'delivery_mode' => $delivery_mode,
+                'is_all_delivered' => $is_all_delivered
+            ],
+            'upload_time' => date(DATE_RFC3339),
+            'payer' => [
+                'openid' => $payer_openid
+            ]
+        ];
+
+        foreach ($sub_orders as $order) {
+            $sub_order = [
+                'order_key' => [
+                    'order_number_type' => 1,
+                    'mchid' => $this->config['order_shipping']['merchant_id'],
+                    'out_trade_no' => $order['out_trade_no'],
+                    'logistics_type' => $logistics_type,
+                ],
+                'delivery_mode' => $delivery_mode,
+                'is_all_delivered' => $is_all_delivered
+            ];
+            foreach ($sub_orders['shipping_list'] as $shipping) {
+                $sub_order['shipping_list'][] = [
+                    'tracking_no' => $shipping['tracking_no'],
+                    'express_company' => $this->getDelivery($shipping['express_company']),
+                    'item_desc' => $shipping['item_desc'],
+                    'contact' => $shipping['contact'] ?? []
+                ];
+            }
+            $params['sub_orders'][] = $sub_order;
+        }
+
+        return $this->combinedShipping($params);
+    }
+
+
+    /**
+     * 签收通知
+     * @param string $merchant_trade_no
+     * @param string $received_time
+     * @return array
+     * @throws HttpException
+     *
+     * @date 2023/05/10
+     * @author yyw
+     */
+    public function notifyConfirmByTradeNo(string $merchant_trade_no, string $received_time)
+    {
+        $params = [
+            'merchant_id' => $this->config['payment']['merchant_id'],
+            'merchant_trade_no' => $merchant_trade_no,
+            'received_time' => $received_time
+        ];
+        return $this->notifyConfirm($params);
+    }
+
+    /**
+     * 设置小程序管理服务开通状态
+     * @return bool
+     * @throws HttpException
+     *
+     * @date 2023/05/09
+     * @author yyw
+     */
+    public function setManaged()
+    {
+        $res = $this->isManaged();
+        if ($res['is_trade_managed']) {
+            $key = self::redis_prefix . '_is_trade_managed';
+            $this->getRedis()->set($key, $res['is_trade_managed']);
+            return true;
+        } else {
+            return false;
+        }
+
+    }
+
+    /**
+     * @return bool
+     * @throws HttpException
+     *
+     * @date 2023/05/10
+     * @author yyw
+     */
+    public function checkManaged()
+    {
+        $key = self::redis_prefix . '_is_trade_managed';
+        if ($this->getRedis()->exists($key)) {
+            return true;
+        } else {
+            return $this->setManaged();
+        }
+    }
+
+    /**
+     * 同步去微信物流列表
+     * @return array
+     * @throws HttpException
+     *
+     * @date 2023/05/10
+     * @author yyw
+     */
+    public function setDeliveryList()
+    {
+        $list = $this->getDeliveryList();
+        if ($list) {
+            $key = self::redis_prefix . '_delivery_list';
+            $date = array_column($list, 'delivery_id', 'delivery_name');
+            // 创建缓存
+            $this->getRedis()->hMSet($key, $date);
+
+            return $date;
+        } else {
+            throw new AdminException('物流公司列表异常');
+        }
+    }
+
+    /**
+     * 获取物流公司编码
+     * @param $company_name
+     * @return array|mixed
+     * @throws HttpException
+     *
+     * @date 2023/05/10
+     * @author yyw
+     */
+    public function getDelivery($company_name)
+    {
+        $key = self::redis_prefix . '_delivery_list';
+        if (!$this->getRedis()->exists($key)) {
+            $date = $this->setDeliveryList();
+            if (!isset($date[$company_name])) {
+                throw new AdminException('物流公司异常');
+            }
+            $express_company = $date[$company_name];
+        } else {
+            $express_company = $this->getRedis()->hMGet($key, $company_name);
+        }
+
+        return $express_company;
+    }
+}

+ 36 - 0
crmeb/crmeb/services/easywechat/orderShipping/ServiceProvider.php

@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of the overtrue/wechat.
+ *
+ * (c) overtrue <i@overtrue.me>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace crmeb\services\easywechat\orderShipping;
+
+use EasyWeChat\Payment\Merchant;
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+use EasyWeChat\MiniProgram\AccessToken;
+
+/**
+ * Class ServiceProvider.
+ *
+ * @package crmeb\services\easywechat\order_ship
+ * @package crmeb\services\easywechat\mini_express
+ */
+class ServiceProvider implements ServiceProviderInterface
+{
+    /**
+     * {@inheritdoc}.
+     */
+    public function register(Container $pimple)
+    {
+        $pimple['order_ship'] = function ($pimple) {
+            return new OrderClient($pimple['access_token'], $pimple);
+        };
+    }
+}