关于京东溯源数据上传的心得

京东溯源数据上传,也是碰到好多问题,现在整理下,给后面的人一个思路

开发语言:java

开发工具:sts

相关技术:StringBootMvc、myBatis、shiro、thymeleaf等

一、注册宙斯系统并申请应用

  宙斯地址:https://jos.jd.com  

  创建应用:https://jos.jd.com/commondoc?listId=160

二、下载SDK并导入本地库

  我用的是maven,所以需要把下载的java 京东SDKjar包导入到本地maven库中

  mvn install:install-file -Dfile=open-api-sdk-2.0-2022-03-23.jar  -DgroupId=jd.open.api -DartifactId=jdsdk2 -Dversion=2.0.0 -Dpackaging=jar

  -Dfile:jar包所在本地的具体路径
  -DgroupId:项目组织唯一的标识符,实际对应JAVA的包的结构
  -DartifactId:项目的唯一的标识符,实际对应项目的名称,就是项目根目录的名称
  -Dversion:版本号
  -Dpackaging:打包的类型

  运行后出现BUILD SUCCESS就表示导入成功了,在pom.xml里引用即可。

三、获取code

  在创建好的应用审核通过,点击【管理】获取到改应用的appKey和appSecret,可用配置到数据库中。

  在应用设置里,配置回调URL,如果没有回调URL可用设置成功http://www.baidu.com

  拼接连接获取code:

  拼接的连接:https://open-oauth.jd.com/oauth2/to_login?app_key=appKey&response_type=code&redirect_uri=回调URL&state=20220331&scope=snsapi_base

  app_key:对应应用的appKey

  redirect_uri: 回调URL地址

  state:当日时间 20220331 

  1、通过回调URL获取code

  此方式需要自己在写一个回调方法,确保地址能访问通,回调方法中获取code后直接在此获取accessToken;

  回调方法代码:

 1 @GetMapping("/jdSyReceipt")
 2     public void jdSyReceipt(HttpServletRequest request, HttpServletResponse response)
 3     {
 4         String appKey = "appkey";    // 应用key
 5         String appSecret = "appSecret";    // 应用秘钥
 6         // 获取地址栏里的code
 7         String code = request.getParameter("code");
 8         System.out.println(code);
 9         
10         // 根据类型获取应用访问令牌
11         OutsideAccessToken accessToken = outsideAccessTokenService.selectOutsideAccessTokenByType("jd_suyuan");
12         
13         String to_token_url = "https://open-oauth.jd.com/oauth2/access_token";
14         String token_param = "app_key="+appKey+"&app_secret="+appSecret+"&grant_type=authorization_code&code="+code;
15         
16         // 通过url和参数,通过httpget方式请求获取accessToken
17         String jsonToken = HttpUtils.sendGet(to_token_url, token_param);
18                 // 把JSON字符串转成成对象 import com.alibaba.fastjson.JSON;
19         JdAccessToken jdAccessToken = (JdAccessToken) JsonUtil.parseObject(jsonToken, JdAccessToken.class);
20         if(jdAccessToken.getCode().equals("0")) {
21             // 判断京东令牌是否为空
22             if(StringUtils.isNotNull(accessToken)) { // 不为空
23                 accessToken.setAccessToken(jdAccessToken.getAccess_token());
24                 accessToken.setExpiresIn(jdAccessToken.getExpires_in());
25                 accessToken.setRefreshToken(jdAccessToken.getRefresh_token());
26                 accessToken.setScope(jdAccessToken.getScope());
27                 accessToken.setOpenId(jdAccessToken.getOpen_id());
28                 accessToken.setUid(jdAccessToken.getUid());
29                 if(null != jdAccessToken.getTime()) {
30                     Date date = new Date(jdAccessToken.getTime());
31                     accessToken.setTime(date);
32                 }
33                 accessToken.setTokenType(jdAccessToken.getToken_type());
34                 accessToken.setCode(jdAccessToken.getCode());
35                 accessToken.setXid(jdAccessToken.getXid());
36                 outsideAccessTokenService.updateOutsideAccessToken(accessToken);
37                 log.info("jdSyReceipt:结果》》》》更新成功");
38             }else { // 为空
39                 accessToken.setAccessToken(jdAccessToken.getAccess_token());
40                 accessToken.setExpiresIn(jdAccessToken.getExpires_in());
41                 accessToken.setRefreshToken(jdAccessToken.getRefresh_token());
42                 accessToken.setScope(jdAccessToken.getScope());
43                 accessToken.setOpenId(jdAccessToken.getOpen_id());
44                 accessToken.setUid(jdAccessToken.getUid());
45                 if(null != jdAccessToken.getTime()) {
46                     Date date = new Date(jdAccessToken.getTime());
47                     accessToken.setTime(date);
48                 }
49                 accessToken.setTokenType(jdAccessToken.getToken_type());
50                 accessToken.setCode(jdAccessToken.getCode());
51                 accessToken.setXid(jdAccessToken.getXid());
52                 accessToken.setTypeName("jd_suyuan");
53                 outsideAccessTokenService.insertOutsideAccessToken(accessToken);
54                 log.info("jdSyReceipt:结果》》》》添加成功");
55             }
56         }else {
57             //return AjaxResult.error(jdAccessToken.getMsg());
58             log.info("jdSyReceipt:结果》》》》"+jdAccessToken.getMsg());
59         }
60     }
View Code

  2、浏览器地址栏获取code

  此方式需要在浏览器地址栏获取到code,获取code后在拼接获取accessToken的连接,成功后获取JSON字符串。

 四、获取accessToken  

  1、通过回调URL获取,第三获取code时有代码

   2、自己拼接连接:https://open-oauth.jd.com/oauth2/access_token?app_key=appKey&app_secret=appSecret&grant_type=authorization_code&code=code

    访问后获取JSON字符串,不建议此方式。

