springboot接入顺丰
springBoot集成顺丰接口
·
1. 注册及申请
注册及申请自己的顾客编码及校验码
地址
2. 下载sdk及引入
<dependency>
<groupId>com.sf</groupId>
<artifactId>SF-CSIM-EXPRESS-SDK</artifactId>
<version>2.1.7</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/SF-CSIM-EXPRESS-SDK-V2.1.7.jar</systemPath>
</dependency>
3.代码
3.1 实体类
吐槽一下 都提供sdk了 也不给提供参数类,这里只创建几个关键的,没用到了比如报关什么都没建立
package com.shimao.iibs.common.sf.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.shimao.iibs.common.sf.ExpredssTypeEnum;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Data
//@FieldDefaults(level = lombok.AccessLevel.PRIVATE)
@TableName(value = "sf_order")
@Accessors(chain = true)
public class Order {
// ==================== 必填字段 ====================
/**
* id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 客户订单号(必填)
*/
@NotBlank(message = "订单号不能为空")
@Size(max = 64, message = "订单号长度不能超过64")
@TableField(value = "order_id")
private String orderId;
/**
* 运单号
*/
@TableField(value = "waybill_no")
private String waybillNo;
/**
* 付款方式,支持以下值: 1:寄方付 2:收方付 3:第三方付
* 字典 sf_pay_method
*/
@Min(value = 1, message = "必须为1-3")
@Max(value = 3, message = "必须为1-3")
@TableField(value = "pay_method")
private Integer payMethod = 1;
/**
* 收寄双方信息列表(必填)
*/
@NotEmpty(message = "联系人信息不能为空")
@TableField(exist = false)
private List<ContactInfo> contactInfoList;
/**
* 托寄物信息(必填)
*/
@NotEmpty(message = "托寄物信息不能为空")
@TableField(exist = false)
private List<CargoDetail> cargoDetails;
/**
* 快件产品类别代码
* 字典 sf_expredss_type
*/
@NotNull(message = "快件产品类别代码不能为空")
@TableField(value = "express_type_id")
private Integer expressTypeId = ExpredssTypeEnum.T4_1.getCode();
/**
* 快件产品类别名称
*/
@NotNull(message = "快件产品类别名称")
@TableField(value = "express_type_name")
private Integer expressTypeName;
/**
* 响应报文的语言(必填,默认zh-CN)
*/
@NotBlank(message = "语言不能为空")
@Size(max = 10, message = "语言长度不能超过10")
@Pattern(regexp = "zh-CN|zh-TW|zh-HK|zh-MO|en", message = "不支持的语种类型")
@TableField(exist = false)
private String language = "zh-CN";
/**
* 是否返回路由标签(必填,默认1)
*/
@NotNull(message = "是否返回路由标签不能为空")
@Min(value = 0, message = "必须为0或1")
@Max(value = 1, message = "必须为0或1")
@TableField(exist = false)
private Integer isReturnRoutelabel = 1;
/**
* 顺丰月结卡号(月结支付时必填)
*/
@Size(max = 20, message = "月结卡号长度不能超过20")
@TableField(value = "monthly_Card")
private String monthlyCard;
/**
* 订单货物总重量(子母件/郑州空港海关必填)
*/
@Digits(integer = 17, fraction = 5, message = "总重量格式不正确")
@DecimalMin(value = "0.001", inclusive = false, message = "总重量必须大于0")
@TableField(exist = false)
private BigDecimal totalWeight = new BigDecimal(0.5);
/**
* 上门取件开始时间
* 要求上门取件开始时间, 格式: YYYY-MM-DD HH24:MM:SS, 示例: 2012-7-30 09:30:00 ,
* 若该字段没有赋值,默认开始时间为当前时间,(可配合上门取件截止时间pickupAppointEndTime扩展字段备注进行下发,
* 若没有给截止时间则系统默认1小时的截止时间)
*/
@TableField(value = "send_start_tm")
private Date sendStartTm;
/**
* 状态
* 字典 sf_order_status
*/
@TableField(value = "status")
private String status;
/**
* 备注
*/
@Size(max = 100, message = "长度不能超过100")
@TableField(value = "remark")
private String remark;
/**
* 是否通过手持终端 通知顺丰收派 员上门收件,支持以下值: 1:要求 0:不要求 (默认0)
*/
@Min(value = 0, message = "必须为0或1")
@Max(value = 1, message = "必须为0或1")
@TableField(value = "is_docall")
private Integer isDocall = 1;
/**
* 寄件人id
*/
@TableField(value = "send_contact_id")
private String sendContactId;
/**
* 收件人id
*/
@TableField(value = "receive_contact_id")
private String receiveContactId;
/**
* 邮寄内容
*/
@TableField(value = "cargo_item")
private String cargoItem;
/**
* 总费用
*/
@TableField(exist = false)
private BigDecimal totalWaybill;
/**
* 请求报文
*/
@TableField(value = "params")
private String params;
/**
* 结果报文
*/
@TableField(value = "result")
private String result;
/**`
* 创建者
*/
@TableField(value = "create_by")
private String createBy;
/**
* 创建用户
*/
@TableField(exist = false)
private String createName;
/**
* 创建时间
*/
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
// ==================== 取消订单用 ====================
/**
* 客户订单操作标识: 1:确认 (丰桥下订单接口默认自动确认,不需客户重复确认,该操作用在其它非自动确认的场景) 2:取消
*/
@TableField(exist = false)
private Integer dealType = 1;
// ==================== 取消订单用 ====================
// ==================== 查订单用 ====================
/**
* 查询类型:1正向单 2退货单
*/
@Size(max = 2, message = "查询类型:1正向单 2退货单")
@TableField(exist = false)
private String searchType = "1";
// ==================== 查订单用 ====================
// ==================== 清单运费 ====================
/**
* 费用清单
*/
@TableField(exist = false)
private List<Waybill> waybillList;
// ==================== 清单运费 ====================
// ==================== 路由查询 ====================
/**
* 查询号类别:
* 1:根据顺丰运单号查询,trackingNumber将被当作顺丰运单号处理
* 2:根据客户订单号查询, trackingNumber将被当作客户订单号处理
*/
@TableField(exist = false)
private Integer trackingType = 2;
/**
* 查询号:
* 1、如果trackingType=1,则此值为顺丰运单号
* 2、如果trackingType=2,则此值为客户订单号
*/
@TableField(exist = false)
private List<String> trackingNumber;
/**
* 路由查询结果
*/
@TableField(exist = false)
private List<Routes> routesList;
// ==================== 路由查询 ====================
/**
* 包裹数(默认1)
*/
@Min(value = 1, message = "必须大于0")
@TableField(exist = false)
private Integer parcelQty = 1;
/**
* 是否返回二维码(默认0)
*/
@Min(value = 0, message = "必须为0或1")
@Max(value = 1, message = "必须为0或1")
@TableField(exist = false)
private Integer isReturnQRCode = 0;
/**
* 是否返回签回单路由标签(默认0)
*/
@Min(value = 0, message = "必须为0或1")
@Max(value = 1, message = "必须为0或1")
@TableField(exist = false)
private Integer isReturnSignBackRouteLabel = 0;
/**
* 是否使用统一面单号(默认0)
*/
@Min(value = 0, message = "必须为0或1")
@Max(value = 1, message = "必须为0或1")
@TableField(exist = false)
private Integer isUnifiedWaybillNo = 0;
/**
* 是否生成运单号(默认1)
*/
@Min(value = 0, message = "必须为0或1")
@Max(value = 1, message = "必须为0或1")
@TableField(exist = false)
private Integer isGenWaybillNo = 1;
/**
* 头程运单号(郑州空港海关必填)
*/
//private String inProcessWaybillNo;
/**
* 订单货物总长
*/
//private BigDecimal totalLength;
/**
* 订单货物总宽
*/
//private BigDecimal totalWidth;
/**
* 订单货物总高
*/
//private BigDecimal totalHeight;
/**
* 订单货物总体积
*/
//private BigDecimal totalVolume;
/**
* 商品总净重
*/
//private BigDecimal totalNetWeight;
}
package com.shimao.iibs.common.sf.domain;
import lombok.Data;
/**
* 公共响应参数
*/
@Data
public class ApiResultData {
/**
* 请求是否成功(必填)
* true-请求成功,false-请求失败
*/
private Boolean success;
/**
* 错误编码(必填)
* S0000表示成功
*/
private String errorCode;
/**
* 错误描述(必填)
*/
private String errorMsg;
/**
* 顺丰运单号
*/
private String waybillNo;
/**
* 请求信息
*/
private String params;
/**
* 返回的详细数据(必填)
* 使用泛型适应不同数据类型
*/
private String msgData;
}
package com.shimao.iibs.common.sf.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.*;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 顺丰订单货物明细 仅下单使用 不存库
*/
@Data
@Accessors(chain = true)
public class CargoDetail implements Serializable {
/**
* 货物名称(必填,电子运单必填)
*/
@NotBlank(message = "货物名称不能为空")
@Size(max = 128, message = "货物名称长度不能超过128")
private String name;
/**
* 货物数量(跨境件报关必填)
*/
@Min(value = 1, message = "货物数量必须大于0")
@Max(value = 99999, message = "货物数量不能超过99999")
private Integer count;
/**
* 货物单位重量(跨境件报关必填)
*/
@Digits(integer = 16, fraction = 3, message = "重量格式不正确")
@DecimalMin(value = "0.001", message = "重量必须大于0")
private BigDecimal weight;
/**
* 货物单位(跨境件报关必填)
*/
@Size(max = 30, message = "货物单位长度不能超过30")
private String unit;
/**
* 货物单价(跨境件报关必填)
*/
//@Digits(integer = 17, fraction = 3, message = "金额格式不正确")
//@DecimalMin(value = "0.001", message = "金额必须大于0")
//private BigDecimal amount;
/**
* 货物单价的币别(跨境件报关必填)
*/
//@Size(max = 5, message = "币别长度不能超过5")
//private String currency;
/**
* 原产地国别(跨境件报关必填)
*/
//@Size(max = 5, message = "原产地国别长度不能超过5")
//private String sourceArea;
}
package com.shimao.iibs.common.sf.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.*;
import java.util.Date;
/**
* 收发人信息
*/
@Data
@Accessors(chain = true)
@TableName(value = "sf_contactInfo")
public class ContactInfo {
/**
* id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* sf_order表主键
*/
@TableField(value = "marter_id")
private Long marterId;
/**
* 客户订单号(必填)
*/
@NotBlank(message = "订单号不能为空")
@Size(max = 64, message = "订单号长度不能超过64")
@TableField(value = "order_id")
private String orderId;
/**
* 运单号
*/
@TableField(value = "waybill_no")
private String waybillNo;
/**
* 地址类型:1-寄件方信息,2-到件方信息(必填)
*/
@NotNull(message = "地址类型不能为空")
@Min(value = 1, message = "地址类型必须为1或2")
@Max(value = 2, message = "地址类型必须为1或2")
@TableField(value = "contact_type")
private Integer contactType;
/**
* 联系人(条件必填)
*/
@TableField(value = "contact")
private String contact;
/**
* 公司名称(条件必填)
*/
@TableField(value = "company")
private String company;
/**
* 手机(条件必填:tel和mobile必填其中一个)
*/
@TableField(value = "mobile")
private String mobile;
/**
* 电话(条件必填:tel和mobile必填其中一个)
*/
//private String tel;
/**
* 国家或地区代码 例如:内地件CN 香港852(必填)
*/
@NotBlank(message = "国家代码不能为空")
@Size(max = 30, message = "国家代码长度不能超过30")
@TableField(value = "country")
private String country = "CN";
/**
* 所在省级行政区名称(非必填)
*/
@Size(max = 30, message = "省份长度不能超过30")
@TableField(value = "province")
private String province;
/**
* 所在地级行政区名称(非必填)
*/
@Size(max = 100, message = "城市长度不能超过100")
@TableField(value = "city")
private String city;
/**
* 所在县/区级行政区名称(非必填)
*/
@Size(max = 30, message = "区县长度不能超过30")
@TableField(value = "county")
private String county;
/**
* 详细地址(必填)
* 详细地址,若有四级行政区划,如镇/街道等信息可拼接至此字段,格式样例:镇/街道+详细地址。
* 若province/city 字段的值不传,此字段必须包含省市信息,避免影响原寄地代码识别,
* 如:广东省深圳市福田区新洲十一街万基商务大厦10楼;此字段地址必须详细,否则会影响目的地中转识别
*/
@NotBlank(message = "详细地址不能为空")
@Size(max = 200, message = "地址长度不能超过200")
@TableField(value = "address")
private String address;
/**
* 备注
*/
@Size(max = 100, message = "长度不能超过100")
@TableField(value = "remark")
private String remark;
/**`
* 创建者
*/
@TableField(value = "create_by")
private String createBy;
/**
* 创建用户
*/
@TableField(exist = false)
private String createName;
/**
* 创建时间
*/
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
/**
* 邮编(条件必填:跨境件必填,中国内地、港澳台互寄除外)
*/
//@Size(max = 25, message = "邮编长度不能超过25")
//private String postCode;
/**
* 证件类型(非必填)
*/
//@Size(max = 200, message = "证件类型长度不能超过200")
//private String certType;
/**
* 证件号码(非必填)
*/
//@Size(max = 1000, message = "证件号码长度不能超过1000")
//private String certNo;
/**
* 邮箱地址(非必填)
*/
//@Email(message = "邮箱格式不正确")
//@Size(max = 200, message = "邮箱长度不能超过200")
//private String email;
/**
* 税号(非必填)
*/
//@Size(max = 100, message = "税号长度不能超过100")
//private String taxNo;
/**
* 联系人属性(非必填)
*/
//@Pattern(regexp = "01|02", message = "联系人属性必须是01或02")
//@Size(max = 100, message = "联系人属性长度不能超过100")
//private String contactRemark;
}
package com.shimao.iibs.common.sf.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* 路由信息
*/
@Data
@Accessors(chain = true)
@TableName(value = "sf_routes")
public class Routes implements Serializable {
/**
* id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* sf_order表主键
*/
@TableField(value = "marter_id")
private Long marterId;
/**
* 订单id
*/
@TableField(value = "order_id")
private String orderId;
/**
* 运单号
*/
@TableField(value = "waybill_no")
private String waybillNo;
/**
* 路由节点时间
* 格式:YYYY-MM-DD HH24:MM:SS
*/
@TableField(value = "accept_time")
private Date acceptTime;
/**
* 路由节点描述(必填)
*/
@TableField(value = "remark")
private String remark;
/**
* 操作码(必填)
*/
@TableField(value = "op_code")
private String opCode;
/**
* 路由节点地点
*/
@TableField(value = "accept_address")
private String acceptAddress;
/**
* 一级状态编码
*/
@TableField(value = "first_status_code")
private String firstStatusCode;
/**
* 一级状态名称
*/
@TableField(value = "first_status_name")
private String firstStatusName;
/**
* 二级状态编码(必填)
*/
@TableField(value = "secondary_status_code")
private String secondaryStatusCode;
/**
* 二级状态名称(必填)
*/
@TableField(value = "secondary_status_name")
private String secondaryStatusName;
/**`
* 创建者
*/
@TableField(value = "create_by", fill = FieldFill.INSERT)
private String createBy;
/**
* 创建用户
*/
@TableField(exist = false)
private String createName;
/**
* 创建时间
*/
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
}
package com.shimao.iibs.common.sf.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 费用清单
*/
@Data
@TableName(value = "sf_waybill")
public class Waybill implements Serializable {
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* sf_order表主键
*/
@TableField(value = "marter_id")
private Long marterId;
/**
* 订单id
*/
@TableField(value = "order_id")
private String orderId;
/**
* 运单号
*/
@TableField(value = "waybill_no")
private String waybillNo;
/**
* 查费用类型
*/
@TableField(value = "waybill_type")
private String waybillType;
/**
* 查费用名称
*/
@TableField(value = "waybill_name")
private String waybillName;
/**
* 费用金额
*/
@TableField(value = "waybill_value")
private BigDecimal waybillValue;
/**
* 付款类型:1、寄付;2、到付;3、第三方付
* 字典 sf_payment_type
*/
@TableField(value = "payment_type_code")
private String paymentTypeCode;
/**
* 结算类型:1为现结;2为月结
*/
@TableField(value = "settlement_type_code")
private String settlementTypeCode;
/**
* 月结账号
*/
@TableField(value = "customer_acct_code")
private String customerAcctCode;
/**`
* 创建者
*/
@TableField(value = "create_by", fill = FieldFill.INSERT)
private String createBy;
/**
* 创建用户
*/
@TableField(exist = false)
private String createName;
/**
* 创建时间
*/
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
}
3.2 工具类
package com.shimao.iibs.common.sf;
/**
* 快递类型枚举
* sf_expredss_type
*/
public enum ExpredssTypeEnum {
T4_1(1, "T4", "顺丰特快"),
T6_2(2, "T6", "顺丰标快"),
T104_6(6, "T104", "顺丰即日"),
T14_10(10, "T14", "国际小包"),
T9_23(23, "T9", "顺丰国际特惠(文件)"),
T9_24(24, "T9", "顺丰国际特惠(包裹)"),
T7_26(26, "T7", "国际大件"),
T7_29(29, "T7", "国际电商专递-标准"),
T4_30(30, "T4", "三号便利箱(特快)"),
T4_31(31, "T4", "便利封/袋(特快)"),
T4_32(32, "T4", "二号便利箱(特快)"),
T4_33(33, "T4", "岛内件(80CM)"),
T23_35(35, "T23", "物资配送"),
T4_39(39, "T4", "岛内件(110CM)"),
T4_40(40, "T4", "岛内件(140CM)"),
T4_41(41, "T4", "岛内件(170CM)"),
T4_42(42, "T4", "岛内件(210CM)"),
T4_43(43, "T4", "台湾岛内件-批(80CM)"),
T4_44(44, "T4", "台湾岛内件-批(110CM)"),
T4_45(45, "T4", "台湾岛内件-批(140CM)"),
T4_46(46, "T4", "台湾岛内件-批(170CM)"),
T4_47(47, "T4", "台湾岛内件-批(210CM)"),
T4_48(48, "T4", "台湾岛内件店取(80CM)"),
T4_49(49, "T4", "台湾岛内件店取(110CM)"),
T4_50(50, "T4", "千点取60"),
T4_51(51, "T4", "千点取80"),
T4_52(52, "T4", "千点取100"),
T4_53(53, "T4", "电商盒子F1"),
T4_54(54, "T4", "电商盒子F2"),
T4_55(55, "T4", "电商盒子F3"),
T4_56(56, "T4", "电商盒子F4"),
T4_57(57, "T4", "电商盒子F5"),
T4_58(58, "T4", "电商盒子F6"),
SP202_59(59, "SP202", "E顺递"),
T4_60(60, "T4", "顺丰特快(文件)"),
T4_61(61, "T4", "C1类包裹"),
T4_62(62, "T4", "C2类包裹"),
T4_63(63, "T4", "C3类包裹"),
T4_64(64, "T4", "C4类包裹"),
T4_65(65, "T4", "C5类包裹"),
T4_66(66, "T4", "特快D类"),
T4_73(73, "T4", "F5超值箱"),
T4_99(99, "T4", "顺丰国际标快(文件)"),
T4_100(100, "T4", "顺丰国际标快(包裹)"),
T4_104(104, "T4", "岛内件(80CM,1kg以内)"),
T9_106(106, "T9", "国际运输-门到门"),
T36_111(111, "T36", "顺丰干配"),
T6_113(113, "T6", "便利封/袋(标快)"),
T6_114(114, "T6", "二号便利箱(标快)"),
T6_115(115, "T6", "三号便利箱(标快)"),
T4_116(116, "T4", "国际标快-BD2"),
T4_117(117, "T4", "国际标快-BD3"),
T4_118(118, "T4", "国际标快-BD4"),
T4_119(119, "T4", "国际标快-BD5"),
T4_120(120, "T4", "国际标快-BD6"),
T4_121(121, "T4", "国际标快-BDE"),
T4_126(126, "T4", "掌柜-大格"),
T4_127(127, "T4", "掌柜-中格"),
T4_128(128, "T4", "掌柜-小格"),
T4_129(129, "T4", "掌柜-柜到柜(单程)"),
T4_130(130, "T4", "掌柜-柜到柜(双程)"),
T9_132(132, "T9", "顺丰国际特惠(FBA)"),
T4_136(136, "T4", "国际集运"),
T104_144(144, "T104", "当日配-门(80CM/1KG以内)"),
T104_145(145, "T104", "当日配-门(80CM)"),
T104_146(146, "T104", "当日配-门(110CM)"),
T104_147(147, "T104", "当日配-门(140CM)"),
T104_148(148, "T104", "当日配-门(170CM)"),
T104_149(149, "T104", "当日配-门(210CM)"),
T6_150(150, "T6", "标快D类"),
T12_153(153, "T12", "整车直达"),
T9_160(160, "T9", "国际运输-港到港"),
T4_178(178, "T4", "一号便利箱(特快)"),
T6_179(179, "T6", "一号便利箱(标快)"),
T4_180(180, "T4", "岛內件-专车普运"),
T4_184(184, "T4", "顺丰国际标快+(文件)"),
T4_186(186, "T4", "顺丰国际标快+(包裹)"),
T15_201(201, "T15", "冷运标快"),
T4_202(202, "T4", "顺丰微小件"),
SP619_207(207, "SP619", "限时次日"),
T39_215(215, "T39", "大票直送"),
T7_218(218, "T7", "国际电商专递-CD"),
T15_221(221, "T15", "香港冷运到家(≤60厘米)"),
T15_222(222, "T15", "香港冷运到家(61-80厘米)"),
T15_223(223, "T15", "香港冷运到家(81-100厘米)"),
T15_224(224, "T15", "香港冷运到家(101-120厘米)"),
T15_225(225, "T15", "香港冷运到家(121-150厘米)"),
T6_231(231, "T6", "陆运包裹"),
T66_235(235, "T66", "预售当天达"),
T68_236(236, "T68", "电商退货"),
T7_241(241, "T7", "国际电商专递-快速"),
T4_244(244, "T4", "店到店"),
T4_245(245, "T4", "店到门"),
T4_246(246, "T4", "门到店"),
T68_247(247, "T68", "电商标快"),
T4_249(249, "T4", "丰礼遇"),
T123_252(252, "T123", "即时城配"),
T122_253(253, "T122", "前置当天达"),
T28_255(255, "T28", "顺丰卡航"),
T28_256(256, "T28", "顺丰卡航(D类)"),
T4_257(257, "T4", "医药温控配送"),
T4_258(258, "T4", "退换自寄"),
T104_259(259, "T104", "极速配"),
T68_261(261, "T68", "O2O店配"),
T6_262(262, "T6", "前置标快"),
T11_263(263, "T11", "顺丰半日达"),
T67_265(265, "T67", "预售电标"),
T5_266(266, "T5", "顺丰空配(新)"),
T4_267(267, "T4", "失物送递"),
T4_268(268, "T4", "行李送递"),
T4_269(269, "T4", "酒类配送"),
T4_270(270, "T4", "行李托运-上门"),
T4_271(271, "T4", "行李托运"),
T4_272(272, "T4", "行李送递-上门 (九龙)"),
SP7_273(273, "SP7", "温控配送自取"),
SP7_274(274, "SP7", "温控配送上门"),
SP7_275(275, "SP7", "酒类温控自取"),
SP7_276(276, "SP7", "酒类温控上门"),
T73_277(277, "T73", "跨境FBA空运"),
T74_278(278, "T74", "跨境FBA海运"),
T75_283(283, "T75", "填舱标快"),
T76_285(285, "T76", "填舱电标"),
T41_293(293, "T41", "特快包裹(新)"),
T98_297(297, "T98", "样本安心递"),
T99_299(299, "T99", "标快零担"),
T105_303(303, "T105", "专享即日"),
T43_308(308, "T43", "国际特快(文件)"),
T43_310(310, "T43", "国际特快(包裹)"),
T78_314(314, "T78", "中国内地集运"),
T44_316(316, "T44", "前置次日达"),
T69_318(318, "T69", "航空港到港"),
T79_323(323, "T79", "电商微小件"),
T682_325(325, "T682", "温控包裹"),
T281_329(329, "T281", "填舱大件"),
T124_331(331, "T124", "区域城配"),
T125_355(355, "T125", "计划城配");
private final int code;
private final String typeCode;
private final String description;
ExpredssTypeEnum(int code, String typeCode, String description) {
this.code = code;
this.typeCode = typeCode;
this.description = description;
}
public int getCode() {
return code;
}
public String getTypeCode() {
return typeCode;
}
public String getDescription() {
return description;
}
/**
* 根据code获取枚举
*/
public static ExpredssTypeEnum getByCode(int code) {
for (ExpredssTypeEnum type : values()) {
if (type.code == code) {
return type;
}
}
return null;
}
/**
* 根据typeCode获取枚举
*/
public static ExpredssTypeEnum getByTypeCode(String typeCode) {
for (ExpredssTypeEnum type : values()) {
if (type.typeCode.equals(typeCode)) {
return type;
}
}
return null;
}
}
package com.shimao.iibs.common.sf;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.shimao.iibs.common.sf.domain.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.util.*;
/**
* 顺丰报文格式转换
*/
public class SFDataFormat {
private static final Logger log = LoggerFactory.getLogger("sf-api-callBack");
public static ApiResultData createOrderFormat(String str) {
//订单信息
String resultDataStr = JSONUtil.parseObj(str).get("apiResultData") + "";
ApiResultData appResultData = JSONUtil.toBean(resultDataStr, ApiResultData.class);
JSONObject apiResultData = JSONUtil.parseObj(JSONUtil.parseObj(str).get("apiResultData"));
if (apiResultData.getBool("success")) {
//单号信息
String waybillNo = JSONUtil.getByPath(apiResultData, "$.msgData.routeLabelInfo[0].routeLabelData.waybillNo") + "";
appResultData.setWaybillNo(waybillNo);
log.info("顺丰单号:" + waybillNo);
}
log.info("顺丰结果:" + appResultData);
return appResultData;
}
public static ApiResultData queryWaybillFormat(String str, Order order) {
//订单信息
String resultDataStr = JSONUtil.parseObj(str).get("apiResultData") + "";
ApiResultData appResultData = JSONUtil.toBean(resultDataStr, ApiResultData.class);
JSONObject apiResultData = JSONUtil.parseObj(JSONUtil.parseObj(str).get("apiResultData"));
if (apiResultData.getBool("success")) {
JSONObject json = JSONUtil.parseObj(str);//层级获取
JSONObject apiResultJson = json.getJSONObject("apiResultData");
JSONObject msgDataJson = apiResultJson.getJSONObject("msgData");
JSONArray waybillFeeList = msgDataJson.getJSONArray("waybillFeeList");
JSONObject waybillInfo = msgDataJson.getJSONObject("waybillInfo");
List<Waybill> waybills = new ArrayList<>();
for (int i = 0; i < waybillFeeList.size(); i++) {
JSONObject waybillFee = waybillFeeList.getJSONObject(i);
Waybill waybill = new Waybill();
waybill.setOrderId(order.getOrderId());
waybill.setWaybillNo(waybillInfo.getStr("waybillNo"));//运单号
waybill.setWaybillType(waybillFee.getStr("type"));//查费用类型
waybill.setWaybillName(waybillFee.getStr("name"));//查费用名称
waybill.setWaybillValue(new BigDecimal(waybillFee.getStr("value")));//费用金额
waybill.setPaymentTypeCode(waybillFee.getStr("paymentTypeCode"));//付款类型:1、寄付;2、到付;3、第三方付
waybill.setSettlementTypeCode(waybillFee.getStr("settlementTypeCode"));//结算类型:1为现结;2为月结
waybill.setCustomerAcctCode(waybillFee.getStr("customerAcctCode"));//月结账号
waybills.add(waybill);
}
order.setWaybillList(waybills);
}
log.info("顺丰清单运费查询结果:" + order);
return appResultData;
}
public static ApiResultData queryRoutesFormat(String str, Order order) {
//订单信息
String resultDataStr = JSONUtil.parseObj(str).get("apiResultData") + "";
ApiResultData appResultData = JSONUtil.toBean(resultDataStr, ApiResultData.class);
JSONObject apiResultData = JSONUtil.parseObj(JSONUtil.parseObj(str).get("apiResultData"));
if (apiResultData.getBool("success")) {
JSONObject json = JSONUtil.parseObj(str);//层级获取
JSONObject apiResultJson = json.getJSONObject("apiResultData");
JSONObject msgDataJson = apiResultJson.getJSONObject("msgData");
//JSONObject routeResps = msgDataJson.getJSONObject("routeResps");
JSONArray routeRespsList = msgDataJson.getJSONArray("routeResps");
//JSONArray routesList = routeRespsList.getJSONArray("routes");
System.out.println("routeRespsList" + routeRespsList);
List<Routes> routes = new ArrayList<>();
for (int i = 0; i < routeRespsList.size(); i++) {
JSONObject routeResps = routeRespsList.getJSONObject(i);
JSONArray routesList = routeResps.getJSONArray("routes");
for (int x = 0; x < routesList.size(); x++) {
JSONObject routeJson = routesList.getJSONObject(x);
Routes route = new Routes()
.setOrderId(order.getOrderId())
.setWaybillNo(routeJson.getStr("mailNo"))//运单号
.setAcceptTime(routeJson.getDate("acceptTime"))//路由节点时间
.setAcceptAddress(routeJson.getStr("acceptAddress"))//路由节点地址
.setOpCode(routeJson.getStr("opCode"))//操作码
.setSecondaryStatusCode(routeJson.getStr("secondaryStatusCode"))//二级状态码
.setSecondaryStatusName(routeJson.getStr("secondaryStatusName"))//二级状态名称
.setFirstStatusCode(routeJson.getStr("firstStatusCode"))//一级状态码
.setFirstStatusName(routeJson.getStr("firstStatusName"))//一级状态名称
.setRemark(order.getRemark())
.setCreateTime(new Date());
routes.add(route);
}
}
order.setRoutesList( routes);
}
log.info("顺丰清单运费查询结果:" + order);
return appResultData;
}
public static void main(String[] args) {
String jsonString = "{\"apiErrorMsg\":\"\",\"apiResponseID\":\"000198A0E95AAF3FE48701968B22EF3F\",\"apiResultCode\":\"A1000\",\"apiResultData\":\"{\\\"success\\\":true,\\\"errorCode\\\":\\\"S0000\\\",\\\"errorMsg\\\":null,\\\"msgData\\\":{\\\"orderId\\\":\\\"0000001\\\",\\\"originCode\\\":\\\"755\\\",\\\"destCode\\\":\\\"010\\\",\\\"filterResult\\\":2,\\\"remark\\\":\\\"\\\",\\\"url\\\":null,\\\"paymentLink\\\":null,\\\"isUpstairs\\\":null,\\\"isSpecialWarehouseService\\\":null,\\\"mappingMark\\\":null,\\\"agentMailno\\\":null,\\\"returnExtraInfoList\\\":null,\\\"waybillNoInfoList\\\":[{\\\"waybillType\\\":1,\\\"waybillNo\\\":\\\"SF7444498114972\\\",\\\"boxNo\\\":null,\\\"length\\\":null,\\\"width\\\":null,\\\"height\\\":null,\\\"weight\\\":null,\\\"volume\\\":null}],\\\"routeLabelInfo\\\":[{\\\"code\\\":\\\"1000\\\",\\\"routeLabelData\\\":{\\\"waybillNo\\\":\\\"SF7444498114972\\\",\\\"sourceTransferCode\\\":\\\"755W\\\",\\\"sourceCityCode\\\":\\\"755\\\",\\\"sourceDeptCode\\\":\\\"755\\\",\\\"sourceTeamCode\\\":\\\"\\\",\\\"destCityCode\\\":\\\"010\\\",\\\"destDeptCode\\\":\\\"010\\\",\\\"destDeptCodeMapping\\\":\\\"\\\",\\\"destTeamCode\\\":\\\"\\\",\\\"destTeamCodeMapping\\\":\\\"\\\",\\\"destTransferCode\\\":\\\"010W\\\",\\\"destRouteLabel\\\":\\\"010W-010\\\",\\\"proName\\\":\\\"\\\",\\\"cargoTypeCode\\\":\\\"C201\\\",\\\"limitTypeCode\\\":\\\"T4\\\",\\\"expressTypeCode\\\":\\\"B1\\\",\\\"codingMapping\\\":\\\"WU\\\",\\\"codingMappingOut\\\":\\\"\\\",\\\"xbFlag\\\":\\\"0\\\",\\\"printFlag\\\":\\\"000000000\\\",\\\"twoDimensionCode\\\":\\\"MMM={'k1':'010W','k2':'010','k3':'','k4':'T4','k5':'SF7444498114972','k6':'','k7':'86e53682'}\\\",\\\"proCode\\\":\\\"特快\\\",\\\"printIcon\\\":\\\"00000000\\\",\\\"abFlag\\\":\\\"\\\",\\\"destPortCode\\\":\\\"\\\",\\\"destCountry\\\":\\\"\\\",\\\"destPostCode\\\":\\\"\\\",\\\"goodsValueTotal\\\":\\\"\\\",\\\"currencySymbol\\\":\\\"\\\",\\\"cusBatch\\\":\\\"\\\",\\\"goodsNumber\\\":\\\"\\\",\\\"errMsg\\\":\\\"\\\",\\\"checkCode\\\":\\\"86e53682\\\",\\\"proIcon\\\":\\\"\\\",\\\"fileIcon\\\":\\\"\\\",\\\"fbaIcon\\\":\\\"\\\",\\\"icsmIcon\\\":\\\"\\\",\\\"destGisDeptCode\\\":\\\"010\\\",\\\"newIcon\\\":null,\\\"sendAreaCode\\\":null,\\\"destinationStationCode\\\":null,\\\"sxLabelDestCode\\\":null,\\\"sxDestTransferCode\\\":null,\\\"sxCompany\\\":null,\\\"newAbFlag\\\":null,\\\"destAddrKeyWord\\\":\\\"\\\",\\\"rongType\\\":null,\\\"waybillIconList\\\":null},\\\"message\\\":\\\"SF7444498114972:\\\"}],\\\"contactInfoList\\\":null,\\\"sendStartTm\\\":null,\\\"customerRights\\\":null,\\\"expressTypeId\\\":null}}\"}\n";
createOrderFormat(jsonString);
}
}
package com.shimao.iibs.common.sf;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
/**
* 顺丰加密通用接口工具类
*/
public class SFMd5EncodeUtil {
/**
* MD5加密
* @param str 报文
* @param timeStamp 时间戳
* @param key 平台获取的校验码
* @return 加密后的密文
*/
public static String getMD5(String str,String timeStamp,String key) throws UnsupportedEncodingException {
String toVerifyText = URLEncoder.encode(str+ timeStamp + key, "UTF8");
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
md5.update(toVerifyText.getBytes(StandardCharsets.UTF_8));
byte[] md = md5.digest();
//通过BASE64生成数字签名
String msgDigest = Base64.getEncoder().encodeToString(md);
if(msgDigest != null){
return msgDigest;
}
return null;
}
}
可以直接main方法执行,记得换成你的顾客编码及效验码
package com.shimao.iibs.common.sf;
import cn.hutool.json.JSONUtil;
import com.sf.csim.express.service.HttpClientUtil;
import com.sf.csim.express.service.code.ExpressServiceCodeEnum;
import com.shimao.iibs.common.core.domain.R;
import com.shimao.iibs.common.sf.domain.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 顺丰接口工具类
*/
public class SFUtils {
private static final Logger log = LoggerFactory.getLogger("sf-api");
private static final String CLIENT_CODE ="SMKJFRW1ERL2"; //顾客编码
private static final String CHECK_WORD = "MEvLbOPOCrEfbSXM2L2lcyf5kgQ2OBdZ";//校验码
private static final String CALL_URL_BOX = "https://sfapi-sbox.sf-express.com/std/service";//沙箱环境的地址 -Test
//private static final String CALL_URL_BOX = "https://sfapi.sf-express.com/std/service";//生产环境的地址 -PROD
private static final String MONTHLY_CARD = "7551234567";//月结卡号
// ExpressServiceCodeEnum.EXP_RECE_CREATE_ORDER; //下订单 1
// ExpressServiceCodeEnum.EXP_RECE_SEARCH_ORDER_RESP; //查订单 1
// ExpressServiceCodeEnum.EXP_RECE_UPDATE_ORDER;//订单取消 1
// ExpressServiceCodeEnum.EXP_RECE_FILTER_ORDER_BSP;//订单筛选
// ExpressServiceCodeEnum.EXP_RECE_SEARCH_ROUTES;//查路由 1
// ExpressServiceCodeEnum.EXP_RECE_GET_SUB_MAILNO;//子单号
// ExpressServiceCodeEnum.EXP_RECE_QUERY_SFWAYBILL;//查运费 1
// ExpressServiceCodeEnum.EXP_RECE_REGISTER_ROUTE;//注册路由
// ExpressServiceCodeEnum.EXP_RECE_CREATE_REVERSE_ORDER;//退货下单
// ExpressServiceCodeEnum.EXP_RECE_CANCEL_REVERSE_ORDER;//退货消单
// ExpressServiceCodeEnum.EXP_RECE_WANTED_INTERCEPT;//截单转寄
// ExpressServiceCodeEnum.EXP_RECE_QUERY_DELIVERTM;//时效标准及价格查询
// ExpressServiceCodeEnum.COM_RECE_CLOUD_PRINT_WAYBILLS;//面单打印
// ExpressServiceCodeEnum.EXP_RECE_UPLOAD_ROUTE;//路由上传
// ExpressServiceCodeEnum.EXP_RECE_SEARCH_PROMITM;//预计派送时间查询
// ExpressServiceCodeEnum.EXP_EXCE_CHECK_PICKUP_TIME;//揽件服务时间查询
// ExpressServiceCodeEnum.EXP_RECE_VALIDATE_WAYBILLNO;//运单号合法性校验
/**
* 创建顺丰订单
*/
public static R createOrder(Order order) throws UnsupportedEncodingException {
order.setMonthlyCard(MONTHLY_CARD);//月卡
String jsonStr = JSONUtil.toJsonStr(order);
Map<String, String> params = new HashMap<>();
//获取当前时间戳
String timeStamp = String.valueOf(System.currentTimeMillis());
params.put("partnerID", CLIENT_CODE);
params.put("requestID", order.getOrderId());
params.put("serviceCode", ExpressServiceCodeEnum.EXP_RECE_CREATE_ORDER.getCode());// 接口服务码
params.put("timestamp", timeStamp);
params.put("msgData", jsonStr);
String md5 = SFMd5EncodeUtil.getMD5(jsonStr, timeStamp, CHECK_WORD);
params.put("msgDigest", md5);
log.info("====顺丰下单请求:" + params);
order.setParams(params.toString());
try {
String result = HttpClientUtil.post(CALL_URL_BOX, params);
log.info("====顺丰下单接口报文:" + result);
ApiResultData resultData = SFDataFormat.createOrderFormat(result);
if (resultData.getSuccess()) {
log.info("====顺丰下单成功");
return R.ok(null, "顺丰下单成功");
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return R.fail("顺丰快递下单失败");
}
/**
* 查询顺丰订单
* 因Internet环境下,网络不是绝对可靠,用户系统下订单到顺丰后,不一定可以收到顺丰系统返回的数据,
* 此接口用于在未收到返回数据时,查询订单创建接口客户订单当前的处理情况。
*/
public static R queryOrder(Order order) throws UnsupportedEncodingException {
String jsonStr = JSONUtil.toJsonStr(order);
Map<String, String> params = new HashMap<>();
//获取当前时间戳
String timeStamp = String.valueOf(System.currentTimeMillis());
params.put("partnerID", CLIENT_CODE);
params.put("requestID", order.getOrderId());
params.put("serviceCode", ExpressServiceCodeEnum.EXP_RECE_SEARCH_ORDER_RESP.getCode());// 接口服务码
params.put("timestamp", timeStamp);
params.put("msgData", jsonStr);
String md5 = SFMd5EncodeUtil.getMD5(jsonStr, timeStamp, CHECK_WORD);
params.put("msgDigest", md5);
log.info("====顺丰查询订单请求:" + params);
order.setParams(params.toString());
try {
String result = HttpClientUtil.post(CALL_URL_BOX, params);
order.setResult(result);
log.info("====顺丰查询订单接口报文:" + result);
ApiResultData resultData = SFDataFormat.createOrderFormat(result);
if (resultData.getSuccess()) {
log.info("====顺丰查询订单成功");
return R.ok(null, "顺丰查询订单成功");
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return R.fail("顺丰查询订单失败");
}
/**
* 订单确认/取消接口
* (1)客户在确定将货物交付给顺丰托运后,将运单上的一些重要信息,如快件重量通过此接口发送给顺丰。
* (2)客户在发货前取消订单。
*/
public static R updateOrder(Order order) throws UnsupportedEncodingException {
order.setDealType(2);//客户订单操作标识: 1:确认 2:取消
String jsonStr = JSONUtil.toJsonStr(order);
Map<String, String> params = new HashMap<>();
//获取当前时间戳
String timeStamp = String.valueOf(System.currentTimeMillis());
params.put("partnerID", CLIENT_CODE);
params.put("requestID", order.getOrderId());
params.put("serviceCode", ExpressServiceCodeEnum.EXP_RECE_UPDATE_ORDER.getCode());// 接口服务码
params.put("timestamp", timeStamp);
params.put("msgData", jsonStr);
String md5 = SFMd5EncodeUtil.getMD5(jsonStr, timeStamp, CHECK_WORD);
params.put("msgDigest", md5);
log.info("====顺丰订单取消请求:" + params);
order.setParams(params.toString());
try {
String result = HttpClientUtil.post(CALL_URL_BOX, params);
order.setResult(result);
log.info("====顺丰订单取消接口报文:" + result);
ApiResultData resultData = SFDataFormat.createOrderFormat(result);
if (resultData.getSuccess()) {
log.info("====顺丰订单取消成功");
return R.ok(null, "顺丰订单取消成功");
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return R.fail("顺丰订单取消失败");
}
/**
* 清单运费查询接口
* 此功能主要是根据订单号或者运单号查询清单运费信息。
* 默认校验月结信息,只能查询顾客编码下绑定成功的月结卡的订单
*/
public static R queryWaybill(Order order) throws UnsupportedEncodingException {
Map map = new HashMap();
map.put("trackingType", "1");//1:表示按订单查询 2:表示按运单查询
map.put("trackingNum", order.getOrderId());//订单号或运单号;
String jsonStr = JSONUtil.toJsonStr(map);
Map<String, String> params = new HashMap<>();
//获取当前时间戳
String timeStamp = String.valueOf(System.currentTimeMillis());
params.put("partnerID", CLIENT_CODE);
params.put("requestID", order.getOrderId());
params.put("serviceCode", ExpressServiceCodeEnum.EXP_RECE_QUERY_SFWAYBILL.getCode());// 接口服务码
params.put("timestamp", timeStamp);
params.put("msgData", jsonStr);
String md5 = SFMd5EncodeUtil.getMD5(jsonStr, timeStamp, CHECK_WORD);
params.put("msgDigest", md5);
order.setParams(params.toString());
log.info("====顺丰清单运费查询请求:" + params);
try {
String result = HttpClientUtil.post(CALL_URL_BOX, params);
log.info("====顺丰清单运费查询接口报文:" + result);
ApiResultData resultData = SFDataFormat.queryWaybillFormat(result, order);
if (resultData.getSuccess()) {
log.info("====顺丰清单运费查询成功");
return R.ok(null, "顺丰清单运费查询成功");
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return R.fail("顺丰清单运费查询失败");
}
/**
* 路由查询接口
* 客户可通过此接口查询顺丰运单路由,顺丰会在响应Json报文返回当时点要求的全部路由节点信息。
* 说明:
* ①可查询3个月内运单路由,路由响应空值代表无查询权限/无路由/超3个月。
* ②响应报文为MOCK,不受全流程测试工具影响。
* 此路由查询接口支持三类查询方式:
* 1)根据顺丰运单号查询(限月结付款):所查询运单号付款使用的月结卡号,与调用接口时所用的partnerID(顾客编码)存在绑定关系,系统返回运单路由信息;反之routes路由响应空值。
* 2)根据客户订单号查询:查询请求中提供partnerID(顾客编码)与订单号,验证partnerID(顾客编码)与所有请求订单号的归属关系,对于归属关系正确的订单号,找到对应的运单号,然后返回订单对应运单号的路由信息。适用于通过该partnerID(顾客编码)下单的客户。
* 3)根据运单号+运单对应的收寄人任一方电话号码后4位(参数checkPhoneNo中传入)查询,系统校验信息匹配将返回对应运单路由信息。一次性查多个路由,checkPhoneNo传入多个电话号码后4位,用英文逗号隔开,作为一个字符串
*/
public static R queryRoutes(Order order) throws UnsupportedEncodingException {
order.setDealType(2);//客户订单操作标识: 1:确认 2:取消
String jsonStr = JSONUtil.toJsonStr(order);
Map<String, String> params = new HashMap<>();
//获取当前时间戳
String timeStamp = String.valueOf(System.currentTimeMillis());
params.put("partnerID", CLIENT_CODE);
params.put("requestID", timeStamp);
params.put("serviceCode", ExpressServiceCodeEnum.EXP_RECE_SEARCH_ROUTES.getCode());// 接口服务码
params.put("timestamp", timeStamp);
params.put("msgData", jsonStr);
String md5 = SFMd5EncodeUtil.getMD5(jsonStr, timeStamp, CHECK_WORD);
params.put("msgDigest", md5);
log.info("====顺丰路由查询接口请求:" + params);
order.setParams(params.toString());
try {
String result = HttpClientUtil.post(CALL_URL_BOX, params);
order.setResult(result);
log.info("====顺丰路由查询接口报文:" + result);
ApiResultData resultData = SFDataFormat.queryRoutesFormat(result, order);
if (resultData.getSuccess()) {
log.info("====顺丰路由查询成功");
return R.ok(null, "顺丰路由查询成功");
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return R.fail("顺丰路由查询失败");
}
public static void main(String[] args) throws UnsupportedEncodingException {
//下单
//createOrder(initCreateOrder());
//查询订单
//queryOrder(initQueryOrder());
//取消订单
//updateOrder(initUpdateOrder());
//清单运费
//queryWaybill(initWaybillOrder());
//路由查询
//queryRoutes(initRoutesOrder());
}
static String ORDER_ID = "0000003";//订单号
/**
* 初始创建订单测试参数
*/
static Order initCreateOrder(){
// 设置订单信息
Order order = new Order()
.setOrderId(ORDER_ID)//客户订单号,重复使用订单号时返回第一次下单成功时的运单信息
.setDealType(1) //1:确认 (丰桥下订单接口默认自动确认,不需客户重复确认,该操作用在其它非自动确认的场景) 2:取消
.setParcelQty(1)//包裹数,一个包裹对应一个运单号;若包裹数大于1,则返回一个母运单号和N-1个子运单号
.setExpressTypeId(ExpredssTypeEnum.T4_1.getCode())//快件产品类别
.setIsReturnRoutelabel(1)//是否返回路由标签: 默认1, 1:返回路由标签, 0:不返回;
.setIsDocall(1);//是否通过手持终端 通知顺丰收派 员上门收件,支持以下值: 1:要求 0:不要求
// 设置货物信息
List<CargoDetail> cargoDetails = new ArrayList<>();
CargoDetail cargoDetail = new CargoDetail()
.setName("护肤品1");//货物名称
//.setCount(1)//货物数量 跨境件报关需要填写
//.setUnit("件")//跨境件报关需要填写
//.setWeight(new BigDecimal("3.5"));//订单货物单位重量,包含子母件, 单位千克,精确到小数点后3位 跨境件报关需要填写
cargoDetails.add(cargoDetail);
order.setCargoDetails(cargoDetails);
// 设置收寄双方信息
List<ContactInfo> contactInfoList = new ArrayList<>();
ContactInfo senderInfo = new ContactInfo()
.setContact("张三")//联系人
.setContactType(1) // 地址类型: 1,寄件方信息 2,到件方信息
.setAddress("广东省深圳市南山区科技园南区")
.setCountry("CN")//国家代码
.setProvince("广东省")//省份
.setCity("深圳市")// 城市
.setCounty("南山区")//区县
.setMobile("13800138000");
contactInfoList.add(senderInfo);
ContactInfo receiverInfo = new ContactInfo()
.setContact("李四")//联系人
.setContactType(2) // 地址类型: 1,寄件方信息 2,到件方信息
//.setCompany("顺丰速运")//公司名称
//.setPostCode("518000")//邮编,跨境件必填
.setAddress("北京市朝阳区望京街道")
.setCountry("CN")//国家代码
.setProvince("北京市")//省份
.setCity("北京市")// 城市
.setCounty("朝阳区")//区县
.setMobile("13900139000");
contactInfoList.add(receiverInfo);
order.setContactInfoList(contactInfoList);
return order;
}
/**
* 初始查询订单测试参数
*/
static Order initQueryOrder(){
// 设置订单信息
Order order = new Order()
.setOrderId(ORDER_ID)
.setSearchType("1"); //查询类型:1正向单 2退货单
//.setMainWaybillNo("")//顺丰下单接口返回的15或12位运单号,母单号 如:SF10116351372291
return order;
}
/**
* 初始取消订单测试参数
*/
static Order initUpdateOrder(){
// 设置订单信息
Order order = new Order()
.setOrderId(ORDER_ID)//客户订单号,重复使用订单号时返回第一次下单成功时的运单信息
.setDealType(2); //1:确认 (丰桥下订单接口默认自动确认,不需客户重复确认,该操作用在其它非自动确认的场景) 2:取消
return order;
}
/**
* 初始清单运费测试参数
*/
static Order initWaybillOrder(){
// 设置订单信息
Order order = new Order().setOrderId(ORDER_ID);
return order;
}
/**
* 初始路由查询测试参数
*/
static Order initRoutesOrder(){
// 订单号
String orderNo = "SF7444498111484";
List<String> orderList = new ArrayList<>();
orderList.add(orderNo);
// 设置订单信息
Order order = new Order()
.setTrackingType(1)//查询号类别: 1:根据顺丰运单号查询, 2:根据客户订单号查询
.setTrackingNumber(orderList);//查询号 trackingType=1,则此值为顺丰运单号 如果trackingType=2,则此值为客户订单号
return order;
}
}
顺丰提供的 呵呵
package com.shimao.iibs.common.sf;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import com.sf.csim.express.service.CallExpressServiceTools;
import com.sf.csim.express.service.HttpClientUtil;
import com.sf.csim.express.service.IServiceCodeStandard;
import com.sf.csim.express.service.code.ExpressServiceCodeEnum;
import com.sf.csim.express.service.code.HZTServiceCodeEnum;
public class TestCallExpressNewAPIService {
/**丰桥新沙箱测试顾客编码 Yg4Zf06w_sxZs3A5D
校验码 3Xdk1jqeG1Xod9nUXus8Op7DNOkchTnw
**/
private static final String CLIENT_CODE = "SMKJFRW1ERL2"; //此处替换为您在丰桥平台获取的顾客编码
private static final String CHECK_WORD = "MEvLbOPOCrEfbSXM2L2lcyf5kgQ2OBdZ";//此处替换为您在丰桥平台获取的校验码
//沙箱环境的地址 -PRO
private static final String CALL_URL_BOX = "https://sfapi-sbox.sf-express.com/std/service";
//生产环境的地址 -PRO
private static final String CALL_URL_PROD = "https://sfapi.sf-express.com/std/service";
public static void main(String[] args) throws UnsupportedEncodingException {
/**ExpressServiceCodeEnum 对应速运类-快递APIs
POSTServiceCodeEnum 对应速运类-驿站APIs
YJTServiceCodeEnum 对应解决方案-医寄通APIs
EPSServiceCodeEnum 对应解决方案-快递管家APIs
HZTServiceCodeEnum 对应解决方案-函证通APIs 2022-2-24 新增
详情见code目录下枚举类,客户可自行修改引用的该类
**/
IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_CREATE_ORDER; //下订单
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_SEARCH_ORDER_RESP; //查订单
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_UPDATE_ORDER;//订单取消
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_FILTER_ORDER_BSP;//订单筛选
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_SEARCH_ROUTES;//查路由
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_GET_SUB_MAILNO;//子单号
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_QUERY_SFWAYBILL;//查运费
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_REGISTER_ROUTE;//注册路由
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_CREATE_REVERSE_ORDER;//退货下单
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_CANCEL_REVERSE_ORDER;//退货消单
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_WANTED_INTERCEPT;//截单转寄
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_QUERY_DELIVERTM;//时效标准及价格查询
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.COM_RECE_CLOUD_PRINT_WAYBILLS;//面单打印
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_UPLOAD_ROUTE;//路由上传
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_SEARCH_PROMITM;//预计派送时间查询
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_EXCE_CHECK_PICKUP_TIME;//揽件服务时间查询
// IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_VALIDATE_WAYBILLNO;//运单号合法性校验
CallExpressServiceTools tools=CallExpressServiceTools.getInstance();
// set common header
Map<String, String> params = new HashMap<String, String>();
String timeStamp = String.valueOf(System.currentTimeMillis());
String msgData =tools.packageMsgData(standardService);
params.put("partnerID", CLIENT_CODE); // 顾客编码 ,对应丰桥上获取的clientCode
params.put("requestID", UUID.randomUUID().toString().replace("-", ""));
params.put("serviceCode",standardService.getCode());// 接口服务码
params.put("timestamp", timeStamp);
params.put("msgData", msgData);
params.put("msgDigest", tools.getMsgDigest(msgData,timeStamp,CHECK_WORD));
// System.out.println(params.get("requestID"));
long startTime = System.currentTimeMillis();
// System.out.println("====调用请求:" + params.get("msgData"));
System.out.println("====调用实际请求:" + params);
String result = HttpClientUtil.post(CALL_URL_BOX, params);
System.out.println("====调用丰桥的接口服务代码:" + String.valueOf(standardService.getCode()) + " 接口耗时:"+ String.valueOf(System.currentTimeMillis()-startTime)+"====");
System.out.println("===调用地址 ==="+CALL_URL_BOX);
System.out.println("===顾客编码 ==="+CLIENT_CODE);
System.out.println("===返回结果:" +result);
}
}
更多推荐




所有评论(0)