当前位置: 首页 > 工具软件 > java-express > 使用案例 >

【第三方API】顺丰API调用总结-java

呼延永新
2023-12-01

一、获取顾客编码及校验码

   https://qiao.sf-express.com/index.html 丰桥系统中申请api接口,获得url(调用地址)、clientCode(顾客编码)、checkword(校验码)。

    url:http://bsp-oisp.sf-express.com/bsp-oisp/sfexpressService

二、XML报文说明

    1.请求XML报文:

    service 属性定义“服务名”;Head元素定义“顾客编码”

<Request service="服务名" lang="zh-CN">
<Head>顾客编码</Head>
<Body>请求数据XML</Body>

    2.响应XML报文:

     Head元素值为“OK”或“ERR”;OK代表交易成功,ERR代表发生系统或业务异常,交易失败;对于批量交易场景,只能为成功/失败,无部分成功/部分失败

<Response service="服务名">
<Head>OK|ERR</HEAD>
<Body>正常响应数据XML</Body>
<ERROR code="NNNN">错误详细信息</ERROR>

三、API接口详情

    1.下订单接口(OrderService):

    ①客户系统向顺丰下发订单 ②为订单分配运单号

/**
 * 获取顺丰下订单接口xml
 * @param params
 * @return
 */
private String getOrderServiceRequestXml(Map<String,String> params){
    //订单号
    String orderNo = params.get("orderNo");
    //收件人
    String receiverName = params.get("receiverName");
    //收件人电话
    String receiverMobile = params.get("receiverMobile");
    //收件人详细地址
    String receiverAddress = params.get("address");
    //商品名称
    String commodityName = params.get("commodityName");
    //商品数量
    String orderNum = params.get("orderNum");


    StringBuilder strBuilder = new StringBuilder();
    strBuilder.append("<Request service='OrderService' lang='zh-CN'>");
    strBuilder.append("<Head>" + clientCode + "</Head>");
    strBuilder.append("<Body>");
    strBuilder.append("<Order").append(" ");
    strBuilder.append("orderid='" + orderNo.toString().trim() + "" + "'").append(" ");
    //返回顺丰运单号
    strBuilder.append("is_gen_bill_no='1'").append(" ");
    //寄件方信息
    strBuilder.append("j_company='" + j_company + "'").append(" ");
    strBuilder.append("j_contact='" + j_contact + "'").append(" ");
    strBuilder.append("j_tel='" + j_tel + "'").append(" ");
    strBuilder.append("j_address='" + j_province+j_city+j_county+j_address + "'").append(" ");
    //收件方信息
    strBuilder.append("d_company='" + d_company + "'").append(" ");
    strBuilder.append("d_contact='" + receiverName.toString().trim() + "'").append(" ");
    strBuilder.append("d_tel='" + receiverMobile.toString().trim() + "'").append(" ");
    strBuilder.append("d_address='" + receiverAddress.toString().trim() + "'").append(" ");
    strBuilder.append(" > ");
    //货物信息
    strBuilder.append("<Cargo").append(" ");
    strBuilder.append("name='" + commodityName + "'").append(" ");
    strBuilder.append("count='" + orderNum.toString() + "'").append(" ");
    strBuilder.append("unit='双'").append(">");
    strBuilder.append("</Cargo>");

    strBuilder.append("</Order>");
    strBuilder.append("</Body>");
    strBuilder.append("</Request>");

    return strBuilder.toString();
}


    2.订单结果查询接口(OrderSearchService):

      因Internet环境下,网络不是绝对可靠,用户系统下订单到顺丰后,不一定可以收到顺丰系统返回的数据,此接口用于在未收到返回数据时,查询下订单(含筛选)接口客户订单当前的处理情况。重复下单时可调用此接口查询下单顺丰单号

/**
 * 获取顺丰订单结果查询接口xml
 * @param params
 * @return
 */
