Quellcode durchsuchen

:sparkles: #1009 实现微信小程序物流助手相关接口

* 快递公司

* 绑定、解绑物流账号

* 配置面单打印员

* 获取打印员

* 增加微信文档地址说明

* 快递下单

* 快递下单和订单操作

* 补充文档地址
mrxiao vor 5 Jahren
Ursprung
Commit
80f885fbfb
21 geänderte Dateien mit 1736 neuen und 1 gelöschten Zeilen
  1. 203 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaExpressService.java
  2. 5 1
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java
  3. 98 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaExpressServiceImpl.java
  4. 4 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java
  5. 103 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/WxMaExpressAccount.java
  6. 83 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/WxMaExpressDelivery.java
  7. 75 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/WxMaExpressPath.java
  8. 44 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/WxMaExpressPrinter.java
  9. 169 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressAddOrderRequest.java
  10. 73 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressBindAccountRequest.java
  11. 63 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressGetOrderRequest.java
  12. 74 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderCargo.java
  13. 33 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderCargoDetail.java
  14. 43 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderInsured.java
  15. 110 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderPerson.java
  16. 55 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderShop.java
  17. 54 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressPrinterUpdateRequest.java
  18. 94 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressTestUpdateOrderRequest.java
  19. 70 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/result/WxMaExpressOrderInfoResult.java
  20. 52 0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java
  21. 231 0
      weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaExpressServiceImplTest.java

+ 203 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaExpressService.java

@@ -0,0 +1,203 @@
+package cn.binarywang.wx.miniapp.api;
+
+import cn.binarywang.wx.miniapp.bean.express.WxMaExpressAccount;
+import cn.binarywang.wx.miniapp.bean.express.WxMaExpressDelivery;
+import cn.binarywang.wx.miniapp.bean.express.WxMaExpressPath;
+import cn.binarywang.wx.miniapp.bean.express.WxMaExpressPrinter;
+import cn.binarywang.wx.miniapp.bean.express.request.*;
+import cn.binarywang.wx.miniapp.bean.express.result.WxMaExpressOrderInfoResult;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+import java.util.List;
+
+/**
+ * 小程序物流助手
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+public interface WxMaExpressService {
+  /**
+   * 获取支持的快递公司列表
+   */
+  String ALL_DELIVERY_URL = "https://api.weixin.qq.com/cgi-bin/express/business/delivery/getall";
+
+  /**
+   * 获取所有绑定的物流账号
+   */
+  String ALL_ACCOUNT_URL = "https://api.weixin.qq.com/cgi-bin/express/business/account/getall";
+
+  /**
+   * 绑定、解绑物流账号
+   */
+  String BIND_ACCOUNT_URL = "https://api.weixin.qq.com/cgi-bin/express/business/account/bind";
+
+  /**
+   * 获取电子面单余额
+   */
+  String GET_QUOTA_URL = "https://api.weixin.qq.com/cgi-bin/express/business/quota/get";
+
+  /**
+   * 配置面单打印员
+   */
+  String UPDATE_PRINTER_URL = "https://api.weixin.qq.com/cgi-bin/express/business/printer/update";
+
+  /**
+   * 获取打印员
+   */
+  String GET_PRINTER_URL = "https://api.weixin.qq.com/cgi-bin/express/business/printer/getall";
+
+  /**
+   * 生成运单
+   */
+  String ADD_ORDER_URL = "https://api.weixin.qq.com/cgi-bin/express/business/order/add";
+
+  /**
+   * 批量获取运单数据
+   */
+  String BATCH_GET_ORDER_URL = "https://api.weixin.qq.com/cgi-bin/express/business/order/batchget";
+
+  /**
+   * 取消运单
+   */
+  String CANCEL_ORDER_URL = "https://api.weixin.qq.com/cgi-bin/express/business/order/cancel";
+
+  /**
+   * 获取运单数据
+   */
+  String GET_ORDER_URL = "https://api.weixin.qq.com/cgi-bin/express/business/order/get";
+
+  /**
+   * 查询运单轨迹
+   */
+  String GET_PATH_URL = "https://api.weixin.qq.com/cgi-bin/express/business/path/get";
+
+  /**
+   * 模拟快递公司更新订单状态
+   */
+  String TEST_UPDATE_ORDER_URL = "https://api.weixin.qq.com/cgi-bin/express/business/test_update_order";
+
+  /**
+   * 获取支持的快递公司列表
+   * @return  快递公司列表
+   * @throws WxErrorException 获取失败时返回
+   * <pre>
+   *   <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.getAllDelivery.html">查看文档</a>
+   * </pre>
+   */
+  List<WxMaExpressDelivery> getAllDelivery() throws WxErrorException;
+
+  /**
+   * 获取所有绑定的物流账号
+   * @return 物流账号list
+   * @throws WxErrorException 获取失败时返回
+   * <pre>
+   *   <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.getAllAccount.html">查看文档</a>
+   * </pre>
+   */
+  List<WxMaExpressAccount> getAllAccount() throws WxErrorException;
+
+  /**
+   * 绑定、解绑物流账号
+   * @param wxMaExpressBindAccountRequest 物流账号对象
+   * @throws WxErrorException 请求失败时返回
+   * <pre>
+   *   <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.bindAccount.html">查看文档</a>
+   * </pre>
+   */
+  void bindAccount(WxMaExpressBindAccountRequest wxMaExpressBindAccountRequest) throws WxErrorException;
+
+  /**
+   * 获取电子面单余额。仅在使用加盟类快递公司时,才可以调用。
+   * @param wxMaExpressBindAccountRequest 物流账号对象
+   * @return 电子面单余额
+   * @throws WxErrorException 获取失败时返回
+   * <pre>
+   *   <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.getQuota.html">查看文档</a>
+   * </pre>
+   */
+  Integer getQuota(WxMaExpressBindAccountRequest wxMaExpressBindAccountRequest) throws WxErrorException;
+
+  /**
+   * 配置面单打印员,可以设置多个,若需要使用微信打单 PC 软件,才需要调用。
+   * @param wxMaExpressPrinterUpdateRequest  面单打印员对象
+   * @throws WxErrorException 请求失败时返回
+   * <pre>
+   *   <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.updatePrinter.html">查看文档</a>
+   * </pre>
+   */
+  void updatePrinter(WxMaExpressPrinterUpdateRequest wxMaExpressPrinterUpdateRequest) throws WxErrorException;
+
+  /**
+   * 获取打印员。若需要使用微信打单 PC 软件,才需要调用
+   * @return 打印员
+   * @throws WxErrorException 获取失败时返回
+   * <pre>
+   *   <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.getPrinter.html">查看文档</a>
+   * </pre>
+   */
+  WxMaExpressPrinter getPrinter() throws WxErrorException;
+
+  /**
+   * 生成运单
+   * @param wxMaExpressAddOrderRequest 生成运单请求对象
+   * @return 生成运单结果
+   * @throws WxErrorException 请求失败时返回
+   * <pre>
+   *   <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.addOrder.html">查看文档</a>
+   * </pre>
+   */
+  WxMaExpressOrderInfoResult addOrder(WxMaExpressAddOrderRequest wxMaExpressAddOrderRequest) throws WxErrorException;
+
+  /**
+   * 批量获取运单数据
+   * @param requests 获取运单请求对象集合,最多不能超过1000个
+   * @return 运单信息集合
+   * @throws WxErrorException 获取失败时返回
+   * <pre>
+   *   <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.batchGetOrder.html">查看文档</a>
+   * </pre>
+   */
+  List<WxMaExpressOrderInfoResult> batchGetOrder(List<WxMaExpressGetOrderRequest> requests) throws WxErrorException;
+
+  /**
+   * 取消运单
+   * @param wxMaExpressGetOrderRequest 运单信息请求对象
+   * @throws WxErrorException 取消失败时返回
+   * <pre>
+   *   <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.cancelOrder.html">查看文档</a>
+   * </pre>
+   */
+  void cancelOrder(WxMaExpressGetOrderRequest wxMaExpressGetOrderRequest) throws WxErrorException;
+
+  /**
+   * 获取运单数据
+   * @param wxMaExpressGetOrderRequest 运单信息请求对象
+   * @return 运单信息
+   * @throws WxErrorException 获取失败时返回
+   * <pre>
+   *   <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.getOrder.html">查看文档</a>
+   * </pre>
+   */
+  WxMaExpressOrderInfoResult getOrder(WxMaExpressGetOrderRequest wxMaExpressGetOrderRequest) throws WxErrorException;
+
+  /**
+   * 查询运单轨迹
+   * @param wxMaExpressGetOrderRequest 运单信息请求对象
+   * @return 运单轨迹对象
+   * @throws WxErrorException 查询失败时返回
+   * <pre>
+   *   <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.getPath.html">查看文档</a>
+   * </pre>
+   */
+  WxMaExpressPath getPath(WxMaExpressGetOrderRequest wxMaExpressGetOrderRequest) throws WxErrorException;
+
+  /**
+   * 模拟快递公司更新订单状态, 该接口只能用户测试
+   * @param wxMaExpressTestUpdateOrderRequest  模拟快递公司更新订单状态请求对象
+   * @throws WxErrorException 模拟更新订单状态失败时返回
+   * <pre>
+   *   <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/express/by-business/logistics.testUpdateOrder.html">查看文档</a>
+   * </pre>
+   */
+  void testUpdateOrder(WxMaExpressTestUpdateOrderRequest wxMaExpressTestUpdateOrderRequest) throws WxErrorException;
+}

