收藏
回答

一直没有成功上传发货信息到微信官方平台上

问题类型 API/组件名称 终端类型 微信版本 基础库版本
Bug POST https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token=ACCESS_TOKEN 工具 8.0.67 3.13.2

https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order_center/order_center.html

2026-01-22 10:08:44.556 [http-nio-8080-exec-7] INFO  c.s.service.impl.WeChatShippingServiceImpl - 获取到用户openid - userId: 2, openid: o3p5F1-U_mwHIlLFZQTr3brxhPik

2026-01-22 10:08:44.556 [http-nio-8080-exec-7] INFO  c.s.service.impl.WeChatShippingServiceImpl - 上传发货信息参数 - orderSn: ORD202601221008048420, uploadTime: 2026-01-22T10:08:44.555+08:00

2026-01-22 10:08:44.556 [http-nio-8080-exec-7] INFO  c.s.service.impl.WeChatShippingServiceImpl - ========== 开始预检查订单状态 ==========

2026-01-22 10:08:44.556 [http-nio-8080-exec-7] INFO  c.s.service.impl.WeChatShippingServiceImpl - 查询微信系统中的订单状态 - transactionId: 4200002990202601226107283773

2026-01-22 10:08:44.750 [http-nio-8080-exec-7] INFO  c.s.service.impl.WeChatShippingServiceImpl - 微信订单状态查询响应: {"errcode":40066,"errmsg":"invalid url rid: 697186a9-41ef2c13-329d0d8d"}

2026-01-22 10:08:44.751 [http-nio-8080-exec-7] ERROR c.s.service.impl.WeChatShippingServiceImpl - ========== 预检查失败 ==========

2026-01-22 10:08:44.751 [http-nio-8080-exec-7] ERROR c.s.service.impl.WeChatShippingServiceImpl - 微信系统中查询不到此订单 - errcode: 40066, errmsg: invalid url rid: 697186a9-41ef2c13-329d0d8d

不能成功上传发货信息,这个要怎么处理

