商品库

[toc]

1 背景介绍

商米数字店铺(SUNMI Store)是商米提供的基于店铺物联网设备的店铺管理系统。

商米数字店铺作为一个开放平台,支持与第三方软件进行各种对接,包括设备层面智能摄像机、电子价签的对接,数据层面的商品信息、交易信息对接等。

电子价签等物联网设备需要对接店铺的商品,价格以及策略等信息,所以在数字店铺系统内保存了一个基本的商品库。

对于商品数据来源,用户既可以选择直接在数字店铺的页面进行编辑,也可以选择与第三方软件进行数据打通。

下文列出的就是实现商品信息在第三方软件与商米数字店铺之间实时同步的相关接口。

2 接口规范

2.1 协议说明

对接的openAPI接口目前只开放HTTPS方式,所有的消息一律采用POST方式。

注:消息体大小不得超过1M,超过1M的请求,直接拒绝!

Content-Typeapplication/x-www-form-urlencoded
数据格式返回为JSON格式
字符编码UTF-8字符编码
签名算法MD5
签名规则参考2.2 签名规则

2.2 签名规则

参考《鉴权认证》文档。

2.3 公共参数

参数名

必填类型说明
app_idstring唯一标识接入身份,联系商米数字店铺提供
randomstring随机字符串,由数字和字母组成,长度范围为6-10位
timestampint当前的unix timestamp,精度到秒级,10位数字
signstring 签名信息,详见上文签名规则

3 商米提供接口

3.1. 商品字段属性

下面的表格描述了数字店铺开放平台中商品字段的属性,适用于后面所有的新增、修改等接口。

商品字段中预留了一些自定义字段,对接时可以将第三方软件中的特殊字段对应到这些字段上。


商米数字平台商品参数类型说明是否必须
1idstring数据库ID,唯一,可以与商品编号相同
2seq_numstring商品编号,唯一,可以和数据库ID相同
推荐填写,在网页创建和Excel导入中均会用到
3namestring商品名称
4pricedouble价格
5bar_codestring条码
6aliasstring别名
7unitstring单位
8levelstring等级
9areastring产地
10brandstring品牌
11qr_codestring二维码链接
12statusstring商品状态
13descriptionstring商品描述
14promote_pricedouble促销价
15promote_price_descriptionstring促销价描述
16member_pricedouble会员价
17member_price_descriptionstring会员价描述
18extra_infojson扩展信息
19extra_price_infojson其它价格信息
20extra_custom_infojson自定义信息

extra_info:


商米数字平台商品参数类型说明是否必须
1pack_sizeint箱规
2stockfloat64库存
3safety_stockfloat64安全库存
4daily_mean_salesfloat64日均销售量
5today_sales_qtyfloat64当日销售量
6cumulated_sales_qtyfloat64累计销售量
7on_order_qtyfloat64在途订单量
8shelf_qtyfloat64陈列量
9shelf_codestring货架编号
10shelf_tierstring货架层
11shelf_columnstring货架列
12display_locationstring摆放位置
13supplier_codestring供应商编号
14supplier_namestring供应商名称
15manufacturerstring生产商名称
16manufacturer_addressstring生产商地址
17expiry_datedatetime过期日期
18storage_lifestring保质期限
19shelf_lifeint已上架时间
20ingredient_tablestring配料表
21fresh_item_codestring生鲜商品码
22supervised_bystring监制单位
23supervision_hotlinestring监督电话
24pricing_staffstring计价员
25category_level1_idstring一级分类编号
26category_level1_namestring一级分类名称
27category_level2_idstring二级分类编号
28category_level2_namestring二级分类名称
29category_level3_idstring三级分类编号
30category_level3_namestring三级分类名称
31category_level4_idstring四级分类编号
32category_level4_namestring四级分类名称
33category_level5_idstring五级分类编号
34category_level5_namestring五级分类名称

extra_price_info:


商米数字平台商品参数类型说明是否必须
1custom_price1float64自定义价格1

2custom_price1_descriptionstring自定义价格1描述
3custom_price2float64自定义价格2

