diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaImmediateDeliveryService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaImmediateDeliveryService.java new file mode 100644 index 000000000..d372799ec --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaImmediateDeliveryService.java @@ -0,0 +1,100 @@ +package cn.binarywang.wx.miniapp.api; + +import cn.binarywang.wx.miniapp.bean.delivery.AbnormalConfirmRequest; +import cn.binarywang.wx.miniapp.bean.delivery.AbnormalConfirmResponse; +import cn.binarywang.wx.miniapp.bean.delivery.AddOrderRequest; +import cn.binarywang.wx.miniapp.bean.delivery.AddOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.BindAccountResponse; +import cn.binarywang.wx.miniapp.bean.delivery.CancelOrderRequest; +import cn.binarywang.wx.miniapp.bean.delivery.CancelOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.GetOrderRequest; +import cn.binarywang.wx.miniapp.bean.delivery.GetOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.MockUpdateOrderRequest; +import cn.binarywang.wx.miniapp.bean.delivery.MockUpdateOrderResponse; +import me.chanjar.weixin.common.error.WxErrorException; + +/** + * 微信小程序即时配送服务. + *
+ *     文档地址:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/immediate-delivery/overview.html
+ * 
+ * + * @author Luo + * @version 1.0 + * @date 2021-10-13 16:40 + */ +public interface WxMaImmediateDeliveryService { + + /** + * 拉取已绑定账号. + *
+     * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.getBindAccount.html
+     * 
+ * + * @return 响应 + * @throws WxErrorException 异常 + */ + BindAccountResponse getBindAccount() throws WxErrorException; + + /** + * 下配送单接口. + *
+     * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.addOrder.html
+     * 
+ * + * @param request request + * @return 响应 + * @throws WxErrorException 异常 + */ + AddOrderResponse addOrder(AddOrderRequest request) throws WxErrorException; + + /** + * 拉取配送单信息. + *
+     * 商家可使用本接口查询某一配送单的配送状态,便于商家掌握配送情况。
+     * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.getOrder.html
+     * 
+ * + * @param request request + * @return 响应 + * @throws WxErrorException 异常 + */ + GetOrderResponse getOrder(GetOrderRequest request) throws WxErrorException; + + /** + * 取消配送单接口. + *
+     * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.cancelOrder.html
+     * 
+ * + * @param request request + * @return 响应 + * @throws WxErrorException 异常 + */ + CancelOrderResponse cancelOrder(CancelOrderRequest request) throws WxErrorException; + + /** + * 异常件退回商家商家确认收货接口. + *
+     * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.abnormalConfirm.html
+     * 
+ * + * @param request request + * @return 响应 + * @throws WxErrorException 异常 + */ + AbnormalConfirmResponse abnormalConfirm(AbnormalConfirmRequest request) throws WxErrorException; + + /** + * 模拟配送公司更新配送单状态, 该接口只用于沙盒环境,即订单并没有真实流转到运力方. + *
+     * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.mockUpdateOrder.html
+     * 
+ * + * @param request request + * @return 响应 + * @throws WxErrorException 异常 + */ + MockUpdateOrderResponse mockUpdateOrder(MockUpdateOrderRequest request) throws WxErrorException; + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java index 225a52a55..81ed12aa8 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java @@ -476,4 +476,12 @@ public interface WxMaService extends WxService { * @return WxMaDeviceSubscribeService plugin service */ WxMaMarketingService getMarketingService(); + + /** + * 返回微信小程序即时配送服务接口. + * + * @return WxMaImmediateDeliveryService + */ + WxMaImmediateDeliveryService getWxMaImmediateDeliveryService(); + } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java index bf8e1e903..21ca0f721 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java @@ -77,6 +77,7 @@ public abstract class BaseWxMaServiceImpl implements WxMaService, RequestH private final WxMaReimburseInvoiceService reimburseInvoiceService = new WxMaReimburseInvoiceServiceImpl(this); private final WxMaDeviceSubscribeService deviceSubscribeService = new WxMaDeviceSubscribeServiceImpl(this); private final WxMaMarketingService marketingService = new WxMaMarketingServiceImpl(this); + private final WxMaImmediateDeliveryService immediateDeliveryService = new WxMaImmediateDeliveryServiceImpl(this); private Map configMap; private int retrySleepMillis = 1000; private int maxRetryTimes = 5; @@ -581,4 +582,9 @@ public abstract class BaseWxMaServiceImpl implements WxMaService, RequestH @Override public WxMaMarketingService getMarketingService() {return this.marketingService; } + + @Override + public WxMaImmediateDeliveryService getWxMaImmediateDeliveryService() { + return this.immediateDeliveryService; + } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaImmediateDeliveryServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaImmediateDeliveryServiceImpl.java new file mode 100644 index 000000000..75f88eb63 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaImmediateDeliveryServiceImpl.java @@ -0,0 +1,190 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaImmediateDeliveryService; +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.delivery.AbnormalConfirmRequest; +import cn.binarywang.wx.miniapp.bean.delivery.AbnormalConfirmResponse; +import cn.binarywang.wx.miniapp.bean.delivery.AddOrderRequest; +import cn.binarywang.wx.miniapp.bean.delivery.AddOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.BindAccountResponse; +import cn.binarywang.wx.miniapp.bean.delivery.CancelOrderRequest; +import cn.binarywang.wx.miniapp.bean.delivery.CancelOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.GetOrderRequest; +import cn.binarywang.wx.miniapp.bean.delivery.GetOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.MockUpdateOrderRequest; +import cn.binarywang.wx.miniapp.bean.delivery.MockUpdateOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.base.WxMaDeliveryBaseResponse; +import cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import javassist.bytecode.ConstPool; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.enums.WxType; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.json.GsonParser; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +/** + * 微信小程序即时配送服务. + *
+ *     文档地址:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/immediate-delivery/overview.html
+ * 
+ * + * @author Luo + * @version 1.0 + * @date 2021-10-13 16:40 + */ +@RequiredArgsConstructor +public class WxMaImmediateDeliveryServiceImpl implements WxMaImmediateDeliveryService { + + /** + * 微信响应码. + */ + public static final String ERR_CODE = "errcode"; + + /** + * 顺丰同城响应码. + */ + public static final String SF_ERR_CODE = "resultcode"; + + /** + * 顺丰同城响应说明. + */ + public static final String SF_ERR_MSG = "resultmsg"; + + /** + * 成功响应状态码. + */ + public static final int SUCCESS_CODE = 0; + + private final WxMaService wxMaService; + + /** + * 拉取已绑定账号. + *
+   * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.getBindAccount.html
+   * 
+ * + * @return 响应 + * @throws WxErrorException 异常 + */ + @Override + public BindAccountResponse getBindAccount() throws WxErrorException { + return this.parse(this.wxMaService.post(WxMaApiUrlConstants.InstantDelivery.GET_BIND_ACCOUNT, "{}"), + BindAccountResponse.class); + } + + /** + * 下配送单接口. + *
+   * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.addOrder.html
+   * 
+ * + * @param request request + * @return 响应 + * @throws WxErrorException 异常 + */ + @Override + public AddOrderResponse addOrder(final AddOrderRequest request) throws WxErrorException { + return this.parse(this.wxMaService.post(WxMaApiUrlConstants.InstantDelivery.PlaceAnOrder.ADD_ORDER, request), + AddOrderResponse.class); + } + + /** + * 拉取配送单信息. + *
+   * 商家可使用本接口查询某一配送单的配送状态,便于商家掌握配送情况。
+   * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.getOrder.html
+   * 
+ * + * @param request request + * @return 响应 + * @throws WxErrorException 异常 + */ + @Override + public GetOrderResponse getOrder(final GetOrderRequest request) throws WxErrorException { + return this.parse(this.wxMaService.post(WxMaApiUrlConstants.InstantDelivery.GET_ORDER, request), + GetOrderResponse.class); + } + + /** + * 取消配送单接口. + *
+   * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.cancelOrder.html
+   * 
+ * + * @param request request + * @return 响应 + * @throws WxErrorException 异常 + */ + @Override + public CancelOrderResponse cancelOrder(final CancelOrderRequest request) throws WxErrorException { + return this.parse(this.wxMaService.post(WxMaApiUrlConstants.InstantDelivery.Cancel.CANCEL_ORDER, request), + CancelOrderResponse.class); + } + + /** + * 异常件退回商家商家确认收货接口. + *
+   * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.abnormalConfirm.html
+   * 
+ * + * @param request request + * @return 响应 + * @throws WxErrorException 异常 + */ + @Override + public AbnormalConfirmResponse abnormalConfirm(final AbnormalConfirmRequest request) throws WxErrorException { + return this.parse(this.wxMaService.post(WxMaApiUrlConstants.InstantDelivery.Cancel.ABNORMAL_CONFIRM, request), + AbnormalConfirmResponse.class); + } + + /** + * 模拟配送公司更新配送单状态, 该接口只用于沙盒环境,即订单并没有真实流转到运力方. + *
+   * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.mockUpdateOrder.html
+   * 
+ * + * @param request request + * @return 响应 + * @throws WxErrorException 异常 + */ + @Override + public MockUpdateOrderResponse mockUpdateOrder(final MockUpdateOrderRequest request) throws WxErrorException { + return this.parse(this.wxMaService.post(WxMaApiUrlConstants.InstantDelivery.MOCK_UPDATE_ORDER, request), + MockUpdateOrderResponse.class); + } + + /** + * 解析响应. + * + * @param responseContent 响应内容 + * @param valueType 类型 + * @param 类型 + * @return 结果 + * @throws WxErrorException 异常 + */ + private T parse(final String responseContent, final Class valueType) throws WxErrorException { + if (StringUtils.isBlank(responseContent)) { + throw new RuntimeException("the responseContent cannot be empty"); + } + // 解析成Json对象 + JsonObject jsonObject = GsonParser.parse(responseContent); + // 是否为微信错误响应 当 errcode==0 或者 不存在 还需要看 运力方 resultcode 状态码 + JsonElement element = jsonObject.get(ERR_CODE); + // 正常响应下不会有该字段返回 + if (!ObjectUtils.isEmpty(element) && SUCCESS_CODE != element.getAsInt()) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + // 是否为运力方错误响应 + JsonElement delivery = jsonObject.get(SF_ERR_CODE); + if (!ObjectUtils.isEmpty(delivery) && SUCCESS_CODE != delivery.getAsInt()) { + throw new WxErrorException(jsonObject.get(SF_ERR_MSG).getAsString()); + } + // 解析成对应响应对象 + return WxMaDeliveryBaseResponse.fromJson(responseContent, valueType); + } + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/AbnormalConfirmRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/AbnormalConfirmRequest.java new file mode 100644 index 000000000..af461e47c --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/AbnormalConfirmRequest.java @@ -0,0 +1,43 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import cn.binarywang.wx.miniapp.bean.delivery.base.WxMaDeliveryBaseRequest; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 微信小程序即时配送 异常件退回商家商家确认收货接口 请求参数. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:49 + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class AbnormalConfirmRequest extends WxMaDeliveryBaseRequest implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + + /** + * 配送单id. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("waybill_id") + private String waybillId; + + /** + * 备注. + *
+     * 是否必填:否
+     * 
+ */ + @SerializedName("remark") + private String remark; + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/AbnormalConfirmResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/AbnormalConfirmResponse.java new file mode 100644 index 000000000..641ab7e38 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/AbnormalConfirmResponse.java @@ -0,0 +1,25 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import cn.binarywang.wx.miniapp.bean.delivery.base.WxMaDeliveryBaseResponse; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 微信小程序即时配送 异常件退回商家商家确认收货接口 响应参数. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:49 + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class AbnormalConfirmResponse extends WxMaDeliveryBaseResponse implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/AddOrderRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/AddOrderRequest.java new file mode 100644 index 000000000..c8a220776 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/AddOrderRequest.java @@ -0,0 +1,639 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import cn.binarywang.wx.miniapp.bean.delivery.base.WxMaDeliveryBaseRequest; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +/** + * 微信小程序即时配送 下配送单接口 请求参数. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:49 + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class AddOrderRequest extends WxMaDeliveryBaseRequest implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + + /** + * 子商户id,区分小程序内部多个子商户. + *
+     * 是否必填:否
+     * 
+ */ + @SerializedName("sub_biz_id") + private String subBizId; + + /** + * 发件人信息,顺丰同城急送必须填写,美团配送、达达、闪送,若传了shop_no的值可不填该字段. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("sender") + private Sender sender; + + /** + * 收件人信息. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("receiver") + private Receiver receiver; + + /** + * 货物信息. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("cargo") + private Cargo cargo; + + /** + * 订单信息. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("order_info") + private OrderInfo orderInfo; + + /** + * 商品信息,会展示到物流通知消息中. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("shop") + private Shop shop; + + /** + * 发件人信息. + */ + @Data + @Accessors(chain = true) + public static class Sender implements Serializable { + + private static final long serialVersionUID = -8101805250220380047L; + + /** + * 姓名,最长不超过256个字符. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("name") + private String name; + + /** + * 城市名称,如广州市. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("city") + private String city; + + /** + * 地址(街道、小区、大厦等,用于定位). + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("address") + private String address; + + /** + * 地址(街道、小区、大厦等,用于定位). + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("address_detail") + private String addressDetail; + + /** + * 坐标类型,默认 0:火星坐标(高德,腾讯地图均采用火星坐标) 1:百度坐标. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("coordinate_type") + private int coordinateType; + + /** + * 经度(火星坐标或百度坐标,和 coordinate_type 字段配合使用,确到小数点后6位. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("lng") + private BigDecimal lng; + + /** + * 纬度(火星坐标或百度坐标,和 coordinate_type 字段配合使用,精确到小数点后6位). + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("lat") + private BigDecimal lat; + + /** + * 电话/手机号,最长不超过64个字符. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("phone") + private String phone; + + } + + /** + * 收件人信息. + */ + @Data + @Accessors(chain = true) + public static class Receiver implements Serializable { + + private static final long serialVersionUID = -8101805250220380047L; + + /** + * 姓名,最长不超过256个字符. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("name") + private String name; + + /** + * 城市名称,如广州市. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("city") + private String city; + + /** + * 地址(街道、小区、大厦等,用于定位). + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("address") + private String address; + + /** + * 地址(街道、小区、大厦等,用于定位). + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("address_detail") + private String addressDetail; + + /** + * 坐标类型,默认 0:火星坐标(高德,腾讯地图均采用火星坐标) 1:百度坐标. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("coordinate_type") + private int coordinateType; + + /** + * 经度(火星坐标或百度坐标,和 coordinate_type 字段配合使用,确到小数点后6位. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("lng") + private BigDecimal lng; + + /** + * 纬度(火星坐标或百度坐标,和 coordinate_type 字段配合使用,精确到小数点后6位). + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("lat") + private BigDecimal lat; + + /** + * 电话/手机号,最长不超过64个字符. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("phone") + private String phone; + + } + + /** + * 商品信息. + */ + @Data + @Accessors(chain = true) + public static class Shop implements Serializable { + + private static final long serialVersionUID = -8958461649711388689L; + + /** + * 商品数量. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("goods_count") + private Integer goodsCount; + + /** + * 商品名称. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("goods_name") + private String goodsName; + + /** + * 商品缩略图 url. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("img_url") + private String imgUrl; + + /** + * 商家小程序的路径,建议为订单页面. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("wxa_path") + private String wxaPath; + + /** + * 若结算方式为:第三方向配送公司统一结算,商户后续和第三方结算,则该参数必填. + * 在该结算模式下,第三方用自己的开发小程序替授权商户发起下单,并将授权小程序的appid给平台,后续配送通知中可回流授权商户小程序. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("wxa_appid") + private String wxaAppid; + + } + + /** + * 订单信息. + */ + @Data + @Accessors(chain = true) + public static class OrderInfo implements Serializable { + + private static final long serialVersionUID = 5277759430030747900L; + + /** + * 配送服务代码 不同配送公司自定义, 顺丰和达达不填. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("delivery_service_code") + private String deliveryServiceCode; + + /** + * 订单类型, 0: 即时单 1 预约单,如预约单,需要设置expected_delivery_time或expected_finish_time或expected_pick_time. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("order_type") + private Integer orderType; + + /** + * 期望派单时间(达达支持,表示达达系统调度时间, 到那个时间才会有状态更新的回调通知),unix-timestamp, 比如1586342180. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("expected_delivery_time") + private Long expectedDeliveryTime; + + /** + * 期望送达时间(美团、顺丰同城急送支持),unix-timestamp, 比如1586342180. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("expected_finish_time") + private Long expectedFinishTime; + + /** + * 期望取件时间(闪送、顺丰同城急送支持,闪送需要设置两个小时后的时间,顺丰同城急送只需传expected_finish_time或expected_pick_time其中之一即可,同时都传则以expected_finish_time为准),unix-timestamp, 比如1586342180. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("expected_pick_time") + private Long expectedPickTime; + + /** + * 备注,最长不超过200个字符. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("note") + private String note; + + /** + * 门店订单流水号,建议提供,方便骑手门店取货,最长不超过32个字符. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("poi_seq") + private String poiSeq; + + /** + * 用户下单付款时间, 顺丰必填, 比如1555220757. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("order_time") + private Long orderTime; + + /** + * 是否保价,0:非保价,1:保价. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("is_insured") + private Integer isInsured; + + /** + * 保价金额,单位为元,精确到分. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("declared_value") + private BigDecimal declaredValue; + + /** + * 小费,单位为元, 下单一般不加小费. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("tips") + private Integer tips; + + /** + * 是否选择直拿直送(0:不需要;1:需要。选择直拿直送后,同一时间骑手只能配送此订单至完成,配送费用也相应高一些,闪送必须选1,达达可选0或1,其余配送公司不支持直拿直送). + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("is_direct_delivery") + private Integer isDirectDelivery; + + /** + * 骑手应付金额,单位为元,精确到分. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("cash_on_delivery") + private BigDecimal cashOnDelivery; + + /** + * 骑手应收金额,单位为元,精确到分. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("cash_on_pickup") + private BigDecimal cashOnPickup; + + /** + * 物流流向,1:从门店取件送至用户;2:从用户取件送至门店. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("rider_pick_method") + private Integer riderPickMethod; + + /** + * 收货码(0:不需要;1:需要。收货码的作用是:骑手必须输入收货码才能完成订单妥投). + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("is_finish_code_needed") + private Integer isFinishCodeNeeded; + + /** + * 取货码(0:不需要;1:需要。取货码的作用是:骑手必须输入取货码才能从商家取货). + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("is_pickup_code_needed") + private Integer isPickupCodeNeeded; + + } + + /** + * 货物信息. + */ + @NoArgsConstructor + @Data + @Accessors(chain = true) + public static class Cargo implements Serializable { + + private static final long serialVersionUID = -8339389045820636620L; + + /** + * 货物价格,单位为元,精确到小数点后两位(如果小数点后位数多于两位,则四舍五入保留两位小数),范围为(0-5000]. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("goods_value") + private BigDecimal goodsValue; + + /** + * 货物高度,单位为cm,精确到小数点后两位(如果小数点后位数多于两位,则四舍五入保留两位小数),范围为(0-45]. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("goods_height") + private BigDecimal goodsHeight; + + /** + * 货物长度,单位为cm,精确到小数点后两位(如果小数点后位数多于两位,则四舍五入保留两位小数),范围为(0-65]. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("goods_length") + private BigDecimal goodsLength; + + /** + * 货物宽度,单位为cm,精确到小数点后两位(如果小数点后位数多于两位,则四舍五入保留两位小数),范围为(0-50]. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("goods_width") + private BigDecimal goodsWidth; + + /** + * 货物重量,单位为kg,精确到小数点后两位(如果小数点后位数多于两位,则四舍五入保留两位小数),范围为(0-50]. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("goods_weight") + private BigDecimal goodsWeight; + + /** + * 货物详情,最长不超过10240个字符. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("goods_detail") + private GoodsDetail goodsDetail; + + /** + * 货物取货信息,用于骑手到店取货,最长不超过100个字符. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("goods_pickup_info") + private String goodsPickupInfo; + + /** + * 货物交付信息,最长不超过100个字符. + *
+         * 是否必填:否
+         * 
+ */ + @SerializedName("goods_delivery_info") + private String goodsDeliveryInfo; + + /** + * 品类一级类目, 详见品类表 https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/union/access-guidelines/promoter/api/product/category.html. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("cargo_first_class") + private String cargoFirstClass; + + /** + * 品类二级类目. + *
+         * 是否必填:是
+         * 
+ */ + @SerializedName("cargo_second_class") + private String cargoSecondClass; + + /** + * 货物详情. + */ + @Data + @Accessors(chain = true) + public static class GoodsDetail implements Serializable { + + private static final long serialVersionUID = -8339389045820636620L; + + /** + * 货物列表. + *
+             * 是否必填:是
+             * 
+ */ + @SerializedName("goods") + private List goods; + + /** + * 货物详情. + */ + @NoArgsConstructor + @Data + @Accessors(chain = true) + public static class Goods implements Serializable { + + private static final long serialVersionUID = -8339389045820636620L; + + /** + * 货物数量. + *
+                 * 是否必填:是
+                 * 
+ */ + @SerializedName("good_count") + private Integer goodCount; + + /** + * 货品名称. + *
+                 * 是否必填:是
+                 * 
+ */ + @SerializedName("good_name") + private String goodName; + + /** + * 货品单价,精确到小数点后两位(如果小数点后位数多于两位,则四舍五入保留两位小数). + *
+                 * 是否必填:否
+                 * 
+ */ + @SerializedName("good_price") + private BigDecimal goodPrice; + + /** + * 货品单位,最长不超过20个字符. + *
+                 * 是否必填:否
+                 * 
+ */ + @SerializedName("good_unit") + private String goodUnit; + + } + + } + + } + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/AddOrderResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/AddOrderResponse.java new file mode 100644 index 000000000..5f56b007b --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/AddOrderResponse.java @@ -0,0 +1,92 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import cn.binarywang.wx.miniapp.bean.delivery.base.WxMaDeliveryBaseResponse; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 微信小程序即时配送 下配送单接口 响应参数. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:49 + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class AddOrderResponse extends WxMaDeliveryBaseResponse implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + + /** + * 实际运费(单位:元),运费减去优惠券费用. + */ + @SerializedName("fee") + private BigDecimal fee; + + /** + * 运费(单位:元). + */ + @SerializedName("deliverfee") + private BigDecimal deliverFee; + + /** + * 优惠券费用(单位:元). + */ + @SerializedName("couponfee") + private BigDecimal couponFee; + + /** + * 小费(单位:元). + */ + @SerializedName("tips") + private BigDecimal tips; + + /** + * 保价费(单位:元). + */ + @SerializedName("insurancfee") + private BigDecimal insurancFee; + + /** + * 配送距离(整数单位:米). + */ + @SerializedName("distance") + private BigDecimal distance; + + /** + * 配送单号. + */ + @SerializedName("waybill_id") + private String waybillId; + + /** + * 配送状态. + */ + @SerializedName("order_status") + private Integer orderStatus; + + /** + * 收货码. + */ + @SerializedName("finish_code") + private Integer finishCode; + + /** + * 取货码. + */ + @SerializedName("pickup_code") + private Integer pickupCode; + + /** + * 预计骑手接单时间,单位秒,比如5分钟,就填300, 无法预计填0. + */ + @SerializedName("dispatch_duration") + private BigDecimal dispatchDuration; + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/BindAccountResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/BindAccountResponse.java new file mode 100644 index 000000000..0afb174eb --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/BindAccountResponse.java @@ -0,0 +1,66 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import cn.binarywang.wx.miniapp.bean.delivery.base.WxMaDeliveryBaseResponse; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * 微信小程序即时配送 拉取已绑定账号 响应参数. + *
+ * 使用场景:
+ *      1.商家可通过本接口查询自己已经在小程序后台绑定的和配送公司签约的账号;
+ *      2.服务商可通过本接口查询代开发的小程序在小程序后台绑定的和配送公司签约的账号,为其完成后续的接口代开发业务;
+ * 
+ * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:49 + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class BindAccountResponse extends WxMaDeliveryBaseResponse implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + + /** + * 店铺账号信息集合. + */ + @SerializedName("shop_list") + private List shopList; + + /** + * 店铺账号信息. + */ + @Data + @Accessors(chain = true) + public static class Shop implements Serializable { + + private static final long serialVersionUID = -3759074878713856529L; + + /** + * 配送公司Id. + */ + @SerializedName("delivery_id") + private String deliveryId; + + /** + * 商家id. + */ + @SerializedName("shopid") + private String shopId; + + /** + * 审核状态 0:审核通过、1:审核中、2:审核不通过. + */ + @SerializedName("audit_result") + private String auditResult; + + } + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/CancelOrderRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/CancelOrderRequest.java new file mode 100644 index 000000000..1220e0807 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/CancelOrderRequest.java @@ -0,0 +1,52 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import cn.binarywang.wx.miniapp.bean.delivery.base.WxMaDeliveryBaseRequest; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 微信小程序即时配送 取消配送单接口 请求参数. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:49 + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class CancelOrderRequest extends WxMaDeliveryBaseRequest implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + + /** + * 配送单id. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("waybill_id") + private String waybillId; + + /** + * 取消原因Id. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("cancel_reason_id") + private Integer cancelReasonId; + + /** + * 取消原因. + *
+     * 是否必填:否
+     * 
+ */ + @SerializedName("cancel_reason") + private String cancelReason; + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/CancelOrderResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/CancelOrderResponse.java new file mode 100644 index 000000000..a556fba99 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/CancelOrderResponse.java @@ -0,0 +1,38 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import cn.binarywang.wx.miniapp.bean.delivery.base.WxMaDeliveryBaseResponse; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 微信小程序即时配送 取消配送单接口 响应参数. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:49 + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class CancelOrderResponse extends WxMaDeliveryBaseResponse implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + + /** + * 扣除的违约金(单位:元),精确到分. + */ + @SerializedName("deduct_fee") + private BigDecimal deductFee; + + /** + * 说明. + */ + @SerializedName("desc") + private String desc; + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/GetOrderRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/GetOrderRequest.java new file mode 100644 index 000000000..9927ee06d --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/GetOrderRequest.java @@ -0,0 +1,24 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import cn.binarywang.wx.miniapp.bean.delivery.base.WxMaDeliveryBaseRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 微信小程序即时配送 拉取配送单信息 请求参数. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:49 + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class GetOrderRequest extends WxMaDeliveryBaseRequest implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/GetOrderResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/GetOrderResponse.java new file mode 100644 index 000000000..ec06026a0 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/GetOrderResponse.java @@ -0,0 +1,68 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import cn.binarywang.wx.miniapp.bean.delivery.base.WxMaDeliveryBaseResponse; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 微信小程序即时配送 拉取配送单信息 响应参数. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:49 + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class GetOrderResponse extends WxMaDeliveryBaseResponse implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + + /** + * 配送状态. + */ + @SerializedName("order_status") + private Integer orderStatus; + + /** + * 配送单号. + */ + @SerializedName("waybill_id") + private String waybillId; + + /** + * 骑手姓名. + */ + @SerializedName("rider_name") + private String riderName; + + /** + * 骑手电话. + */ + @SerializedName("rider_phone") + private String riderPhone; + + /** + * 骑手位置经度, 配送中时返回. + */ + @SerializedName("rider_lng") + private BigDecimal riderLng; + + /** + * 骑手位置纬度, 配送中时返回. + */ + @SerializedName("rider_lat") + private BigDecimal riderLat; + + /** + * 预计还剩多久送达时间, 配送中时返回,单位秒, 已取货配送中需返回,比如5分钟后送达,填300. + */ + @SerializedName("reach_time") + private BigDecimal reachTime; + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/MockUpdateOrderRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/MockUpdateOrderRequest.java new file mode 100644 index 000000000..1adf02028 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/MockUpdateOrderRequest.java @@ -0,0 +1,58 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 微信小程序即时配送 模拟配送公司更新配送单状态 请求参数. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:49 + */ +@Data +@Accessors(chain = true) +public class MockUpdateOrderRequest implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + + /** + * 商家id, 必须是 "test_shop_id". + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("shopid") + private String shopId = "test_shop_id"; + + /** + * 唯一标识订单的 ID,由商户生成. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("shop_order_id") + private String shopOrderId; + + /** + * 状态变更时间点,Unix秒级时间戳. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("action_time") + private Long actionTime; + + /** + * 配送状态,枚举值. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("order_status") + private Integer orderStatus; + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/MockUpdateOrderResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/MockUpdateOrderResponse.java new file mode 100644 index 000000000..de861493e --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/MockUpdateOrderResponse.java @@ -0,0 +1,25 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import cn.binarywang.wx.miniapp.bean.delivery.base.WxMaDeliveryBaseResponse; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 微信小程序即时配送 模拟配送公司更新配送单状态 响应参数. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:49 + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class MockUpdateOrderResponse extends WxMaDeliveryBaseResponse implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/base/WxMaDeliveryBaseRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/base/WxMaDeliveryBaseRequest.java new file mode 100644 index 000000000..a139ea907 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/base/WxMaDeliveryBaseRequest.java @@ -0,0 +1,119 @@ +package cn.binarywang.wx.miniapp.bean.delivery.base; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; + +/** + * 微信小程序 即时配送 基础请求参数. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:36 + */ +@Data +@Accessors(chain = true) +public abstract class WxMaDeliveryBaseRequest implements Serializable { + + private static final long serialVersionUID = -6811550517417623460L; + + /** + * 配送公司ID. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("delivery_id") + private String deliveryId; + + /** + * 唯一标识订单的 ID,由商户生成, 不超过 128 字节. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("shop_order_id") + private String shopOrderId; + + /** + * 下单用户的openid. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("openid") + private String openid; + + /** + * 商家门店编号,在配送公司登记,如果只有一个门店,美团闪送必填, 值为店铺id. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("shop_no") + private String shopNo; + + /** + * 商家id,由配送公司分配的appKey. + *
+     * 是否必填:是
+     * 
+ */ + @SerializedName("shopid") + private String shopId; + + /** + * 用配送公司提供的appSecret加密的校验串. + *
+     * 除了平台本身的加解密和签名,和订单相关的请求还需要带上运力侧签名delivery_sign,签名规则为
+     * 如果接口请求里有字段shop_order_id ,则delivery_sign=SHA1(shopid + shop_order_id + AppSecret),其中shopid对应运力侧的appkey,shop_order_id对应订单id,AppSecret即配送公司帐号对应的秘钥
+     * 如果请求里没有字段shop_order_id ,则delivery_sign=SHA1(shopid + AppSecret),其中shopid对应运力侧的appkey,AppSecret即配送公司帐号对应的秘钥
+     * 示例:shopid=“test_shop_id”,shop_order_id =“test_shop_order_id”, AppSecret=“test_app_secrect”,则delivery_sign=“a93d8d6bae9a9483c1b1d4e8670e7f6226ec94cb”
+     * 是否必填:是
+     * 
+ */ + @Setter(AccessLevel.NONE) + @SerializedName("delivery_sign") + private String deliverySign; + + /** + * 配送公司分配的appSecret. + *
+     * 是否必填:是
+     * 
+ */ + @Expose + private String appSecret; + + /** + * 获取签名. + *
+     * 除了平台本身的加解密和签名,和订单相关的请求还需要带上运力侧签名delivery_sign,签名规则为
+     * 如果接口请求里有字段shop_order_id ,则delivery_sign=SHA1(shopid + shop_order_id + AppSecret),其中shopid对应运力侧的appkey,shop_order_id对应订单id,AppSecret即配送公司帐号对应的秘钥
+     * 如果请求里没有字段shop_order_id ,则delivery_sign=SHA1(shopid + AppSecret),其中shopid对应运力侧的appkey,AppSecret即配送公司帐号对应的秘钥
+     * 示例:shopid=“test_shop_id”,shop_order_id =“test_shop_order_id”, AppSecret=“test_app_secrect”,则delivery_sign=“a93d8d6bae9a9483c1b1d4e8670e7f6226ec94cb”
+     * 是否必填:是
+     * 
+ * + * @return 结果 + */ + public String getDeliverySign() { + if (StringUtils.isBlank(getShopId()) || StringUtils.isBlank(getAppSecret())) { + throw new RuntimeException("shopId or appSecret can not be empty"); + } + String str = getShopId(); + if (StringUtils.isNotBlank(getShopOrderId())) { + str = str.concat(getShopOrderId()); + } + str = str.concat(getAppSecret()); + return DigestUtils.sha1Hex(str); + } + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/base/WxMaDeliveryBaseResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/base/WxMaDeliveryBaseResponse.java new file mode 100644 index 000000000..38f354bb7 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/base/WxMaDeliveryBaseResponse.java @@ -0,0 +1,66 @@ +package cn.binarywang.wx.miniapp.bean.delivery.base; + +import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; + +/** + * 微信小程序 即时配送 基础响应参数. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 10:36 + */ +@Data +@Accessors(chain = true) +public abstract class WxMaDeliveryBaseResponse implements Serializable { + + private static final long serialVersionUID = -6811550517417623460L; + + /** + * 成功状态码. + */ + private static final int SUCCESS_CODE = 0; + + /** + * 运力返回的错误码. + */ + @SerializedName("resultcode") + private Integer resultCode; + + /** + * 运力返回的错误描述. + */ + @SerializedName("resultmsg") + private String resultMsg; + + /** + * 是否响应成功. + * + * @return true:成功、false:失败 + */ + public boolean success() { + return SUCCESS_CODE == getResultCode(); + } + + /** + * 解析响应. + * + * @param json 响应内容 + * @param valueType 类型 + * @param 类型 + * @return 结果 + */ + public static T fromJson(final String json, final Class valueType) { + if (StringUtils.isBlank(json)) { + throw new RuntimeException("the json cannot be empty"); + } + // 解析成对应响应对象 + return WxMaGsonBuilder.create().fromJson(json, valueType); + } + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaApiUrlConstants.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaApiUrlConstants.java index ae5707206..5d4379b9d 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaApiUrlConstants.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaApiUrlConstants.java @@ -411,4 +411,118 @@ public class WxMaApiUrlConstants { */ String SEND_DEVICE_SUBSCRIBE_MSG_URL = "https://api.weixin.qq.com/cgi-bin/message/device/subscribe/send"; } + + /** + * 即时配送相关接口. + *
+   * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/immediate-delivery/overview.html
+   * 
+ */ + public interface InstantDelivery { + + /** + * 拉取已绑定账号. + *
+     * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.getBindAccount.html
+     * 
+ */ + String GET_BIND_ACCOUNT = "https://api.weixin.qq.com/cgi-bin/express/local/business/shop/get"; + + /** + * 拉取配送单信息. + *
+     * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.getOrder.html
+     * 
+ */ + String GET_ORDER = "https://api.weixin.qq.com/cgi-bin/express/local/business/order/get"; + + /** + * 模拟配送公司更新配送单状态. + *
+     * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.mockUpdateOrder.html
+     * 
+ */ + String MOCK_UPDATE_ORDER = "https://api.weixin.qq.com/cgi-bin/express/local/business/test_update_order"; + + /** + * 下单接口. + */ + interface PlaceAnOrder { + + /** + * 获取已支持的配送公司列表接口. + *
+       * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.getAllImmeDelivery.html
+       * 
+ */ + String GET_ALL_IMME_DELIVERY = "https://api.weixin.qq.com/cgi-bin/express/local/business/delivery/getall"; + + /** + * 预下配送单接口. + *
+       * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.preAddOrder.html
+       * 
+ */ + String PRE_ADD_ORDER = "https://api.weixin.qq.com/cgi-bin/express/local/business/order/pre_add"; + + /** + * 下配送单接口. + *
+       * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.addOrder.html
+       * 
+ */ + String ADD_ORDER = "https://api.weixin.qq.com/cgi-bin/express/local/business/order/add"; + + /** + * 重新下单. + *
+       * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.reOrder.html
+       * 
+ */ + String RE_ORDER = "https://api.weixin.qq.com/cgi-bin/express/local/business/order/readd"; + + /** + * 增加小费. + *
+       * 可以对待接单状态的订单增加小费。需要注意:订单的小费,以最新一次加小费动作的金额为准,故下一次增加小费额必须大于上一次小费额.
+       * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.addTip.html
+       * 
+ */ + String ADD_TIP = "https://api.weixin.qq.com/cgi-bin/express/local/business/order/addtips"; + + } + + /** + * 取消接口. + */ + interface Cancel { + + /** + * 预取消配送单接口. + *
+       * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.preCancelOrder.html
+       * 
+ */ + String PRE_CANCEL_ORDER = "https://api.weixin.qq.com/cgi-bin/express/local/business/order/precancel"; + + /** + * 取消配送单接口. + *
+       * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.cancelOrder.html
+       * 
+ */ + String CANCEL_ORDER = "https://api.weixin.qq.com/cgi-bin/express/local/business/order/cancel"; + + /** + * 异常件退回商家商家确认收货接口. + *
+       * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/immediate-delivery/by-business/immediateDelivery.abnormalConfirm.html
+       * 
+ */ + String ABNORMAL_CONFIRM = "https://api.weixin.qq.com/cgi-bin/express/local/business/order/confirm_return"; + + } + + } + } diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaImmediateDeliveryServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaImmediateDeliveryServiceImplTest.java new file mode 100644 index 000000000..739bc998f --- /dev/null +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaImmediateDeliveryServiceImplTest.java @@ -0,0 +1,203 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.delivery.AbnormalConfirmRequest; +import cn.binarywang.wx.miniapp.bean.delivery.AbnormalConfirmResponse; +import cn.binarywang.wx.miniapp.bean.delivery.AddOrderRequest; +import cn.binarywang.wx.miniapp.bean.delivery.AddOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.BindAccountResponse; +import cn.binarywang.wx.miniapp.bean.delivery.CancelOrderRequest; +import cn.binarywang.wx.miniapp.bean.delivery.CancelOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.GetOrderRequest; +import cn.binarywang.wx.miniapp.bean.delivery.GetOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.MockUpdateOrderRequest; +import cn.binarywang.wx.miniapp.bean.delivery.MockUpdateOrderResponse; +import cn.binarywang.wx.miniapp.test.ApiTestModule; +import com.google.common.collect.Lists; +import com.google.inject.Inject; +import me.chanjar.weixin.common.error.WxErrorException; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.math.BigDecimal; + +/** + * 微信小程序即时配送服务测试. + * + * @author Luo + * @version 1.0 + * @date 2021-10-14 11:48 + */ +@Guice(modules = ApiTestModule.class) +public class WxMaImmediateDeliveryServiceImplTest { + + /** + * 对应配送公司的appKey. + */ + private static final String SHOP_ID = "***"; + + /** + * 对应配送公司appSecret. + */ + private static final String APP_SECRET = "****"; + + /** + * 商家门店编号. + */ + private static final String SHOP_NO = "***"; + + /** + * 快递公司Id. + */ + private static final String DELIVERY_ID = "SFTC"; + + @Inject + private WxMaService wxMaService; + + /** + * 测试拉取已绑定账号接口. + * + * @throws WxErrorException 异常 + */ + @Test + public void testGetBindAccount() throws WxErrorException { + BindAccountResponse response = wxMaService.getWxMaImmediateDeliveryService().getBindAccount(); + System.out.println("response = " + response); + } + + /** + * 测试下配送单接口. + * + * @throws WxErrorException 异常 + */ + @Test + public void testAddOrder() throws WxErrorException { + AddOrderRequest request = new AddOrderRequest(); + // 下单用户的openid + request.setOpenid("*****"); + // 微信平台字段,对应配送公司的appkey + request.setShopId(SHOP_ID); + // 对应配送公司appSecret + request.setAppSecret(APP_SECRET); + // 商家门店编号,在配送公司登记,如果只有一个门店,美团闪送必填, 值为店铺id + // 商家对不同门店进行的编号,需要在配送公司系统有过登记,比如商家自己门店系统中有100个门店,编号是1-100,在顺丰同城的系统中有登记过这100个门店,且在顺丰同城登记的编号也是1-100,那么下单的时候传shop_no + // =1,就是编号为1 的门店下的配送单 + request.setShopNo(SHOP_NO); + // 配送公司Id + request.setDeliveryId(DELIVERY_ID); + // 唯一标识订单的 ID,由商户生成, 不超过 128 字节 + String shopOrderId = String.valueOf(System.currentTimeMillis()); + request.setShopOrderId(shopOrderId); + + // 订单信息 + AddOrderRequest.OrderInfo orderInfo = new AddOrderRequest.OrderInfo(); + orderInfo.setOrderTime(System.currentTimeMillis() / 1000L); + request.setOrderInfo(orderInfo); + + // 发件人信息 + AddOrderRequest.Sender sender = new AddOrderRequest.Sender(); + sender.setCity("上海市").setAddress("***").setAddressDetail("****"); + sender.setName("***").setPhone("166****8829"); + sender.setLng(new BigDecimal("121.281379")).setLat(new BigDecimal("31.049363")); + request.setSender(sender); + + // 收件人信息 + AddOrderRequest.Receiver receiver = new AddOrderRequest.Receiver().setCoordinateType(1); + receiver.setCity("北京市").setAddress("海淀区").setAddressDetail("北京市海淀区学清嘉创大厦A座15层"); + receiver.setName("顺丰同城").setPhone("166****8829"); + receiver.setLng(new BigDecimal("116.359442")).setLat(new BigDecimal("40.020407")); + request.setReceiver(receiver); + + // 商品信息 + AddOrderRequest.Cargo cargo = new AddOrderRequest.Cargo(); + cargo.setCargoFirstClass("电商").setCargoSecondClass("线上商城"); + cargo.setGoodsHeight(BigDecimal.valueOf(1)).setGoodsLength(BigDecimal.valueOf(3)); + cargo.setGoodsValue(BigDecimal.valueOf(5)).setGoodsWeight(BigDecimal.valueOf(1)).setGoodsWidth(BigDecimal.valueOf(2)); + // 商品列表 + AddOrderRequest.Cargo.GoodsDetail goodsDetail = new AddOrderRequest.Cargo.GoodsDetail(); + AddOrderRequest.Cargo.GoodsDetail.Goods goods1 = new AddOrderRequest.Cargo.GoodsDetail.Goods(); + goods1.setGoodCount(1).setGoodName("水果").setGoodPrice(new BigDecimal(10)); + AddOrderRequest.Cargo.GoodsDetail.Goods goods2 = new AddOrderRequest.Cargo.GoodsDetail.Goods(); + goods2.setGoodCount(2).setGoodName("蔬菜").setGoodPrice(new BigDecimal(20)); + goodsDetail.setGoods(Lists.newArrayList(goods1, goods2)); + cargo.setGoodsDetail(goodsDetail); + request.setCargo(cargo); + + // 店铺信息 + AddOrderRequest.Shop shop = new AddOrderRequest.Shop(); + int sum = + request.getCargo().getGoodsDetail().getGoods().stream().mapToInt(AddOrderRequest.Cargo.GoodsDetail.Goods::getGoodCount).sum(); + shop.setGoodsCount(sum).setGoodsName("商品"); + shop.setImgUrl("https://").setWxaPath("pages/index/index"); + request.setShop(shop); + + AddOrderResponse response = wxMaService.getWxMaImmediateDeliveryService().addOrder(request); + System.out.println("response = " + response); + + } + + /** + * 测试拉取配送单信息接口. + * + * @throws WxErrorException 异常 + */ + @Test + public void testGetOrder() throws WxErrorException { + GetOrderRequest request = new GetOrderRequest(); + request.setShopId(SHOP_ID).setShopNo(SHOP_NO).setAppSecret(APP_SECRET); + request.setShopOrderId("1561399675737608193"); + GetOrderResponse response = wxMaService.getWxMaImmediateDeliveryService().getOrder(request); + System.out.println("response = " + response); + } + + /** + * 测试取消配送单信息接口. + * + * @throws WxErrorException 异常 + */ + @Test + public void testCancelOrder() throws WxErrorException { + CancelOrderRequest request = new CancelOrderRequest(); + request.setShopId(SHOP_ID).setShopNo(SHOP_NO).setAppSecret(APP_SECRET); + request.setDeliveryId(DELIVERY_ID); + request.setCancelReasonId(1); + request.setShopOrderId("1560365275348471809"); + request.setWaybillId("3427365636312065025"); + CancelOrderResponse response = wxMaService.getWxMaImmediateDeliveryService().cancelOrder(request); + System.out.println("response = " + response); + } + + /** + * 测试异常件退回商家商家确认收货接口. + * + * @throws WxErrorException 异常 + */ + @Test + public void testAbnormalConfirm() throws WxErrorException { + AbnormalConfirmRequest request = new AbnormalConfirmRequest(); + request.setShopId(SHOP_ID).setShopNo(SHOP_NO).setAppSecret(APP_SECRET); + request.setDeliveryId(DELIVERY_ID); + request.setShopOrderId("1561399675737608193"); + request.setWaybillId("3427882855372591617"); + request.setRemark("测试签收异常订单"); + AbnormalConfirmResponse response = wxMaService.getWxMaImmediateDeliveryService().abnormalConfirm(request); + System.out.println("response = " + response); + } + + /** + * 测试模拟配送公司更新配送单状态接口. + * + * @throws WxErrorException 异常 + */ + @Test + public void testMockUpdateOrder() throws WxErrorException { + // 请求参数 + MockUpdateOrderRequest request = new MockUpdateOrderRequest(); + request.setActionTime(System.currentTimeMillis() / 1000L); + request.setOrderStatus(102); + request.setShopOrderId(""); + MockUpdateOrderResponse response = wxMaService.getWxMaImmediateDeliveryService().mockUpdateOrder(request); + System.out.println("response = " + response); + } + +}