package com.skyphantom.service.impl; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestAlgorithm; import cn.hutool.crypto.digest.Digester; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.skyphantom.common.dto.Result; import com.skyphantom.common.exception.BusinessException; import com.skyphantom.config.WeChatMiniAppConfig; import com.skyphantom.entity.OmsOrder; import com.skyphantom.entity.User; import com.skyphantom.entity.OmsOrderItem; import com.skyphantom.mapper.OmsOrderMapper; import com.skyphantom.mapper.UserMapper; import com.skyphantom.mapper.OmsOrderItemMapper; import com.skyphantom.service.WeChatShippingService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * 微信订单发货管理服务实现类 * <p> * 核心功能: * 1. 上传发货信息到微信(实物商品) * 2. 查询订单发货状态 * 3. 获取物流公司列表 * 4. 确认收货提醒 * </p> * <p> * API文档: * - 发货信息上传: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html * - 确认收货提醒: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html * </p> * * @author chengyuwen * @since 2025/01/20 */ @Slf4j @Service @RequiredArgsConstructor public class WeChatShippingServiceImpl implements WeChatShippingService { /** * 微信小程序配置(获取AppID和Secret用于获取access_token) */ private final WeChatMiniAppConfig weChatMiniAppConfig; /** * 订单Mapper */ private final OmsOrderMapper omsOrderMapper; /** * 用户Mapper */ private final UserMapper userMapper; /** * 订单项Mapper */ private final OmsOrderItemMapper omsOrderItemMapper; /** * 微信发货管理API地址 * 根据微信官方文档:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html */ // 发货信息录入接口 private static final String SHIPPING_UPLOAD_URL = "https://api.weixin.qq.com/wxa/sec/order/shipping/upload_shipping_info"; // 查询订单发货状态接口(注意:需要 /shipping 路径) private static final String SHIPPING_QUERY_URL = "https://api.weixin.qq.com/wxa/sec/order/shipping/get_order"; // 获取物流公司列表接口 private static final String DELIVERY_LIST_URL = "https://api.weixin.qq.com/wxa/sec/order/get_express_list"; // 查询小程序是否已开通发货信息管理服务 private static final String CHECK_SERVICE_URL = "https://api.weixin.qq.com/wxa/sec/order/check_is_trade_managed"; // 确认收货提醒接口 private static final String CONFIRM_RECEIPT_URL = "https://api.weixin.qq.com/wxa/sec/order/shipping/notify_confirm_receipt"; /** * RFC 3339 时间格式(微信要求格式:2022-12-15T13:29:35.120+08:00) */ private static final DateTimeFormatter RFC3339_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); /** * access_token缓存 */ private String cachedAccessToken; private long tokenExpireTime; @Value("${wechat.shipping.enabled:true}") private Boolean shippingEnabled; @Override @Transactional(rollbackFor = Exception.class) public Result uploadShippingInfo(String orderSn, Integer logisticsType, Integer deliveryMode, String logisticsList) { log.info("========== 开始上传发货信息到微信 =========="); log.info("订单号: {}, 物流类型: {}, 发货模式: {}", orderSn, logisticsType, deliveryMode); // 检查发货管理功能是否启用 if (!shippingEnabled) { log.info("微信发货管理功能已禁用,跳过上传"); return Result.success("发货管理功能已禁用,无需上传"); } // 查询订单信息 OmsOrder order = omsOrderMapper.selectOne( new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<OmsOrder>() .eq(OmsOrder::getOrderSn, orderSn) ); if (order == null) { log.error("订单不存在 - orderSn: {}", orderSn); return Result.fail("订单不存在"); } // 检查是否已上传 if (order.getShippingUploaded() != null && order.getShippingUploaded() == 1) { log.info("订单发货信息已上传 - orderSn: {}", orderSn); return Result.success("发货信息已上传"); } // 只对实物商品(无人机及配件)上传发货信息 // 订单类型:1=普通商品订单(无人机及配件),2=租赁订单,3=服务订单 if (order.getOrderType() != 1) { log.info("非实物商品订单,无需上传发货信息 - orderSn: {}, orderType: {}", orderSn, order.getOrderType()); return Result.success("非实物商品订单,无需上传发货信息"); } try { // 获取access_token String accessToken = getAccessToken(); if (StrUtil.isBlank(accessToken)) { log.error("获取access_token失败"); return Result.fail("获取access_token失败"); } // 验证并解析 logisticsList if (StrUtil.isBlank(logisticsList)) { log.error("物流信息列表为空 - orderSn: {}", orderSn); return Result.fail("物流信息列表不能为空"); } // 检查 transaction_id 是否存在 if (StrUtil.isBlank(order.getTransactionId())) { log.error("微信交易订单号为空,无法上传发货信息 - orderSn: {}", orderSn); return Result.fail("订单尚未支付或微信交易订单号为空"); } // 获取订单项信息,用于构造 item_desc List<OmsOrderItem> orderItems = omsOrderItemMapper.selectList( new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<OmsOrderItem>() .eq(OmsOrderItem::getOrderId, order.getId()) ); if (orderItems == null || orderItems.isEmpty()) { log.error("订单项为空 - orderSn: {}", orderSn); return Result.fail("订单项为空"); } // 构造商品描述字符串(微信要求格式:商品名*数量,多个商品用分号分隔,最多120字) String itemDesc = orderItems.stream() .map(item -> { String desc = item.getProductName() != null ? item.getProductName() : "商品"; if (item.getQuantity() != null && item.getQuantity() > 1) { desc += "*" + item.getQuantity(); } return desc; }) .collect(Collectors.joining(";")); // 限制 item_desc 长度为120字符 if (itemDesc.length() > 120) { itemDesc = itemDesc.substring(0, 117) + "..."; } log.info("构造商品描述 - orderSn: {}, itemDesc: {}", orderSn, itemDesc); Object shippingList; try { shippingList = JSONUtil.parseArray(logisticsList); } catch (Exception e) { log.error("物流信息列表JSON格式错误 - logisticsList: {}", logisticsList, e); return Result.fail("物流信息列表格式错误,必须是JSON数组格式"); } // 将 item_desc 添加到每个物流信息中 if (shippingList instanceof List) { List<?> shippingListObj = (List<?>) shippingList; for (Object item : shippingListObj) { if (item instanceof Map) { ((Map<String, Object>) item).put("item_desc", itemDesc); } } } // 构造请求参数 Map<String, Object> params = new HashMap<>(); params.put("order_key", Map.<String, Object>of("order_number_type", 2, "transaction_id", order.getTransactionId())); params.put("logistics_type", logisticsType); params.put("delivery_mode", deliveryMode); params.put("shipping_list", shippingList); // 分拆发货时,is_all_delivered为必填字段(微信要求) if (deliveryMode == 2) { params.put("is_all_delivered", true); // 分拆发货场景,表示已全部发货完成 } // 使用 RFC 3339 格式的时间(微信文档要求) String uploadTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).format(RFC3339_FORMATTER); params.put("upload_time", uploadTime); // payer.openid 为必填字段,从数据库查询用户获取 String userOpenid = null; if (order.getUserId() != null) { User user = userMapper.selectById(order.getUserId()); if (user != null && StrUtil.isNotBlank(user.getOpenid())) { userOpenid = user.getOpenid(); log.info("获取到用户openid - userId: {}, openid: {}", order.getUserId(), userOpenid); } else { log.warn("用户不存在或openid为空 - userId: {}", order.getUserId()); } } if (StrUtil.isBlank(userOpenid)) { log.error("无法获取用户openid,无法上传发货信息 - orderSn: {}, userId: {}", orderSn, order.getUserId()); return Result.fail("用户openid为空,无法上传发货信息"); } params.put("payer", Map.<String, Object>of("openid", userOpenid)); log.info("上传发货信息参数 - orderSn: {}, uploadTime: {}", orderSn, uploadTime); // 创建HTTP客户端 OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .build(); // 🔍 预检查:先查询订单在微信系统中的状态 log.info("========== 开始预检查订单状态 =========="); log.info("查询微信系统中的订单状态 - transactionId: {}", order.getTransactionId()); try { Map<String, Object> queryParams = new HashMap<>(); queryParams.put("order_key", Map.<String, Object>of("order_number_type", 2, "transaction_id", order.getTransactionId())); String queryUrl = SHIPPING_QUERY_URL + "?access_token=" + accessToken; MediaType mediaTypeQuery = MediaType.parse("application/json; charset=utf-8"); RequestBody queryBody = RequestBody.create(JSONUtil.toJsonStr(queryParams), mediaTypeQuery); Request queryRequest = new Request.Builder() .url(queryUrl) .post(queryBody) .build(); try (Response queryResponse = client.newCall(queryRequest).execute()) { String queryResponseBody = queryResponse.body() != null ? queryResponse.body().string() : ""; log.info("微信订单状态查询响应: {}", queryResponseBody); JSONObject queryJson = JSONUtil.parseObj(queryResponseBody); Integer queryErrcode = queryJson.getInt("errcode"); if (queryErrcode != null && queryErrcode != 0) { log.error("========== 预检查失败 =========="); log.error("微信系统中查询不到此订单 - errcode: {}, errmsg: {}", queryErrcode, queryJson.getStr("errmsg")); log.error("这说明transaction_id在微信系统中不存在或无效!"); log.error("可能的原因:"); log.error("1. 订单已退款"); log.error("2. 订单被撤销"); log.error("3. AppID/Secret配置错误,查询的不是支付订单所属的小程序"); log.error("4. 小程序未开通发货管理功能"); return Result.fail("订单在微信系统中不存在,请检查transaction_id是否有效。错误:" + queryJson.getStr("errmsg")); } else { log.info("========== 预检查通过 =========="); log.info("订单在微信系统中存在,可以上传发货信息"); } } } catch (Exception e) { log.warn("预检查失败,但将继续尝试上传发货信息 - {}", e.getMessage()); } log.info("========== 预检查完成 =========="); log.info(""); // 发送请求到微信 String url = SHIPPING_UPLOAD_URL + "?access_token=" + accessToken; MediaType mediaType = MediaType.parse("application/json; charset=utf-8"); String jsonBody = JSONUtil.toJsonStr(params); RequestBody requestBody = RequestBody.create(jsonBody, mediaType); log.info("========== 发送发货信息到微信 =========="); log.info("请求URL: {}", url); log.info("请求体: {}", jsonBody); log.info("请求体长度: {} 字节", jsonBody.length()); Request httpRequest = new Request.Builder() .url(url) .post(requestBody) .build(); log.info("发送发货信息到微信 - URL: {}", url); try (Response response = client.newCall(httpRequest).execute()) { if (!response.isSuccessful()) { log.error("微信发货接口调用失败 - HTTP状态码: {}", response.code()); return Result.fail("发货接口调用失败,HTTP状态码:" + response.code()); } String responseBody = response.body().string(); log.info("微信发货接口响应: {}", responseBody); JSONObject json = JSONUtil.parseObj(responseBody); Integer errcode = json.getInt("errcode"); String errmsg = json.getStr("errmsg"); // 微信发货接口:errcode=0表示成功,其他值表示失败 if (errcode == null || errcode != 0) { log.error("========== 发货信息上传失败 =========="); log.error("错误码: {}, 错误信息: {}", errcode, errmsg); log.error("订单号: {}, 微信交易号: {}", orderSn, order.getTransactionId()); log.error("用户openid: {}", userOpenid); log.error("物流信息列表: {}", logisticsList); // 40066错误特别诊断 if (errcode == 40066) { log.error("========== 40066错误诊断 =========="); log.error("可能原因:"); log.error("1. 微信交易号(transaction_id)无效或不存在"); log.error("2. 该订单未完成支付或支付已退款"); log.error("3. 小程序未开通发货管理功能"); log.error("4. 订单不属于当前小程序的AppID"); log.error("5. 请求参数格式不符合微信要求"); log.error("建议:"); log.error("- 检查transaction_id是否真实有效"); log.error("- 确认小程序AppID和Secret配置正确"); log.error("- 在微信后台确认发货管理功能已开通"); log.error("- 尝试使用微信官方接口测试工具测试"); } return Result.fail("上传发货信息失败:" + errmsg); } // 更新订单发货上传状态 OmsOrder updateOrder = new OmsOrder(); updateOrder.setId(order.getId()); updateOrder.setShippingUploaded(1); updateOrder.setShippingUploadTime(LocalDateTime.now()); omsOrderMapper.updateById(updateOrder); log.info("========== 发货信息上传成功 =========="); return Result.success("发货信息上传成功"); } } catch (Exception e) { log.error("上传发货信息异常", e); return Result.fail("上传发货信息异常:" + e.getMessage()); } } @Override public Result getShippingInfo(String orderSn) { log.info("========== 开始查询订单发货状态 =========="); log.info("订单号: {}", orderSn); // 查询订单信息 OmsOrder order = omsOrderMapper.selectOne( new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<OmsOrder>() .eq(OmsOrder::getOrderSn, orderSn) ); if (order == null) { log.error("订单不存在 - orderSn: {}", orderSn); return Result.fail("订单不存在"); } try { // 获取access_token String accessToken = getAccessToken(); if (StrUtil.isBlank(accessToken)) { log.error("获取access_token失败"); return Result.fail("获取access_token失败"); } // 构造请求参数 Map<String, Object> params = new HashMap<>(); params.put("order_key", Map.<String, Object>of("order_number_type", 2, "transaction_id", order.getTransactionId())); // 发送请求到微信 OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .build(); String url = SHIPPING_QUERY_URL + "?access_token=" + accessToken; MediaType mediaType = MediaType.parse("application/json; charset=utf-8"); RequestBody requestBody = RequestBody.create(JSONUtil.toJsonStr(params), mediaType); Request httpRequest = new Request.Builder() .url(url) .post(requestBody) .build(); log.info("查询发货状态 - URL: {}", url); try (Response response = client.newCall(httpRequest).execute()) { if (!response.isSuccessful()) { log.error("查询发货状态失败 - HTTP状态码: {}", response.code()); return Result.fail("查询发货状态失败,HTTP状态码:" + response.code()); } String responseBody = response.body().string(); log.info("查询发货状态响应: {}", responseBody); JSONObject json = JSONUtil.parseObj(responseBody); Integer errcode = json.getInt("errcode"); // 微信查询接口:errcode=0表示成功,其他值表示失败 if (errcode == null || errcode != 0) { log.error("查询发货状态失败 - errcode: {}, errmsg: {}", errcode, json.getStr("errmsg")); return Result.fail("查询发货状态失败:" + json.getStr("errmsg")); } log.info("========== 查询发货状态成功 =========="); return Result.success(json); } } catch (Exception e) { log.error("查询发货状态异常", e); return Result.fail("查询发货状态异常:" + e.getMessage()); } } @Override public Result getDeliveryList() { log.info("========== 开始获取物流公司列表 =========="); try { // 获取access_token String accessToken = getAccessToken(); if (StrUtil.isBlank(accessToken)) { log.error("获取access_token失败"); return Result.fail("获取access_token失败"); } // 发送请求到微信 OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .build(); String url = DELIVERY_LIST_URL + "?access_token=" + accessToken; Request httpRequest = new Request.Builder() .url(url) .get() .build(); log.info("获取物流公司列表 - URL: {}", url); try (Response response = client.newCall(httpRequest).execute()) { if (!response.isSuccessful()) { log.error("获取物流公司列表失败 - HTTP状态码: {}", response.code()); return Result.fail("获取物流公司列表失败,HTTP状态码:" + response.code()); } String responseBody = response.body().string(); log.info("获取物流公司列表响应: {}", responseBody); JSONObject json = JSONUtil.parseObj(responseBody); Integer errcode = json.getInt("errcode"); // 微信物流列表接口:errcode=0表示成功,其他值表示失败 if (errcode == null || errcode != 0) { log.error("获取物流公司列表失败 - errcode: {}, errmsg: {}", errcode, json.getStr("errmsg")); return Result.fail("获取物流公司列表失败:" + json.getStr("errmsg")); } log.info("========== 获取物流公司列表成功 =========="); return Result.success(json); } } catch (Exception e) { log.error("获取物流公司列表异常", e); return Result.fail("获取物流公司列表异常:" + e.getMessage()); } } @Override public Result checkServiceEnabled() { log.info("========== 开始检查小程序发货管理功能 =========="); try { // 获取access_token String accessToken = getAccessToken(); if (StrUtil.isBlank(accessToken)) { log.error("获取access_token失败"); return Result.fail("获取access_token失败"); } log.info("当前使用的微信小程序AppID: {}", weChatMiniAppConfig.getAppId()); // 调用微信接口检查是否开通发货管理功能 // 文档:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html#七、查询小程序是否已开通发货信息管理服务 String url = "https://api.weixin.qq.com/wxa/sec/order/check_is_trade_managed?access_token=" + accessToken; OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .build(); Request httpRequest = new Request.Builder() .url(url) .get() .build(); log.info("调用微信检查接口 - URL: {}", url); try (Response response = client.newCall(httpRequest).execute()) { if (!response.isSuccessful()) { log.error("微信检查接口调用失败 - HTTP状态码: {}", response.code()); return Result.fail("检查接口调用失败,HTTP状态码:" + response.code()); } String responseBody = response.body() != null ? response.body().string() : ""; log.info("微信检查接口响应: {}", responseBody); cn.hutool.json.JSONObject json = cn.hutool.json.JSONUtil.parseObj(responseBody); Integer errcode = json.getInt("errcode"); // 微信检查接口:errcode=0表示成功,其他值表示失败 if (errcode == null || errcode != 0) { log.error("========== 检查失败 =========="); log.error("错误码: {}, 错误信息: {}", errcode, json.getStr("errmsg")); // 特殊错误码说明 if (errcode == 61003) { log.error("小程序未授权发货管理权限集(18或142)"); return Result.fail("小程序未授权发货管理权限集,请先在微信后台开通发货管理功能"); } else if (errcode == 40013) { log.error("AppID非法或Secret错误"); return Result.fail("AppID配置错误或Secret错误,请检查配置文件"); } else if (errcode == 40066) { log.error("========== 40066错误特别说明 =========="); log.error("40066通常表示:"); log.error("1. 小程序未开通发货管理API功能"); log.error("2. 需要在微信后台单独申请API权限"); log.error("3. 不仅仅是开通订单管理,还需要开通API接口权限"); log.error(""); log.error("请检查:"); log.error("- 微信小程序后台 → 开发 → 开发管理 → 接口设置"); log.error("- 确认是否已开通'发货信息管理服务'API权限"); return Result.fail("小程序未开通发货管理API权限。请在微信后台 → 功能 → 功能库中搜索'发货管理'并开通API接口权限"); } return Result.fail("检查失败:" + json.getStr("errmsg")); } // 检查是否已开通发货管理功能 Boolean isTradeManaged = json.getBool("is_trade_managed"); if (isTradeManaged != null && isTradeManaged) { log.info("========== 检查通过 =========="); log.info("小程序已开通发货管理功能 ✓"); return Result.success("小程序已开通发货管理功能", isTradeManaged); } else { log.error("========== 检查未通过 =========="); log.error("小程序未开通发货管理功能 ✗"); return Result.fail("小程序未开通发货管理功能,请在微信后台开通此功能"); } } } catch (Exception e) { log.error("检查小程序发货管理功能异常", e); return Result.fail("检查异常:" + e.getMessage()); } } /** * 获取access_token * <p> * 使用AppID和Secret获取access_token,有效期2小时 * 缓存在内存中,过期后重新获取 * </p> * <p> * 微信API响应格式: * 成功:{"access_token": "xxx", "expires_in": 7200} * 失败:{"errcode": 40013, "errmsg": "invalid appid"} * 注意:成功时不会返回errcode字段 * </p> * * @return access_token */ private String getAccessToken() { // 检查缓存是否有效 if (StrUtil.isNotBlank(cachedAccessToken) && System.currentTimeMillis() < tokenExpireTime) { log.debug("使用缓存的access_token"); return cachedAccessToken; } log.info("开始获取access_token..."); try { String appId = weChatMiniAppConfig.getAppId(); String appSecret = weChatMiniAppConfig.getSecret(); if (StrUtil.isBlank(appId) || StrUtil.isBlank(appSecret)) { log.error("微信小程序配置缺失 - appId或appSecret为空"); return null; } log.info("当前使用的微信小程序AppID: {}", appId); // 构造请求URL String url = String.format( "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appId, appSecret ); OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .build(); Request httpRequest = new Request.Builder() .url(url) .get() .build(); try (Response response = client.newCall(httpRequest).execute()) { if (!response.isSuccessful()) { log.error("获取access_token失败 - HTTP状态码: {}", response.code()); return null; } String responseBody = response.body().string(); log.info("获取access_token响应: {}", responseBody); JSONObject json = JSONUtil.parseObj(responseBody); // 优先检查 errmsg 字段(错误时一定有此字段) String errmsg = json.getStr("errmsg"); if (StrUtil.isNotBlank(errmsg)) { Integer errcode = json.getInt("errcode"); log.error("获取access_token失败 - errcode: {}, errmsg: {}", errcode, errmsg); return null; } // 成功时获取 access_token cachedAccessToken = json.getStr("access_token"); Integer expiresIn = json.getInt("expires_in"); if (StrUtil.isBlank(cachedAccessToken)) { log.error("access_token为空 - 响应: {}", responseBody); return null; } // 提前5分钟过期,避免临界点问题 tokenExpireTime = System.currentTimeMillis() + (expiresIn != null ? expiresIn : 7200) * 1000L - 300000; log.info("获取access_token成功 - 过期时间: {}秒", expiresIn); return cachedAccessToken; } } catch (Exception e) { log.error("获取access_token异常", e); return null; } } @Override public Result notifyConfirmReceipt(String orderSn, String transactionId, String openid) { log.info("========== 开始发送确认收货提醒 =========="); log.info("订单号: {}, 微信订单号: {}, openid: {}", orderSn, transactionId, openid); // 检查发货管理功能是否启用 if (!shippingEnabled) { log.info("微信发货管理功能已禁用,跳过确认收货提醒"); return Result.success("发货管理功能已禁用,无需提醒"); } if (StrUtil.isBlank(transactionId)) { log.error("微信订单号为空 - orderSn: {}", orderSn); return Result.fail("微信订单号不能为空"); } if (StrUtil.isBlank(openid)) { log.error("openid为空 - orderSn: {}", orderSn); return Result.fail("openid不能为空"); } try { // 获取access_token String accessToken = getAccessToken(); if (StrUtil.isBlank(accessToken)) { log.error("获取access_token失败"); return Result.fail("获取access_token失败"); } // 构造请求参数 Map<String, Object> params = new HashMap<>(); params.put("order_key", Map.<String, Object>of( "order_number_type", 2, // 使用微信订单号 "transaction_id", transactionId )); // received_time:快递签收时间,时间戳形式(必填) // 使用当前时间作为签收时间 params.put("received_time", System.currentTimeMillis() / 1000); log.info("发送确认收货提醒参数 - orderSn: {}, receivedTime: {}", orderSn, System.currentTimeMillis() / 1000); // 发送请求到微信 OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .build(); String url = CONFIRM_RECEIPT_URL + "?access_token=" + accessToken; MediaType mediaType = MediaType.parse("application/json; charset=utf-8"); RequestBody requestBody = RequestBody.create(JSONUtil.toJsonStr(params), mediaType); Request httpRequest = new Request.Builder() .url(url) .post(requestBody) .build(); log.info("发送确认收货提醒到微信 - URL: {}", url); try (Response response = client.newCall(httpRequest).execute()) { if (!response.isSuccessful()) { log.error("微信确认收货提醒接口调用失败 - HTTP状态码: {}", response.code()); return Result.fail("确认收货提醒接口调用失败,HTTP状态码:" + response.code()); } String responseBody = response.body().string(); log.info("微信确认收货提醒接口响应: {}", responseBody); JSONObject json = JSONUtil.parseObj(responseBody); Integer errcode = json.getInt("errcode"); String errmsg = json.getStr("errmsg"); // 微信确认收货提醒接口:errcode=0表示成功,其他值表示失败 if (errcode == null || errcode != 0) { log.error("发送确认收货提醒失败 - errcode: {}, errmsg: {}", errcode, errmsg); return Result.fail("发送确认收货提醒失败:" + errmsg); } log.info("========== 发送确认收货提醒成功 =========="); return Result.success("确认收货提醒发送成功"); } } catch (Exception e) { log.error("发送确认收货提醒异常", e); return Result.fail("发送确认收货提醒异常:" + e.getMessage()); } } }
回答关注问题邀请回答
收藏

1 个回答

登录 后发表内容