4custom_price2_descriptionstring自定义价格2描述
5custom_price3float64自定义价格3
6custom_price3_descriptionstring自定义价格3描述
7promote_start_datedatetime促销开始日期
8promote_end_datedatetime促销结束日期
9member_promote_start_datedatetime会员促销开始日期
10member_promote_end_datedatetime会员促销结束日期
11member_pointfloat64会员积分
12promote_reasonstring促销原因
13promote_flagint促销标识

extra_custom_info:


商米数字平台商品参数类型说明是否必须
1custom_text1string自定义字段1
2custom_text2string自定义字段2
3custom_text3string自定义字段3
4custom_text4string自定义字段4
5custom_text5string自定义字段5
6custom_text6string自定义字段6
7custom_text7string自定义字段7
8custom_text8string自定义字段8
9custom_text9string自定义字段9
10custom_text10string自定义字段10
11custom_text11string自定义字段11
12custom_text12string自定义字段12
13custom_text13string自定义字段13
14custom_text14string自定义字段14
15custom_text15string自定义字段15
16custom_text16string自定义字段16
17custom_text17string自定义字段17
18custom_text18string自定义字段18
19custom_text19string自定义字段19
20custom_text20string自定义字段20
21custom_int1int自定义整数1
22custom_int2int自定义整数2
23custom_int3int自定义整数3
24custom_int4int自定义整数4
25custom_int5int自定义整数5
26custom_dec1float64自定义小数1
27custom_dec2float64自定义小数2
28custom_dec3float64自定义小数3
29custom_dec4float64自定义小数4
30custom_dec5float64自定义小数5
31othersstring其他

3.2 新建商品

接口说明:第三方对接的软件新建商品后,通过该接口推送通知到我方,商米数字店铺会根据推送的商品信息新建对应商品。

本接口只对应于新增商品接口,如果商品【数据库ID】已经存在,则会将存在的id添加入exist_list,如果商品信息中的必填字段(比如名称)未输入,则将id添加入invalid_list并返回.。

接口链接:/product/create

接口参数

参数名称是否必须类型说明示例
sunmi_shop_nostring商米数字店铺平台中门店的唯一编号(v2.0之后为必填项)100939070408
shop_idstring第三方对接软件中门店的唯一编号(此参数为后向兼容v2.0之前版本的字段,在v2.0及以后版本使用sunmi_shop_no替代,作为门店唯一标识即可)10001
product_listarray新建商品对象列表[{“name”:”cola”,”id”:”1″,”bar_code”:”6958644000259″,”unit”:”bottle”,”price”:”3.5″,”member_price”:”3″,”spec”:”250ml”,”level”:””,”brand”:”coca”}]

product 参数类型参考前文中【商品字段属性】。

请求示例

'method': 'POST',
  'url': 'https://store.uat.sunmi.com/openapi/product/create',
  'headers': {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  formData: {
    'shop_id': '10001',
    'app_id': 'I4VI99A0JDS21',
    'timestamp': '1581658876',
    'random': '5dsf6698',
    'sign': 'DDCB590591531D9B85729EE13E9B9095',
    'product_list': '[
        {
	"name": "milk",
	"id": "1",
	"bar_code": "6958644000259",
	"unit": "bottle",
	"price": "4.5",
	"member_price": "3",
	"spec": "250ml",
	"level": "",
	"brand": "test"
    }] '
  }

返回值: 

{
    code:0
    msg: "succeed"
    data: {
        “exist_list”: ["100",
                "200"],
       "invalid_list:["400",
        ]}
}
}

错误列表:

错误代码错误原因
5000数据库错误
5041非法对接软件
5015非法商品

3.3 更新商品

接口说明:第三方对接的软件更新商品后,通过该接口推送通知到我方,商米数字店铺会根据推送的商品信息更新对应商品。如果该商品已经绑定到电子价签上,会触发电子价签的自动更新。

 更新接口只会更新商米数字店铺中已经存在的商品,通过数据库ID匹配到的商品,则会进行更新操作, 未匹配到则新增对应商品,这些新增商品的id可以在返回中”not_exist_list”中查看。