+ 5 - 1
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java

@@ -224,5 +224,9 @@ public interface WxMaService {
    */
   RequestHttp getRequestHttp();
 
-
+  /**
+   * 获取物流助手接口服务对象
+   * @return
+   */
+  WxMaExpressService getExpressService();
 }

+ 98 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaExpressServiceImpl.java

@@ -0,0 +1,98 @@
+package cn.binarywang.wx.miniapp.api.impl;
+
+import cn.binarywang.wx.miniapp.api.WxMaExpressService;
+import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.bean.express.WxMaExpressAccount;
+import cn.binarywang.wx.miniapp.bean.express.WxMaExpressDelivery;
+import cn.binarywang.wx.miniapp.bean.express.WxMaExpressPath;
+import cn.binarywang.wx.miniapp.bean.express.WxMaExpressPrinter;
+import cn.binarywang.wx.miniapp.bean.express.request.*;
+import cn.binarywang.wx.miniapp.bean.express.result.WxMaExpressOrderInfoResult;
+import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
+import lombok.AllArgsConstructor;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@AllArgsConstructor
+public class WxMaExpressServiceImpl implements WxMaExpressService {
+
+  private WxMaService wxMaService;
+
+  @Override
+  public List<WxMaExpressDelivery> getAllDelivery() throws WxErrorException {
+    String responseContent = this.wxMaService.get(ALL_DELIVERY_URL, null);
+    return WxMaExpressDelivery.fromJson(responseContent);
+  }
+
+  @Override
+  public List<WxMaExpressAccount> getAllAccount() throws WxErrorException {
+    String responseContent = this.wxMaService.get(ALL_ACCOUNT_URL, null);
+    return WxMaExpressAccount.fromJsonList(responseContent);
+  }
+
+  @Override
+  public void bindAccount(WxMaExpressBindAccountRequest wxMaExpressBindAccountRequest) throws WxErrorException {
+    this.wxMaService.post(BIND_ACCOUNT_URL,wxMaExpressBindAccountRequest.toJson());
+  }
+
+  @Override
+  public Integer getQuota(WxMaExpressBindAccountRequest wxMaExpressBindAccountRequest) throws WxErrorException {
+    String responseContent = this.wxMaService.post(GET_QUOTA_URL,wxMaExpressBindAccountRequest.toJson());
+    WxMaExpressAccount account = WxMaExpressAccount.fromJson(responseContent);
+    return account.getQuotaNum();
+  }
+
+  @Override
+  public void updatePrinter(WxMaExpressPrinterUpdateRequest wxMaExpressPrinterUpdateRequest) throws WxErrorException {
+    this.wxMaService.post(UPDATE_PRINTER_URL,wxMaExpressPrinterUpdateRequest.toJson());
+  }
+
+  @Override
+  public WxMaExpressPrinter getPrinter() throws WxErrorException {
+    String responseContent = this.wxMaService.get(GET_PRINTER_URL, null);
+    return WxMaExpressPrinter.fromJson(responseContent);
+  }
+
+  @Override
+  public WxMaExpressOrderInfoResult addOrder(WxMaExpressAddOrderRequest wxMaExpressAddOrderRequest) throws WxErrorException {
+    String responseContent = this.wxMaService.post(ADD_ORDER_URL,wxMaExpressAddOrderRequest.toJson());
+    return WxMaExpressOrderInfoResult.fromJson(responseContent);
+  }
+
+  @Override
+  public List<WxMaExpressOrderInfoResult> batchGetOrder(List<WxMaExpressGetOrderRequest> requests) throws WxErrorException {
+    Map<String, Object> param = new HashMap<>(1);
+    param.put("order_list", requests);
+    String responseContent = this.wxMaService.post(BATCH_GET_ORDER_URL, WxMaGsonBuilder.create().toJson(param));
+    return WxMaExpressOrderInfoResult.toList(responseContent);
+  }
+
+  @Override
+  public void cancelOrder(WxMaExpressGetOrderRequest wxMaExpressGetOrderRequest) throws WxErrorException {
+    this.wxMaService.post(CANCEL_ORDER_URL,wxMaExpressGetOrderRequest.toJson());
+  }
+
+  @Override
+  public WxMaExpressOrderInfoResult getOrder(WxMaExpressGetOrderRequest wxMaExpressGetOrderRequest) throws WxErrorException {
+    String responseContent = this.wxMaService.post(GET_ORDER_URL,wxMaExpressGetOrderRequest.toJson());
+    return WxMaExpressOrderInfoResult.fromJson(responseContent);
+  }
+
+  @Override
+  public WxMaExpressPath getPath(WxMaExpressGetOrderRequest wxMaExpressGetOrderRequest) throws WxErrorException {
+    String responseContent = this.wxMaService.post(GET_PATH_URL,wxMaExpressGetOrderRequest.toJson());
+    return WxMaExpressPath.fromJson(responseContent);
+  }
+
+  @Override
+  public void testUpdateOrder(WxMaExpressTestUpdateOrderRequest wxMaExpressTestUpdateOrderRequest) throws WxErrorException {
+    this.wxMaService.post(TEST_UPDATE_ORDER_URL,wxMaExpressTestUpdateOrderRequest.toJson());
+  }
+}

