顺丰开放平台
纯讨论我也是第一次对接,有更好的优化方案一起讨论

前提准备工作

官网根据流程注册账号与创建应用获取对应的appkey与secret

代码展示

 顺丰config类
@Component
@ConfigurationProperties(prefix = SfConfig.CONF_PREFIX)
@Validated
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SfConfig {

    public static final String CONF_PREFIX = "sf";

    //用户编码
    private String partnerId;

    //校验
    private String checkWord;
    //月结账号
    private String monthlyCard;
    //调用地址
    private String callUrl;
    //OAuth2获取accessToken地址
    private String accessTokenUrl;

}
统一顺丰请求方法util 
@Component
@Log4j2
public class SfUtils {

    @Autowired
    private SfConfig sfConfig;

    public SfMsgDto commonHttp(String msgData, String serivceCode) {
        String timeStamp = String.valueOf(System.currentTimeMillis());
        Map<String, Object> params = new HashMap<>();
        //顾客编码
        params.put("partnerID", sfConfig.getPartnerId());
        //请求唯一号UUID
        params.put("requestID", UUID.randomUUID().toString().replace("-", ""));
        //下单serviceCode
        params.put("serviceCode", serivceCode);
        //时间戳
        params.put("timestamp", timeStamp);
        //下单数据
        params.put("msgData", msgData);
        //访问令牌
        params.put("accessToken", getAccessToken());
        //将业务报文+时间戳+校验码组合成需加密的字符串(注意顺序)
        String toVerifyText = msgData + timeStamp + sfConfig.getCheckWord();
        //因业务报文中可能包含加号、空格等特殊字符,需要urlEnCode处理
        try {
            toVerifyText = URLEncoder.encode(toVerifyText, "UTF-8");
            //进行Md5加密
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(toVerifyText.getBytes("UTF-8"));
            byte[] md = md5.digest();
            //通过BASE64生成数字签名
            String msgDigest = new String(encode(md));
            //数据签名
            params.put("msgDigest", msgDigest);
        } catch (Exception e) {
            log.error("顺丰请求异常;业务Code:{};异常信息:{}", serivceCode, e);
        }
        log.info("顺丰请求参数:{}", JSON.toJSONString(params));
        //返回打印所需数据  访问接口
        SfRespDto sfRespDto = HttpsUtil.postFormUrlEncoded(sfConfig.getCallUrl(), params, null, SfRespDto.class);
        log.info("顺丰请求结果:{}", sfRespDto);
        if (!"A1000".equals(sfRespDto.getApiResultCode())) {
            log.error("顺丰请求异常;业务Code:{};异常信息:{}", serivceCode, sfRespDto.getApiErrorMsg());
        }
        return JSONObject.parseObject(sfRespDto.getApiResultData(), SfMsgDto.class);
    }

    private String getAccessToken() {
        Map<String, Object> params = new HashMap<>();
        //顾客编码
        params.put("partnerID", sfConfig.getPartnerId());
        params.put("secret", sfConfig.getCheckWord());
        params.put("grantType", "password");
        SfRespDto sfRespDto = HttpsUtil.postFormUrlEncoded(sfConfig.getAccessTokenUrl(), params, null, SfRespDto.class);
        return sfRespDto.getAccessToken();
    }
    // 编码
    public static String encode(byte[] data) {
        return Base64.getEncoder().encodeToString(data);
    }

    // 解码
    public static byte[] decode(String base64) {
        return Base64.getDecoder().decode(base64);
    }
}

统一响应对象 

/**
 * 顺丰公共响应接口
 */
@Data
public class SfRespDto implements Serializable {
    private String apiErrorMsg;
    private String apiResponseID;
    private String apiResultCode;
    private String apiResultData;
    private String accessToken;

}
 下订单接口 EXP_RECE_CREATE_ORDER

入参

/**
 * 顺丰下单参数
 */
@Data
public class SfOrder implements Serializable {
    /**
     * 快件产品类别, 支持附录 《快件产品类别表》 的产品编码值,仅可使用与顺丰销售约定的快件产品
     */
    private Integer expressTypeId;
    /**
     * 快件自取,支持以下值: 1:客户同意快件自取 0:客户不同意快件自取
     */
    private Integer isOneselfPickup;
    /**
     * 	响应报文的语言, 缺省值为zh-CN,目前支持以下值zh-CN 表示中文简体, zh-TW或zh-HK或 zh-MO表示中文繁体, en表示英文
     */
    private String language;
    /**
     * 要求上门取件开始时间
     */
    private String sendStartTm;
    /**
     * 	顺丰月结卡号 月结支付时传值,现结不需传值;沙箱联调可使用测试月结卡号7551234567(非正式,无须绑定,仅支持联调使用)
     */
    private String monthlyCard;
    /**
     * 客户订单号,重复使用订单号时返回第一次下单成功时的运单信息
     */
    private String orderId;
    /**
     * 包裹数,一个包裹对应一个运单号;若包裹数大于1,则返回一个母运单号和N-1个子运单号
     */
    private Integer parcelQty;
    /**
     * 付款方式,支持以下值: 1:寄方付 2:收方付 3:第三方付
     */
    private Integer payMethod;
    /**
     * 订单货物总重量(郑州空港海关必填), 若为子母件必填, 单位千克, 精确到小数点后3位,如果提供此值, 必须>0 (子母件需>6)
     */
    private BigDecimal totalWeight;
    /**
     * 备注
     */
    private String remark;
    /**
     * 是否返回路由标签: 默认1, 1:返回路由标签, 0:不返回;除部分特殊用户外,其余用户都默认返回
     */
    private Integer isReturnRoutelabel;

    /**
     * 是否通过手持终端 通知顺丰收派 员上门收件,支持以下值: 1:要求 0:不要求
     */
    private Integer isDocall;

    /**
     * 是否返回签回单 (签单返还)的运单号, 支持以下值: 1:要求 0:不要求
     */
    private Integer isSignBack;
    /**
     *cargoDetails
     */
    private List<CargoDetail> cargoDetails;
    /**
     * 收寄双方信息
     */
    private List<ContactInfo> contactInfoList;

}
 统一调用顺丰util方法
@Service
@Slf4j
public class SfServiceImpl implements SfService {

    @Autowired
    private SfUtils sfUtils;


    @Override
    public SfMsgDto pushOrder(SfOrder req) {
        return sfUtils.commonHttp(JSON.toJSONString(req),SfServiceCodeEnum.EXP_RECE_CREATE_ORDER.getValue());
    }
}

 其他的顺丰接口都是按照此方法去调用就行了,官网上面接口文档上面生成相应入参就可以了。

接口太多,入参跟响应对象太多就不一一放了。如果有什么不清楚的可以留言或者私聊

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