更新操作只会修改接收到的商品字段,不存在的字段则保持原有数据不做处理。

接口链接:/product/update

接口版本:v2.0

接口参数

参数名称是否必须类型说明示例
sunmi_shop_nostring商米数字店铺平台中门店的唯一编号(v2.0之后为必填项)100939070408
shop_idstring第三方对接软件中门店的唯一编号(此参数为后向兼容v2.0之前版本的字段,在v2.0及以后版本使用sunmi_shop_no替代,作为门店唯一标识即可)10001
product_listarray更新商品对象列表[{“name”:”milk”,”id”:”1″,”bar_code”:”6958644000259″,”unit”:”bottle”,”price”:”4.5″,”member_price”:”3″,”spec”:”250ml”,”level”:””,”brand”:”test”}]

product 参数类型参考前文中【商品字段属性】。

请求示例

'method': 'POST',
  'url': 'https://store.uat.sunmi.com/openapi/product/create',
  'headers': {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  formData: {
    'shop_id': '10001',
    'app_id': 'I4VI99A0JDS21',
    'timestamp': '1581658876',
    'random': '5dsf6698',
    'sign': 'DDCB590591531D9B85729EE13E9B9095',
    'product_list': '[
        {
	"name": "milk",
	"id": "1",
	"bar_code": "6958644000259",
	"unit": "bottle",
	"price": "4.5",
	"member_price": "3",
	"spec": "250ml",
	"level": "",
	"brand": "test"
    }] '
  }

返回值: 

{
    "code": 0,
    "msg": "succeed",
    "data": {
        "exist_list": [
            "1"
        ],
        "invalid_list": []
    }
}

错误列表:

错误代码错误原因
5000数据库错误
5041非法对接软件
5015非法商品

3.4 删除商品

接口说明:第三方对接的软件删除商品后,可通过该接口推送通知到我方,商米数字店铺会根据推送的商品信息删除对应商品。

删除接口只会删除商米数字店铺中已经存在的商品,若根据商品数据库ID字段匹配不到,会将不存在的id添加入not_exist_list并返回。匹配到的商品,则会进行删除操作。

接口链接:/product/delete

接口版本:v2.0

接口参数

参数名称是否必须类型说明示例
sunmi_shop_nostring商米数字店铺平台中门店的唯一编号(v2.0之后为必填项)100939070408
shop_idstring第三方对接软件中门店的唯一编号(此参数为后向兼容v2.0之前版本的字段,在v2.0及以后版本使用sunmi_shop_no替代,作为门店唯一标识即可)10001
product_key_listlist 唯一标识商品的属性字段列表 [1]

 请求示例

'method': 'POST',
'url': 'https://store.uat.sunmi.com/openapi/product/delete',
'headers': {
  'Content-Type': 'application/x-www-form-urlencoded'
},
formData: {
  'shop_id': '10001',
  'app_id': 'I4VI99A0JDS21',
  'timestamp': '1581659359',
  'random': '5dsf6698',
  'sign': '00E5E55999C3C5BCA85DA3844928A70B',
  'product_key_list': '[1]'
}

返回值: 

{
    "code": 0,
    "msg": "succeed",
    "data": {
        "not_exist_list": [
            "1"
        ]
    }
}

错误列表:

错误代码错误原因
5000数据库错误
5041非法对接软件
5015非法商品

4 返回值检查

4.1 返回错误分类

作为HTTP消息返回,如果消息签名认证失败,HTTP消息会返回 401等作为提示。 如果消息签名认证通过,则进入业务层处理,此次HTTP请求返回200 OK。

具体业务层面的操作返回JSON值在消息体中。常见的消息返回类型为:

{
    code:0
    msg: "succeed"
    data: {}
}

错误列表:

错误代码错误原因
5000数据库错误
5041非法对接软件
5015非法商品

4.2 返回错误代码

参考《错误代码列表》文档

5 对接软件提供接口

在商品对接的过程中,如果有需要在数字店铺从第三方对接软件中拉取该门店的现有商品信息,需要对接软件提供相应的接口。

一般来说不推荐这种做法,所有数据尽可能直接从对接软件中推送到数字店铺。