五、使用SDK上传溯源数据

  先说下我这边的逻辑:先通过订单查询改单据的罐数,因为京东SDK上传数据量要求1500条,我们组合的list时一罐产品对应4条(流通信息、生产信息、商品信息、检测信息),一次上传要限定下罐数,我这边设置的是360罐

  看下列代码:

  以下代码只供参考,获取accessToken这个要根据自己实际情况来。TraceDataItem 这个包含四个字段:key、val、fileName、fileType,可以根据自己公司的实际情况来命名和上传。

 

public AjaxResult syncJdSuyuan() {
        try {
            String traceaccount = "自己的溯源账号";    // 溯源账号
            String industryCode = "jdbiz";     //行业编码
            // 获取第4部时的accessToken信息
            OutsideAccessToken accessToken = outsideAccessTokenService.selectOutsideAccessTokenByType("jd_suyuan");
            String appKey = "应用的appkey"; 
            String appSecret = "应用的秘钥";
            if(StringUtils.isNotNull(accessToken)) {
                /// 我这是根据订单查询发往京东的罐数
                List<BillDistDetail> ListBillDetails = billDistDetailService.selectBillDistDetailListByInBocde("订单号");
                // 增加线程锁,避免循环提交是错乱
                synchronized (obj) {
                    /*** 批量处理 list */
                    int pointsDataLimit = 360;// 限制条数
                    int part = ListBillDetails.size() / pointsDataLimit;// 分批数
                    // 分批处理结果为OK的list条码对象
                    if(ListBillDetails.size() > pointsDataLimit) {  
                        for (int i = 0; i < part; i++) {
                            List<TraceData> record = new ArrayList<TraceData>();
                            // 获取分批后的条码list
                            List<BillDistDetail> listPageCodes = ListBillDetails.subList(0, pointsDataLimit);
                            // 循环遍历分割后list的产品信息
                            for (BillDistDetail billDetail : listPageCodes) {
                
                                String uniquecode = "自己的唯一产品码";
                                //流通信息:17137  生产信息:17138  商品信息:17139  检测信息:17140
                                /** 流通信息17137(原产地、品牌出库仓库、收货仓库) Start */
                                TraceData ltData= new TraceData();
                                ltData.setUniquecode(uniquecode); // 追溯编码
                                ltData.setTraceaccount(traceaccount); // 追溯账号
                                List<TraceDataItem> ltDataList = new ArrayList<TraceDataItem>();
                                TraceDataItem ycd = new TraceDataItem();
                                ycd.setKey("原产地");
                                ycd.setFiledName("countryOrigin");
                                ycd.setFiledType("text");
                                ycd.setVal("");    // 溯源信息原产地
                                ltDataList.add(ycd);
                                TraceDataItem ppckck = new TraceDataItem();
                                ppckck.setKey("品牌出库仓库");
                                ppckck.setFiledName("exWarehouse");
                                ppckck.setFiledType("text");
                                ppckck.setVal("成品库");
                                ltDataList.add(ppckck);
                                TraceDataItem shck = new TraceDataItem();
                                shck.setKey("收货仓库");
                                shck.setFiledName("receivingWarehouse");
                                shck.setFiledType("text");
                                shck.setVal("北京京东世纪信息技术有限公司");
                                ltDataList.add(shck);
                                ltData.setDataList(ltDataList);    //追溯流通信息详情
                                ltData.setDataType(17137);    //追溯流通信息环节
                                ltData.setSkuid(1000L);    //京东商品ID
                                ltData.setIndustryCode(industryCode);    //行业编码
                                record.add(ltData);
                                /** 流通信息17137 End */
                                /** 生产信息17138(生产批号、生产日期、保质期、有效日期) Start */
                                TraceData scData= new TraceData();
                                scData.setUniquecode(uniquecode); // 追溯编码
                                scData.setTraceaccount(traceaccount); // 追溯账号
                                List<TraceDataItem> scdataList = new ArrayList<TraceDataItem>();
                                TraceDataItem scpcItem = new TraceDataItem();
                                scpcItem.setKey("生产批号");
                                scpcItem.setFiledName("BatchNumber");
                                scpcItem.setFiledType("text");
                                scpcItem.setVal("生产批次");
                                scdataList.add(scpcItem);
                                TraceDataItem scrqItem = new TraceDataItem();
                                scrqItem.setKey("生产日期");
                                scrqItem.setFiledName("produceDate");
                                scrqItem.setFiledType("text");
                                scrqItem.setVal("生产日期");
                                scdataList.add(scrqItem);
                                TraceDataItem bzqItem = new TraceDataItem();
                                bzqItem.setKey("保质期");
                                bzqItem.setFiledName("shelfLife");
                                bzqItem.setFiledType("text");
                                bzqItem.setVal("730");
                                scdataList.add(bzqItem);
                                TraceDataItem yxrqItem = new TraceDataItem();
                                yxrqItem.setKey("有效日期");
                                yxrqItem.setFiledName("effectiveDate");
                                yxrqItem.setFiledType("text");
                                yxrqItem.setVal("有效日期");
                                scdataList.add(yxrqItem);
                                scData.setDataList(scdataList);    //追溯生产信息详情
                                scData.setDataType(17138);    //追溯生产信息环节
                                scData.setSkuid(1000L);    //京东商品ID
                                scData.setIndustryCode(industryCode);    //行业编码
                                record.add(scData);
                                /** 生产信息17138(生产批号、生产日期、保质期、有效日期) End */
                                /** 商品信息17139(产品检验报告)Start */
                                TraceData spData= new TraceData();
                                spData.setUniquecode(uniquecode); // 追溯编码
                                spData.setTraceaccount(traceaccount); // 追溯账号
                                spData.setDataType(17139);    //追溯商品信息环节
                                spData.setSkuid(1000L);    //京东商品ID
                                spData.setIndustryCode(industryCode);    //行业编码
                                List<TraceDataItem> spDataList = new ArrayList<TraceDataItem>();
//                                    TraceDataItem ppmcItem = new TraceDataItem();
//                                    ppmcItem.setKey("品牌名称");
//                                    ppmcItem.setFiledName("brandName");
//                                    ppmcItem.setFiledType("text");
//                                    ppmcItem.setVal(jdSuyuanGoods.getBrandName());
//                                    spDataList.add(ppmcItem);
                                TraceDataItem xlItem = new TraceDataItem();
                                xlItem.setKey("系列");
                                xlItem.setFiledName("series");
                                xlItem.setFiledType("text");
                                xlItem.setVal("产品系列");
                                spDataList.add(xlItem);
                                TraceDataItem dwItem = new TraceDataItem();
                                dwItem.setKey("段位");
                                dwItem.setFiledName("goodsLevel");
                                dwItem.setFiledType("text");
                                dwItem.setVal("产品段位");
                                spDataList.add(dwItem);
                                spData.setDataList(spDataList);    //追溯商品信息详情
                                record.add(spData);
                                /** 商品信息17139(产品检验报告)End */
                                /** 检测信息17140(产品检验报告)Start */
                                TraceData jyData= new TraceData();
                                jyData.setUniquecode(uniquecode); // 追溯编码
                                jyData.setTraceaccount("haiwangshipin"); // 追溯账号
                                List<TraceDataItem> jyDataList = new ArrayList<TraceDataItem>();
                                TraceDataItem zjbgItem = new TraceDataItem();
                                zjbgItem.setKey("产品质检报告");
                                zjbgItem.setFiledName("inspectionReportImg");
                                zjbgItem.setFiledType("img");
                                zjbgItem.setVal("检测报告httpsURL地址");// 产品质检报告
                                jyDataList.add(zjbgItem);
                                jyData.setDataList(jyDataList);    //追溯检测信息详情
                                jyData.setDataType(17140);    //追溯检测信息环节
                                jyData.setSkuid(1000L);    //京东商品ID
                                jyData.setIndustryCode(industryCode);    //行业编码
                                record.add(jyData);
                                /** 检测信息17140(产品检验报告)End */
                            }// 请求京东
                            JdClient client = new DefaultJdClient("https://api.jd.com/routerjson", accessToken.getAccessToken(), appKey, appSecret);
                            BtBlockchainMiddleTraceDataVendorServiceGateWayInsertBatchRequest request = new BtBlockchainMiddleTraceDataVendorServiceGateWayInsertBatchRequest();
                            request.setRecord(record);
                            BtBlockchainMiddleTraceDataVendorServiceGateWayInsertBatchResponse response = client.execute(request);
                            // 打印上传数据结果,依此判断是否提交成功
                            System.out.println(response.getMsg());
                            // 清除分批处理的数据
                            ListBillDetails.subList(0, pointsDataLimit).clear();
                        }
                            
                    }
                    // 剩余部分
                    if(!ListBillDetails.isEmpty()) {
                        List<TraceData> record = new ArrayList<TraceData>();
                        // 为避免accessToken在循环中失效,再次获取
                        OutsideAccessToken accessToken2 = outsideAccessTokenService.selectOutsideAccessTokenByType("jd_suyuan");
                        for (BillDistributorDetail billDetail : ListBillDetails) {
                            String uniquecode = "自己的唯一产品码";
                            //流通信息:17137  生产信息:17138  商品信息:17139  检测信息:17140
                            /** 流通信息17137(原产地、品牌出库仓库、收货仓库) Start */
                            TraceData ltData= new TraceData();
                            ltData.setUniquecode(uniquecode); // 追溯编码
                            ltData.setTraceaccount(traceaccount); // 追溯账号
                            List<TraceDataItem> ltDataList = new ArrayList<TraceDataItem>();
                            TraceDataItem ycd = new TraceDataItem();
                            ycd.setKey("原产地");
                            ycd.setFiledName("countryOrigin");
                            ycd.setFiledType("text");
                            ycd.setVal("");    // 溯源信息原产地
                            ltDataList.add(ycd);
                            TraceDataItem ppckck = new TraceDataItem();
                            ppckck.setKey("品牌出库仓库");
                            ppckck.setFiledName("exWarehouse");
                            ppckck.setFiledType("text");
                            ppckck.setVal("成品库");
                            ltDataList.add(ppckck);
                            TraceDataItem shck = new TraceDataItem();
                            shck.setKey("收货仓库");
                            shck.setFiledName("receivingWarehouse");
                            shck.setFiledType("text");
                            shck.setVal("北京京东世纪信息技术有限公司");
                            ltDataList.add(shck);
                            ltData.setDataList(ltDataList);    //追溯流通信息详情
                            ltData.setDataType(17137);    //追溯流通信息环节
                            ltData.setSkuid(1000L);    //京东商品ID
                            ltData.setIndustryCode(industryCode);    //行业编码
                            record.add(ltData);
                            /** 流通信息17137 End */
                            /** 生产信息17138(生产批号、生产日期、保质期、有效日期) Start */
                            TraceData scData= new TraceData();
                            scData.setUniquecode(uniquecode); // 追溯编码
                            scData.setTraceaccount(traceaccount); // 追溯账号
                            List<TraceDataItem> scdataList = new ArrayList<TraceDataItem>();
                            TraceDataItem scpcItem = new TraceDataItem();
                            scpcItem.setKey("生产批号");
                            scpcItem.setFiledName("BatchNumber");
                            scpcItem.setFiledType("text");
                            scpcItem.setVal("生产批次");
                            scdataList.add(scpcItem);
                            TraceDataItem scrqItem = new TraceDataItem();
                            scrqItem.setKey("生产日期");
                            scrqItem.setFiledName("produceDate");
                            scrqItem.setFiledType("text");
                            scrqItem.setVal("生产日期");
                            scdataList.add(scrqItem);
                            TraceDataItem bzqItem = new TraceDataItem();
                            bzqItem.setKey("保质期");
                            bzqItem.setFiledName("shelfLife");
                            bzqItem.setFiledType("text");
                            bzqItem.setVal("730");
                            scdataList.add(bzqItem);
                            TraceDataItem yxrqItem = new TraceDataItem();
                            yxrqItem.setKey("有效日期");
                            yxrqItem.setFiledName("effectiveDate");
                            yxrqItem.setFiledType("text");
                            yxrqItem.setVal("有效日期");
                            scdataList.add(yxrqItem);
                            scData.setDataList(scdataList);    //追溯生产信息详情
                            scData.setDataType(17138);    //追溯生产信息环节
                            scData.setSkuid(1000L);    //京东商品ID
                            scData.setIndustryCode(industryCode);    //行业编码
                            record.add(scData);
                            /** 生产信息17138(生产批号、生产日期、保质期、有效日期) End */
                            /** 商品信息17139(产品检验报告)Start */
                            TraceData spData= new TraceData();
                            spData.setUniquecode(uniquecode); // 追溯编码
                            spData.setTraceaccount(traceaccount); // 追溯账号
                            spData.setDataType(17139);    //追溯商品信息环节
                            spData.setSkuid(1000L);    //京东商品ID
                            spData.setIndustryCode(industryCode);    //行业编码
                            List<TraceDataItem> spDataList = new ArrayList<TraceDataItem>();
//                                TraceDataItem ppmcItem = new TraceDataItem();
//                                ppmcItem.setKey("品牌名称");
//                                ppmcItem.setFiledName("brandName");
//                                ppmcItem.setFiledType("text");
//                                ppmcItem.setVal(jdSuyuanGoods.getBrandName());
//                                spDataList.add(ppmcItem);
                            TraceDataItem xlItem = new TraceDataItem();
                            xlItem.setKey("系列");
                            xlItem.setFiledName("series");
                            xlItem.setFiledType("text");
                            xlItem.setVal("产品系列");
                            spDataList.add(xlItem);
                            TraceDataItem dwItem = new TraceDataItem();
                            dwItem.setKey("段位");
                            dwItem.setFiledName("goodsLevel");
                            dwItem.setFiledType("text");
                            dwItem.setVal("产品段位");
                            spDataList.add(dwItem);
                            spData.setDataList(spDataList);    //追溯商品信息详情
                            record.add(spData);
                            /** 商品信息17139(产品检验报告)End */
                            /** 检测信息17140(产品检验报告)Start */
                            TraceData jyData= new TraceData();
                            jyData.setUniquecode(uniquecode); // 追溯编码
                            jyData.setTraceaccount("haiwangshipin"); // 追溯账号
                            List<TraceDataItem> jyDataList = new ArrayList<TraceDataItem>();
                            TraceDataItem zjbgItem = new TraceDataItem();
                            zjbgItem.setKey("产品质检报告");
                            zjbgItem.setFiledName("inspectionReportImg");
                            zjbgItem.setFiledType("img");
                            zjbgItem.setVal("检测报告httpsURL地址");// 产品质检报告
                            jyDataList.add(zjbgItem);
                            jyData.setDataList(jyDataList);    //追溯检测信息详情
                            jyData.setDataType(17140);    //追溯检测信息环节
                            jyData.setSkuid(1000L);    //京东商品ID
                            jyData.setIndustryCode(industryCode);    //行业编码
                            record.add(jyData);
                            /** 检测信息17140(产品检验报告)End */
                        }
                        JdClient client = new DefaultJdClient("https://api.jd.com/routerjson", accessToken.getAccessToken(), appKey, appSecret);
                        BtBlockchainMiddleTraceDataVendorServiceGateWayInsertBatchRequest request = new BtBlockchainMiddleTraceDataVendorServiceGateWayInsertBatchRequest();
                        request.setRecord(record);
                        BtBlockchainMiddleTraceDataVendorServiceGateWayInsertBatchResponse response = client.execute(request);
                        // // 打印上传数据结果,依此判断是否提交成功
                        System.out.println(response.getMsg());
                    }
                }
            }else {
                return AjaxResult.error("访问令牌不存在");
            }
            return AjaxResult.success("执行成功"); 
            
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("运行出现异常:",e.getMessage());
        }
    }

 

六、上传数据是遇到的一些坑

  问题1:应用未发布之前,SDK方式只能提交一次,不能循环提交多次,如果批量上传,需要发布应用。

  问题2:如果record的list超过限制也会报错,请合理分割list进行上传。

  问题3:如果报时间差异比较大,看下自己服务器和京东服务器时间是否存在误差。误差时间不能超过10分钟。

    京东服务器时间查看:https://api.m.jd.com/client.action?functionId=queryMaterialProducts&client=wh5

  问题4:检验报告的URL,一定要外网测试是否能装车访问,要用https。

  错误详解:https://jos.jd.com/faqdetail?listId=447&itemId=1805 

 

  还有千万千万不要用API HTTP方式上传,会遇见更多的问题,我没搞通。

  友情提示:最好把应用信息、请求信息、访问令牌信息,都存到数据库里,直接调用获取即可。

  

posted @ 2022-03-31 10:11  小温2597  阅读(260)  评论(0编辑  收藏  举报