diff --git a/crmeb/app/adminapi/controller/Test.php b/crmeb/app/adminapi/controller/Test.php index 9d0b051e4..217fe65eb 100644 --- a/crmeb/app/adminapi/controller/Test.php +++ b/crmeb/app/adminapi/controller/Test.php @@ -6,11 +6,18 @@ namespace app\adminapi\controller; +use crmeb\services\easywechat\orderShipping\MiniOrderService; + class Test { public function index() { - + $ship_list = [ + [ + 'item_desc' => '蓝牙音乐手表 | Jeep智能表蓝牙' + ] + ]; + MiniOrderService::shippingByTradeNo('cp179280225803173888', 3, $ship_list, 'oZEAhsy60rrq96hE86LmBb9v_Kes'); } } diff --git a/crmeb/app/dao/service/StoreServiceDao.php b/crmeb/app/dao/service/StoreServiceDao.php index ab5d6566b..044c5f245 100644 --- a/crmeb/app/dao/service/StoreServiceDao.php +++ b/crmeb/app/dao/service/StoreServiceDao.php @@ -86,4 +86,20 @@ class StoreServiceDao extends BaseDao return $this->getModel()->whereNotIn('uid', $where['notUid'])->update($data); } + /** + * 统计数量 + * @param array $where + * @param bool $search + * @return int + * @throws \ReflectionException + * @author 吴汐 + * @email 442384644@qq.com + * @date 2023/05/10 + */ + public function count($where = [], $search = true) + { + return $this->search($where, false)->when(isset($where['noId']), function ($query) use ($where) { + $query->whereNotIn('uid', $where['noId']); + })->count(); + } } diff --git a/crmeb/app/services/other/export/ExportServices.php b/crmeb/app/services/other/export/ExportServices.php index 10a4bc281..86da2fa75 100644 --- a/crmeb/app/services/other/export/ExportServices.php +++ b/crmeb/app/services/other/export/ExportServices.php @@ -74,7 +74,7 @@ class ExportServices extends BaseServices */ public function exportOrderList($where) { - $header = ['订单号', '收货人姓名', '收货人电话', '收货地址', '商品信息', '总价格', '实际支付', '支付状态', '支付时间', '订单状态', '下单时间', '用户备注']; + $header = ['订单号', '收货人姓名', '收货人电话', '收货地址', '商品信息', '总价格', '实际支付', '支付状态', '支付时间', '订单状态', '下单时间', '用户备注', '表单信息']; $filename = '订单列表_' . date('YmdHis', time()); $export = $fileKey = []; /** @var StoreOrderServices $orderServices */ @@ -127,6 +127,11 @@ class ExportServices extends BaseServices } else if ($item['paid'] == 1 && $item['refund_status'] == 2) { $item['status_name'] = '已退款'; } + $custom_form = ''; + foreach ($item['custom_form'] as $custom_form_value) { + $custom_form .= $custom_form_value['title'] . ':' . $custom_form_value['value'] . ';'; + } + $goodsName = []; foreach ($item['_info'] as $value) { $_info = $value['cart_info']; @@ -157,6 +162,7 @@ class ExportServices extends BaseServices 'status_name' => $item['status_name'] ?? '未知状态', 'add_time' => $item['add_time'], 'mark' => $item['mark'], + 'custom_form' => $custom_form, ]; $export[] = $one_data; if ($i == 0) { diff --git a/crmeb/crmeb/services/AccessTokenServeService.php b/crmeb/crmeb/services/AccessTokenServeService.php index 282754c4b..1d39fd59c 100644 --- a/crmeb/crmeb/services/AccessTokenServeService.php +++ b/crmeb/crmeb/services/AccessTokenServeService.php @@ -51,6 +51,16 @@ class AccessTokenServeService extends HttpService */ protected $apiHost = 'http://sms.crmeb.net/api/'; + /** + * @var string + */ + protected $sandBoxApi = 'https://api_v2.crmeb.net/'; + + /** + * @var bool + */ + protected $sandBox = true; + /** * 登录接口 */ @@ -166,6 +176,9 @@ class AccessTokenServeService extends HttpService */ public function get(string $apiUrl = '') { + if ($this->sandBox) { + return $this->sandBoxApi . $apiUrl; + } return $this->apiHost . $apiUrl; } } diff --git a/crmeb/crmeb/services/easywechat/Application.php b/crmeb/crmeb/services/easywechat/Application.php index d5a976b1e..b96ba8dae 100644 --- a/crmeb/crmeb/services/easywechat/Application.php +++ b/crmeb/crmeb/services/easywechat/Application.php @@ -14,10 +14,12 @@ namespace crmeb\services\easywechat; use crmeb\services\easywechat\miniPayment\ServiceProvider; use crmeb\services\easywechat\oauth2\wechat\WechatOauth2Provider; +use crmeb\services\easywechat\orderShipping\OrderClient; use crmeb\services\easywechat\subscribe\ProgramProvider; use crmeb\services\easywechat\v3pay\PayClient; use crmeb\services\easywechat\wechatlive\ProgramProvider as LiveProgramProvider; 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 WechatOauth2Provider $oauth2 * @property PayClient $v3pay + * @property OrderClient $order_ship */ class Application extends \EasyWeChat\Foundation\Application { @@ -40,6 +43,7 @@ class Application extends \EasyWeChat\Foundation\Application ProgramProvider::class, V3PayServiceProvider::class, \crmeb\services\easywechat\Open3rd\ProgramProvider::class, + OrderServiceProvider::class ]; /** diff --git a/crmeb/crmeb/services/easywechat/orderShipping/BaseOrder.php b/crmeb/crmeb/services/easywechat/orderShipping/BaseOrder.php new file mode 100644 index 000000000..ca1cba014 --- /dev/null +++ b/crmeb/crmeb/services/easywechat/orderShipping/BaseOrder.php @@ -0,0 +1,131 @@ +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['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'])); + } +} diff --git a/crmeb/crmeb/services/easywechat/orderShipping/MiniOrderService.php b/crmeb/crmeb/services/easywechat/orderShipping/MiniOrderService.php new file mode 100644 index 000000000..6851c16c8 --- /dev/null +++ b/crmeb/crmeb/services/easywechat/orderShipping/MiniOrderService.php @@ -0,0 +1,133 @@ + [ + 'appid' => $payment['routine_appId'] ?? '', + 'secret' => $payment['routine_appsecret'] ?? '', + 'merchant_id' => empty($payment['pay_new_weixin_open']) ? trim($payment['pay_weixin_mchid']) : trim($payment['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); + } + + +} diff --git a/crmeb/crmeb/services/easywechat/orderShipping/OrderClient.php b/crmeb/crmeb/services/easywechat/orderShipping/OrderClient.php new file mode 100644 index 000000000..b75cbc50f --- /dev/null +++ b/crmeb/crmeb/services/easywechat/orderShipping/OrderClient.php @@ -0,0 +1,276 @@ +redis)) { + $this->redis = Cache::store('redis')->handler(); + } + return $this->redis; + } + + /** + * 处理联系人 + * @param array $contact + * @return array + * + * @date 2023/05/10 + * @author yyw + */ + protected function handleContact(array $contact = []): array + { + if (isset($contact)) { + if (isset($contact['consignor_contact']) && $contact['consignor_contact']) { + $contact['consignor_contact'] = Utility::encryptTel($contact['consignor_contact']); + } + if (isset($contact['receiver_contact']) && $contact['receiver_contact']) { + $contact['receiver_contact'] = Utility::encryptTel($contact['receiver_contact']); + } + } + return $contact; + } + + /** + * 发货 + * @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['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) { + $contact = $this->handleContact($shipping['contact'] ?? []); + $params['shipping_list'][] = [ + 'tracking_no' => $shipping['tracking_no'] ?? '', + 'express_company' => isset($shipping['express_company']) ? $this->getDelivery($shipping['express_company']) : '', + 'item_desc' => $shipping['item_desc'], + 'contact' => $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, + ], + '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) { + $contact = $this->handleContact($shipping['contact'] ?? []); + $sub_order['shipping_list'][] = [ + 'tracking_no' => $shipping['tracking_no'] ?? '', + 'express_company' => isset($shipping['express_company']) ? $this->getDelivery($shipping['express_company']) : '', + 'item_desc' => $shipping['item_desc'], + 'contact' => $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; + } +} diff --git a/crmeb/crmeb/services/easywechat/orderShipping/ServiceProvider.php b/crmeb/crmeb/services/easywechat/orderShipping/ServiceProvider.php new file mode 100644 index 000000000..989b02c02 --- /dev/null +++ b/crmeb/crmeb/services/easywechat/orderShipping/ServiceProvider.php @@ -0,0 +1,44 @@ + + * + * 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['mini_program.access_token'] = function ($pimple) { + return new AccessToken( + $pimple['config']['order_shipping']['app_id'], + $pimple['config']['order_shipping']['secret'], + $pimple['cache'] + ); + }; + + $pimple['order_ship'] = function ($pimple) { + return new OrderClient($pimple['access_token'], $pimple); + }; + } +} diff --git a/crmeb/crmeb/services/easywechat/orderShipping/Utility.php b/crmeb/crmeb/services/easywechat/orderShipping/Utility.php new file mode 100644 index 000000000..5cb8d33c0 --- /dev/null +++ b/crmeb/crmeb/services/easywechat/orderShipping/Utility.php @@ -0,0 +1,42 @@ +getPublicKey(), $padding)) { + throw new AdminException('Encrypting the input $plaintext failed, please checking your $publicKey whether or nor correct.'); + } + + return base64_encode($encrypted); + } + + public static function encryptTel($tel) + { + $new_tel = substr_replace($tel, '****', 3, 4); + return $new_tel; + } + +} diff --git a/crmeb/crmeb/services/express/storage/Express.php b/crmeb/crmeb/services/express/storage/Express.php index a556f037b..cb3b796d1 100644 --- a/crmeb/crmeb/services/express/storage/Express.php +++ b/crmeb/crmeb/services/express/storage/Express.php @@ -165,6 +165,9 @@ class Express extends BaseExpress if ($expressData['check_man'] == 1) $param['checkMan'] = $expressData['courier_name']; if ($expressData['partner_name'] == 1) $param['partnerName'] = $expressData['customer_name']; if ($expressData['is_code'] == 1) $param['code'] = $expressData['code_name']; + if (!$data['siid']) { + $param['print_type'] = 'IMAGE'; + } return $this->accessToken->httpRequest(self::EXPRESS_DUMP, $param, 'POST'); } diff --git a/template/admin/vue.config.js b/template/admin/vue.config.js index 87b7397cb..14dc7ac7f 100644 --- a/template/admin/vue.config.js +++ b/template/admin/vue.config.js @@ -18,7 +18,7 @@ const resolve = (dir) => { // 例如:https://www.foobar.com/my-app/ // 需要将它改为'/my-app/' // iview-admin线上演示打包路径: https://file.iviewui.com/admin-dist/ -// const BASE_URL = process.env.NODE_ENV === 'production' ? '/' : '/'; +const BASE_URL = process.env.NODE_ENV === 'production' ? '/' : '/'; const env = process.env.NODE_ENV; module.exports = { // Project deployment base @@ -31,7 +31,7 @@ module.exports = { outputDir: Setting.outputDir, runtimeCompiler: true, productionSourceMap: false, //关闭生产环境下的SourceMap映射文件 - baseUrl: '/', + baseUrl: BASE_URL, // tweak internal webpack configuration. // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md // 如果你不需要使用eslint,把lintOnSave设为false即可