+ 4 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java

@@ -54,6 +54,7 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
   private WxMaRunService runService = new WxMaRunServiceImpl(this);
   private WxMaSecCheckService secCheckService = new WxMaSecCheckServiceImpl(this);
   private WxMaPluginService pluginService = new WxMaPluginServiceImpl(this);
+  private WxMaExpressService expressService = new WxMaExpressServiceImpl(this);
 
   private int retrySleepMillis = 1000;
   private int maxRetryTimes = 5;
@@ -365,4 +366,7 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
   public WxMaPluginService getPluginService() {
     return this.pluginService;
   }
+
+  @Override
+  public WxMaExpressService getExpressService() { return this.expressService; }
 }

+ 103 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/WxMaExpressAccount.java

@@ -0,0 +1,103 @@
+package cn.binarywang.wx.miniapp.bean.express;
+
+import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.reflect.TypeToken;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * <pre>
+ * 物流账号对象
+ * </pre>
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+public class WxMaExpressAccount implements Serializable {
+
+  private static final JsonParser JSON_PARSER = new JsonParser();
+  private static final long serialVersionUID = -4991983596742569736L;
+
+  /**
+   * 快递公司客户编码
+   */
+  @SerializedName("biz_id")
+  private String bizId;
+
+  /**
+   * 快递公司ID
+   */
+  @SerializedName("delivery_id")
+  private String deliveryId;
+
+  /**
+   * 账号绑定时间
+   */
+  @SerializedName("create_time")
+  private Long createTime;
+
+  /**
+   * 账号更新时间
+   */
+  @SerializedName("update_time")
+  private Long updateTime;
+
+  /**
+   * 绑定状态
+   * status_code 的合法值 : 0-绑定成功;1-审核中;2-绑定失败
+   */
+  @SerializedName("status_code")
+  private Integer statusCode;
+
+  /**
+   * 账号别名
+   */
+  @SerializedName("alias")
+  private String alias;
+
+  /**
+   * 账号绑定失败的错误信息(EMS审核结果)
+   */
+  @SerializedName("remark_wrong_msg")
+  private String remarkWrongMsg;
+
+  /**
+   * 账号绑定时的备注内容(提交EMS审核需要)
+   */
+  @SerializedName("remark_content")
+  private String remarkContent;
+
+  /**
+   * 电子面单余额
+   */
+  @SerializedName("quota_num")
+  private Integer quotaNum;
+
+  /**
+   * 电子面单余额更新时间
+   */
+  @SerializedName("quota_update_time")
+  private Integer quotaUpdateTime;
+
+  /**
+   * 支持的服务类型
+   */
+  @SerializedName("service_type")
+  private List<WxMaExpressDelivery.ServiceType> serviceType;
+
+  public static List<WxMaExpressAccount> fromJsonList(String json) {
+    JsonObject jsonObject = JSON_PARSER.parse(json).getAsJsonObject();
+    return WxMaGsonBuilder.create().fromJson(jsonObject.get("list").toString(),
+      new TypeToken<List<WxMaExpressAccount>>() {
+      }.getType());
+  }
+
+  public static WxMaExpressAccount fromJson(String json) {
+    return WxMaGsonBuilder.create().fromJson(json, WxMaExpressAccount.class);
+  }
+}

+ 83 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/WxMaExpressDelivery.java

@@ -0,0 +1,83 @@
+package cn.binarywang.wx.miniapp.bean.express;
+
+import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.reflect.TypeToken;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * <pre>
+ * 快递公司对象
+ * </pre>
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+public class WxMaExpressDelivery implements Serializable {
+  private static final JsonParser JSON_PARSER = new JsonParser();
+  private static final long serialVersionUID = -8394544895730223810L;
+
+  /**
+   * 快递公司 ID
+   */
+  @SerializedName("delivery_id")
+  private String deliveryId;
+
+  /**
+   * 快递公司名称
+   */
+  @SerializedName("delivery_name")
+  private String deliveryName;
+
+  /**
+   * 是否支持散单, 1表示支持
+   */
+  @SerializedName("can_use_cash")
+  private Integer canUseCash;
+
+  /**
+   * 是否支持查询面单余额, 1表示支持
+   */
+  @SerializedName("can_get_quota")
+  private Integer canGetQuota;
+
+  /**
+   * 散单对应的bizid,当can_use_cash=1时有效
+   */
+  @SerializedName("cash_biz_id")
+  private String cashBizId;
+
+  /**
+   * 支持的服务类型
+   */
+  @SerializedName("service_type")
+  private List<ServiceType> serviceType;
+
+  public static List<WxMaExpressDelivery> fromJson(String json) {
+    JsonObject jsonObject = JSON_PARSER.parse(json).getAsJsonObject();
+    return WxMaGsonBuilder.create().fromJson(jsonObject.get("data").toString(),
+      new TypeToken<List<WxMaExpressDelivery>>() {
+      }.getType());
+  }
+
+  @Data
+  public static class ServiceType{
+
+    /**
+     * 服务类型ID
+     */
+    @SerializedName("service_type")
+    private Integer serviceType;
+
+    /**
+     * 服务类型名称
+     */
+    @SerializedName("service_name")
+    private String serviceName;
+  }
+}

