商家自研OMS奇门对接-SDK踩坑录

前言:为自家零售行业的公司做OMS系统,需要通过奇门去对接第三方WMS系统。自家有淘宝店,申请商家自研应用还是很好申请的。就当前在做的OMS系统而言,我们要用的奇门的接口其实也就3个模块,发货,退换货,取消。介于官方接口那一堆要传的参数,我们还是选择用他们的SDK(.net core版本)。

对于官方SDK,咱还是100%信任的,出问题,首先咱就觉得是自己的问题,加班加点N次轮番测试,绞尽脑汁从自身找问题,快要崩溃的时候,扛不住了。

这里要感谢官方提供了SDK的源码,让我终于找出了问题所在。找到问题的那一瞬间,爆粗口 的有木有,气死人不偿命的有木有。我忍,呼~

故此篇不会叙述申请应用那块的流程,这个自己去百度或官方文档就行,只重点叙述对接过程的坑点

言归正传,进入接口对接主题,首先是先跟奇门测试环境进行自测,测试通过之后就进入跟第三方的联调。

接口统一参数说明:

     奇门测试环境接口地址Url:http://qimen.api.taobao.com/top/router/qmtest

     淘宝应用Appkey:你在淘宝开放平台申请的应用的Appkey

     淘宝应用Secretkey:你在淘宝开放平台申请的应用的Secretkey

     CustomerId:测试环境统一用mockCustomerId模拟测试,转正式的第三方对接的公司会提供

    OwnerCode:货主编码,这是第三方公司需要的参数,他们会提供

 对接SDK版本:.net core,自己系统框架:.net 5.0

一、回传接口坑点(自测测出的问题)

  以此接口为例taobao.qimen.deliveryorder.confirm(发货单已发货回传接口)

  进入淘宝开放平台 - 奇门 - 三方互通 - 我的场景,点击 taobao.qimen.deliveryorder.confirm 接口 进入,填写自测地址(即奇门回传信息给我们的地址,这需要咱将回写接口发布并且可外网访问)。在“系统检测的API列表” 中找到  taobao.qimen.deliveryorder.confirm,点击“进入”,有5项是需要进行测试的, 直接点击 “自测” 按钮,奇门官方测试环境就会逐个发送 请求到你的回传接口那里,只要其中一个没校验成功便会中断后面的校验。

坑点:

1. 网络&返回格式验收,内容里写着:要求返回的内容是api指定的格式(json/xml),即可以返回JSON也可以XML

     注意:只能返回XML格式它才认为是校验成功的,即你的回传代码里,ContentType 要这样写:

HttpContext.Response.ContentType = "text/xml; charset=utf-8"

初次写的返回值是JSON格式,坑爹的一直说响应为null,我还以为我的代码响应到宇宙去了。

2.正常签名测试,SDK签名里会根据HttpContext.Request.ContentType的类型走不一样的验证方式

   注意:奇门测试环境返回的ContentType为:application/xml,使用SDK验证签名的时候 永远报错:Unspported SPI request。不看SDK源码,你永远想不到原因是何。

        /// <summary>
        /// 校验SPI请求签名,不支持带上传文件的HTTP请求。
        /// </summary>
        /// <param name="request">HttpRequest对象实例</param>
        /// <param name="secret">APP密钥</param>
        /// <returns>校验结果</returns>
        public static CheckResult CheckSign(HttpRequest request, string secret)
        {
            CheckResult result = new CheckResult();
            string ctype = request.ContentType;
            if (ctype.StartsWith(Constants.CTYPE_APP_JSON) || ctype.StartsWith(Constants.CTYPE_TEXT_XML) || ctype.StartsWith(Constants.CTYPE_TEXT_PLAIN))
            {
                result.Body = GetStreamAsString(request, GetRequestCharset(ctype));
                result.Success = CheckSignInternal(request, result.Body, secret);
            }
            else if (ctype.StartsWith(Constants.CTYPE_FORM_DATA))
            {
                result.Success = CheckSignInternal(request, null, secret);
            }
            else
            {
                throw new TopException("Unspported SPI request");
            }
            return result;
        }

SDK源码里提到的类型解释:

