| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- <?php
- namespace addons\WechatVideoShop\common\service;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\express\ExpressAllFreightCalcMethodModel;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\express\ExpressConditionFreeDetailModel;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\express\ExpressFreightCalcMethodModel;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\express\ExpressNotSendAreaModel;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\express\ExpressTemplateModel;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\express\FreightTemplateModel;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\model\user\AddressInfoModel;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\express\ExpressAddRequest;
- use addons\WechatVideoShop\common\expand\sdk\weixin\src\request\express\ExpressUpdateRequest;
- use addons\WechatVideoShop\common\helper\WechatRequestHelper;
- use addons\WechatVideoShop\common\models\WechatVideoShopExpressTemplate;
- use addons\WechatVideoShop\common\models\WechatVideoShopRegion;
- use common\enums\StatusEnum;
- use common\models\goods\FreightRules;
- use common\models\goods\GoodsAttr;
- use yii\helpers\Json;
- class ExpressTemplateService
- {
- /**
- * @param int $mall_id
- * @param int $is_free
- * @param array $goods
- * @param array $config
- * @param int $shop_id
- * @param null $third_template_id
- * @return string|WechatVideoShopExpressTemplate
- */
- public function create(int $mall_id, int $is_free, array $goods, array $config, int $shop_id, $third_template_id = null)
- {
- try {
- $templateModel = new FreightTemplateModel();
- // 计费类型,PIECE:按件数,WEIGHT:按重量
- $templateModel->valuation_type = FreightTemplateModel::VALIDATION_TYPE_PRICE;
- $templateModel->name = $is_free == StatusEnum::ENABLED ? '包邮模板' : "商品 {$goods['id']} 运费模板" . date('Y-m-d H:i:s', time()); // 模板名称
- $templateModel->send_time = FreightTemplateModel::SEND_TIME_FOUTYEIGHT_HOUR; // 发货时间期限
- $templateModel->delivery_type = FreightTemplateModel::DELIVERY_TYPE_EXPRESS; // 计费方式:FREE:包邮CONDITION_FREE:条件包邮NO_FREE:不包邮
- // 发货地址
- $templateModel->address_info = $this->getShipAddressInfo($mall_id, $config);
- // 不发货区域
- if (!empty($goods['is_area_limit']) && !empty($goods['area_limit'])) {
- $templateModel->not_send_area = $this->getNotSendArea($goods['area_limit']);
- }
- if ($is_free) {
- $templateModel->shipping_method = FreightTemplateModel::SHIPPING_METHOD_FREE; // 运输方式,EXPRESS:快递
- } else {
- // 条件包邮详情 暂时没有条件包邮
- // $templateModel->all_condition_free_detail = '';
- // 具体计费方法,默认运费,指定地区运费等 只有含有运费模板级使用运费模板的时候才需要
- if (!empty($goods['freight_id']) && $goods['freight_rules_type'] == StatusEnum::ENABLED) {
- $templateModel->shipping_method = FreightTemplateModel::SHIPPING_METHOD_CONDITION_FREE;
- $freight = FreightRules::getOne([
- ['mall_id' => $goods['mall_id']],
- ['id' => $goods['freight_id']]
- ]);
- // 计费类型,PIECE:按件数,WEIGHT:按重量
- $templateModel->valuation_type = $freight->type == StatusEnum::ENABLED ?
- FreightTemplateModel::VALIDATION_TYPE_WEIGHT : FreightTemplateModel::VALIDATION_TYPE_PRICE;
- // 是否默认模板
- $templateModel->is_default = $freight->is_default == StatusEnum::ENABLED;
- $templateModel->all_freight_calc_method = $this->getAllFreightCalcMethod($freight);
- } else {
- // 自定义运费 - 所有地区不包邮
- $templateModel->is_default = false;
- $templateModel->shipping_method = FreightTemplateModel::SHIPPING_METHOD_CONDITION_FREE;
- $templateModel->all_condition_free_detail = $this->conditionFreeDetail($goods);
- $templateModel->all_freight_calc_method = $this->fixedExpressPrice($goods);
- }
- }
- $model = new ExpressTemplateModel();
- if (empty($third_template_id)) { // 新建
- $req = new ExpressAddRequest($config);
- } else {
- $req = new ExpressUpdateRequest($config);
- $templateModel->template_id = $third_template_id;
- }
- $model->freight_template = $templateModel;
- // dd($model->toArray());
- $t_hash = md5(json_encode($model->toArray()));
- // 查询一下
- $localExpressModel = WechatVideoShopExpressTemplate::findOne(['mall_id' => $mall_id, 't_hash' => $t_hash]);
- if (!empty($localExpressModel)) return $localExpressModel;
- $resp = WechatRequestHelper::accessTokenAndToArray($req, $model);
- if (empty($third_template_id) && empty($resp['template_id'])) {
- throw new \Exception('响应模板ID为空');
- }
- if (empty($third_template_id)) {
- $localExpressModel = new WechatVideoShopExpressTemplate();
- } else {
- $localExpressModel = WechatVideoShopExpressTemplate::getOne([
- ['mall_id' => $mall_id],
- ['third_template_id' => $third_template_id]
- ]);
- if (empty($localExpressModel)) throw new \Exception("微信运费模板 {$third_template_id} 不存在");
- }
- $localExpressModel->mall_id = $mall_id;
- $localExpressModel->template_id = $goods['freight_id'];
- $localExpressModel->third_template_id = $resp['template_id'] ?? $third_template_id;
- $localExpressModel->content = $model->toArray();
- $localExpressModel->is_free = $is_free;
- $localExpressModel->shop_id = $shop_id;
- $localExpressModel->goods_id = $goods['id'];
- $localExpressModel->t_hash = $t_hash;
- if (!$localExpressModel->save()) throw new \Exception($localExpressModel->getErrorMessage());
- return $localExpressModel;
- } catch (\Exception $e) {
- return "运费模板:{$e->getMessage()}";
- }
- }
- /**
- * 获取发货地址 - 可以在基础设置那边设置这一项
- * @return AddressInfoModel
- * @throws \Exception
- */
- protected function getShipAddressInfo(int $mall_id, array $config)
- {
- $model = new AddressInfoModel();
- $model->user_name = $config['contact_person'];
- $model->province_name = $config['province']; // 省份名称
- $model->city_name = $config['city']; // 城市名称
- $model->county_name = $config['district']; // 区县名称
- $model->detail_info = $config['address'];
- $model->tel_number = $config['phone'];
- return $model;
- }
- protected function getFreightDetail()
- {
- // $model = new Freight
- }
- /**
- * 获取不发货的区域
- * @param string $areas
- * @return ExpressNotSendAreaModel
- */
- protected function getNotSendArea(string $areas)
- {
- $model = new ExpressNotSendAreaModel();
- $areas = Json::decode($areas);
- $regions = $this->getAreaIds($areas);
- $list = [];
- if (!empty($regions)) {
- foreach ($regions as $region) {
- $tmp = $this->packAddrInfo($region);
- if ($tmp) $list[] = $tmp;
- }
- $model->address_infos = $list;
- }
- return $model;
- }
- protected function getAllConditionFreeDetail()
- {
-
- }
- /**
- * 具体计费方法,默认运费,指定地区运费等
- * @param FreightRules $freight
- * @return ExpressAllFreightCalcMethodModel
- * @throws \Exception
- */
- protected function getAllFreightCalcMethod(FreightRules $freight)
- {
- $model = new ExpressAllFreightCalcMethodModel();
- $list = [];
- if (empty($freight)) throw new \Exception("运费模板不存在");
- if (empty($freight->rule)) throw new \Exception("运费模板规则为空");
- $rules = Json::decode($freight->rule);
- if (empty($rules)) throw new \Exception("运费模板规则为空.");
- $firstPrice = 0;
- $secondPrice = 0;
- $first = 1;
- $second = 1;
- foreach ($rules as $key => $rule) {
- // if (empty($rule['list'])) continue;
- $regions = $this->getAreaIds($rule['list']);
- $addr_list = [];
- foreach ($regions as $region) {
- $tmp = $this->packAddrInfo($region);
- if ($tmp) $addr_list[] = $tmp;
- }
- if (!empty($addr_list)) {
- $expressFreightCalcMethodModel = new ExpressFreightCalcMethodModel();
- $expressFreightCalcMethodModel->first_val_amount = (float) $rule['first']; // 首重计算
- $expressFreightCalcMethodModel->first_price = (int) bcmul($rule['firstPrice'], 100); // 首重价格
- $expressFreightCalcMethodModel->second_val_amount = (float) $rule['second'];// 续重计算
- $expressFreightCalcMethodModel->second_price = (int) bcmul($rule['secondPrice'], 100);// 续重价格
- // if ($key == 0) $expressFreightCalcMethodModel->is_default = true; // 默认运费不能指定地区
- if ($rule['firstPrice'] > $firstPrice) {
- $firstPrice = $rule['firstPrice'];
- $secondPrice = $rule['secondPrice'];
- $first = $rule['first'];
- $second = $rule['second'];
- }
- $expressFreightCalcMethodModel->address_infos = $addr_list;
- $list[] = $expressFreightCalcMethodModel;
- }
- }
- // 设置一个默认运费 默认运费不能指定地区
- $expressFreightCalcMethodModel = new ExpressFreightCalcMethodModel();
- $expressFreightCalcMethodModel->first_val_amount = (float) $first; // 首重计算
- $expressFreightCalcMethodModel->first_price = (int) bcmul($firstPrice, 100); // 首重价格
- $expressFreightCalcMethodModel->second_val_amount = (float) $second;;// 续重计算
- $expressFreightCalcMethodModel->second_price = (int) bcmul($secondPrice, 100);// 续重价格
- $expressFreightCalcMethodModel->is_default = true;// 续重价格
- $list[] = $expressFreightCalcMethodModel;
- $model->freight_calc_method_list = $list;
- return $model;
- }
- /**
- * 统一运费
- * @param array $goods
- * @return ExpressAllFreightCalcMethodModel
- */
- protected function fixedExpressPrice(array $goods)
- {
- $model = new ExpressAllFreightCalcMethodModel();
- $expressFreightCalcMethodModel = new ExpressFreightCalcMethodModel();
- if (!empty($goods['shipping_fee'])) {
- $expressFreightCalcMethodModel->first_val_amount = 1; // 首重计算
- $expressFreightCalcMethodModel->first_price = (int) bcmul($goods['shipping_fee'], 100); // 首重价格
- $expressFreightCalcMethodModel->second_val_amount = 1;// 续重计算
- $expressFreightCalcMethodModel->second_price = 0;// 续重价格
- $expressFreightCalcMethodModel->is_default = true;// 续重价格
- // $expressFreightCalcMethodModel->delivery_id = "AJ";
- // $expressFreightCalcMethodModel->address_infos = [];
- }
- $model->freight_calc_method_list = [$expressFreightCalcMethodModel];
- return $model;
- }
- /**
- * @param array $goods
- * @return ExpressConditionFreeDetailModel
- */
- protected function conditionFreeDetail(array $goods)
- {
- $model = new ExpressConditionFreeDetailModel();
- $weight = bcmul(GoodsAttr::find()->where(['goods_id' => $goods['id']])
- ->andWhere(['status' => StatusEnum::ENABLED])
- ->orderBy('weight desc')->select('weight')->scalar(), 100) * $goods['free_shipping_num'];
- // free_shipping_num = 满件包邮
- // free_shipping_money = 满额包邮
- // shipping_fee = 运费金额
- // 如果为0 则不支持
- $model->min_weight = (float) (!empty($weight) ? $weight / 1000 : 20000000); // 最低重量KG
- $model->min_piece = (float) (!empty($goods['free_shipping_num']) ? $goods['free_shipping_num'] : 1000000); // 最低件数
- $model->min_amount = (int) !empty($goods['free_shipping_money']) ? bcmul($goods['free_shipping_money'], 100) : 1000000000; // 最低金额,单位(分)
- if (empty($model->min_amount)) $model->min_amount = 999999999;
- $model->valuation_flag = 1; // 计费方式对应的选项是否已设置
- $model->amount_flag = 1; // 金额是否设置
- $addr_list = [];
- $regions = WechatVideoShopRegion::lists([
- 'where' => [
- ['level' => 1],
- ['status' => 1]
- ]
- ]);
- foreach ($regions as $region) {
- $tmp = $this->packAddrInfo($region);
- if ($tmp) $addr_list[] = $tmp;
- }
- $model->address_infos = $addr_list; // 支持的地址列表
- return $model;
- }
- /**
- * 获取本地地区ID数组
- * @param array $areas
- * @return array|false|mixed
- */
- protected function getAreaIds(array $areas)
- {
- $regions = [];
- if (!empty($areas)) {
- $region_ids = array_column($areas, 'id');
- $regions = WechatVideoShopRegion::lists([
- 'where' => [
- ['local_id' => $region_ids],
- ['level' => 2],
- ['status' => StatusEnum::ENABLED]
- ]
- ]);
- }
- return $regions;
- }
- /**
- * 拼凑地址信息
- * @param array $region
- * @return AddressInfoModel
- */
- protected function packAddrInfo(array $region)
- {
- $addrModel = new AddressInfoModel();
- if ($region['level_two_name'] == '省直辖县级行政区划') return null;
- switch ($region['level']) {
- case 3:
- $addrModel->province_name = $region['level_one_name'];
- if ($region['level_one_name'] == $region['level_two_name']) { // 如果是直辖市
- $addrModel->city_name = $region['name'];
- } else {
- $addrModel->city_name = $region['level_two_name'];
- $addrModel->county_name = $region['name'];
- }
- break;
- case 2:
- $addrModel->city_name = $region['name'];
- $addrModel->province_name = $region['level_one_name'];
- break;
- case 1:
- $addrModel->province_name = $region['name'];
- break;
- }
- return $addrModel;
- }
- }
|