+ 75 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/WxMaExpressPath.java

@@ -0,0 +1,75 @@
+package cn.binarywang.wx.miniapp.bean.express;
+
+import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 运单轨迹对象
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+public class WxMaExpressPath implements Serializable {
+
+  private static final long serialVersionUID = 5643624677715536605L;
+
+  /**
+   * 用户openid
+   */
+  private String openid;
+
+  /**
+   * 快递公司 ID
+   */
+  @SerializedName("delivery_id")
+  private String deliveryId;
+
+  /**
+   * 运单 ID
+   */
+  @SerializedName("waybill_id")
+  private String waybillId;
+
+  /**
+   * 轨迹节点数量
+   */
+  @SerializedName("path_item_num")
+  private Integer pathItemNum;
+
+  /**
+   * 轨迹节点列表
+   */
+  @SerializedName("path_item_list")
+  private List<PathItem> pathItemList;
+
+  public static WxMaExpressPath fromJson(String json) {
+    return WxMaGsonBuilder.create().fromJson(json, WxMaExpressPath.class);
+  }
+
+  @Data
+  private static class PathItem{
+
+    /**
+     * 轨迹节点 Unix 时间戳
+     */
+    @SerializedName("action_time")
+    private Long actionTime;
+
+    /**
+     * 轨迹节点类型
+     */
+    @SerializedName("action_type")
+    private Integer actionType;
+
+    /**
+     * 轨迹节点详情
+     */
+    @SerializedName("action_msg")
+    private String actionMsg;
+
+  }
+}

+ 44 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/WxMaExpressPrinter.java

@@ -0,0 +1,44 @@
+package cn.binarywang.wx.miniapp.bean.express;
+
+import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
+import com.google.gson.JsonParser;
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * <pre>
+ * 面单打印员对象
+ * </pre>
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+public class WxMaExpressPrinter implements Serializable {
+
+  private static final JsonParser JSON_PARSER = new JsonParser();
+  private static final long serialVersionUID = 7164449984700322531L;
+
+  /**
+   * 数量
+   */
+  private Integer count;
+
+  /**
+   * 打印员openid
+   */
+  private List<String> openid;
+
+  /**
+   * 打印员面单打印权限
+   */
+  @SerializedName("tagid_list")
+  private List<String> tagidList;
+
+
+  public static WxMaExpressPrinter fromJson(String json) {
+    return WxMaGsonBuilder.create().fromJson(json, WxMaExpressPrinter.class);
+  }
+}

+ 169 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressAddOrderRequest.java

