根据产品大大的需求描述:
PS: 在寻找AIP时, 可根据需求的不同, 寻找对应的API文档.
找到官方API时, 当时的我感觉调用订单API的方式应该和其他API是一样的, 有了京东宙斯账号就可以, 但…实践调用以后, 很明显我错了.
在调用订单API时, 它返回了一个错误信息给我: 该api是敏感api,请将您的app入驻云鼎平台方可调用
返回的这条信息很明显的告诉我, 要我去申请京东云鼎平台的账号,并且还要入驻.
PS: 入驻云鼎是要钱的, 因为要购买云主机.
入驻京东云鼎的具体流程这里我就展开讲述了, 官方有一套很完善的流程.
这是京东官方入驻云鼎的流程, 如果有感兴趣的小伙伴想了解一下可以点击这个链接: 入鼎公告
至此, 准备工作完成.
PS: 之所以要创建一个新的项目并部署到云鼎, 是因为订单API是属于敏感类型的, 只能内部调用.
京东官方订单API文档
/**
* @Author 蠕动的小蜗牛
* @Description 根据条件检索订单信息 (仅适用于SOP、LBP,SOPL类型,FBP类型请调取FBP订单检索 jingdong.pop.order.search)
* @Date 16:45 2019/8/13
* @Param [accessToken, startDateStr, endDateStr]
* @Param [accessToken, 开始时间, 结束时间, 订单状态, 返回字段, 查询类型, 当前页, 页大小]
* @return com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.enSearch.OrderListResult
**/
public OrderListResult findAllOrderData(String accessToken, String startDateStr, String endDateStr,
String orderState, String optionalFields, Integer dateType,
String page, String pageSize){
try {
JdClient client = new DefaultJdClient(SERVER_URL, accessToken, APPKEY, APPSECRET);
PopOrderEnSearchRequest request = new PopOrderEnSearchRequest();
/** WAIT_SELLER_STOCK_OUT 等待出库,则start_date可以为否(开始时间和结束时间均为空,默认返回前一个月的订单),
order_state为其他值,则start_date必须为是(开始时间和结束时间,不得相差超过1个月。此时间仅针对订单状态及运单号修改的时间) */
request.setStartDate(startDateStr);
/** WAIT_SELLER_STOCK_OUT 等待出库,则start_date可以为否(开始时间和结束时间均为空,默认返回前一个月的订单),
order_state为其他值,则start_date必须为是(开始时间和结束时间,不得相差超过1个月。此时间仅针对订单状态及运单号修改的时间) */
request.setEndDate(endDateStr);
/** 多订单状态可以用英文逗号隔开,请用英文逗号拼接英文状态传递给jos,而不是数字。
1)WAIT_SELLER_STOCK_OUT 等待出库
2)WAIT_GOODS_RECEIVE_CONFIRM 等待确认收货
3)WAIT_SELLER_DELIVERY 等待发货(只适用于海外购商家,含义为'等待境内发货'标签下的订单,非海外购商家无需使用)
4) PAUSE 暂停(loc订单可通过此状态获取)
5)FINISHED_L 完成
6)TRADE_CANCELED 取消
7)LOCKED 已锁定
8)POP_ORDER_PAUSE pop业务暂停,如3c号卡/履约/黄金 可传此状态。*/
request.setOrderState(orderState); // 测试接口阶段, 查询 已取消的订单
/** 需返回的字段列表。可选值,请参考返回结果集中的对象参数描述:orderInfo结构体中的所有字段;字段之间用,分隔 */
request.setOptionalFields(optionalFields);
/** 查询的页数 */
request.setPage(page);
/** 每页的条数(最大page_size 100条) */
request.setPageSize(pageSize);
/** 排序方式,默认升序,1是降序,其它数字都是升序 */
request.setSortType(1);
/** 查询时间类型,默认按修改时间查询。 1为按订单创建时间查询;其它数字为按订单(订单状态、修改运单号)修改时间 */
request.setDateType(dateType);
PopOrderEnSearchResponse response = client.execute(request);
LOGGER.warn(" 京东旗舰店订单信息: " + JSONUtils.toJsonString(response));
if (response.getSearchorderinfoResult() != null) {
LOGGER.warn("************ 查询京东旗舰店订单信息成功 ************");
OrderListResult searchorderinfoResult = response.getSearchorderinfoResult();
return searchorderinfoResult;
}
} catch (Exception e) {
LOGGER.error("************ 查询京东旗舰店订单信息失败 ************", e);
e.printStackTrace();
}
return null;
}
package XXXX;
import com.alibaba.fastjson.JSONObject;
import com.jd.open.api.sdk.DefaultJdClient;
import com.jd.open.api.sdk.JdClient;
import com.jd.open.api.sdk.domain.delivery.DeliveryCompany;
import com.jd.open.api.sdk.domain.order.OrderNotPayService.response.notPayOrderInfo.OrderDataNotPayInfo;
import com.jd.open.api.sdk.domain.order.OrderNotPayService.response.notPayOrderInfo.PaginatedInfo;
import com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.enSearch.OrderListResult;
import com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.get.OrderResult;
import com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.get.OrderSearchInfo;
import com.jd.open.api.sdk.domain.order.OrderShipmentService.response.shipment.OperatorResult;
import com.jd.open.api.sdk.request.delivery.GetVenderAllDeliveryCompanyRequest;
import com.jd.open.api.sdk.request.imgzone.ImgzoneCategoryQueryRequest;
import com.jd.open.api.sdk.request.imgzone.ImgzonePictureUploadRequest;
import com.jd.open.api.sdk.request.order.PopOrderEnSearchRequest;
import com.jd.open.api.sdk.request.order.PopOrderGetRequest;
import com.jd.open.api.sdk.request.order.PopOrderNotPayOrderInfoRequest;
import com.jd.open.api.sdk.request.order.PopOrderShipmentRequest;
import com.jd.open.api.sdk.response.delivery.GetVenderAllDeliveryCompanyResponse;
import com.jd.open.api.sdk.response.imgzone.ImgzoneCategory;
import com.jd.open.api.sdk.response.imgzone.ImgzoneCategoryQueryResponse;
import com.jd.open.api.sdk.response.imgzone.ImgzonePictureUploadResponse;
import com.jd.open.api.sdk.response.order.PopOrderEnSearchResponse;
import com.jd.open.api.sdk.response.order.PopOrderGetResponse;
import com.jd.open.api.sdk.response.order.PopOrderNotPayOrderInfoResponse;
import com.jd.open.api.sdk.response.order.PopOrderShipmentResponse;
import XXX.Config;
import XXX.JSONUtils;
import XXX.CollectionUtils;
import XXX.DateUtils;
import XXX.HttpUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.net.URLEncoder;
import java.util.*;
/**
* @ClassName JdService
* @Description: 京东API接口相关
* @Auther: 蠕动的小蜗牛
* @Date: 2019/4/16 16:05
* @Version: 1.0
**/
@Service
public class JdService {
private static final Logger LOGGER = LoggerFactory.getLogger(JdService.class);
/**
* appKey
*/
private String APPKEY = "XXX";
/**
* AppSecret
*/
private String APPSECRET = "XXX";
/**
* 接口版本
*/
private String V = "2.0";
/**
* 接口URL(线上)
*/
private String SERVER_URL = "https://api.jd.com/routerjson";
@Resource
private Config config;
/**
* @Author 蠕动的小蜗牛
* @Description sop出库发货接口 (jingdong.pop.order.shipment)
* @Date 10:32 2019/8/17
* @Param [accessToken, orderId, logiCoprId, logiNo, installId]
* @Param [accessToken, 订单号, 物流公司ID, 运单号, 安装公司]
* @return 0 发货失败, 1 发货成功
**/
public Boolean doShipment(String accessToken, Long orderId, String logiCoprId, String logiNo, Long installId){
try {
JdClient client = new DefaultJdClient(SERVER_URL, accessToken, APPKEY, APPSECRET);
PopOrderShipmentRequest request = new PopOrderShipmentRequest();
request.setOrderId(orderId);
/** 物流公司ID(只可通过获取商家物流公司接口获得),多个物流公司以|分隔。
如:2100|4700。请注意:如果填写厂家自送(1274),
则不会保存物流单号,也不会有具体的跟踪信息。 request.setLogiCoprId("2100|4700") */
request.setLogiCoprId(logiCoprId);
/** 运单号(当厂家自送时运单号可为空,不同物流公司的运单号用|分隔,
如果同一物流公司有多个运单号,则用英文逗号分隔) 。
如:1200458628372,111232|468778814888,323232323
request.setLogiNo("1200458628372,111232|468778814888,323232323 "); */
request.setLogiNo(logiNo);
request.setInstallId(installId);
PopOrderShipmentResponse response = client.execute(request);
LOGGER.warn("************* sop出库发货接口: " + JSONUtils.toJsonString(response));
OperatorResult sopjosshipmentResult = response.getSopjosshipmentResult();
if (sopjosshipmentResult != null) {
return sopjosshipmentResult.getSuccess();
}
return false;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* @Author 蠕动的小蜗牛
* @Description 获取商家物流公司
* @Date 11:46 2019/8/17
* @Param [accessToken]
* @return void
**/
public List<DeliveryCompany> findAllJdCompanyData(String accessToken){
try {
JdClient client = new DefaultJdClient(SERVER_URL, accessToken, APPKEY, APPSECRET);
GetVenderAllDeliveryCompanyRequest request = new GetVenderAllDeliveryCompanyRequest();
request.setFields("id,name,description");
GetVenderAllDeliveryCompanyResponse response = client.execute(request);
LOGGER.warn("获取商家物流公司: " + JSONUtils.toJsonString(response));
List<DeliveryCompany> deliveryList = response.getDeliveryList();
if (CollectionUtils.notEmpty(deliveryList)) return deliveryList;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @Author 蠕动的小蜗牛
* @Description 输入单个SOP订单id,得到所有相关订单信息 (jingdong.pop.order.get) 拼接URI
* @Date 16:03 2019/8/14
* @Param [accessToken, optionalFields, orderId]
* @Param [accessToken, 返回字段, orderId]
* @return com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.get.OrderSearchInfo
**/
public JSONObject findOrderData(String accessToken, String optionalFields, Long orderId, String pin){
// 生成签名
String method = "jingdong.pop.order.get";
String timestamp = DateUtils.convertDate2String(null, new Date());
Map<String, Object> map = new HashMap<>();
map.put("optional_fields", optionalFields);
map.put("order_id", orderId);
map.put("pin", pin);
String requestParam = JSONUtils.toJsonString(map);
HashMap<String, Object> params = new HashMap<>();
params.put("v", V);
params.put("method", method);
params.put("timestamp", timestamp);
params.put("app_key", APPKEY);
params.put("app_secret", APPSECRET);
params.put("access_token", accessToken);
params.put("360buy_param_json", map);
String sign = jdSign(params);
try {
// 拼接URL
String url = SERVER_URL + "?v=" + V +
"&method=" + method +
"&app_key=" + APPKEY +
"&access_token=" + accessToken +
"&360buy_param_json=" + URLEncoder.encode(requestParam, "UTF-8") +
"×tamp=" + URLEncoder.encode(timestamp, "UTF-8") +
"&sign=" + sign;
JSONObject jsonObject = HttpUtils.doGetJson(url);
LOGGER.warn("===============京东API 输入单个SOP订单id,得到所有相关订单信息: " + jsonObject.toString() + "=====================");
return jsonObject;
} catch (Exception e) {
LOGGER.warn("=============== 京东API 输入单个SOP订单id,得到所有相关订单信息!!! =====================");
e.printStackTrace();
}
return null;
}
/**
* @Author 蠕动的小蜗牛
* @Description 输入单个SOP订单id,得到所有相关订单信息 (jingdong.pop.order.get)
* @Date 16:03 2019/8/14
* @Param [accessToken, optionalFields, orderId]
* @Param [accessToken, 返回字段, orderId]
* @return com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.get.OrderSearchInfo
**/
public OrderResult findOrderDetailsData(String accessToken, String optionalFields, Long orderId){
try {
JdClient client = new DefaultJdClient(SERVER_URL, accessToken, APPKEY, APPSECRET);
PopOrderGetRequest request = new PopOrderGetRequest();
// request.setOrderState("WAIT_SELLER_DELIVERY"); // 不是必填
if (StringUtils.isBlank(optionalFields)) optionalFields = "pin";
request.setOptionalFields(optionalFields);
request.setOrderId(orderId); // 订单号,并且有效的订单号
PopOrderGetResponse response = client.execute(request);
LOGGER.warn("输入单个SOP订单id,得到所有相关订单信息: " + JSONUtils.toJsonString(response));
OrderResult orderDetailInfo = response.getOrderDetailInfo();
if (orderDetailInfo != null) return orderDetailInfo;
} catch (Exception e) {
LOGGER.warn("****************** 输入单个SOP订单id,得到所有相关订单信息失败 *****************");
e.printStackTrace();
}
return null;
}
/**
* @Author 蠕动的小蜗牛
* @Description 批量查询未付款订单(jingdong.pop.order.notPayOrderInfo)
* @Date 15:22 2019/8/14
* @Param [accessToken, startDateStr, endDateStr, page, pageSize]
* @Param [accessToken, 开始时间, 结束时间, 当前页, 页大小]
* @return java.util.List
**/
public List<OrderDataNotPayInfo> findWaitPayOrderData(String accessToken, Date startDateStr, Date endDateStr,
Integer page, Integer pageSize){
try {
JdClient client = new DefaultJdClient(SERVER_URL, accessToken, APPKEY, APPSECRET);
PopOrderNotPayOrderInfoRequest request = new PopOrderNotPayOrderInfoRequest();
request.setStartDate(startDateStr);
request.setEndDate(endDateStr);
request.setPage(page);
request.setPageSize(pageSize);
PopOrderNotPayOrderInfoResponse response = client.execute(request);
LOGGER.warn("***************** 批量查询未付款订单: " + JSONUtils.toJsonString(response));
PaginatedInfo paginatedInfo = response.getPaginatedInfo();
if (paginatedInfo != null) {
List<OrderDataNotPayInfo> pageList = paginatedInfo.getPageList();
if (CollectionUtils.notEmpty(pageList)) return pageList;
}
} catch (Exception e) {
LOGGER.warn("***************** 批量查询未付款订单失败 *****************");
e.printStackTrace();
}
return null;
}
/**
* @Author 蠕动的小蜗牛
* @Description 根据条件检索订单信息 (仅适用于SOP、LBP,SOPL类型,FBP类型请调取FBP订单检索 jingdong.pop.order.search)
* @Date 16:45 2019/8/13
* @Param [accessToken, startDateStr, endDateStr]
* @Param [accessToken, 开始时间, 结束时间, 订单状态, 返回字段, 查询类型, 当前页, 页大小]
* @return com.jd.open.api.sdk.domain.order.OrderQueryJsfService.response.enSearch.OrderListResult
**/
public OrderListResult findAllOrderData(String accessToken, String startDateStr, String endDateStr,
String orderState, String optionalFields, Integer dateType,
String page, String pageSize){
try {
JdClient client = new DefaultJdClient(SERVER_URL, accessToken, APPKEY, APPSECRET);
PopOrderEnSearchRequest request = new PopOrderEnSearchRequest();
/** WAIT_SELLER_STOCK_OUT 等待出库,则start_date可以为否(开始时间和结束时间均为空,默认返回前一个月的订单),
order_state为其他值,则start_date必须为是(开始时间和结束时间,不得相差超过1个月。此时间仅针对订单状态及运单号修改的时间) */
request.setStartDate(startDateStr);
/** WAIT_SELLER_STOCK_OUT 等待出库,则start_date可以为否(开始时间和结束时间均为空,默认返回前一个月的订单),
order_state为其他值,则start_date必须为是(开始时间和结束时间,不得相差超过1个月。此时间仅针对订单状态及运单号修改的时间) */
request.setEndDate(endDateStr);
/** 多订单状态可以用英文逗号隔开,请用英文逗号拼接英文状态传递给jos,而不是数字。
1)WAIT_SELLER_STOCK_OUT 等待出库
2)WAIT_GOODS_RECEIVE_CONFIRM 等待确认收货
3)WAIT_SELLER_DELIVERY 等待发货(只适用于海外购商家,含义为'等待境内发货'标签下的订单,非海外购商家无需使用)
4) PAUSE 暂停(loc订单可通过此状态获取)
5)FINISHED_L 完成
6)TRADE_CANCELED 取消
7)LOCKED 已锁定
8)POP_ORDER_PAUSE pop业务暂停,如3c号卡/履约/黄金 可传此状态。*/
request.setOrderState(orderState); // 测试接口阶段, 查询 已取消的订单
/** 需返回的字段列表。可选值,请参考返回结果集中的对象参数描述:orderInfo结构体中的所有字段;字段之间用,分隔 */
request.setOptionalFields(optionalFields);
/** 查询的页数 */
request.setPage(page);
/** 每页的条数(最大page_size 100条) */
request.setPageSize(pageSize);
/** 排序方式,默认升序,1是降序,其它数字都是升序 */
request.setSortType(1);
/** 查询时间类型,默认按修改时间查询。 1为按订单创建时间查询;其它数字为按订单(订单状态、修改运单号)修改时间 */
request.setDateType(dateType);
PopOrderEnSearchResponse response = client.execute(request);
LOGGER.warn(" 京东旗舰店订单信息: " + JSONUtils.toJsonString(response));
if (response.getSearchorderinfoResult() != null) {
LOGGER.warn("************ 查询京东旗舰店订单信息成功 ************");
OrderListResult searchorderinfoResult = response.getSearchorderinfoResult();
return searchorderinfoResult;
}
} catch (Exception e) {
LOGGER.error("************ 查询京东旗舰店订单信息失败 ************", e);
e.printStackTrace();
}
return null;
}
/**
* @Author 蠕动的小蜗牛
* @Description 上传单张图片
* @Date 11:29 2019/7/17
* @Param [accessToken, imageData, pictureCateId, pictureName]
* @Param [accessToken, 图片二进制文件流,允许png、jpg、gif、jpeg、bmp图片格式,1M以内,
* 上传到的图片分类ID,为空上传至 默认分类,
* 图片名称,不超过64字节,为空默认 未命名]
* @return com.alibaba.fastjson.JSONObject
**/
public ImgzonePictureUploadResponse pictureUpload(String accessToken, byte[] imageData, Long pictureCateId, String pictureName){
try {
JdClient client = new DefaultJdClient(SERVER_URL, accessToken, APPKEY, APPSECRET);
ImgzonePictureUploadRequest request = new ImgzonePictureUploadRequest();
request.setImageData(imageData);
request.setPictureCateId(pictureCateId);
request.setPictureName(pictureName);
ImgzonePictureUploadResponse response = client.execute(request);
LOGGER.warn("===============京东API 上传单张图片: " + JSONUtils.toJsonString(response) + "=====================");
return response;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @Author 蠕动的小蜗牛
* @Description 查询图片分类(所有参数为非必填, 不填时查询所有)
* @Date 14:04 2019/7/17
* @Param [accessToken, cateId, cateName, parentCateId]
* @Param [accessToken, 分类ID, 分类名称,不支持模糊查询, 父分类ID,查询二级分类时为对应父分类id,查询一级分类时为0,查询全部分类的时候为空]
* @return com.jd.open.api.sdk.response.imgzone.ImgzoneCategoryQueryResponse
**/
public List<ImgzoneCategory> imgzoneCategoryQuery(String accessToken, Long cateId, String cateName, Long parentCateId) {
try {
JdClient client = new DefaultJdClient(SERVER_URL, accessToken, APPKEY, APPSECRET);
ImgzoneCategoryQueryRequest request = new ImgzoneCategoryQueryRequest();
request.setCateId(cateId);
request.setCateName(cateName);
request.setParentCateId(parentCateId);
ImgzoneCategoryQueryResponse response = client.execute(request);
List<ImgzoneCategory> cateList = response.getCateList();
if (CollectionUtils.notEmpty(cateList)) {
return cateList;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @Author 蠕动的小蜗牛
* @Description 京东签名规则
* 1. 所有请求参数按照字母先后顺序排列. 例如: 将access_token,app_key,method,timestamp,v 排序为access_token,app_key,method,timestamp,v
* 2. 把所有参数名和参数值进行拼装. 例如:access_tokenxxxapp_keyxxxmethodxxxxxxtimestampxxxxxxvx
* 3. 把appSecret夹在字符串的两端 例如:appSecret+XXXX+appSecret
* 4. 使用MD5进行加密,再转化成大写
* @Date 10:24 2019/6/14
* @Param [params, appSecret]
* @return java.lang.String
**/
public String jdSign(HashMap<String, Object> params) {
StringBuilder valueSb = new StringBuilder();
valueSb.append(APPSECRET);
// 1. 将参数以参数名的字典升序排序
Map<String, Object> sortParams = new TreeMap<>(params);
Set<Map.Entry<String, Object>> entrys = sortParams.entrySet();
// 2. 遍历排序的字典,并拼接value1+value2......格式
for (Map.Entry<String, Object> entry : entrys) {
valueSb.append(entry.getValue());
}
// 3. 把appSecret夹在字符串的两端
valueSb.append(APPSECRET);
String sign = null;
try {
// 4. 使用MD5进行加密,再转化成大写
String inStr = valueSb.toString();
sign = DigestUtils.md5Hex(inStr.getBytes("UTF-8"));
} catch (Exception e) {
throw new RuntimeException("MD5签名过程中出现错误");
}
return sign.toUpperCase();
}
}
PS: 记录日常开发中的点点滴滴…