private String getOrderSearchServiceRequestXml(Map<String,String> params){
    String orderNo = params.get("orderNo");
    StringBuilder strBuilder = new StringBuilder();
    strBuilder.append("<Request service='OrderSearchService' lang='zh-CN'>");
    strBuilder.append("<Head>" + clientCode + "</Head>");
    strBuilder.append("<Body>");
    strBuilder.append("<OrderSearch").append(" ");
    strBuilder.append("orderid='" + orderNo.toString().trim() + "" + "'").append(" > ");
    strBuilder.append("</OrderSearch>");
    strBuilder.append("</Body>");
    strBuilder.append("</Request>");
    return strBuilder.toString();
}

    3.路由查询接口(RouteService):

      支持两类查询方式:①根据顺丰运单号查询 ②根据客户订单号查询 

/**
 * 获取顺丰路由查询接口xml
 * @param params
 * @return
 */
private String getRouteServiceRequestXml(Map<String,String> params){
    String orderNo = params.get("orderNo");
    StringBuilder strBuilder = new StringBuilder();
    strBuilder.append("<Request service='RouteService' lang='zh-CN'>");
    strBuilder.append("<Head>" + clientCode + "</Head>");
    strBuilder.append("<Body>");
    strBuilder.append("<RouteRequest").append(" ");
    strBuilder.append("tracking_type='2'").append(" ");
    strBuilder.append("tracking_number='" + orderNo.toString().trim() + "" + "'").append(" >");
    strBuilder.append("</RouteRequest>");
    strBuilder.append("</Body>");
    strBuilder.append("</Request>");
    return strBuilder.toString();
}

三、API接口调用

    ①把XML报文与checkword前后连接

    ②把连接后的字符串做MD5编码

    ③把MD5编码后的数据进行Base64编码,此时编码后的字符串即为校验码

//接口url
@Value("${express.sf.url}")
private String url = "http://bsp-oisp.sf-express.com/bsp-oisp/sfexpressService"
/**
 * 顺丰接口
 * @param params
 * @param type  1-下订单接口  2-订单结果查询接口 3-路由查询接口
 * @return
 */
@Override
public SfExpressResponse sfExpressMethod(Map<String,String> params, int type) throws Exception{
    logger.info("进入顺丰接口:params={},type={}", JSONObject.toJSONString(params),type);
    if (type < 1){
        logger.warn("调用接口类型传错");
        return null;
    }
    String requestXml = "";
    String methodName = "";
    if (type == 1){
        //1.获取下单xml
        requestXml = getOrderServiceRequestXml(params);
        methodName = "orderSerivce";
    } else if (type == 2){
        //1.获取订单结果查询xml
        requestXml = getOrderSearchServiceRequestXml(params);
        methodName = "orderSearchService";
    } else if (type == 3){
        //1.获取订单物流路由
        requestXml = getRouteServiceRequestXml(params);
        methodName = "routeService";
    }
    //2.xml+checkword
    String verifyCode = requestXml + checkword;
    //3.MD5加密 + Base64编码
    MessageDigest md5 = MessageDigest.getInstance("MD5");
    md5.update(verifyCode.getBytes("utf8"));
    verifyCode = Base64Util.encode(md5.digest());
    //4.post 请求
    Map<String, Object> toHttpParams = new HashMap<>();
    toHttpParams.put("xml",requestXml);
    toHttpParams.put("verifyCode",verifyCode);
    logger.info("请求顺丰接口"+methodName, toHttpParams.toString());
    String resultStr = HttpExtUtil.doPost(url, toHttpParams);
    logger.info("请求顺丰接口"+methodName+",result="+resultStr);
    SfExpressResponse response = (SfExpressResponse) 
                                               XMLUtil.convertToObject(SfExpressResponse.class,resultStr);
    return response;
}

四、响应XML解析

    综合三个接口的response xml,将SfExpressResponse定义如下(树状结构对象):

