确认收货接口
private static String UPLOAD_SHIPPING_INFO = "https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token=";
package cn.xx.modules.wechat.entity.dos;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
@Data
public class WxDeliverGoodsDTO implements Serializable {
@ApiModelProperty(value = "必填 订单,需要上传物流信息的订单")
@NotNull(message = "order_key不能为空")
private OrderKeyDTO order_key;
@ApiModelProperty(value = "必填 物流模式,发货方式枚举值:1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品,虚拟商品,例如话费充值,点卡等,无实体配送形式 4、用户自提")
@NotNull(message = "logistics_type不能为空")
private Integer logistics_type;
@ApiModelProperty(value = "必填 发货模式,发货模式枚举值:1、UNIFIED_DELIVERY(统一发货)2、SPLIT_DELIVERY(分拆发货) 示例值: UNIFIED_DELIVERY")
@NotNull(message = "delivery_mode不能为空")
private Integer delivery_mode;
@ApiModelProperty(value = "分拆发货模式时必填,用于标识分拆发货模式下是否已全部发货完成,只有全部发货完成的情况下才会向用户推送发货完成通知。示例值: true/false")
private Boolean is_all_delivered;
@ApiModelProperty(value = "必填 物流信息列表,发货物流单列表,支持统一发货(单个物流单)和分拆发货(多个物流单)两种模式,多重性: [1, 10]")
@NotNull(message = "shipping_list不能为空")
private List<ShippingDTO> shipping_list;
@ApiModelProperty(value = "必填 上传时间,用于标识请求的先后顺序 示例值: `2022-12-15T13:29:35.120+08:00`")
@NotBlank(message = "upload_time不能为空")
private String upload_time;
@ApiModelProperty(value = "必填 支付者,支付者信息")
@NotNull(message = "payer不能为空")
private PayerDTO payer;
}
package cn.xx.modules.wechat.entity.dos;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@Data
public class OrderKeyDTO implements Serializable {
@ApiModelProperty(value = "必填 订单单号类型,用于确认需要上传详情的订单。枚举值1,使用下单商户号和商户侧单号;枚举值2,使用微信支付单号。")
@NotNull(message = "order_number_type不能为空")
private Integer order_number_type;
@ApiModelProperty(value = "原支付交易对应的微信订单号")
private String transaction_id;
@ApiModelProperty(value = "支付下单商户的商户号,由微信支付生成并下发。")
private String mchid;
@ApiModelProperty(value = "商户系统内部订单号,只能是数字、大小写字母`_-*`且在同一个商户号下唯一")
private String out_trade_no;
}
package cn.xx.modules.wechat.entity.dos;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
@Data
public class ShippingDTO implements Serializable {
@ApiModelProperty(value = "物流单号,物流快递发货时必填,示例值: 323244567777 字符字节限制: [1, 128]")
private String tracking_no;
@ApiModelProperty(value = "物流公司编码,快递公司ID,参见「查询物流公司编码列表」,物流快递发货时必填, 示例值: DHL 字符字节限制: [1, 128]")
private String express_company;
@ApiModelProperty(value = "必填 商品信息,例如:微信红包抱枕*1个,限120个字以内")
@NotBlank(message = "item_desc不能为空")
private String item_desc;
@ApiModelProperty(value = "联系方式,当发货的物流公司为顺丰时,联系方式为必填,收件人或寄件人联系方式二选一")
private ContactDTO contact;
}
package cn.xx.modules.wechat.entity.dos;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
@Data
public class PayerDTO implements Serializable {
@ApiModelProperty(value = "必填 用户标识,用户在小程序appid下的唯一标识。 下单前需获取到用户的Openid 示例值: oUpF8uMuAJO_M2pxb1Q9zNjWeS6o 字符字节限制: [1, 128]")
@NotBlank(message = "openid不能为空")
private String openid;
}
package cn.xx.modules.wechat.entity.dos;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
public class ContactDTO implements Serializable {
@ApiModelProperty(value = "寄件人联系方式,寄件人联系方式,采用掩码传输,最后4位数字不能打掩码 示例值: `189****1234, 021-****1234, ****1234, 0**2-***1234, 0**2-******23-10, ****123-8008` 值限制: 0 ≤ value ≤ 1024")
private String consignor_contact;
@ApiModelProperty(value = "收件人联系方式,收件人联系方式为,采用掩码传输,最后4位数字不能打掩码 示例值: `189****1234, 021-****1234, ****1234, 0**2-***1234, 0**2-******23-10, ****123-8008` 值限制: 0 ≤ value ≤ 1024")
private String receiver_contact;
}
try {
//调用微信
List<OrderItem> orderItemList = orderItemService.lambdaQuery().eq(OrderItem::getOrderSn, order.getSn())
.select(OrderItem::getNum, OrderItem::getGoodsName)
.list();
WechatPaymentSetting setting = wechatPaymentSetting();
WxDeliverGoodsDTO vo = new WxDeliverGoodsDTO();
OrderKeyDTO order_key = new OrderKeyDTO();
order_key.setMchid(setting.getMchId());
order_key.setOrder_number_type(2); // 必填
order_key.setOut_trade_no(order.getSn());
order_key.setTransaction_id(order.getReceivableNo());
List<ShippingDTO> list = new ArrayList<>(orderItemList.size());
orderItemList.forEach(x -> {
ShippingDTO shipping = new ShippingDTO();
shipping.setExpress_company(logistics.getCode());
shipping.setItem_desc(x.getGoodsName() + "*" + x.getNum()); // 必填
shipping.setTracking_no(logisticsNo);
ContactDTO contact = new ContactDTO();
//*****发货人联系方式
contact.setConsignor_contact("*****".replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")); // 手机号掩码处理
contact.setReceiver_contact(order.getConsigneeMobile().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
shipping.setContact(contact);
list.add(shipping);
});
PayerDTO payer = new PayerDTO();
payer.setOpenid(openId); // 必填
vo.setOrder_key(order_key); // 必填
vo.setLogistics_type(1); // 必填
vo.setDelivery_mode(1); // 必填
vo.setIs_all_delivered(false); // 分拆发货模式时必填
vo.setShipping_list(list); // 必填
//线程不安全
SimpleDateFormat sdf = new SimpleDateFormat(DatePattern.UTC_MS_WITH_ZONE_OFFSET_PATTERN);
vo.setUpload_time(sdf.format(new Date())); //必填
vo.setPayer(payer); // 必填
wechatDeliveryUtil.uploadShippingInfo(vo);
} catch (Exception e) {
log.error("调用微信发货异常", e);
}
public void uploadShippingInfo(WxDeliverGoodsDTO wxDeliverGoodsDTO) {
try {
String accessToken = wechatAccessTokenUtil.cgiAccessToken(ClientTypeEnum.WECHAT_MP);
String url = UPLOAD_SHIPPING_INFO + accessToken;
String param = JSONObject.toJSONString(wxDeliverGoodsDTO);
log.info("upload_shipping_info请求入参{} = ", param);
String result = HttpUtil.post(url, param);
log.info("upload_shipping_info请求结果={}", result);
JSONObject jsonObject = JSON.parseObject(result);
int errcode = jsonObject.getInteger("errcode");
if (errcode != 0) {
String errmsg = jsonObject.getString("errmsg");
log.error(String.format("微信小程序-发货信息录入接口异常,code码:%s, msg:%s", errcode, errmsg));
throw new ServiceException(ResultCode.ERROR, "微信小程序-发货信息录入接口异常:" + errmsg);
}
} catch (Exception e) {
throw new ServiceException(e.getMessage());
}
}
确认收货提醒
private static String NOTIFY_CONFIRM_RECEIVE = "https://api.weixin.qq.com/wxa/sec/order/notify_confirm_receive?access_token=";
package cn.xx.modules.wechat.entity.dos;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
public class WxTakeOverGoodsDTO implements Serializable {
@ApiModelProperty("原支付交易对应的微信订单号")
private String transaction_id;
@ApiModelProperty("支付下单商户的商户号,由微信支付生成并下发")
private String merchant_id;
@ApiModelProperty("二级商户号")
private String sub_merchant_id;
@ApiModelProperty("商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一")
private String merchant_trade_no;
@ApiModelProperty("快递签收时间,时间戳形式")
private Long received_time;
}
try {
WechatPaymentSetting setting = wechatPaymentSetting();
WxTakeOverGoodsDTO vo = new WxTakeOverGoodsDTO();
vo.setMerchant_id(setting.getMchId());
vo.setMerchant_trade_no(orderSn);
//一定/1000,否则会报错
vo.setReceived_time(System.currentTimeMillis()/1000L);
vo.setSub_merchant_id("");
vo.setTransaction_id(order.getReceivableNo());
wechatDeliveryUtil.notifyConfirmReceive(vo);
} catch (Exception e) {
log.info("调用微信确认收货提醒异常", e);
}
public void notifyConfirmReceive(WxTakeOverGoodsDTO wxTakeOverGoodsDTO) {
try {
//获取AccessToken
String accessToken = wechatAccessTokenUtil.cgiAccessToken(ClientTypeEnum.WECHAT_MP);
String url = NOTIFY_CONFIRM_RECEIVE + accessToken ;
String param = JSONObject.toJSONString(wxTakeOverGoodsDTO);
log.info("notifyConfirmReceive请求入参={} ", param);
String result = HttpUtil.post(url, param);
log.info("notifyConfirmReceive请求结果={}", result);
JSONObject jsonObject = JSON.parseObject(result);
int errcode = jsonObject.getInteger("errcode");
if (errcode != 0) {
String errmsg = jsonObject.getString("errmsg");
log.error(String.format("微信小程序-确认收货提醒接口异常,code码:%s, msg:%s", errcode, errmsg));
throw new ServiceException(ResultCode.ERROR, "微信小程序-确认收货提醒接口异常:" + errmsg);
}
} catch (Exception e) {
throw new ServiceException(e.getMessage());
}
}
常见问题:
(1)微信小程序-确认收货提醒接口异常,code码:10060029, msg:签收时间不合理 rid: 65f02561-652301bd-7d73f858
1.时间在发货时间之后
2.签收时间为当前时间秒数
(2)调用确认收货之后,微信小程序后台订单状态更新到已发货,
订单进入结算周期需要小程序调用确认收货组件
https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping-half.html
传入用户交易单号或者商户号+用户订单号的方式
订单状态更新到已完成