@@ -0,0 +1,169 @@
+package cn.binarywang.wx.miniapp.bean.express.request;
+
+
+import cn.binarywang.wx.miniapp.bean.express.*;
+import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
+import com.google.gson.annotations.SerializedName;
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * <pre>
+ * 生成运单请求对象
+ * </pre>
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+@Builder
+public class WxMaExpressAddOrderRequest implements Serializable {
+
+  private static final long serialVersionUID = -7538739003766268386L;
+
+
+  /**
+   * 订单来源
+   * <pre>
+   * 是否必填: 是
+   * 描述: 0为小程序订单,2为App或H5订单,填2则不发送物流服务通知
+   * </pre>
+   */
+  @SerializedName("add_source")
+  private Integer addSource;
+
+  /**
+   * App或H5的appid
+   * <pre>
+   * 是否必填: 否
+   * 描述: add_source=2时必填,需和开通了物流助手的小程序绑定同一open帐号
+   * </pre>
+   */
+  @SerializedName("wx_appid")
+  private String wxAppid;
+
+  /**
+   * 订单ID
+   * <pre>
+   * 是否必填: 是
+   * 描述: 须保证全局唯一,不超过512字节
+   * </pre>
+   */
+  @SerializedName("order_id")
+  private String orderId;
+
+  /**
+   * 用户openid
+   * <pre>
+   * 是否必填: 否
+   * 描述: 当add_source=2时无需填写(不发送物流服务通知)
+   * </pre>
+   */
+  @SerializedName("openid")
+  private String openid;
+
+  /**
+   * 快递公司ID
+   * <pre>
+   * 是否必填: 是
+   * 描述: 可通过getAllDelivery查询
+   * </pre>
+   */
+  @SerializedName("delivery_id")
+  private String deliveryId;
+
+  /**
+   * 快递客户编码或者现付编码
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("biz_id")
+  private String bizId;
+
+  /**
+   * 快递备注信息
+   * <pre>
+   * 是否必填: 否
+   * 描述: 比如"易碎物品",不超过1024字节
+   * </pre>
+   */
+  @SerializedName("custom_remark")
+  private String customRemark;
+
+  /**
+   * 订单标签id
+   * <pre>
+   * 是否必填: 否
+   * 描述: 用于平台型小程序区分平台上的入驻方,tagid须与入驻方账号一一对应,非平台型小程序无需填写该字段
+   * </pre>
+   */
+  @SerializedName("tagid")
+  private Integer tagid;
+
+  /**
+   * 预期的上门揽件时间
+   * <pre>
+   * 是否必填: 否
+   * 描述: 顺丰必须传,0表示已事先约定取件时间;否则请传预期揽件时间戳,需大于当前时间,收件员会在预期时间附近上门。例如expect_time为“1557989929”,表示希望收件员将在2019年05月16日14:58:49-15:58:49内上门取货。说明:若选择 了预期揽件时间,请不要自己打单,由上门揽件的时候打印。
+   * </pre>
+   */
+  @SerializedName("expect_time")
+  private Long expectTime;
+
+  /**
+   * 发件人信息
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  private WxMaExpressOrderPerson sender;
+
+  /**
+   * 收件人信息
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  private WxMaExpressOrderPerson receiver;
+
+  /**
+   * 包裹信息
+   * <pre>
+   * 是否必填: 是
+   * 描述: 将传递给快递公司
+   * </pre>
+   */
+  private WxMaExpressOrderCargo cargo;
+
+  /**
+   * 商品信息
+   * <pre>
+   * 是否必填: 否
+   * 描述: 会展示到物流服务通知和电子面单中
+   * </pre>
+   */
+  private WxMaExpressOrderShop shop;
+
+  /**
+   * 保价信息
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  private WxMaExpressOrderInsured insured;
+
+  /**
+   * 服务类型
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  private WxMaExpressDelivery.ServiceType service;
+
+
+  public String toJson() {
+    return WxMaGsonBuilder.create().toJson(this);
+  }
+}

+ 73 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressBindAccountRequest.java

@@ -0,0 +1,73 @@
+package cn.binarywang.wx.miniapp.bean.express.request;
+
+import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
+import com.google.gson.annotations.SerializedName;
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * <pre>
+ * 绑定、解绑物流账号请求对象
+ * </pre>
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+@Builder
+public class WxMaExpressBindAccountRequest implements Serializable {
+
+  private static final long serialVersionUID = 3868003945297939946L;
+
+  /**
+   * 类型
+   * <pre>
+   * 是否必填: 是
+   * 描述: bind表示绑定,unbind表示解除绑定
+   * </pre>
+   */
+  @SerializedName("type")
+  private String type;
+
+  /**
+   * 快递公司客户编码
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("biz_id")
+  private String bizId;
+
+  /**
+   * 快递公司ID
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("delivery_id")
+  private String deliveryId;
+
+  /**
+   * 快递公司客户密码
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("password")
+  private String password;
+
+  /**
+   * 备注内容(提交EMS审核需要)
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("remark_content")
+  private String remarkContent;
+
+  public String toJson() {
+    return WxMaGsonBuilder.create().toJson(this);
+  }
+
+}

+ 63 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressGetOrderRequest.java

@@ -0,0 +1,63 @@
+package cn.binarywang.wx.miniapp.bean.express.request;
+
+import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
+import com.google.gson.annotations.SerializedName;
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * <pre>
+ * 获取运单请求对象
+ * </pre>
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+@Builder
+public class WxMaExpressGetOrderRequest implements Serializable {
+
+  private static final long serialVersionUID = 8239315305577639778L;
+
+  /**
+   * 订单ID
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("order_id")
+  private String orderId;
+
+  /**
+   * 用户openid
+   * <pre>
+   * 是否必填: 否
+   * 描述: 当add_source=2时无需填写(不发送物流服务通知)
+   * </pre>
+   */
+  private String openid;
+
+  /**
+   * 快递公司ID
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("delivery_id")
+  private String deliveryId;
+
+  /**
+   * 运单ID
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("waybill_id")
+  private String waybillId;
+
+
+  public String toJson() {
+    return WxMaGsonBuilder.create().toJson(this);
+  }
+}

+ 74 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderCargo.java

@@ -0,0 +1,74 @@
+package cn.binarywang.wx.miniapp.bean.express.request;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 包裹信息对象
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+public class WxMaExpressOrderCargo implements Serializable {
+
+  private static final long serialVersionUID = 6642536671375396150L;
+
+  /**
+   * 包裹数量
+   * <pre>
+   * 是否必填: 是
+   * 描述: 需要和detail_list size保持一致
+   * </pre>
+   */
+  private Integer count;
+  /**
+   * 包裹总重量
+   * <pre>
+   * 是否必填: 是
+   * 描述: 单位是千克(kg)
+   * </pre>
+   */
+  private Integer weight;
+
+  /**
+   * 包裹长度
+   * <pre>
+   * 是否必填: 是
+   * 描述: 单位是厘米(cm)
+   * </pre>
+   */
+  @SerializedName("space_x")
+  private Integer spaceLength;
+
+  /**
+   * 包裹宽度
+   * <pre>
+   * 是否必填: 是
+   * 描述: 单位是厘米(cm)
+   * </pre>
+   */
+  @SerializedName("space_y")
+  private Integer spaceWidth;
+
+  /**
+   * 包裹高度
+   * <pre>
+   * 是否必填: 是
+   * 描述: 单位是厘米(cm)
+   * </pre>
+   */
+  @SerializedName("space_z")
+  private Integer spaceHeight;
+
+  /**
+   * 包裹中商品详情列表
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("detail_list")
+  private List<WxMaExpressOrderCargoDetail> detailList;
+}

+ 33 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderCargoDetail.java

@@ -0,0 +1,33 @@
+package cn.binarywang.wx.miniapp.bean.express.request;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 包裹商品详情对象
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+public class WxMaExpressOrderCargoDetail implements Serializable {
+
+  private static final long serialVersionUID = 5988620921216969796L;
+
+  /**
+   * 商品名
+   * <pre>
+   * 是否必填: 是
+   * 描述: 不超过128字节
+   * </pre>
+   */
+  private String name;
+
+  /**
+   * 商品数量
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  private Integer count;
+}

+ 43 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderInsured.java

@@ -0,0 +1,43 @@
+package cn.binarywang.wx.miniapp.bean.express.request;
+
+
+import cn.binarywang.wx.miniapp.constant.WxMaConstants;
+import com.google.gson.annotations.SerializedName;
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 保价信息对象
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+@Builder
+public class WxMaExpressOrderInsured implements Serializable {
+
+  private static final long serialVersionUID = -8636857630937445422L;
+
+  /**
+   * 是否保价
+   * <pre>
+   * 是否必填: 是
+   * 描述: 0 表示不保价,1 表示保价
+   * </pre>
+   */
+  @SerializedName("use_insured")
+  private final Integer useInsured = WxMaConstants.OrderAddInsured.INSURED_PROGRAM;
+
+  /**
+   * 保价金额
+   * <pre>
+   * 是否必填: 是
+   * 描述: 单位是分,比如: 10000 表示 100 元
+   * </pre>
+   */
+  @SerializedName("insured_value")
+  @Builder.Default
+  private final Integer insuredValue = WxMaConstants.OrderAddInsured.DEFAULT_INSURED_VALUE;
+
+}

