微信发货接口对接,逻辑编写
This commit is contained in:
parent
dfbd7cd2b5
commit
29e195492b
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2024. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.suisung.mall.common.pojo.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
/**
|
||||
* 标准的地址实体类
|
||||
*/
|
||||
public class WxOrderBaseInfoDTO implements Serializable {
|
||||
private Integer store_id; // 店铺Id
|
||||
private String out_trade_no; // 商户订单号
|
||||
private String transaction_id; // 原支付交易对应的微信订单号
|
||||
private String subject; // 订单标题
|
||||
private Integer user_id; // 用户Id
|
||||
private String openid; // 微信 openId
|
||||
private String lkl_merchant_no; // 拉卡拉商户号
|
||||
private String lkl_term_no; // 拉卡拉终端号
|
||||
private String da_mobile; // 收货人手机
|
||||
private String da_name; // 收货人姓名
|
||||
}
|
||||
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.suisung.mall.common.modules.order.ShopOrderBase;
|
||||
import com.suisung.mall.common.modules.order.dto.MchOrderInfoDTO;
|
||||
import com.suisung.mall.common.pojo.dto.WxOrderBaseInfoDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@ -69,4 +70,13 @@ public interface ShopOrderBaseMapper extends BaseMapper<ShopOrderBase> {
|
||||
* @return
|
||||
*/
|
||||
IPage<MchOrderInfoDTO> selectMchOrderPageList(@Param("storeId") Integer storeId, @Param("keyword") String keyword, @Param("delivery") Integer delivery, @Param("status") Integer status, @Param("expireSeconds") Long expireSeconds, IPage<MchOrderInfoDTO> page);
|
||||
|
||||
|
||||
/**
|
||||
* 获取微信发货订单基本信息
|
||||
*
|
||||
* @param orderId
|
||||
* @return
|
||||
*/
|
||||
WxOrderBaseInfoDTO getWxOrderBaseInfo(@Param("orderId") String orderId);
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import com.suisung.mall.common.modules.order.ShopOrderBase;
|
||||
import com.suisung.mall.common.modules.order.ShopOrderInfo;
|
||||
import com.suisung.mall.common.modules.order.ShopOrderLogistics;
|
||||
import com.suisung.mall.common.modules.order.dto.MchOrderInfoDTO;
|
||||
import com.suisung.mall.common.pojo.dto.WxOrderBaseInfoDTO;
|
||||
import com.suisung.mall.common.pojo.req.SFCreateOrderReq;
|
||||
import com.suisung.mall.core.web.service.IBaseService;
|
||||
import com.suisung.mall.shop.order.vo.OrdeListVo;
|
||||
@ -556,4 +557,12 @@ public interface ShopOrderBaseService extends IBaseService<ShopOrderBase> {
|
||||
* @return
|
||||
*/
|
||||
JSONObject mchOrderCountByStoreId(Integer storeId);
|
||||
|
||||
/**
|
||||
* 获取微信发货订单基本信息
|
||||
*
|
||||
* @param orderId
|
||||
* @return
|
||||
*/
|
||||
WxOrderBaseInfoDTO getWxOrderBaseInfo(String orderId);
|
||||
}
|
||||
|
||||
@ -57,6 +57,7 @@ import com.suisung.mall.common.modules.product.ShopProductValidPeriod;
|
||||
import com.suisung.mall.common.modules.store.*;
|
||||
import com.suisung.mall.common.modules.user.*;
|
||||
import com.suisung.mall.common.pojo.dto.StandardAddressDTO;
|
||||
import com.suisung.mall.common.pojo.dto.WxOrderBaseInfoDTO;
|
||||
import com.suisung.mall.common.pojo.req.*;
|
||||
import com.suisung.mall.common.pojo.to.MsgTO;
|
||||
import com.suisung.mall.common.pojo.to.PayMoneyTO;
|
||||
@ -8641,6 +8642,21 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取微信发货订单基本信息
|
||||
*
|
||||
* @param orderId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public WxOrderBaseInfoDTO getWxOrderBaseInfo(String orderId) {
|
||||
if (StrUtil.isBlank(orderId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return shopOrderBaseMapper.getWxOrderBaseInfo(orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取货单号格式化
|
||||
*
|
||||
|
||||
@ -16,12 +16,13 @@ public interface WxOrderShippingService {
|
||||
* 上传发货信息到微信
|
||||
* 参考:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html#%E4%B8%80%E3%80%81%E5%8F%91%E8%B4%A7%E4%BF%A1%E6%81%AF%E5%BD%95%E5%85%A5%E6%8E%A5%E5%8F%A3
|
||||
*
|
||||
* @param orderId 订单ID
|
||||
* @param expressNo 快递公司编号
|
||||
* @param trackingNo 物流单号
|
||||
* @param logisticsType 物流模式,发货方式枚举值:1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品,虚拟商品,例如话费充值,点卡等,无实体配送形式 4、用户自提
|
||||
* @param orderId 订单ID
|
||||
* @param expressNo 快递公司编号
|
||||
* @param trackingNo 物流单号
|
||||
* @return 返回上传结果,包含成功状态和错误消息
|
||||
*/
|
||||
Pair<Boolean, String> uploadShippingInfoToWx(String orderId, String expressNo, String trackingNo);
|
||||
Pair<Boolean, String> uploadShippingInfoToWx(Integer logisticsType, String orderId, String expressNo, String trackingNo);
|
||||
|
||||
/**
|
||||
* 通知微信用户确认收货
|
||||
|
||||
@ -9,15 +9,23 @@
|
||||
package com.suisung.mall.shop.wechat.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.suisung.mall.common.pojo.dto.WxOrderBaseInfoDTO;
|
||||
import com.suisung.mall.common.utils.DateTimeUtils;
|
||||
import com.suisung.mall.common.utils.RestTemplateHttpUtil;
|
||||
import com.suisung.mall.shop.order.service.ShopOrderBaseService;
|
||||
import com.suisung.mall.shop.wechat.service.WxOrderShippingService;
|
||||
import com.suisung.mall.shop.wechat.utils.WxUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ -27,20 +35,87 @@ public class WxOrderShippingServiceImpl implements WxOrderShippingService {
|
||||
@Autowired
|
||||
private WxUtil wxUtil;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ShopOrderBaseService shopOrderBaseService;
|
||||
|
||||
/**
|
||||
* 上传发货信息到微信
|
||||
* 参考:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html#%E4%B8%80%E3%80%81%E5%8F%91%E8%B4%A7%E4%BF%A1%E6%81%AF%E5%BD%95%E5%85%A5%E6%8E%A5%E5%8F%A3
|
||||
*
|
||||
* @param orderId 订单ID
|
||||
* @param expressNo 快递公司编号
|
||||
* @param trackingNo 物流单号
|
||||
* @param logisticsType 物流模式,发货方式枚举值:1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品,虚拟商品,例如话费充值,点卡等,无实体配送形式 4、用户自提
|
||||
* @param orderId 订单ID
|
||||
* @param expressNo 快递公司编号
|
||||
* @param trackingNo 物流单号
|
||||
* @return 返回上传结果,包含成功状态和错误消息
|
||||
*/
|
||||
@Override
|
||||
public Pair<Boolean, String> uploadShippingInfoToWx(String orderId, String expressNo, String trackingNo) {
|
||||
return null;
|
||||
public Pair<Boolean, String> uploadShippingInfoToWx(Integer logisticsType, String orderId, String expressNo, String trackingNo) {
|
||||
final String PARAMETER_ERROR = "必要参数不能为空";
|
||||
final String ACCESS_TOKEN_ERROR = "获取AccessToken失败";
|
||||
final String ORDER_RECORD_ERROR = "无法获取订单记录";
|
||||
final String SHIPPING_INFO_ERROR = "发货信息录入失败";
|
||||
|
||||
if (StringUtils.isAnyBlank(orderId, expressNo, trackingNo)) {
|
||||
log.error(PARAMETER_ERROR);
|
||||
return Pair.of(false, PARAMETER_ERROR);
|
||||
}
|
||||
|
||||
try {
|
||||
String accessToken = wxUtil.getAccessToken();
|
||||
if (StrUtil.isBlank(accessToken)) {
|
||||
log.error("{},订单ID: {}", ACCESS_TOKEN_ERROR, orderId);
|
||||
return Pair.of(false, ACCESS_TOKEN_ERROR);
|
||||
}
|
||||
|
||||
WxOrderBaseInfoDTO orderBaseInfo = shopOrderBaseService.getWxOrderBaseInfo(orderId);
|
||||
if (orderBaseInfo == null) {
|
||||
log.error("{},订单ID: {}", ORDER_RECORD_ERROR, orderId);
|
||||
return Pair.of(false, ORDER_RECORD_ERROR);
|
||||
}
|
||||
|
||||
JSONObject paramsJSON = new JSONObject()
|
||||
.set("order_key.order_number_type", 2)
|
||||
.set("order_key.transaction_id", orderBaseInfo.getTransaction_id())
|
||||
.set("delivery_mode", 1)
|
||||
.set("logistics_type", logisticsType)
|
||||
.set("shipping_list", new JSONArray())
|
||||
.set("upload_time", DateTimeUtils.formatDateTime(LocalDateTime.now(), "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"))
|
||||
.set("payer.openid", orderBaseInfo.getOpenid());
|
||||
|
||||
JSONObject respObj = RestTemplateHttpUtil.sendPost(
|
||||
"https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token=" + accessToken,
|
||||
null, paramsJSON, JSONObject.class
|
||||
);
|
||||
|
||||
if (respObj == null) {
|
||||
log.error("{},订单ID: {}, 返回结果为空", SHIPPING_INFO_ERROR, orderId);
|
||||
return Pair.of(false, SHIPPING_INFO_ERROR + ",返回结果为空");
|
||||
}
|
||||
|
||||
int errCode = respObj.getInt("errcode", -1);
|
||||
if (errCode != 0) {
|
||||
String errorMsg = respObj.getStr("errmsg", "未知错误");
|
||||
log.error("{},订单ID: {}, 错误码: {}, 错误信息: {}", SHIPPING_INFO_ERROR, orderId, errCode, errorMsg);
|
||||
return Pair.of(false, SHIPPING_INFO_ERROR + ": " + errorMsg);
|
||||
}
|
||||
|
||||
log.info("发货信息录入成功, 订单ID: {}", orderId);
|
||||
return Pair.of(true, "发货信息录入成功");
|
||||
|
||||
} catch (HttpClientErrorException e) {
|
||||
log.error("HTTP请求错误,订单ID: {}, 状态码: {}, 错误信息: {}", orderId, e.getStatusCode(), e.getMessage(), e);
|
||||
return Pair.of(false, "HTTP请求错误: " + e.getMessage());
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("参数错误,订单ID: {}, 错误信息: {}", orderId, e.getMessage(), e);
|
||||
return Pair.of(false, "参数错误: " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("{},订单ID: {}, 错误信息: {}", SHIPPING_INFO_ERROR, orderId, e.getMessage(), e);
|
||||
return Pair.of(false, SHIPPING_INFO_ERROR + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通知微信用户确认收货
|
||||
* 参考:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html#%E4%BA%94%E3%80%81%E7%A1%AE%E8%AE%A4%E6%94%B6%E8%B4%A7%E6%8F%90%E9%86%92%E6%8E%A5%E5%8F%A3
|
||||
@ -55,34 +130,48 @@ public class WxOrderShippingServiceImpl implements WxOrderShippingService {
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// Cache or reuse accessToken to reduce redundant API calls
|
||||
String accessToken = wxUtil.getAccessToken();
|
||||
if (StrUtil.isBlank(accessToken)) {
|
||||
log.error("获取AccessToken失败,订单ID: {}", orderId);
|
||||
return Pair.of(false, "获取AccessToken失败");
|
||||
}
|
||||
|
||||
JSONObject paramsJSON = new JSONObject();
|
||||
paramsJSON.put("transaction_id", orderId);
|
||||
paramsJSON.put("merchant_id", orderId);
|
||||
paramsJSON.put("merchant_trade_no", orderId);
|
||||
paramsJSON.put("received_time", System.currentTimeMillis() / 1000);
|
||||
WxOrderBaseInfoDTO orderBaseInfo = shopOrderBaseService.getWxOrderBaseInfo(orderId);
|
||||
if (orderBaseInfo == null) {
|
||||
log.error("无法获取订单记录,订单ID: {}", orderId);
|
||||
return Pair.of(false, "无法获取订单记录");
|
||||
}
|
||||
|
||||
JSONObject paramsJSON = new JSONObject()
|
||||
.set("transaction_id", orderBaseInfo.getTransaction_id())
|
||||
.set("merchant_id", orderBaseInfo.getLkl_merchant_no())
|
||||
.set("merchant_trade_no", orderId)
|
||||
.set("received_time", System.currentTimeMillis() / 1000);
|
||||
|
||||
JSONObject respObj = RestTemplateHttpUtil.sendPost(
|
||||
"https://api.weixin.qq.com/wxa/sec/order/notify_confirm_receive?access_token=" + accessToken,
|
||||
null, paramsJSON, JSONObject.class
|
||||
);
|
||||
|
||||
JSONObject respObj = RestTemplateHttpUtil.sendPost("https://api.weixin.qq.com/wxa/sec/order/notify_confirm_receive?access_token=" + accessToken, null, paramsJSON, JSONObject.class);
|
||||
if (respObj == null) {
|
||||
log.error("通知微信用户确认收货失败,订单ID: {}, 返回结果为空", orderId);
|
||||
return Pair.of(false, "通知微信用户确认收货失败,返回结果为空");
|
||||
}
|
||||
|
||||
if (respObj.getInt("errcode") != 0) {
|
||||
String errorMsg = respObj.getStr("errmsg");
|
||||
log.error("通知微信用户确认收货失败,订单ID: {}, 错误信息: {}", orderId, errorMsg);
|
||||
int errCode = respObj.getInt("errcode", -1); // Default to -1 if errcode is missing
|
||||
if (errCode != 0) {
|
||||
String errorMsg = respObj.getStr("errmsg", "未知错误");
|
||||
log.error("通知微信用户确认收货失败,订单ID: {}, 错误码: {}, 错误信息: {}", orderId, errCode, errorMsg);
|
||||
return Pair.of(false, "通知微信用户确认收货失败: " + errorMsg);
|
||||
}
|
||||
|
||||
log.info("通知微信用户确认收货成功,订单号:{}", orderId);
|
||||
log.info("通知微信用户确认收货成功, 订单ID: {}", orderId);
|
||||
return Pair.of(true, "通知微信用户确认收货成功");
|
||||
|
||||
} catch (HttpClientErrorException e) {
|
||||
log.error("HTTP请求错误,订单ID: {}, 状态码: {}, 错误信息: {}", orderId, e.getStatusCode(), e.getMessage(), e);
|
||||
return Pair.of(false, "HTTP请求错误: " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("通知微信确认收货失败,订单ID: {}, 错误信息: {}", orderId, e.getMessage(), e);
|
||||
return Pair.of(false, "通知微信确认收货失败: " + e.getMessage());
|
||||
|
||||
@ -8,6 +8,20 @@
|
||||
buyer_user_id, buyer_user_name, order_state_id, easy_pay_id
|
||||
</sql>
|
||||
|
||||
<resultMap id="WxOrderBaseInfoResult" type="com.suisung.mall.common.pojo.dto.WxOrderBaseInfoDTO">
|
||||
<!--订单对象映射-->
|
||||
<result property="store_id" column="store_id"/>
|
||||
<result property="out_trade_no" column="out_trade_no"/>
|
||||
<result property="transaction_id" column="transaction_id"/>
|
||||
<result property="subject" column="subject"/>
|
||||
<result property="user_id" column="user_id"/>
|
||||
<result property="openid" column="openid"/>
|
||||
<result property="lkl_merchant_no" column="lkl_merchant_no"/>
|
||||
<result property="lkl_term_no" column="lkl_term_no"/>
|
||||
<result property="da_mobile" column="da_mobile"/>
|
||||
<result property="da_name" column="da_name"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="getList" resultType="java.util.Map">
|
||||
SELECT a.order_id,
|
||||
a.order_time,
|
||||
@ -737,4 +751,22 @@
|
||||
</where>
|
||||
order by ob.order_time desc
|
||||
</select>
|
||||
|
||||
<select id="getWxOrderBaseInfo" resultMap="WxOrderBaseInfoResult">
|
||||
SELECT a.store_id,
|
||||
a.order_id as out_trade_no,
|
||||
c.deposit_trade_no as transaction_id,
|
||||
c.deposit_subject as subject,
|
||||
c.user_id,
|
||||
c.deposit_buyer_id as openid,
|
||||
d.lkl_merchant_no,
|
||||
d.lkl_term_no,
|
||||
e.da_mobile,
|
||||
e.da_name
|
||||
FROM shop_order_base a
|
||||
JOIN pay_consume_deposit c on a.order_id = c.order_id
|
||||
JOIN shop_store_base d on a.store_id = d.store_id
|
||||
LEFT JOIN shop_order_delivery_address e on a.order_id = e.order_id
|
||||
where a.order_id = #{orderId}
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user