简介:面向有C#基础的软件开发者的旺店通WMS系统对接代码包,适用于需要完成WebAPI接口集成、销售出库单查询及标准定制接口调用的业务场景,也适合作为从接口文档到编码实现的过渡参考。包内共32个文件,以cs源码与csproj工程文件为核心,包含WMSHelper.cs、Program.cs等C#示例,另有dll依赖、json配置、txt说明、py脚本及pdb调试文件,压缩包约380KB,整体保留Debug构建输出与工程配置,并附带wms_integration.py脚本,便于对照Python与C#两种调用写法,整体对刚接触旺店通WMS的团队尤其友好。已有178人学习下载。代码示例覆盖了HttpClient的POST请求构造、签名生成、URL参数处理以及标准定制接口调用等关键环节;结合请求地址、方法、密钥和参数配置样例,可较快掌握销售出库单查询接口的对接思路,并迁移到实际项目中做二次开发。 做电商仓储的朋友应该都躲不开一个场景:店铺订单如潮水般涌进来,ERP里订单状态明明已经推下去了,仓库那边WMS却半天没反应,要么包裹迟迟不出库,要么库存数对不上。旺店通作为电商ERP用得相当广,而WMS(仓库管理系统)则是仓储履约的核心,两者能不能顺畅对接,直接决定了发货效率、库存准确率,甚至大促期间的爆单上限。这篇文章就把旺店通WMS对接这件事掰开揉碎讲清楚,包括整体方案、核心接口、鉴权方式、关键代码实现,以及我实际对接中踩过的坑。适合正在做电商系统集成的后端开发、仓储系统负责人,以及准备优化仓库流程的产品和运维同学参考。
1. 为什么要把旺店通和WMS打通,以及常见的对接思路
1.1 两套系统的典型分工与数据断点
旺店通这类ERP解决的是订单流、采购、财务、商品档案等问题,它知道“该卖什么”“该买什么”,但并不知道仓库里货具体在哪一排货架、哪个库位,也不知道拣货员当前正在拣哪张单。WMS恰恰相反,它管的是库位、波次、拣货、复核、打包、称重、出库这些实际操作流程,但它又不掌握店铺平台的订单规则和售后状态。
如果不做对接,最原始的做法就是人工搬运数据:每天从ERP导出订单表,再导入WMS建单,发货后再把物流单号人工回填。单量少的时候还能撑,单量一上来,问题就全暴露了:订单延迟、漏单、错发、库存回传不及时,客服那边几乎天天被买家催“怎么还不发货”。所以,把两套系统通过接口串起来,让订单自动从ERP流入WMS,让发货结果和库存余量自动回流到ERP,是绝大多数电商仓配业务的刚需。
1.2 直连接口与中间件两种方案怎么选
旺店通开放平台提供了面向外部系统的API,WMS厂商也基本都开放了入库单、出库单、库存查询、单据回传等接口。对接方案上大致分两类。
第一种是点对点直连,也就是ERP和WMS各自出接口,中间写一套同步服务来做数据转换和状态回写。优点是没有额外依赖,网络拓扑简单,适合业务逻辑比较固定、双方接口能力都明确的场景。缺点是一旦其中一方接口更新或者业务规则调整,同步层就得跟着动,耦合度偏高。
第二种是引入集成中间件,比如用消息队列、ETL工具,或者一些开源的集成框架把两套系统做解耦。ERP只需要把单据和状态消息发到MQ,WMS侧监听消息再转成自己的业务数据,回传时同理。好处是扩展性好,多个仓库甚至异构系统都能挂在同一条链路上,而且大促时有缓冲作用,不会因为瞬时流量直接把某一方的接口打挂。代价是架构复杂度上去了,需要额外运维一套消息组件或中间件服务。
我的建议是:如果你的仓库流程相对标准、单据类型不超过两三种、单量也稳定,点对点直连完全够用,开发周期也短。如果公司是多仓、多ERP、多平台、业务变化频繁,那从一开始就上中间件加消息队列,后期会省很多事。
2. 对接前必须搞清楚的几个核心概念
2.1 授权鉴权:签名、密钥、访问令牌
对接旺店通开放平台,首先绕不开鉴权机制。通常每个开发者账号会拿到一组应用标识和密钥,接口请求时需要通过签名来保证参数没有被篡改,同时保证请求方身份可信。常见的签名方式是把所有请求参数(去除签名字段)按字典序排序,拼接成字符串,再混入应用密钥做MD5或HMAC加密,最终得到签名串。
另外,部分接口还会校验授权令牌或会话凭证,尤其是涉及店铺维度数据的时候,需要先获取授权,再拿授权令牌去请求业务接口。令牌会有有效期,过期后需要走刷新逻辑,这一步非常容易在联调阶段踩坑。你在设计同步程序时,最好把令牌的获取和刷新做成自动化的,而不是配置一个写死的值放在配置文件里。
2.2 主数据口径与单号规则必须提前对齐
接口对接不只是把数据传过去就完了,两边对数据含义的理解必须一致。比如SKU编码,ERP里一套编码,WMS里又一套编码,单据推下去仓库根本没法拣货。通常做法是以ERP的商品编码作为主键,WMS通过映射表建立关联。
再比如单据号,订单号、出库单号、入库单号在两边叫法可能不同,而且旺店通有它的单号,WMS也会生成自己的单号。对接时需要在回传报文里同时携带两边的单号,确保后续对账能串起来。还有单位、精度、货品属性(是否称重、是否批次管理)这些基础信息,如果不一致,WMS入库上架时就会报错。所以对接启动前,第一步永远是梳理主数据映射,而不是先写代码。
2.3 同步模式:实时调用还是异步轮询
接口同步有两种典型模式:一种是ERP主动调用WMS接口创建单据并等待返回,另一种是ERP把单据推送到平台或MQ后,WMS按一定频率去拉取或者接收消息通知。前者响应快、逻辑直观,但接口超时或WMS短暂不可用时,会导致ERP侧阻塞甚至丢单。后者更稳,WMS可以按照自己的节奏处理,掉单可以重新拉取,但实时性会差一些,极端情况下可能有几十秒到几分钟的延迟。
实际项目中很多团队会做混合模式:核心出库单用实时推送加失败重试,库存和物流回传用异步补偿。具体怎么选,要看你仓库业务对实时性的要求。一般B2C发货场景,分钟级延迟完全可接受;如果是门店紧急调拨或者O2O即时配送,就需要实时推送加状态通知。
3. 核心代码实现与关键流程细节
3.1 一个通用的签名请求封装
下面这段代码我按常见实践整理了一个参考模板,用来做旺店通开放平台接口的签名和HTTP请求。应用到你自己项目时,需要把业务参数、接口路径、应用密钥和令牌替换成旺店通实际开通的凭证,接口签名规则也以开放平台最新的开发文档为准。
<?php class WangdiantongClient { private $appKey; private $appSecret; private $sessionKey; private $gatewayUrl; public function __construct($appKey, $appSecret, $sessionKey, $gatewayUrl) { $this->appKey = $appKey; $this->appSecret = $appSecret; $this->sessionKey = $sessionKey; $this->gatewayUrl = $gatewayUrl; } public function execute($method, $bizParams = [], $pageNo = 0, $pageSize = 100) { // 系统级参数汇总 $params = array_merge([ 'method' => $method, 'app_key' => $this->appKey, 'session' => $this->sessionKey, 'timestamp' => date('Y-m-d H:i:s'), 'format' => 'json', 'v' => '2.0', 'page_no' => $pageNo, 'page_size' => $pageSize, ], $bizParams); // 生成签名并加入参数 $params['sign'] = $this->generateSign($params); return $this->httpPost($this->gatewayUrl, $params); } private function generateSign($params) { // 1. 去除sign参数,按key的ASCII码升序排列 ksort($params); // 2. 拼接成 k=v 字符串 $stringToBeSigned = ''; foreach ($params as $k => $v) { if ($v === '' || $v === null) { continue; } $stringToBeSigned .= $k . '=' . $v . '&'; } $stringToBeSigned = rtrim($stringToBeSigned, '&'); // 3. 混入应用密钥并进行摘要 return strtoupper(md5($stringToBeSigned . $this->appSecret)); } private function httpPost($url, $data) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $response = curl_exec($ch); curl_close($ch); return json_decode($response, true); } }这段封装里最需要注意的是签名拼接顺序。很多刚接触开放平台的同学会忽略“按key的ASCII升序”这个条件,直接把参数按自己习惯的先后顺序拼起来,结果签名一直校验失败。另外,拼完参数串之后混入密钥的时机和位置也很关键,比如是拼接在字符串末尾还是开头,不同平台约定不一样,务必以文档为准。
3.2 订单下发:从ERP出库单到WMS拣货任务
订单下发是整个对接链路中数据量最大的环节,也是问题最多的环节。我梳理一下这个过程的完整逻辑:先查待发货订单列表,再把订单头信息和明细行信息整理成WMS能识别的结构,调用WMS创建出库单接口,然后根据返回结果更新订单状态。为了避免下游抖动导致的数据不一致,这个环节必须有重试和幂等设计。
// 伪代码示例:从旺店通拉取待发货订单,并推送到WMS $client = new WangdiantongClient($appKey, $appSecret, $sessionKey, $gatewayUrl); // 1. 分页拉取待发货订单 $page = 1; do { $pushed = $client->execute('wms.stockout.order.query', [ 'status' => 'pending', 'start_ts' => date('Y-m-d H:i:s', strtotime('-5 minutes')), ], $page, 100); foreach ($pushed['orders'] ?? [] as $order) { // 2. 组装WMS出库单结构 $wmsOrder = [ 'outer_no' => $order['order_no'], // 外部单号,用于幂等 'warehouse_code' => $order['warehouse_code'], // 仓库编码 'receiver' => $this->buildReceiver($order), 'items' => $this->buildItems($order['items']), 'remark' => $order['remark'] ?? '', ]; // 3. 调用WMS创建出库单 $result = $this->wmsApi->createStockOutOrder($wmsOrder); if ($result['success']) { // 4. 成功后回写旺店通,标记该订单已推送,防止重复下发 $client->execute('wms.stockout.order.push.confirm', [ 'order_no' => $order['order_no'], 'status' => 'accepted', ]); } else { // 记录错误日志,进入待重试队列 $this->retryQueue->push($order); } } $page++; } while ($page <= $pushed['total_page']);这里面的核心是幂等控制。WMS创建出库单这个动作不能随意重复执行,否则仓库里会出现一模一样的两个拣货单。我常用的策略是用“外部单号”作为WMS侧的幂等键,如果同一单号已经创建过任务,WMS应直接返回已存在,而不是重复创建。这一点在对接前要跟WMS厂商确认清楚,接口是否具备天然幂等能力,如果对方不支持,就得自己加一层去重逻辑。
3.3 库存回传与物流单号回写
仓库出库后,WMS需要把发货状态和物流单号回传给ERP,否则ERP这边还傻傻地显示“待发货”,库存也无法正确扣减。回传动作一般发生在WMS完成出库、生成物流单号之后。
回传的数据要包含这几个要素:仓库单号、外部单号、物流公司编码、物流单号、发货时间、操作人。旺店通收到回传后会把订单状态更新为已发货,并把物流信息同步给平台。如果回传失败,最常见的结果是买家看到“已发货但无物流信息”,所以重试和补偿尤其重要。
// 伪代码示例:WMS回传发货结果到旺店通 $shipResult = [ 'outer_no' => 'SO20250115001', // 对应ERP原始订单号 'wms_order_no' => 'WH202501150016', // WMS生成的单号 'logistics_code' => 'ZTO', // 物流公司编码 'logistics_no' => '773012345678901', // 物流单号 'ship_time' => date('Y-m-d H:i:s'), 'status' => 'SHIPPED', ]; try { $resp = $client->execute('wms.stockout.ship.confirm', $shipResult); // 如果接口返回需要重试的错误码,放入消息队列延时重试 if (in_array($resp['code'], ['INVALID_SESSION', 'SYSTEM_BUSY'])) { $this->mq->push($shipResult, ['delay' => 60]); } } catch (Exception $e) { // 记录明细日志,方便事后核对 log_error('ship confirm fail', $e->getMessage(), $shipResult); }回传接口同样需要做幂等。物流单号一旦录入,如果因为网络抖动重发了几次,不能把WMS的发货记录重复提交,否则ERP侧可能出现多条发货流水。最好的做法是WMS在本地生成一个“回传批次号”,ERP侧用这个批次号做唯一约束,同一个批次最多生效一次。
3.4 回调与状态双向同步不可忽视
除了下单和回传,两步双向同步也要做:一方面是WMS的库存变化回传,另一方面是ERP商品信息、库存阈值等变更同步到WMS。库存回传尤其重要,电商平台上的可售库存,本质上等于ERP库存减去冻结库存,如果WMS已经实际出库了但库存没有回传给ERP,就会出现超卖。
我建议库存回传采用“事件驱动+定期全量”的双保险策略。每次出入库完成WMS实时推一条库存变动消息;每天晚上再跑一次全量库存对账,把两边差值捞出来。大促期间甚至可以每小时对一次。库存数字对不上,早晚要出事,越早发现越好。
4. 常见问题与排查技巧实录
4.1 签名错误:90%都出在细节上
签名错误是整个对接试运行期间最折磨人的问题。我排查过多次,最终发现的原因五花八门:有的是URL编码后加号变成了空格;有的是时间戳格式不统一,平台要求“Y-m-d H:i:s”,代码里却传了秒级时间戳;有的是密钥前后多了个空格,复制粘贴时带进来的;还有一种很隐蔽,就是拼接参数时把空值也拼进去了,而平台侧签名时是过滤掉空值的。
排查签名问题时,我的习惯是先在代码里把最终用于签名的原始字符串打出来,跟开放平台文档上的示例一步步比对,定位是排序问题、拼接问题还是混入密钥的位置问题。几乎绝大多数签名问题都能靠这个方法快速找到。不要一上来就怀疑什么加密算法不对,99%的概率是你参数没对齐。
4.2 会话失效或权限不足:令牌要自动续期
旺店通开放平台的会话凭证有有效期,过期之后所有业务接口都会报错或者返回未授权。这个坑最大特点是上线初期不容易暴露,因为联调时令牌刚申请不久,等跑了一两个月突然报错,排查时很难第一时间想到。
正确做法是写一个令牌刷新任务,在有效期剩余一定比例时就主动刷新,刷新的逻辑同时在同步进程启动时校验一次。另外,权限不足的问题也很常见:开发者账号开通了A接口权限,但B接口没申请,调用时就报权限不足。对接前先拉一遍接口权限清单,确认所有要用的接口都开通了,免得开发到一半才发现调不通。
4.3 重复发货、漏单和延迟单的应对
重复发货的根因通常是接口超时后的重试。第一笔请求实际已经成功了,但响应超时,你的程序又重发了一次,WMS就建了两张单。解决方案就是我前面说的幂等键方案,以外部单号为准。漏单一般是拉取订单时过滤条件不对,或者分页逻辑处理有缺陷。比如订单状态枚举值搞错了,把待发货订单漏掉;再比如订单量超过一期,程序停在中间一页没有继续翻页。这个问题可以在同步程序里加“最近5分钟的数据重新拉取校验”逻辑,每次任务启动时把最近5分钟的单据做一次对账,如果发现WMS侧没有记录的,自动补推。
延迟单大多数出在消息队列积压或者WMS处理能力不足上。如果用了MQ,要监控消费积压数,一旦积压超过阈值就报警并扩容消费者实例。如果是WMS处理慢,一方面看WMS端的日志和数据库慢查询,另一方面考虑调整下发批次大小,千万不要一次性把几千单全推过去,容易把对方接口压垮。
4.4 接口返回数据字典不明确:建立一张状态映射表
旺店通和WMS两边单据状态的定义经常不一样。比如旺店通里有一堆订单状态,而WMS可能只分“待处理”“处理中”“已完成”。如果直接拿原始状态码互相传递,两边都识别不了。建议在同步服务中建一张状态映射表,把两边的枚举对应关系维护好,界面化配置最好,这样业务调整时不用改代码,改配置就行。
5. 上线前必须做的联调验证与监控
5.1 联调阶段先跑通最小闭环
不要一上来就追求全流程,先把最小闭环跑通:创建一条测试商品,在ERP生成一个测试订单,推到WMS完成拣货出库,再回传发货状态和物流单号,确认两边数据一致。这个过程走通之后,再逐步覆盖异常场景,比如取消订单、缺货、部分发货、多包裹发货。凡是主流程的变体,都要有对应的测试case。
5.2 监控告警与日志规范一个都不能少
对接系统平时不出问题,一出问题就是大问题,所以监控必须做到位。我给自己的项目定的标准是:同步任务的成功率、失败量、重试次数、消息积压数都要有可视化看板;失败重试超过3次的单据要单独列表展示;每笔同步记录都要保留完整请求报文和响应报文,方便问题回溯。日志里一定要打印单据号、接口名、请求时间、耗时、返回码,后续排查能省大量时间。
6. 一点沉淀下来的实操心得
旺店通WMS对接这件事,技术上并不复杂,真正难的是业务细节。不同仓库的作业流程差异很大,同样是出库单,有的仓库需要拣货单,有的需要波次下发,有的还要支持越库操作。所以对接方案一定要留出扩展点,不要把单据类型写死在代码里,通过配置驱动才是长久之计。
另外,上线节奏上强烈建议先做一家仓或一个店铺的试点。我见过不少项目,上来就想把全国所有仓库一次性切过去,结果对接初期一堆返工需求,切换成本和业务压力都翻倍。先让一个仓库跑顺,数据、状态、异常都稳定了,再逐步推广到其他仓,整体风险会小很多。最后再分享一个细节:所有外部系统联调前,先把两边接口文档里关于必填字段、上限值、枚举值约定逐条过一遍,落实成一份双方确认的字段映射清单,这比什么都管用。
本文还有配套的精品资源,点击获取