- 引入 alibabacloud/dysmsapi-20170525 依赖,集成阿里云短信服务 - 将短信验证码从6位改为4位,优化用户体验 - 添加聚水潭商品按时间范围同步功能,支持分页拉取 - 增强Cron任务异常处理,添加错误日志记录 - 修复系统附件服务中图片路径处理逻辑 - 更新阿里云SDK相关组件至最新版本 - 添加think-trace调试扩展,便于问题排查 - 优化跨域中间件,使用str_contains替代strpos
13 KiB
13 KiB
商城商品推送到聚水潭分析
一、答案
❌ 当前状态:推送功能已禁用
在 CreateSuccess.php#L80-99 中,推送到ERP的代码被注释掉了:
//ERP功能开启
// if (sys_config('erp_open') && $data['product_type'] == 0) {
// //上传商品至ERP平台
// ProductSyncErp::dispatchDo('upProductToErp', [$id]);
// ...
// }
二、推送功能架构
2.1 推送流程图
商城商品创建成功
↓
触发 CreateSuccess 事件监听器
↓
检查 ERP 功能是否开启 (erp_open = 1)
↓
├─ 未开启 → 不推送
│
└─ 开启 → ProductSyncErp::dispatchDo('upProductToErp', [$id])
↓
┌──────────────┐
│ 商品数据转换 │
│ │
│ 商品主数据 │
│ SPU编码 │
│ 商品名称 │
│ SKU规格 │
│ 价格信息 │
└──────┬───────┘
↓
调用聚水潭API
/open/jushuitan/itemsku/upload
↓
推送商品到聚水潭平台
2.2 核心文件
| 文件 | 职责 |
|---|---|
| CreateSuccess.php | 商品创建事件监听器 |
| ProductSyncErp.php | 推送任务(upProductToErp方法) |
| Product.php | 聚水潭API调用封装 |
三、推送逻辑详解
3.1 商品创建监听器
//ERP功能开启
if (sys_config('erp_open') && $data['product_type'] == 0) {
// 1. 上传商品至ERP平台
ProductSyncErp::dispatchDo('upProductToErp', [$id]);
// 2. 上传商品至ERP默认门店
ProductSyncErp::dispatchDo('upBranchProductToErp', [
$id,
['erp_shop_id' => sys_config('jst_default_shopid')]
]);
// 3. 给所有绑定了ERP店铺的门店增加该商品
$systemStoreServices = app()->make(SystemStoreServices::class);
$erpStoreList = $systemStoreServices->getStoreList([
['erp_shop_id', '>', 0]
]);
foreach ($erpStoreList['list'] as $item) {
if ($item['erp_shop_id'] < 1) continue;
ProductSyncErp::dispatchDo('upBranchProductToErp', [$id, $item]);
}
// 4. 如果是新商品,同步库存
if ($is_new) {
ProductSyncErp::dispatchDo('stockFromErp', [[$id]]);
}
}
触发条件:
- ✅
erp_open配置已开启 - ✅ 商品类型为
product_type == 0(普通商品,非虚拟商品等) - ✅ 商品创建成功事件被触发
3.2 数据转换逻辑
public function upProductToErp($id)
{
try {
// 1. 获取商品信息
$productServices = app()->make(StoreProductServices::class);
$productInfo = $productServices->getInfo($id)['productInfo'];
// 2. 准备数据
$data = [];
$attrs = $productInfo['attrs'] ?? [$productInfo['attr']];
foreach ($attrs as $item) {
// 处理图片URL
if ($item['pic'] && strstr($item['pic'], 'http') === false) {
$siteUrl = sys_config('site_url');
$item['pic'] = $siteUrl . $item['pic'];
}
// 3. 构建推送数据
$data[] = [
'i_id' => $productInfo['code'], // SPU编码
'sku_id' => $item['code'], // SKU编码
'name' => $productInfo['store_name'], // 商品名称
'properties_value' => str_replace(',', ' ', $item['values']), // 规格属性
's_price' => $item['price'], // 售价
'pic' => $item['pic'], // 图片URL
'c_price' => $item['cost'], // 成本价
'market_price' => $item['ot_price'], // 划线价
];
}
// 4. 调用聚水潭API
(new erpServices())->serviceDriver('product')->updateProduct($data);
} catch (\Exception $e) {
response_log_write([
'message' => '上传商品到ERP失败, 原因: ' . $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
]);
}
}
3.3 API调用
public function updateProduct($data)
{
$url = $this->accessToken->getApiUrl("/open/jushuitan/itemsku/upload");
// 业务参数
$biz['items'] = $data;
// 拼装请求参数
$params = $this->getParams($biz);
// 请求平台接口
$request = $this->postRequest($url, $params);
if ($request['code'] == 0) {
return true;
} else {
return false;
}
}
调用API: POST /open/jushuitan/itemsku/upload
四、数据映射关系
4.1 推送数据格式
{
"items": [
{
"i_id": "4651127369", // SPU编码(来自CRMEB的code字段)
"sku_id": "1N55001102", // SKU编码(来自CRMEB的attrs.code字段)
"name": "贝肽斯夏季儿童防晒帽", // 商品名称
"properties_value": "卡其布黄;M码:头围50-54cm", // 规格属性
"s_price": 35.9, // 售价
"pic": "https://img.yzcdn.cn/...", // 图片URL
"c_price": 0, // 成本价
"market_price": 0 // 划线价
}
]
}
4.2 字段对应关系
| 聚水潭字段 | CRMEB字段 | 说明 |
|---|---|---|
i_id |
productInfo.code |
SPU编码(商品唯一标识) |
sku_id |
attrs[].code |
SKU编码 |
name |
productInfo.store_name |
商品名称 |
properties_value |
attrs[].values |
规格属性(逗号替换为空格) |
s_price |
attrs[].price |
售价 |
pic |
attrs[].pic |
SKU图片 |
c_price |
attrs[].cost |
成本价 |
market_price |
attrs[].ot_price |
划线价 |
五、推送触发场景
5.1 自动推送(已禁用)
触发时机: 商品创建成功
// 在 CreateSuccess.php 中被注释
if (sys_config('erp_open') && $data['product_type'] == 0) {
ProductSyncErp::dispatchDo('upProductToErp', [$id]);
}
5.2 手动推送
触发方式: 后台手动操作
可以通过后台页面触发,调用接口:
POST /adminapi/product/sync_jst_product
{
"spu_str": "商品SPU编码"
}
5.3 门店商品推送
除了主商品库,还会推送到绑定了ERP店铺的门店:
// 上传到ERP默认门店
ProductSyncErp::dispatchDo('upBranchProductToErp', [
$id,
['erp_shop_id' => sys_config('jst_default_shopid')]
]);
// 上传到所有绑定ERP店铺的门店
foreach ($erpStoreList['list'] as $item) {
ProductSyncErp::dispatchDo('upBranchProductToErp', [$id, $item]);
}
六、当前状态分析
6.1 为什么推送功能被禁用?
查看代码注释,ERP推送功能是被有意注释掉的,可能原因:
- 测试阶段 - 功能尚未完善,避免生产环境误操作
- 数据同步策略 - 可能改为只从聚水潭拉取,不推送到聚水潭
- 业务调整 - 业务方向改变,暂不需要此功能
- 数据一致性 - 避免双向同步导致的数据冲突
6.2 如何启用推送功能?
步骤1: 取消注释推送代码
编辑 CreateSuccess.php#L80-99,取消注释:
//ERP功能开启
if (sys_config('erp_open') && $data['product_type'] == 0) {
//上传商品至ERP平台
ProductSyncErp::dispatchDo('upProductToErp', [$id]);
//上传商品至ERP默认门店
ProductSyncErp::dispatchDo('upBranchProductToErp', [
$id,
['erp_shop_id' => sys_config('jst_default_shopid')]
]);
//给所有绑定了ERP店铺的门店增加该商品
$systemStoreServices = app()->make(SystemStoreServices::class);
$erpStoreList = $systemStoreServices->getStoreList([['erp_shop_id', '>', 0]]);
foreach ($erpStoreList['list'] as $item) {
if ($item['erp_shop_id'] < 1) continue;
ProductSyncErp::dispatchDo('upBranchProductToErp', [$id, $item]);
}
if ($is_new) {
ProductSyncErp::dispatchDo('stockFromErp', [[$id]]);
}
}
步骤2: 确保ERP配置正确
在后台配置:
- ✅ 开启ERP功能
- ✅ 配置聚水潭AppKey和Secret
- ✅ 配置默认门店ID
步骤3: 测试推送功能
# 创建测试商品
POST /adminapi/product/save
{
"store_name": "测试商品",
"price": 99.00
}
# 检查日志
tail -f runtime/log/xxx.log | grep "upProductToErp"
七、推送 vs 拉取
7.1 对比表
| 特性 | 拉取(已有) | 推送(已禁用) |
|---|---|---|
| 触发方式 | 手动/定时任务 | 商品创建时自动 |
| 数据流向 | 聚水潭 → CRMEB | CRMEB → 聚水潭 |
| 代码状态 | ✅ 正常 | ❌ 被注释 |
| 使用场景 | 从ERP同步商品 | 上传新品到ERP |
| 功能完整性 | ✅ 完善 | ⚠️ 需启用 |
7.2 推荐策略
方案A: 仅拉取(当前)
适用场景:
- 聚水潭是主数据源
- CRMEB作为销售前端
- 商品信息在聚水潭维护
优点:
- ✅ 数据单一来源,避免冲突
- ✅ 商品信息统一管理
- ✅ 降低系统复杂度
方案B: 仅推送
适用场景:
- CRMEB是主数据源
- 聚水潭仅用于库存/订单管理
- 商品信息在CRMEB维护
优点:
- ✅ 快速响应商品变化
- ✅ 统一商品发布渠道
- ✅ 便于营销活动管理
方案C: 双向同步
适用场景:
- 两边都需要管理商品
- 有专业团队分别维护
- 需要数据一致性保障机制
挑战:
- ⚠️ 数据冲突解决策略
- ⚠️ 同步延迟处理
- ⚠️ 异常情况处理
八、启用推送的注意事项
8.1 数据一致性
// 推送时,确保商品编码唯一
$productInfo['code'] 必须在聚水潭中是唯一的
// 如果推送失败,需要记录日志并重试
if (!(new erpServices())->serviceDriver('product')->updateProduct($data)) {
// 记录失败日志
Log::error('商品推送失败', ['product_id' => $id]);
// 可以加入重试队列
}
8.2 性能考虑
// 当前是异步队列推送,无需担心性能
ProductSyncErp::dispatchDo('upProductToErp', [$id]);
// 但需要注意:
// 1. 批量创建商品时,可能产生大量队列任务
// 2. 建议限制推送频率
// 3. 添加推送限流机制
8.3 错误处理
try {
(new erpServices())->serviceDriver('product')->updateProduct($data);
} catch (\Exception $e) {
// 1. 记录错误日志
Log::error('推送商品到聚水潭失败', [
'product_id' => $id,
'error' => $e->getMessage()
]);
// 2. 可以加入失败重试队列
ProductSyncErp::dispatchDo('upProductToErp', [$id]);
// 3. 通知管理员
// sendNotify('商品推送失败,需要人工处理');
}
九、总结
❌ 当前状态
商城创建的商品推送到聚水潭的功能已被禁用
✅ 推送功能已实现
代码逻辑完整,包括:
- ✅ 商品数据转换
- ✅ SKU规格处理
- ✅ 聚水潭API调用
- ✅ 门店商品推送
- ✅ 库存同步
🔧 如何启用
- 取消 CreateSuccess.php 中的注释
- 配置ERP功能
- 测试推送流程
💡 建议
根据业务需求选择合适的数据同步策略:
- 推荐仅拉取:单数据源,避免冲突
- 慎用双向同步:需要完善冲突处理机制
十、相关文件清单
| 文件路径 | 说明 | 状态 |
|---|---|---|
| CreateSuccess.php | 商品创建监听器 | ⚠️ 推送代码被注释 |
| ProductSyncErp.php | 推送任务 | ✅ 已实现 |
| Product.php | API调用 | ✅ 已实现 |
| Jushuitan.php | 聚水潭SDK | ✅ 已实现 |
| HaichaoJstServices.php | 业务封装 | ✅ 已实现 |