+ 110 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderPerson.java

@@ -0,0 +1,110 @@
+package cn.binarywang.wx.miniapp.bean.express.request;
+
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 发件人/收件人信息对象
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+public class WxMaExpressOrderPerson implements Serializable {
+
+  private static final long serialVersionUID = -7816060207882761506L;
+
+  /**
+   * 发件人/收件人姓名
+   * <pre>
+   * 是否必填: 是
+   * 描述: 不超过64字节
+   * </pre>
+   */
+  private String name;
+
+  /**
+   * 发件人/收件人座机号码
+   * <pre>
+   * 是否必填: 否
+   * 描述: 若不填写则必须填写 mobile,不超过32字节
+   * </pre>
+   */
+  private String tel;
+
+  /**
+   * 发件人/收件人手机号码
+   * <pre>
+   * 是否必填: 否
+   * 描述: 若不填写则必须填写 tel,不超过32字节
+   * </pre>
+   */
+  private String mobile;
+
+  /**
+   * 发件人/收件人公司名
+   * <pre>
+   * 是否必填: 否
+   * 描述: 不超过64字节
+   * </pre>
+   */
+  private String company;
+
+  /**
+   * 发件人/收件人邮编
+   * <pre>
+   * 是否必填: 否
+   * 描述: 不超过10字节
+   * </pre>
+   */
+  @SerializedName("post_code")
+  private String postCode;
+
+  /**
+   * 发件人/收件人所在国家
+   * <pre>
+   * 是否必填: 否
+   * 描述: 不超过64字节
+   * </pre>
+   */
+  private String country;
+
+  /**
+   * 发件人/收件人省份
+   * <pre>
+   * 是否必填: 是
+   * 描述: 比如:"广东省",不超过64字节
+   * </pre>
+   */
+  private String province;
+
+  /**
+   * 发件人/收件人地区或市
+   * <pre>
+   * 是否必填: 是
+   * 描述: 比如:"广州市",不超过64字节
+   * </pre>
+   */
+  private String city;
+
+  /**
+   * 发件人/收件人区或县
+   * <pre>
+   * 是否必填: 是
+   * 描述: 比如:"天河区",不超过64字节
+   * </pre>
+   */
+  private String area;
+
+  /**
+   * 发件人/收件人详细地址
+   * <pre>
+   * 是否必填: 是
+   * 描述: 比如:"XX路XX号XX大厦XX",不超过512字节
+   * </pre>
+   */
+  private String address;
+
+}

+ 55 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderShop.java

@@ -0,0 +1,55 @@
+package cn.binarywang.wx.miniapp.bean.express.request;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 商品信息对象
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+public class WxMaExpressOrderShop implements Serializable {
+
+  private static final long serialVersionUID = 7256509453502211830L;
+
+  /**
+   * 商家小程序的路径
+   * <pre>
+   * 是否必填: 是
+   * 描述: 建议为订单页面
+   * </pre>
+   */
+  @SerializedName("wxa_path")
+  private String wxaPath;
+
+  /**
+   * 商品缩略图url
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("img_url")
+  private String imgUrl;
+
+  /**
+   * 商品名称
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("goods_name")
+  private String goodsName;
+
+  /**
+   * 商品数量
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("goods_count")
+  private Integer goodsCount;
+
+}

+ 54 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressPrinterUpdateRequest.java

@@ -0,0 +1,54 @@
+package cn.binarywang.wx.miniapp.bean.express.request;
+
+import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
+import com.google.gson.annotations.SerializedName;
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * <pre>
+ * 配置面单打印员请求对象
+ * </pre>
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+@Builder
+public class WxMaExpressPrinterUpdateRequest implements Serializable {
+
+  private static final long serialVersionUID = 9119040050963924127L;
+
+  /**
+   * 打印员 openid
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  private String openid;
+
+  /**
+   * 更新类型
+   * <pre>
+   * 是否必填: 是
+   * 描述: bind表示绑定,unbind表示解除绑定
+   * </pre>
+   */
+  @SerializedName("update_type")
+  private String updateType;
+
+  /**
+   * 打印员面单打印权限
+   * <pre>
+   * 是否必填: 否
+   * 描述: 用于平台型小程序设置入驻方的打印员面单打印权限,同一打印员最多支持10个tagid,使用逗号分隔,如填写123,456,表示该打印员可以拉取到tagid为123和456的下的单,非平台型小程序无需填写该字段
+   * </pre>
+   */
+  @SerializedName("tagid_list")
+  private String tagidList;
+
+  public String toJson() {
+    return WxMaGsonBuilder.create().toJson(this);
+  }
+}

+ 94 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressTestUpdateOrderRequest.java

@@ -0,0 +1,94 @@
+package cn.binarywang.wx.miniapp.bean.express.request;
+
+import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
+import com.google.gson.annotations.SerializedName;
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * <pre>
+ * 模拟快递公司更新订单状态请求对象
+ * </pre>
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+@Builder
+public class WxMaExpressTestUpdateOrderRequest implements Serializable {
+
+  private static final long serialVersionUID = -3701602332580704140L;
+
+  /**
+   * 商户id
+   * <pre>
+   * 是否必填: 是
+   * 描述: 需填test_biz_id,默认值已设置
+   * </pre>
+   */
+  @SerializedName("biz_id")
+  @Builder.Default
+  private final String bizId = "test_biz_id";
+
+  /**
+   * 快递公司id
+   * <pre>
+   * 是否必填: 是
+   * 描述: 需填TEST,默认值已设置
+   * </pre>
+   */
+  @SerializedName("delivery_id")
+  @Builder.Default
+  private final String deliveryId = "TEST";
+
+  /**
+   * 订单号
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("order_id")
+  private String orderId;
+
+  /**
+   * 运单号
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("waybill_id")
+  private String waybillId;
+
+  /**
+   * 轨迹变化 Unix 时间戳
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("action_time")
+  private Long actionTime;
+
+  /**
+   * 轨迹变化类型
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("action_type")
+  private Integer actionType;
+
+  /**
+   * 轨迹变化具体信息说明,使用UTF-8编码
+   * <pre>
+   * 是否必填: 是
+   * </pre>
+   */
+  @SerializedName("action_msg")
+  private String actionMsg;
+
+  public String toJson() {
+    return WxMaGsonBuilder.create().toJson(this);
+  }
+
+}