public const string CTYPE_TEXT_XML = "text/xml";
public const string CTYPE_TEXT_PLAIN = "text/plain";
public const string CTYPE_APP_JSON = "application/json";
public const string CTYPE_FORM_DATA = "application/x-www-form-urlencoded";

压根没提到过 application/xml,你说它能不走Unspported SPI request吗!坑死我了!

没办法我改源码,加一个类型上去

//Constants.CTYPE_APP_PLAIN 为application/xml
if (ctype.StartsWith(Constants.CTYPE_APP_JSON) || ctype.StartsWith(Constants.CTYPE_TEXT_XML) || ctype.StartsWith(Constants.CTYPE_TEXT_PLAIN) || ctype.StartsWith(Constants.CTYPE_APP_PLAIN))
{
     result.Body = GetStreamAsString(request, GetRequestCharset(ctype));
     result.Success = CheckSignInternal(request, result.Body, secret);
}

好了,到此以为应该没问题了,奈何又报错:Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead

这是读取请求body的时候出错的,不用想了SDK中异常的,一看源码就找到这句话:reader.ReadToEnd()。

这个错是说CORE 3.0中默认禁了AllowSynchronousIO,同步读取body的方式需要ConfigureServices中配置允许同步读取IO流或者直接使用异步读取方式。没用过3.0以前的版本,我们就采用直接使用异步读取方式 方式做的,把代码改成:

ReadToEndAsync().Result。

然后再一次测试,终于签名通过了,其他的就都好说了。

二、推送接口坑点(跟第三方直连 联调)

 1.签名验证:

     这是直连测试,我们对接的第三方也据说都是用的SDK,它们那是对接了好些公司的成熟系统了,理论应该不会出错的吧,并未知晓他们用的何种语言开发的。首次跟他们用奇门对接,就是一直签名通不过,后来查看他们返回的Request.ContentType = "application/x-www-form-urlencoded"。再去查看SDK源码(第一章已经贴出来了),发现生成sign的方法体中不会将解析后的body组装进去。当时我就在想,第三方传过来的签名不会是 走的组装了body生成签名的吧,所以我这里就将Request.ContentType强制修改成"text/xml",然后再去调SDK验证签名方法,结果成功了。

    到这里,有2种可能

       第一:第三方生成签名不正确,SDK验证方法是对的

       第二:SDK生成签名方式与组装请求ContentType 相矛盾,默认都是将body组装生成的签名,但是 请求ContentType 却默认设置了 "application/x-www-form-urlencoded"。

这里我去看了下.net core的版本的SDK,其实发现 它发送请求时候,生成的签名确实是组装了body,但ContentType设置是"text/xml"。按理它不会走偏。但是 第三方说他们是用的SDK组装参数发送请求,不会有错,不知道他们那用的是什么版本的SDK,也没法子验证。后面没法子,就只能在验证签名的之前 强重写了Request.ContentType="text/xml",不然签名验证不过啊。

2. 问题接口:taobao.qimen.returnorder.create(退货单入库推送)

 这个是直接跟第三方联调的时候出现的问题,我们按照正常的数据组装发送请求到第三方那里。然后他们那边一直返回参数得不到,解析不了。但是我们的请求跟“发货单创建”接口一样的组装和请求模式,都是用的官方SDK组装参数的,为何 “发货单创建”接口可以成功,“退货单入库”接口就不行呢。这次学聪明了,去看SDK源码,嗯找到问题了。

ReturnorderCreateRequest里的参数,凡是List类型的参数,类名上都没有打上XML解析标志,就是没有下面框中的这句话:

所以没有这句话,它最终生成的报文格式会变成这样,多出<list`1>的玩意。

<request><orderLines><list`1><inventoryType>ZP</inventoryType>...

加上这句话之后就可以了。

至此,我发现的SDK坑点就这些了,当然这只是我所用到的SDK的相关部分接口发现的坑点而已,还有没有其他地方有,后续用到了在发现吧,至少现在留了心眼,看sdk源码找BUG。

结语:官方称为官方是因为它们一定是经过仔细测试成为了标准唯一。但不可太过依赖官方,不是它们就一定不会出错,凡事留个心眼吧。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值