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; } }