+ 70 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/result/WxMaExpressOrderInfoResult.java

@@ -0,0 +1,70 @@
+package cn.binarywang.wx.miniapp.bean.express.result;
+
+import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.reflect.TypeToken;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <pre>
+ * 运单信息返回结果对象
+ * </pre>
+ * @author <a href="https://github.com/mr-xiaoyu">xiaoyu</a>
+ * @since 2019-11-26
+ */
+@Data
+public class WxMaExpressOrderInfoResult implements Serializable {
+  private static final JsonParser JSON_PARSER = new JsonParser();
+  private static final long serialVersionUID = -9166603059965942285L;
+
+  /**
+   * 错误码
+   */
+  private Integer errcode;
+
+  /**
+   * 错误信息
+   */
+  private String errmsg;
+  /**
+   * 订单ID
+   */
+  @SerializedName("order_id")
+  private String orderId;
+
+  /**
+   * 运单ID
+   */
+  @SerializedName("waybill_id")
+  private String waybillId;
+
+  /**
+   * 运单 html 的 BASE64 结果
+   */
+  @SerializedName("print_html")
+  private String printHtml;
+
+  /**
+   * 运单信息
+   */
+  @SerializedName("waybill_data")
+  private List<Map<String,String>> waybillData;
+
+
+  public static WxMaExpressOrderInfoResult fromJson(String json) {
+    return WxMaGsonBuilder.create().fromJson(json, WxMaExpressOrderInfoResult.class);
+  }
+
+  public static List<WxMaExpressOrderInfoResult> toList(String json) {
+    JsonObject jsonObject = JSON_PARSER.parse(json).getAsJsonObject();
+    return WxMaGsonBuilder.create().fromJson(jsonObject.get("order_list").toString(),
+      new TypeToken<List<WxMaExpressOrderInfoResult>>() {
+      }.getType());
+  }
+}

+ 52 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java

@@ -85,4 +85,56 @@ public class WxMaConstants {
      */
     public static final int IMAGE = 2;
   }
+
+  /**
+   * 快递账号绑定类型
+   */
+  public static final class BindAccountType{
+
+    /**
+     * 绑定
+     */
+    public static final String BIND = "bind";
+
+    /**
+     * 解绑
+     */
+    public static final String UNBIND = "unbind";
+  }
+
+  /**
+   * 快递下单订单来源
+   */
+  public static final class OrderAddSource{
+
+    /**
+     * 小程序
+     */
+    public static final int MINI_PROGRAM = 0;
+
+    /**
+     * APP或H5
+     */
+    public static final int APP_OR_H5 = 2;
+  }
+
+  /**
+   * 快递下单保价
+   */
+  public static final class OrderAddInsured{
+    /**
+     * 不保价
+     */
+    public static final int INSURED_PROGRAM = 0;
+
+    /**
+     * 保价
+     */
+    public static final int USE_INSURED = 1;
+
+    /**
+     * 默认保价金额
+     */
+    public static final int DEFAULT_INSURED_VALUE = 0;
+  }
 }

+ 231 - 0
weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaExpressServiceImplTest.java