/**
 * 顺丰接口response对象
 * author: jing.mn
 * date: 2018/4/9 16:17
 * copyright wonhigh.net.cn
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Response")
public class SfExpressResponse implements Serializable {

    private static final long serialVersionUID = 1L;
    //响应状态
    @XmlElement(name = "Head")
    private String Head;
    //响应失败原因
    @XmlElement(name = "ERROR")
    private ERROR ERROR;
    //响应结果
    @XmlElement(name = "Body")
    private Body Body;


    @XmlAccessorType(XmlAccessType.NONE)
    public static class ERROR {
        @XmlAttribute(name = "code")
        private String code;
        @XmlValue
        private String text;

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }
    }

    @XmlAccessorType(XmlAccessType.NONE)
    public static class Body {
        @XmlElement(name = "OrderResponse")
        private OrderResponse OrderResponse;

        @XmlElement(name = "RouteResponse")
        private RouteResponse RouteResponse;

        public SfExpressResponse.OrderResponse getOrderResponse() {
            return OrderResponse;
        }

        public void setOrderResponse(SfExpressResponse.OrderResponse orderResponse) {
            OrderResponse = orderResponse;
        }

        public SfExpressResponse.RouteResponse getRouteResponse() {
            return RouteResponse;
        }

        public void setRouteResponse(SfExpressResponse.RouteResponse routeResponse) {
            RouteResponse = routeResponse;
        }

    }

    @XmlRootElement(name="OrderResponse")
    @XmlAccessorType(XmlAccessType.NONE)
    public static class OrderResponse {
        //订单号
        @XmlAttribute(name = "orderid")
        private String orderId;
        //运单号
        @XmlAttribute(name = "mailno")
        private String mailNo;
        //原寄地区域代码(可用于顺丰电子运单标签打印)
        @XmlAttribute(name = "origincode")
        private String originCode;
        //目的地区域代码(可用于顺丰电子运单标签打印)
        @XmlAttribute(name = "destcode")
        private String destCode;
        //筛单结果:1:人工确认 2:可收派 3:不可以收派
        @XmlAttribute(name = "filter_result")
        private String filterResult;


        public String getOrderId() {
            return orderId;
        }

        public void setOrderId(String orderId) {
            this.orderId = orderId;
        }

        public String getMailNo() {
            return mailNo;
        }

        public void setMailNo(String mailNo) {
            this.mailNo = mailNo;
        }

        public String getOriginCode() {
            return originCode;
        }

        public void setOriginCode(String originCode) {
            this.originCode = originCode;
        }

        public String getDestCode() {
            return destCode;
        }

        public void setDestCode(String destCode) {
            this.destCode = destCode;
        }

        public String getFilterResult() {
            return filterResult;
        }

        public void setFilterResult(String filterResult) {
            this.filterResult = filterResult;
        }
    }

    @XmlRootElement(name="RouteResponse")
    @XmlAccessorType(XmlAccessType.NONE)
    public static class RouteResponse {
        //运单号
        @XmlAttribute(name = "mailno")
        private String mailNo;
        //路由
        @XmlElement(name = "Route")
        private List<Route> Route ;

        public String getMailNo() {
            return mailNo;
        }

        public void setMailNo(String mailNo) {
            this.mailNo = mailNo;
        }

        public List<SfExpressResponse.Route> getRoute() {
            return Route;
        }

        public void setRoute(List<SfExpressResponse.Route> route) {
            Route = route;
        }
    }

    @XmlRootElement(name="Route")
    @XmlAccessorType(XmlAccessType.NONE)
    public static class Route {
        //路由节点发生的时间
        @XmlAttribute(name = "accept_time")
        private String acceptTime;

        //路由节点具体描述
        @XmlAttribute(name = "remark")
        private String remark;

        //路由节点操作码
        @XmlAttribute(name = "opcode")
        private String opcode;

        public String getAcceptTime() {
            return acceptTime;
        }

        public void setAcceptTime(String acceptTime) {
            this.acceptTime = acceptTime;
        }

        public String getRemark() {
            return remark;
        }

        public void setRemark(String remark) {
            this.remark = remark;
        }

        public String getOpcode() {
            return opcode;
        }

        public void setOpcode(String opcode) {
            this.opcode = opcode;
        }
    }

    public String getHead() {
        return Head;
    }

    public void setHead(String head) {
        Head = head;
    }

    public SfExpressResponse.ERROR getERROR() {
        return ERROR;
    }

    public void setERROR(SfExpressResponse.ERROR ERROR) {
        this.ERROR = ERROR;
    }

    public SfExpressResponse.Body getBody() {
        return Body;
    }

    public void setBody(SfExpressResponse.Body body) {
        Body = body;
    }
}

 

 类似资料: