今天使用Java去访问顺丰的开放平台时,JSON转换一直不成功,最终发现是

可以看到这里是

"apiResultData": "{\"success\": .........

它是以 " 开头的!!!如果是对象的话,那么json是这样的:

"address": {"street": "123 Main St","city": "Anytown","state": "CA","zip": "12345"}

对象是以 { 开头 !!!
然后我一天的bug都是因为,我的接收对象使用了

 private static class RouteQueryResponse {public String apiResponseID;public String apiErrorMsg;public String apiResultCode;public ApiResultData apiResultData;
}

这里的apiResultData应该是String类型

那么言归正传,这里是要讲Java连接顺丰开放平台,那么首先是需要认证,认证的话 顺丰认证 有两种方式,OAuth2 和 数字签名,这里我实践发现,第二种一直是服务不可用,所以这里只能用前一种。

看一下官网的请求示例

他发的请求是

https://sfapi-sbox.sf-express.com/oauth2/accessToken?partnerID=XXXXXXXX&grantType=password&secret=0705GuswG6BwiTTEbYMkIkZHxxxxxxxxx

所以我们只要拼接一下即可。
然后他响应成功是返回accessToken,我们直接存到缓存里即可,后面请求其他接口必须使用这个accessToken

public String SFToken(Object request) throws IOException {// TODO SF-获取签名-数字签名认证说明//目前是测试方式获得String url = "https://sfapi-sbox.sf-express.com/oauth2/accessToken?partnerID=" + partnerId + "&grantType=password&secret=" + verifyTestCode;HttpPost post = new HttpPost(url);post.setHeader("Content-type", "application/x-www-form-urlencoded;charset=UTF-8");String response = httpClient.execute(post);log.info("#sf-Token response, {}", JsonUtils.toStr(response));SFTokenResponseBody str = JsonUtils.fromStr(response, SFTokenResponseBody.class);//把accessToken放到cache中,2小时cacheManager.put(CommonCacheManager.CacheType.SF_ACCESS_TOKEN_V2, "accessTokenv2", str.getAccessToken(), 120 * 60);return str.getAccessToken();}
@Data
@AllArgsConstructor
public class SFTokenResponseBody {String accessToken;String refreshToken;public SFTokenResponseBody(){}
}

partnerIdverifyTestCode都是你注册顺丰时发给你的。
httpClient和JsonUtils均可使用其他的平替
放到cache中的那一句代码可以自己进行修改

这只是认证,然后拿到了accessToken,可以去请求其他接口。

这里先看一下通用的方法:

 public void setCommonParams(HttpPost httpPost, SFCommonReq req) throws UnsupportedEncodingException {httpPost.setHeader("Content-type", "application/x-www-form-urlencoded;charset=UTF-8");List<NameValuePair> params = new ArrayList<>();params.add(new BasicNameValuePair("accessToken", req.getAccessToken()));params.add(new BasicNameValuePair("partnerID", req.getPartnerID()));params.add(new BasicNameValuePair("requestID", req.getRequestID()));params.add(new BasicNameValuePair("serviceCode", req.getServiceCode()));params.add(new BasicNameValuePair("timestamp", req.getTimestamp()));params.add(new BasicNameValuePair("msgData", req.getMsgData()));UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");httpPost.setEntity(entity);}

顺丰下订单

官网是
下订单
看到这里的
公共请求,我们需要创建一个这样的类,使用内部类即可。
然后响应的json也需要一个对象接收。
然后代码如下:


public SFOrderResponseBody orderV2(int orderId, int cityId, ExpressAddressDTO expressAddressDTO) throws IOException {// SF-下订单接口-速运类APISFCommonReq req = SFCommonReq.builder().partnerID(partnerId).requestID(UUID.randomUUID().toString()).serviceCode(serviceCode.makeOrder).timestamp(String.valueOf(System.currentTimeMillis())).accessToken(getOrGenerateToken()) //这里只是从缓存获取accessToken.build();HashMap<String, String> msgData = new HashMap<>();msgData.put("language", "zh-CN");LinkedList<CargoDetails> cargoDetails = new LinkedList<>();CargoDetails details = new CargoDetails();details.setName(expressAddressDTO.getName());cargoDetails.add(details);ContactInfo contactInfo = new ContactInfo();contactInfo.setAddress(expressAddressDTO.getAddress());contactInfo.setTel(expressAddressDTO.getPhone());contactInfo.setCity(districtService.findById(cityId).getName());contactInfo.setContact(expressAddressDTO.getName());//只能发到中国contactInfo.setCountry("CN");contactInfo.setCounty(expressAddressDTO.getDistrictName());contactInfo.setMobile(expressAddressDTO.getPhone());// "postCode":"580058",不用填//找到省contactInfo.setProvince(districtService.findByCode(districtService.findById(cityId).getCode()).getName());msgData.put("cargoDetails", String.valueOf(cargoDetails));msgData.put("contactInfoList", String.valueOf(Collections.singletonList(contactInfo)));msgData.put("orderId", String.valueOf(orderId));//顺丰特快msgData.put("expressTypeId", String.valueOf(1));//1:寄方付 2:收方付 3:第三方付msgData.put("payMethod", String.valueOf(2));msgData.put("isReturnRoutelabel", String.valueOf(1));req.setMsgData(JsonUtils.toStr(msgData));//沙箱URLHttpPost httpPost = new HttpPost("https://sfapi-sbox.sf-express.com/std/service");setCommonParams(httpPost, req);log.info("发送的请求是:" + httpPost);String s = httpClient.execute(httpPost);try {// 解析 JSON 格式的响应createOrderResponse cor = JsonUtils.fromStr(s, createOrderResponse.class);//特殊处理createOrderResponse.ApiResultData apiResultData = JsonUtils.fromStr(cor.getApiResultData(), createOrderResponse.ApiResultData.class);if (!"A1000".equals(cor.getApiResultCode())) {//请求失败log.error("请求失败,响应是:" + s);SFOrderResponseBody sfOrderResponseBody = new SFOrderResponseBody();sfOrderResponseBody.setRetry(true);sfOrderResponseBody.setOrderId(s);return sfOrderResponseBody;}//请求成功Boolean success = apiResultData.getSuccess();SFOrderResponseBody sfOrderResponseBody = new SFOrderResponseBody();if (success) {sfOrderResponseBody.setOrderId(apiResultData.getMsgData().getOrderId());sfOrderResponseBody.setRetry(false);} else {sfOrderResponseBody.setRetry(true);}return sfOrderResponseBody;} catch (Exception e) {e.printStackTrace();SFOrderResponseBody sfOrderResponseBody = new SFOrderResponseBody();sfOrderResponseBody.setRetry(true);sfOrderResponseBody.setOrderId("异常是" + e + ",响应是" + s);return sfOrderResponseBody;}}@Data@Builder@AllArgsConstructor@NoArgsConstructorprivate static class SFCommonReq {String partnerID;String requestID;String serviceCode;String timestamp;String accessToken;String msgData;}private static class serviceCode {//下单private static final String makeOrder = "EXP_RECE_CREATE_ORDER";//查询路径private static final String route = "EXP_RECE_SEARCH_ROUTES";//查询订单private static final String searchOrder = "EXP_RECE_SEARCH_ORDER_RESP";private static final String print = "COM_RECE_CLOUD_PRINT_WAYBILLS";private static final String cloudPrint = "COM_PUSH_CLOUD_PRINT_WAYBILLS";}@Dataprivate static class CargoDetails {@NotNullprivate BigDecimal amount;@NotNullprivate BigDecimal count;@NotNullprivate String currency;private String goodPrepardNo;private String hsCode;@NotNullprivate String name;private String productRecordNo;@NotNullprivate String sourceArea;private String taxNo;@NotNullprivate String unit;@NotNullprivate BigDecimal weight;}public class ExpressAddressDTO implements Serializable {Integer districtId;String districtName;String phone;String address;String name;
}@Dataprivate static class ContactInfo {private String address;private String city;private String contact;private Integer contactType;private String country;private String county;private String mobile;private String postCode;private String province;private String tel;}@Data   //这个就是接收的对象private static class createOrderResponse {public String apiErrorMsg;public String apiResponseID;public String apiResultCode;public String apiResultData;@Dataprivate static class ApiResultData {public Boolean success;public String errorCode;public String errorMsg;public MsgData msgData;@Dataprivate static class MsgData {public String orderId;public String originCode;public String destCode;public Integer filterResult;public String remark;public String url;public String paymentLink;public Boolean isUpstairs;public Boolean isSpecialWarehouseService;public String mappingMark;public String agentMailno;public Object returnExtraInfoList;public List<WaybillNoInfo> waybillNoInfoList;public List<RouteLabelInfo> routeLabelInfo;public Object contactInfoList;@Dataprivate static class WaybillNoInfo {public Integer waybillType;public String waybillNo;}@Dataprivate static class RouteLabelInfo {public String code;public RouteLabelData routeLabelData;public String message;@Dataprivate static class RouteLabelData {public String waybillNo;public String sourceTransferCode;public String sourceCityCode;public String sourceDeptCode;public String sourceTeamCode;public String destCityCode;public String destDeptCode;public String destDeptCodeMapping;public String destTeamCode;public String destTeamCodeMapping;public String destTransferCode;public String destRouteLabel;public String proName;public String cargoTypeCode;public String limitTypeCode;public String expressTypeCode;public String codingMapping;public String codingMappingOut;public String xbFlag;public String printFlag;public String twoDimensionCode;public String proCode;public String printIcon;public String abFlag;public String destPortCode;public String destCountry;public String destPostCode;public String goodsValueTotal;public String currencySymbol;public String cusBatch;public String goodsNumber;public String errMsg;public String checkCode;public String proIcon;public String fileIcon;public String fbaIcon;public String icsmIcon;public String destGisDeptCode;public Object newIcon;}}}}}

路由查询接口

和上面类似,也是创建json的接收类,然后设置一下请求,这里不放完整代码了,最后放整个类的代码

//沙箱环境String url = "https://sfapi-sbox.sf-express.com/std/service";HttpPost post = new HttpPost(url);SFCommonReq req = SFCommonReq.builder().partnerID(partnerId).requestID(UUID.randomUUID().toString()).serviceCode(serviceCode.route).timestamp(String.valueOf(System.currentTimeMillis())).accessToken(getOrGenerateToken()).build();HashMap<String, String> msgData = new HashMap<>();msgData.put("language", "zh-CN");msgData.put("trackingType", String.valueOf(1));msgData.put("trackingNumber", mailNo);req.setMsgData(JsonUtils.toStr(msgData));setCommonParams(post, req);log.info("发送的请求是:" + post);String s = httpClient.execute(post);try {// 解析 JSON 格式的响应RouteQueryResponse rqr = JsonUtils.fromStr(s, RouteQueryResponse.class);if (!"A1000".equals(rqr.getApiResultCode())) {//请求失败log.error("请求失败,响应是:" + s);SFResponse<SFRouteInfos> response = new SFResponse<>();response.setBody(null);SFResponseHead head = new SFResponseHead();head.setCode("500");head.setMessage("请求失败了,返回的响应是" + s);response.setHead(head);return response;}//请求成功//特殊处理RouteQueryResponse.ApiResultData apiResultData = JsonUtils.fromStr(rqr.getApiResultData(), RouteQueryResponse.ApiResultData.class);

订单结果查询接口

链接

//沙箱环境String url = "https://sfapi-sbox.sf-express.com/std/service";HttpPost post = new HttpPost(url);SFCommonReq req = SFCommonReq.builder().partnerID(partnerId).requestID(UUID.randomUUID().toString()).serviceCode(serviceCode.searchOrder).timestamp(String.valueOf(System.currentTimeMillis())).accessToken(getOrGenerateToken()).build();OrderSearchReqDto orderSearchReqDto = new OrderSearchReqDto();orderSearchReqDto.setOrderId(String.valueOf(orderId));orderSearchReqDto.setSearchType(String.valueOf(1));orderSearchReqDto.setLanguage("zh-CN");req.setMsgData(JsonUtils.toStr(orderSearchReqDto));setCommonParams(post, req);String s = httpClient.execute(post);
@Data
private static class OrderSearchReqDto {String orderId;//查询类型:1正向单 2退货单String searchType;//响应报文的语言, 缺省值为zh-CNString language;}

顺丰云打印

链接是 云打印

这里采用的是同步,也就是访问了接口,顺丰就返回文件url

String url = "https://sfapi-sbox.sf-express.com/std/service";HttpPost post = new HttpPost(url);SFCommonReq req = SFCommonReq.builder().partnerID(partnerId).requestID(UUID.randomUUID().toString()).serviceCode(serviceCode.print).timestamp(String.valueOf(System.currentTimeMillis())).accessToken(getOrGenerateToken()).build();PrintTemplate template = PrintTemplate.builder().sync(true) //设置同步.templateCode(templateCode).version("2.0").build();Document document = new Document();document.setMasterWaybillNo(String.valueOf(orderId));LinkedList<Document> documents = new LinkedList<>();template.setDocuments(documents);req.setMsgData(JsonUtils.toStr(template));setCommonParams(post, req);String s = httpClient.execute(post);@Data@AllArgsConstructor@NoArgsConstructor@Builderprivate static class PrintTemplate {//关联云打印接口后,点击查看,可在接口详情页获取模板编码private String templateCode;//版本号,传固定值:2.0private String version;//pdf格式private String fileType;private List<Document> documents;//true: 同步,false: 异步,默认异步private Boolean sync;private ExtJson extJson;}@Data@AllArgsConstructor@NoArgsConstructorprivate static class Document {private String masterWaybillNo;private String branchWaybillNo;private String backWaybillNo;private String seq;private String sum;private Boolean isPrintLogo;private String remark;private String waybillNoCheckType;private String waybillNoCheckValue;private String customData;}

Java连接顺丰开放平台相关推荐

  1. Java对接微盟开放平台

    Java对接微盟开放平台 1. 微盟开放平台概述 1.1 微盟云简介 1.2 微盟云接入方式 1.3 微盟云能力介绍 2. 微盟授权商户自用对接 2.1 微盟授权业务需求 2.2 微盟商户授权流程 2 ...

  2. php开放平台,顺丰开放平台API PHP SDK demo

    顺丰开放平台Api PHP SDK demo 引用 对接前期工作注册 提交接入申请 接口初始化配置,获得 app_id 和app_secret 完成测试环境测试 进入生产使用 接入注意事项申请令牌 ( ...

  3. 【百度智能云】教程:连接百度ai开放平台api接口并完成语音识别的任务

    前言与介绍 本文章介绍了如何在Pycharm上用python语言简单的对连接百度ai开放平台的语音识别功能api端口的调用,并在代码里实现了现录音识别内容. 平台与相关工具 windows10.Pyc ...

  4. 微信第三方扫描登录 java源代码_微信开放平台基于网站应用授权登录源码(java)...

    1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数: 2. 通过code参数加上AppID和AppSecret等,通过 ...

  5. Java调用百度AI开放平台API

    百度AI开放平台 百度AI开放平台是全球领先的人工智能服务平台,面向开发者及企业开放120多项全球领先的AI能力和软硬一体组件,并提供 EasyDL定制化训练平台.对话系统开发平台UNIT.自定义模板 ...

  6. 顺丰开放平台开发者接入指引

    开发者接入主要是接入方通过使用顺丰API方式完成自有系统的对接,在接入方触发业务场景时调用已调试成功的顺丰服务API完成业务请求. 注:专线对接客户请提前联系客户经理确认对接方案后再进行对接. 一.接 ...

  7. Java实现抖音开放平台二维码授权功能

    一.在yml中添加抖音开放平台的账号基本信息 # 抖音开放平台配置信息 dy:clientKey: #抖音开放平台keyclientSecret: #抖音开放平台密钥scope: data.exter ...

  8. 微信用户绑定java实例_微信开放平台 帐号管理 绑定在同一个开放平台帐号下的公众号及小程序让用户unionid一致...

    第三方平台在获得此权限后,可以代替已授权的公众号/小程序创建开放平台帐号或进行绑定/解绑操作. 绑定在同一个开放平台帐号下的公众号及小程序,用户unionid一致.开发者可调用"获取用户基本 ...

  9. java对接钉钉开放平台接口_后端项目与钉钉接口(第三方)对接要注意的问题...

    开发前所需 推荐postman测试,这工具谁用谁知道. 1:需要管理员在钉钉后台给予开发者 开发者权限 2:开发者权限给予后,开发者需要进入:https://open-dev.dingtalk.com ...

最新文章

  1. [转]REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR
  2. C++ Primer 5th笔记(2)chapter 2变量和基本类型:constexpr 、auto、类型别名、decltype
  3. 一步步学习微软InfoPath2010和SP2010--第三章节--表单设计基础:处理InfoPath布局、控件和视图(4)--控件属性功能区...
  4. 2015/12/15--Document对象
  5. 【刘晓燕语法长难句】 并列句
  6. 关于SBUS信号在单片机中的一些个人理解
  7. vulnhub-DC-9靶机渗透记录(适合新手详细版)
  8. 3.实现蛇和基本游戏界面
  9. 高中补习数学:导数与函数的综合问题(2019年测试题)
  10. 和黄医药宣布获霸菱亚洲投资基金1亿美元股权投资
  11. 美团、飞猪基础架构组实习经历分享
  12. 14、odoo的仪表板
  13. android圆角glide,使用Glide加载圆角矩形图片、圆形图片
  14. 张正友棋盘法定标--Matlab【Camera Calibration Toolbox】
  15. 乌镇互联网大会 阿里云飞天当选世界互联网代表性领先科技成果
  16. 选择适合的Node.js授权认证策略
  17. 解析B2C电子商务网站系统架构
  18. 琼斯是计算体心立方弹性模量_固体物体第三章习题
  19. java基本数据_Java基本数据类型-Java基本数据类型大小-嗨客网
  20. 数据结构-3 堆积木

热门文章

  1. 8个Python免费网站,一周熟练Python,知道就是赚到
  2. 怎样锻炼孩子的意志力?
  3. c语言的零碎小知识~
  4. 游标(概念、优点、分类、静态游标的使用(显示游标(显示游标的属性、遍历显示游标、显示游标的FOR循环)、隐式游标(隐式游标的属性))、动态游标的使用、静态游标和动态游标的区别、更新或删除当前游标数据
  5. 计算机中实时与在线的关系,为什么新版QQ不再区分手机在线和电脑在线
  6. ZZNUOJ_用C语言编写程序实现1539:读数字(附完整源码)
  7. 深度学习+知识图谱,一个不小心就顶流的话题
  8. 想要提高生产效率?做好物料齐套管理很关键
  9. Asp.net mvc 强类型View
  10. 修改excel图表中的“系列一”