5.1 获取全量商品 

接口说明:本接口是商米数字开放平台发起到对接软件的请求,用于商米数字平台从对接软件拉取该门店的所有商品。

对于不同的对接软件,返回的内容可能不同,具体模式需要在对接时确认确认,这里给出接口示例。

接口链接:https://example.SaaS.com/api/getProductList(示例接口,仅供参考)

接口参数

参数名称是否必须类型说明
shop_idstring对接软件的店铺标识
page_numint本次请求的页码
page_sizeint本次请求页的内容数量

返回值

{
    code:0
    msg: "succeed"
    data: {}
}

6 商品库对接示例

本部分提供了商品库对接的接口示例。仅供参考。

以下接口需在成功进行商户店铺对接后方能正常使用。店铺对接相关请参考《商户店铺》文档

本部分示例使用参数如下(接口中与签名校验相关的timestamp、random、sign等参数已省略):

app_idsecret_keyshop_id
APPID6917LTYtokenlty1237948

如下图,商户店铺对接后,商米数字店铺的商品库页面无任何商品。

此图像的alt属性为空;文件名为image2019-11-3_14-17-30.png

6.1 新建商品

6.1.1 新建商品成功

商户店铺对接成功后,调用product/create接口来增加商品。

请求参数:

app_idAPPID6917LTY
shop_id7948
product_list[{“name”:”\u53ef\u53e3\u53ef\u4e50\/\u704c\u88c5″,”id”:”1″,”seq_num”:”cola58476″,”bar_code”:”6958644000259″,”unit”:”\u7f50″,”price”:”3.2″,”member_price”:”3″,”spec”:”250ml”,”level”:””,”brand”:”\u53ef\u4e50″}]

返回结果:

{
    "code": 0,
    "msg": "succeed",
    "data": {
        "exist_list": [],
        "invalid_list": []
    }
}

刷新商米数字店铺的商品库页面,可以看到商品库中新增了一条商品

此图像的alt属性为空;文件名为image2019-11-3_14-29-23.png

点击详情查看详细信息:

此图像的alt属性为空;文件名为image2019-11-3_14-29-58.png

6.1.2 新建商品失败-商品已存在

将6.1.1中的请求再次发送,则接口会返回该商品已存在,并给出已存在的商品id。

请求参数:

app_idAPPID6917LTY
shop_id7948
product_list[{“name”:”\u53ef\u53e3\u53ef\u4e50\/\u704c\u88c5″,”id”:”1″,”seq_num”:”cola58476″,”bar_code”:”6958644000259″,”unit”:”\u7f50″,”price”:”3.2″,”member_price”:”3″,”spec”:”250ml”,”level”:””,”brand”:”\u53ef\u4e50″}]

返回结果:

{
    "code": 0,
    "msg": "succeed",
    "data": {
        "exist_list": [
            "1"
        ],
        "invalid_list": []
    }
}

6.1.3 新建商品失败-商品列表不是合法JSON字符串

商品列表中插入字符,使得参数不是合法json字符串

请求参数:

app_idAPPID6917LTY
shop_id7948
product_list[{“name”:”\u53ef\u53e3\u53ef\u4e50\/\u704c\u88c5″,,,”id”:”1″,”seq_num”:”cola58476″,”bar_code”:”6958644000259″,”unit”:”\u7f50″,”price”:”3.2″,”member_price”:”3″,”spec”:”250ml”,”level”:””,”brand”:”\u53ef\u4e50″}]

返回结果:

{
    "code": 1,
    "msg": "product_list: JSON.parse error"
}

6.1.4 新建商品失败-未提供商品必要字段

在商品列表中,不提供商品必填字段“id”。

请求参数:

app_idAPPID6917LTY
shop_id7948
product_list[{“name”:”\u53ef\u53e3\u53ef\u4e50\/\u704c\u88c5″,“id”:”1“,”seq_num”:”cola58476″,”bar_code”:”6958644000259″,”unit”:”\u7f50″,”price”:”3.2″,”member_price”:”3″,”spec”:”250ml”,”level”:””,”brand”:”\u53ef\u4e50″}]