@@ -0,0 +1,231 @@
+package cn.binarywang.wx.miniapp.api.impl;
+
+import cn.binarywang.wx.miniapp.api.WxMaExpressService;
+import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.bean.express.*;
+import cn.binarywang.wx.miniapp.bean.express.request.*;
+import cn.binarywang.wx.miniapp.bean.express.result.WxMaExpressOrderInfoResult;
+import cn.binarywang.wx.miniapp.constant.WxMaConstants;
+import cn.binarywang.wx.miniapp.test.ApiTestModule;
+import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
+import com.google.inject.Inject;
+import me.chanjar.weixin.common.error.WxErrorException;
+import org.apache.commons.lang3.StringUtils;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+@Guice(modules = ApiTestModule.class)
+public class WxMaExpressServiceImplTest {
+
+  @Inject
+  private WxMaService wxMaService;
+
+  @Test
+  public void testGetAllDelivery() throws WxErrorException {
+    final WxMaExpressService service = wxMaService.getExpressService();
+    List<WxMaExpressDelivery> list = service.getAllDelivery();
+    System.out.println(WxMaGsonBuilder.create().toJson(list));
+  }
+
+  @Test
+  public void testGetAllAccount() throws WxErrorException {
+    final WxMaExpressService service = wxMaService.getExpressService();
+    List<WxMaExpressAccount> list = service.getAllAccount();
+    System.out.println(WxMaGsonBuilder.create().toJson(list));
+  }
+
+  @Test
+  public void testBindAccount() throws WxErrorException {
+    final WxMaExpressService service = wxMaService.getExpressService();
+    WxMaExpressBindAccountRequest request = WxMaExpressBindAccountRequest.builder()
+      .deliveryId("YUNDA")
+      .bizId("******")
+      .password("*********")
+      .remarkContent("####")
+      .type(WxMaConstants.BindAccountType.BIND)
+      .build();
+    service.bindAccount(request);
+  }
+
+  @Test
+  public void testGetQuota() throws WxErrorException {
+    final WxMaExpressService service = wxMaService.getExpressService();
+    WxMaExpressBindAccountRequest request = WxMaExpressBindAccountRequest.builder()
+      .deliveryId("YUNDA")
+      .bizId("******")
+      .build();
+    Integer quotaNum = service.getQuota(request);
+    System.out.println(quotaNum);
+  }
+
+
+
+  @Test
+  public void testUpdatePrinter() throws WxErrorException {
+    final WxMaExpressService service = wxMaService.getExpressService();
+    WxMaExpressPrinterUpdateRequest request = WxMaExpressPrinterUpdateRequest.builder()
+      .openid("*************")
+      .updateType(WxMaConstants.BindAccountType.UNBIND)
+      .build();
+    service.updatePrinter(request);
+  }
+
+  @Test
+  public void testGetPrinter() throws WxErrorException {
+    final WxMaExpressService service = wxMaService.getExpressService();
+    WxMaExpressPrinter printer = service.getPrinter();
+    System.out.println(WxMaGsonBuilder.create().toJson(printer));
+  }
+
+  @Test
+  public void testAddOrder() throws WxErrorException {
+    final WxMaExpressService service = wxMaService.getExpressService();
+
+    WxMaExpressOrderPerson sender = new WxMaExpressOrderPerson();
+    sender.setName("张三");
+    sender.setMobile("177****9809");
+    sender.setProvince("北京市");
+    sender.setCity("朝阳区");
+    sender.setArea("朝阳区");
+    sender.setAddress("西坝河****C-102");
+
+    WxMaExpressOrderPerson receiver = new WxMaExpressOrderPerson();
+    receiver.setName("李四");
+    receiver.setMobile("180****8772");
+    receiver.setProvince("北京市");
+    receiver.setCity("朝阳区");
+    receiver.setArea("朝阳区");
+    receiver.setAddress("西坝河北里****101");
+
+
+    WxMaExpressOrderCargo cargo = new WxMaExpressOrderCargo();
+    List<WxMaExpressOrderCargoDetail> detailList = new ArrayList<>();
+    List<String> shopNames = new ArrayList<>();
+    Integer goodsCount = 0;
+    for (int i = 0; i < 4; i++) {
+      WxMaExpressOrderCargoDetail detail = new WxMaExpressOrderCargoDetail();
+      String shopName = "商品_"+i;
+      detail.setName(shopName);
+      detail.setCount(1);
+      detailList.add(detail);
+      shopNames.add(shopName);
+      goodsCount ++;
+    }
+    cargo.setCount(detailList.size());
+    cargo.setWeight(5);
+    cargo.setSpaceHeight(10);
+    cargo.setSpaceLength(10);
+    cargo.setSpaceWidth(10);
+    cargo.setDetailList(detailList);
+
+
+    WxMaExpressOrderShop shop = new WxMaExpressOrderShop();
+    shop.setWxaPath("/index/index?from=waybill&id=01234567890123456789");
+    shop.setGoodsName(StringUtils.join(shopNames,"&"));
+    shop.setGoodsCount(goodsCount);
+    shop.setImgUrl("https://mmbiz.qpic.cn/mmbiz_png/OiaFLUqewuIDNQnTiaCInIG8ibdosYHhQHPbXJUrqYSNIcBL60vo4LIjlcoNG1QPkeH5GWWEB41Ny895CokeAah8A/640");
+
+    WxMaExpressDelivery.ServiceType serviceType = new WxMaExpressDelivery.ServiceType();
+    serviceType.setServiceName("test_service_name");
+    serviceType.setServiceType(1);
+
+    WxMaExpressAddOrderRequest request = WxMaExpressAddOrderRequest.builder()
+      .addSource(WxMaConstants.OrderAddSource.MINI_PROGRAM)
+      .orderId("test201911271429004")
+      .openid("oAg_-0PDUPuLbQw9V9kXE9OkU-Vo")
+      .deliveryId("TEST")
+      .bizId("test_biz_id")
+      .customRemark("")
+      .expectTime(0L)
+      .sender(sender)
+      .receiver(receiver)
+      .cargo(cargo)
+      .shop(shop)
+      .insured(WxMaExpressOrderInsured.builder().build())
+      .service(serviceType)
+      .build();
+
+    WxMaExpressOrderInfoResult result = service.addOrder(request);
+    System.out.println(WxMaGsonBuilder.create().toJson(result));
+  }
+
+  @Test
+  public void testBatchGetOrder() throws WxErrorException {
+    final WxMaExpressService service = wxMaService.getExpressService();
+    List<WxMaExpressGetOrderRequest> requests = new ArrayList<>();
+
+    List<String> orderIds = new ArrayList<>();
+    orderIds.add("test201911271429000");
+
+    List<String> waybillIds = new ArrayList<>();
+    waybillIds.add("test201911271429000_1574836404_waybill_id");
+    for (int i = 0; i < orderIds.size(); i++) {
+      WxMaExpressGetOrderRequest request = WxMaExpressGetOrderRequest.builder()
+        .orderId(orderIds.get(i))
+        .deliveryId("TEST")
+        .waybillId(waybillIds.get(i))
+        .build();
+      requests.add(request);
+    }
+
+    List<WxMaExpressOrderInfoResult> results = service.batchGetOrder(requests);
+    System.out.println(WxMaGsonBuilder.create().toJson(results));
+  }
+
+  @Test
+  public void testCancelOrder() throws WxErrorException {
+    final WxMaExpressService service = wxMaService.getExpressService();
+    WxMaExpressGetOrderRequest request = WxMaExpressGetOrderRequest.builder()
+      .orderId("test201911271429000")
+      .deliveryId("TEST")
+      .waybillId("test201911271429000_1574836404_waybill_id")
+      .openid("oAg_-0PDUPuLbQw9V9kXE9OkU-Vo")
+      .build();
+    service.cancelOrder(request);
+  }
+
+
+  @Test
+  public void testGetOrder() throws WxErrorException {
+    final WxMaExpressService service = wxMaService.getExpressService();
+    WxMaExpressGetOrderRequest request = WxMaExpressGetOrderRequest.builder()
+      .orderId("test201911271429000")
+      .deliveryId("TEST")
+      .waybillId("test201911271429000_1574836404_waybill_id")
+      .openid("oAg_-0PDUPuLbQw9V9kXE9OkU-Vo")
+      .build();
+    WxMaExpressOrderInfoResult result = service.getOrder(request);
+    System.out.println(WxMaGsonBuilder.create().toJson(result));
+  }
+
+
+  @Test
+  public void testGetPath() throws WxErrorException {
+    final WxMaExpressService service = wxMaService.getExpressService();
+    WxMaExpressGetOrderRequest request = WxMaExpressGetOrderRequest.builder()
+      .orderId("test201911271429000")
+      .deliveryId("TEST")
+      .waybillId("test201911271429000_1574836404_waybill_id")
+      .openid("oAg_-0PDUPuLbQw9V9kXE9OkU-Vo")
+      .build();
+    WxMaExpressPath path = service.getPath(request);
+    System.out.println(WxMaGsonBuilder.create().toJson(path));
+  }
+
+  @Test
+  public void testTestUpdateOrder() throws WxErrorException {
+    final WxMaExpressService service = wxMaService.getExpressService();
+    WxMaExpressTestUpdateOrderRequest request = WxMaExpressTestUpdateOrderRequest.builder()
+      .orderId("test201911271429000")
+      .waybillId("test201911271429000_1574836404_waybill_id")
+      .actionTime(1574850455L)
+      .actionType(300002)
+      .actionMsg("开始派送")
+      .build();
+    service.testUpdateOrder(request);
+  }
+}