返回结果:

{
    "code": 1,
    "msg": "invalid saas product info"
}

6.2 更新商品

6.2.1 更新商品成功-更新已经存在的商品

商户店铺对接成功后,调用product/update接口来更新商品信息(此处以价格为例)。

请求参数:

app_idAPPID6917LTY
shop_id7948
product_list[{“id”:1, “price”:”3.5″}]

返回结果:

{
    "code": 0,
    "msg": "succeed",
    "data": {
        "not_exist_list": [],
        "invalid_list": []
    }
}

回到商米数字店铺商品库界面,可以发现商品价格已由3.2元变为3.5元,“最后修改时间”已经更新为修改商品价格的时间。

更新前

此图像的alt属性为空;文件名为image2019-11-3_14-29-23.png
此图像的alt属性为空;文件名为image2019-11-3_14-29-58.png

更新后

此图像的alt属性为空;文件名为image2019-11-3_14-54-7.png
此图像的alt属性为空;文件名为image2019-11-3_14-55-57.png

6.2.2 更新商品成功-新建不存在的商品

商户店铺对接成功后,调用product/update接口来新建一个不存在商品信息。

请求参数:

app_idAPPID6917LTY
shop_id7948
product_list[{“id”:2, “name”:”Non-Exist Product”,”seq_num”:”nonexist1″,”price”:”58.2″}]

返回结果:

{
    "code": 0,
    "msg": "succeed",
    "data": {
        "not_exist_list": [
            "2"
        ],
        "invalid_list": []
    }
}

返回值中提示了商品id为“2”的商品原本不存在于商品库中,已采取新建操作。回到商品库,可以看到该商品已经被新建。

更新前

此图像的alt属性为空;文件名为image2019-11-3_14-54-7.png

更新后

此图像的alt属性为空;文件名为image2019-11-3_15-1-15.png

6.2.3 更新商品失败-商品列表不是合法JSON字符串

商品列表中插入字符,使得参数不是合法json字符串

请求参数:

app_idAPPID6917LTY
shop_id7948
product_list[{“name”:”\u53ef\u53e3\u53ef\u4e50\/\u704c\u88c5″,,,”id”:”1″,”seq_num”:”cola58476″,”bar_code”:”6958644000259″,”unit”:”\u7f50″,”price”:”3.2″,”member_price”:”3″,”spec”:”250ml”,”level”:””,”brand”:”\u53ef\u4e50″}]

返回结果:

{
    "code": 1,
    "msg": "product_list: JSON.parse error"
}

6.2.4 更新商品失败-未提供商品必要字段

在商品列表中,不提供商品必填字段“id”。

请求参数:

app_idAPPID6917LTY
shop_id7948
product_list[{“name”:”\u53ef\u53e3\u53ef\u4e50\/\u704c\u88c5″,“id”:”1″,”seq_num”:”cola58476″,”bar_code”:”6958644000259″,”unit”:”\u7f50″,”price”:”3.2″,”member_price”:”3″,”spec”:”250ml”,”level”:””,”brand”:”\u53ef\u4e50″}]

返回结果:

{
    "code": 1,
    "msg": "invalid saas product info"
}

6.3 删除商品

6.3.1 删除商品成功

商户店铺对接成功后,调用product/delete接口来删除商品信息。

请求参数:

app_idAPPID6917LTY
shop_id7948
product_key_list[2]

返回结果:

{
    "code": 0,
    "msg": "succeed",
    "data": {
        "not_exist_list": []
    }
}

回到商品库,可以看到id为2的商品已经被删除。

删除前

此图像的alt属性为空;文件名为image2019-11-3_15-1-15.png

删除后

此图像的alt属性为空;文件名为image2019-11-3_15-7-35.png

6.3.2 删除商品失败-商品不存在

商户店铺对接成功后,调用product/delete接口来删除一个不存在的商品信息。

请求参数:

app_idAPPID6917LTY
shop_id7948
product_key_list[3]

返回结果:

{
     "code": 0,
     "msg": "succeed",
     "data": {
         "not_exist_list": [
             "3"
         ]
     }
 }