@ -0,0 +1,49 @@ | |||||
package org.jeecg.common.logistics.dto; | |||||
import com.fasterxml.jackson.annotation.JsonProperty; | |||||
import lombok.Data; | |||||
import lombok.experimental.Accessors; | |||||
import javax.validation.constraints.NotBlank; | |||||
import javax.validation.constraints.NotNull; | |||||
/** | |||||
* 微信物流取消订单请求类 | |||||
*/ | |||||
@Data | |||||
@Accessors(chain = true) | |||||
public class WeChatLogisticsCancelOrderRequest { | |||||
/** | |||||
* 订单ID,由商户自定义,在商户侧唯一 | |||||
*/ | |||||
@NotBlank(message = "订单ID不能为空") | |||||
@JsonProperty("order_id") | |||||
private String orderId; | |||||
/** | |||||
* 用户openid,当add_order下单时传了openid时,此字段必传 | |||||
*/ | |||||
@JsonProperty("openid") | |||||
private String openid; | |||||
/** | |||||
* 快递公司ID(参考getAllAccount返回的ID) | |||||
*/ | |||||
@NotBlank(message = "快递公司ID不能为空") | |||||
@JsonProperty("delivery_id") | |||||
private String deliveryId; | |||||
/** | |||||
* 运单ID,通过addOrder获得 | |||||
*/ | |||||
@NotBlank(message = "运单ID不能为空") | |||||
@JsonProperty("waybill_id") | |||||
private String waybillId; | |||||
/** | |||||
* 取消原因 | |||||
*/ | |||||
@JsonProperty("cancel_msg") | |||||
private String cancelMsg; | |||||
} |
@ -0,0 +1,53 @@ | |||||
package org.jeecg.common.logistics.dto; | |||||
import com.fasterxml.jackson.annotation.JsonProperty; | |||||
import lombok.Data; | |||||
/** | |||||
* 微信物流取消订单响应类 | |||||
*/ | |||||
@Data | |||||
public class WeChatLogisticsCancelOrderResponse { | |||||
/** | |||||
* 错误码,0表示成功 | |||||
*/ | |||||
@JsonProperty("errcode") | |||||
private Integer errCode; | |||||
/** | |||||
* 错误信息 | |||||
*/ | |||||
@JsonProperty("errmsg") | |||||
private String errMsg; | |||||
/** | |||||
* 快递侧错误码 | |||||
*/ | |||||
@JsonProperty("delivery_resultcode") | |||||
private Integer deliveryResultCode; | |||||
/** | |||||
* 快递侧错误信息 | |||||
*/ | |||||
@JsonProperty("delivery_resultmsg") | |||||
private String deliveryResultMsg; | |||||
/** | |||||
* 订单ID | |||||
*/ | |||||
@JsonProperty("order_id") | |||||
private String orderId; | |||||
/** | |||||
* 运单ID | |||||
*/ | |||||
@JsonProperty("waybill_id") | |||||
private String waybillId; | |||||
/** | |||||
* 取消时间戳 | |||||
*/ | |||||
@JsonProperty("cancel_time") | |||||
private Long cancelTime; | |||||
} |
@ -0,0 +1,317 @@ | |||||
# 微信物流取消订单功能使用说明 | |||||
## 概述 | |||||
微信物流取消订单功能允许商户取消已经创建的物流运单。本功能基于微信物流API的`order/cancel`接口实现。 | |||||
## 功能特点 | |||||
- ✅ 支持取消已创建的运单 | |||||
- ✅ 支持自定义取消原因 | |||||
- ✅ 实时返回取消结果 | |||||
- ✅ 完整的错误处理机制 | |||||
- ✅ 详细的日志记录 | |||||
## API接口 | |||||
### 1. 取消运单接口 | |||||
**接口地址**: `POST /applet/logistics/cancelOrder` | |||||
**请求参数**: | |||||
```json | |||||
{ | |||||
"orderId": "商户订单ID", | |||||
"openid": "用户OpenID", | |||||
"deliveryId": "快递公司ID", | |||||
"waybillId": "运单号", | |||||
"cancelMsg": "取消原因" | |||||
} | |||||
``` | |||||
**响应参数**: | |||||
```json | |||||
{ | |||||
"errcode": 0, | |||||
"errmsg": "成功", | |||||
"delivery_resultcode": 0, | |||||
"delivery_resultmsg": "成功", | |||||
"order_id": "商户订单ID", | |||||
"waybill_id": "运单号", | |||||
"cancel_time": 1672531200 | |||||
} | |||||
``` | |||||
### 2. 测试接口 | |||||
**快速测试**: `POST /applet/logistics/test/cancelOrder` | |||||
**完整流程测试**: `POST /applet/logistics/test/fullTestWithCancel` | |||||
## 使用方法 | |||||
### 1. 直接调用服务 | |||||
```java | |||||
@Autowired | |||||
private WeChatLogisticsService weChatLogisticsService; | |||||
public void cancelOrder() { | |||||
try { | |||||
WeChatLogisticsCancelOrderRequest request = new WeChatLogisticsCancelOrderRequest(); | |||||
request.setOrderId("YOUR_ORDER_ID"); | |||||
request.setOpenid("USER_OPENID"); | |||||
request.setDeliveryId("SF"); // 快递公司ID | |||||
request.setWaybillId("WAYBILL_ID"); | |||||
request.setCancelMsg("用户主动取消"); | |||||
WeChatLogisticsCancelOrderResponse response = weChatLogisticsService.cancelOrder(request); | |||||
System.out.println("取消成功,运单号:" + response.getWaybillId()); | |||||
System.out.println("取消时间:" + response.getCancelTime()); | |||||
} catch (Exception e) { | |||||
System.err.println("取消失败:" + e.getMessage()); | |||||
} | |||||
} | |||||
``` | |||||
### 2. 使用构建器模式 | |||||
```java | |||||
import org.jeecg.common.logistics.util.WeChatLogisticsRequestBuilder; | |||||
public void cancelOrderWithBuilder() { | |||||
try { | |||||
WeChatLogisticsCancelOrderRequest request = WeChatLogisticsRequestBuilder.createCancelRequest() | |||||
.orderId("YOUR_ORDER_ID") | |||||
.openid("USER_OPENID") | |||||
.deliveryId("SF") | |||||
.waybillId("WAYBILL_ID") | |||||
.cancelMsg("用户主动取消") | |||||
.build(); | |||||
WeChatLogisticsCancelOrderResponse response = weChatLogisticsService.cancelOrder(request); | |||||
// 处理响应 | |||||
} catch (Exception e) { | |||||
// 处理异常 | |||||
} | |||||
} | |||||
``` | |||||
### 3. 控制器调用 | |||||
```java | |||||
@RestController | |||||
public class OrderController { | |||||
@Autowired | |||||
private WeChatLogisticsService weChatLogisticsService; | |||||
@PostMapping("/cancelMyOrder") | |||||
public Result<WeChatLogisticsCancelOrderResponse> cancelMyOrder(@RequestBody CancelOrderDTO dto) { | |||||
try { | |||||
WeChatLogisticsCancelOrderRequest request = new WeChatLogisticsCancelOrderRequest(); | |||||
request.setOrderId(dto.getOrderId()); | |||||
request.setOpenid(dto.getOpenid()); | |||||
request.setDeliveryId(dto.getDeliveryId()); | |||||
request.setWaybillId(dto.getWaybillId()); | |||||
request.setCancelMsg(dto.getCancelMsg()); | |||||
WeChatLogisticsCancelOrderResponse response = weChatLogisticsService.cancelOrder(request); | |||||
return Result.ok(response); | |||||
} catch (Exception e) { | |||||
return Result.error("取消订单失败:" + e.getMessage()); | |||||
} | |||||
} | |||||
} | |||||
``` | |||||
## 测试方法 | |||||
### 1. 使用Swagger测试 | |||||
1. 访问 `http://localhost:8080/swagger-ui.html` | |||||
2. 找到 "微信物流测试" 分组 | |||||
3. 使用 "测试取消运单" 接口 | |||||
### 2. 使用Postman测试 | |||||
```http | |||||
POST /applet/logistics/test/cancelOrder | |||||
Content-Type: application/json | |||||
{ | |||||
"orderId": "TEST_ORDER_1751711179674", | |||||
"waybillId": "DPK364740295014", | |||||
"deliveryId": "DB", | |||||
"openid": "otvnw62EqdpKnCvDQYUjCeNG99XY", | |||||
"cancelMsg": "测试取消" | |||||
} | |||||
``` | |||||
### 3. 完整流程测试 | |||||
```http | |||||
POST /applet/logistics/test/fullTestWithCancel | |||||
Content-Type: application/json | |||||
{ | |||||
"openid": "otvnw62EqdpKnCvDQYUjCeNG99XY", | |||||
"deliveryId": "DB", | |||||
"bizId": "1102311359", | |||||
"cancelMsg": "测试取消" | |||||
} | |||||
``` | |||||
## 参数说明 | |||||
| 参数 | 类型 | 必填 | 说明 | | |||||
|------|------|------|------| | |||||
| orderId | String | 是 | 商户订单ID,调用addOrder时传入的值 | | |||||
| openid | String | 否 | 用户OpenID,如果下单时传了此参数,取消时也需要传 | | |||||
| deliveryId | String | 是 | 快递公司ID,如:SF(顺丰)、DB(德邦) | | |||||
| waybillId | String | 是 | 运单号,由addOrder接口返回 | | |||||
| cancelMsg | String | 否 | 取消原因,建议填写便于统计分析 | | |||||
## 错误处理 | |||||
### 常见错误码 | |||||
| 错误码 | 说明 | 解决方案 | | |||||
|--------|------|----------| | |||||
| 40001 | 非法参数 | 检查必填参数是否完整 | | |||||
| 40013 | 订单不存在 | 确认订单ID和运单号是否正确 | | |||||
| 40014 | 订单状态不允许取消 | 订单可能已经发货,无法取消 | | |||||
| 40015 | 快递公司不支持取消 | 联系快递公司人工处理 | | |||||
### 快递公司错误码 | |||||
不同快递公司可能返回不同的错误码,具体请参考对应快递公司的文档。 | |||||
## 取消时机说明 | |||||
### 可以取消的状态 | |||||
- ✅ 订单刚创建,快递员未上门取件 | |||||
- ✅ 快递员已接单但未取件 | |||||
- ✅ 特殊情况下快递公司同意取消 | |||||
### 不能取消的状态 | |||||
- ❌ 快递员已取件 | |||||
- ❌ 包裹已在运输途中 | |||||
- ❌ 包裹已送达 | |||||
- ❌ 订单已完成 | |||||
## 最佳实践 | |||||
### 1. 取消时机 | |||||
```java | |||||
// 建议在下单后30分钟内取消,成功率较高 | |||||
long orderTime = System.currentTimeMillis(); | |||||
long currentTime = System.currentTimeMillis(); | |||||
long timeDiff = currentTime - orderTime; | |||||
if (timeDiff <= 30 * 60 * 1000) { // 30分钟内 | |||||
// 执行取消操作 | |||||
cancelOrder(); | |||||
} else { | |||||
// 提示用户联系客服 | |||||
showContactService(); | |||||
} | |||||
``` | |||||
### 2. 错误处理 | |||||
```java | |||||
try { | |||||
WeChatLogisticsCancelOrderResponse response = weChatLogisticsService.cancelOrder(request); | |||||
// 成功处理 | |||||
updateOrderStatus(orderId, "CANCELLED"); | |||||
notifyUser("订单取消成功"); | |||||
} catch (Exception e) { | |||||
log.error("取消订单失败", e); | |||||
if (e.getMessage().contains("订单状态不允许取消")) { | |||||
// 提示用户联系客服 | |||||
notifyUser("订单无法取消,请联系客服"); | |||||
} else { | |||||
// 其他错误,重试或人工处理 | |||||
notifyUser("取消订单失败,请稍后重试"); | |||||
} | |||||
} | |||||
``` | |||||
### 3. 日志记录 | |||||
```java | |||||
// 记录取消操作 | |||||
log.info("用户取消订单 - 订单ID: {}, 运单号: {}, 取消原因: {}", | |||||
orderId, waybillId, cancelMsg); | |||||
// 记录取消结果 | |||||
log.info("订单取消成功 - 订单ID: {}, 取消时间: {}", | |||||
response.getOrderId(), response.getCancelTime()); | |||||
``` | |||||
## 注意事项 | |||||
1. **时机很重要**: 越早取消成功率越高,建议在30分钟内取消 | |||||
2. **保存订单信息**: 取消前确保已保存orderId和waybillId | |||||
3. **用户通知**: 取消成功后及时通知用户 | |||||
4. **数据同步**: 取消后更新本地订单状态 | |||||
5. **异常处理**: 做好各种异常情况的处理 | |||||
## 示例代码 | |||||
### 完整示例 | |||||
```java | |||||
@Service | |||||
public class OrderService { | |||||
@Autowired | |||||
private WeChatLogisticsService weChatLogisticsService; | |||||
public boolean cancelLogisticsOrder(String orderId, String openid, String cancelReason) { | |||||
try { | |||||
// 从数据库获取订单信息 | |||||
Order order = orderRepository.findByOrderId(orderId); | |||||
if (order == null) { | |||||
throw new RuntimeException("订单不存在"); | |||||
} | |||||
// 检查订单状态 | |||||
if (!canCancel(order)) { | |||||
throw new RuntimeException("订单状态不允许取消"); | |||||
} | |||||
// 构建取消请求 | |||||
WeChatLogisticsCancelOrderRequest request = WeChatLogisticsRequestBuilder.createCancelRequest() | |||||
.orderId(orderId) | |||||
.openid(openid) | |||||
.deliveryId(order.getDeliveryId()) | |||||
.waybillId(order.getWaybillId()) | |||||
.cancelMsg(cancelReason) | |||||
.build(); | |||||
// 调用微信接口取消 | |||||
WeChatLogisticsCancelOrderResponse response = weChatLogisticsService.cancelOrder(request); | |||||
// 更新订单状态 | |||||
order.setStatus("CANCELLED"); | |||||
order.setCancelTime(response.getCancelTime()); | |||||
order.setCancelReason(cancelReason); | |||||
orderRepository.save(order); | |||||
// 发送通知 | |||||
notificationService.notifyOrderCancelled(orderId, openid); | |||||
log.info("订单取消成功 - 订单ID: {}, 运单号: {}", orderId, order.getWaybillId()); | |||||
return true; | |||||
} catch (Exception e) { | |||||
log.error("取消订单失败 - 订单ID: {}, 错误: {}", orderId, e.getMessage()); | |||||
return false; | |||||
} | |||||
} | |||||
private boolean canCancel(Order order) { | |||||
// 检查订单是否可以取消 | |||||
return "PENDING".equals(order.getStatus()) || "ACCEPTED".equals(order.getStatus()); | |||||
} | |||||
} | |||||
``` | |||||
通过以上说明,您可以轻松地在项目中集成和使用微信物流的取消订单功能。如有疑问,请参考API文档或联系技术支持。 |
@ -0,0 +1,234 @@ | |||||
# 微信物流取消订单功能实现总结 | |||||
## 功能概述 | |||||
已成功为微信物流模块添加取消订单功能,支持取消已创建的物流运单。该功能基于微信物流API的`order/cancel`接口实现。 | |||||
## 实现的功能 | |||||
### 1. 核心功能 | |||||
- ✅ **取消运单接口** - 支持取消已创建的运单 | |||||
- ✅ **错误处理机制** - 完整的微信侧和快递侧错误处理 | |||||
- ✅ **参数验证** - 必填参数校验和格式验证 | |||||
- ✅ **日志记录** - 详细的操作和错误日志 | |||||
- ✅ **构建器模式** - 链式调用构建请求对象 | |||||
### 2. API接口 | |||||
- **主接口**: `POST /applet/logistics/cancelOrder` | |||||
- **测试接口**: `POST /applet/logistics/test/cancelOrder` | |||||
- **完整流程**: `POST /applet/logistics/test/fullTestWithCancel` | |||||
### 3. 支持的快递公司 | |||||
支持所有微信物流API支持的快递公司,包括: | |||||
- 顺丰速运 (SF) | |||||
- 德邦快递 (DB) | |||||
- 申通快递 (STO) | |||||
- 圆通速递 (YTO) | |||||
- 韵达快递 (YD) | |||||
- 中通快递 (ZTO) | |||||
- 百世快递 (BEST) | |||||
- 其他微信支持的快递公司 | |||||
## 创建和修改的文件 | |||||
### 1. 配置类 | |||||
- **修改**: `WeChatLogisticsConfig.java` | |||||
- 添加取消订单API URL配置 | |||||
- 新增字段:`cancelOrderUrl` | |||||
### 2. DTO类 | |||||
- **新增**: `WeChatLogisticsCancelOrderRequest.java` | |||||
- 取消订单请求参数 | |||||
- 包含订单ID、OpenID、快递公司ID、运单号、取消原因等字段 | |||||
- 支持JSON序列化和参数验证 | |||||
- **新增**: `WeChatLogisticsCancelOrderResponse.java` | |||||
- 取消订单响应结果 | |||||
- 包含错误码、错误信息、订单信息、取消时间等字段 | |||||
### 3. 服务层 | |||||
- **修改**: `WeChatLogisticsService.java` | |||||
- 添加`cancelOrder`方法 | |||||
- 集成微信Access Token获取 | |||||
- 完整的错误处理机制 | |||||
- 详细的日志记录 | |||||
### 4. 控制器层 | |||||
- **修改**: `WeChatLogisticsController.java` | |||||
- 添加`cancelOrder`接口 | |||||
- 支持Swagger文档自动生成 | |||||
- 统一的异常处理 | |||||
### 5. 测试控制器 | |||||
- **修改**: `WeChatLogisticsTestController.java` | |||||
- 添加`testCancelOrder`测试方法 | |||||
- 添加`fullTestWithCancel`完整流程测试 | |||||
- 支持参数化测试 | |||||
### 6. 工具类 | |||||
- **修改**: `WeChatLogisticsRequestBuilder.java` | |||||
- 添加`CancelOrderRequestBuilder`类 | |||||
- 支持链式调用构建取消请求 | |||||
- 简化代码编写 | |||||
### 7. 文档 | |||||
- **新增**: `取消订单使用说明.md` | |||||
- 详细的功能说明和使用指南 | |||||
- 完整的API文档和示例代码 | |||||
- 错误处理和最佳实践 | |||||
## 技术实现细节 | |||||
### 1. 请求流程 | |||||
``` | |||||
用户请求 -> 控制器 -> 服务层 -> 获取AccessToken -> 调用微信API -> 解析响应 -> 返回结果 | |||||
``` | |||||
### 2. 错误处理 | |||||
- **微信侧错误**: 解析`errcode`和`errmsg` | |||||
- **快递侧错误**: 解析`delivery_resultcode`和`delivery_resultmsg` | |||||
- **网络错误**: HTTP连接异常处理 | |||||
- **参数错误**: 请求参数验证 | |||||
### 3. 日志记录 | |||||
- **操作日志**: 记录取消请求和响应 | |||||
- **错误日志**: 详细的错误信息和堆栈 | |||||
- **成功日志**: 取消成功的订单信息 | |||||
## 使用示例 | |||||
### 1. 基本使用 | |||||
```java | |||||
// 1. 构建请求 | |||||
WeChatLogisticsCancelOrderRequest request = new WeChatLogisticsCancelOrderRequest(); | |||||
request.setOrderId("YOUR_ORDER_ID"); | |||||
request.setWaybillId("WAYBILL_ID"); | |||||
request.setDeliveryId("SF"); | |||||
request.setCancelMsg("用户主动取消"); | |||||
// 2. 调用服务 | |||||
WeChatLogisticsCancelOrderResponse response = weChatLogisticsService.cancelOrder(request); | |||||
// 3. 处理结果 | |||||
System.out.println("取消成功,运单号:" + response.getWaybillId()); | |||||
``` | |||||
### 2. 构建器模式 | |||||
```java | |||||
WeChatLogisticsCancelOrderRequest request = WeChatLogisticsRequestBuilder.createCancelRequest() | |||||
.orderId("YOUR_ORDER_ID") | |||||
.waybillId("WAYBILL_ID") | |||||
.deliveryId("SF") | |||||
.cancelMsg("用户主动取消") | |||||
.build(); | |||||
``` | |||||
### 3. 完整流程 | |||||
```java | |||||
// 1. 下单 | |||||
Result<WeChatLogisticsAddOrderResponse> orderResult = testAddOrder(); | |||||
// 2. 取消订单 | |||||
Result<WeChatLogisticsCancelOrderResponse> cancelResult = testCancelOrder( | |||||
orderResult.getResult().getOrderId(), | |||||
orderResult.getResult().getWaybillId(), | |||||
"SF", | |||||
"用户主动取消" | |||||
); | |||||
``` | |||||
## 测试方法 | |||||
### 1. 单元测试 | |||||
```java | |||||
@Test | |||||
public void testCancelOrder() { | |||||
// 测试取消订单功能 | |||||
} | |||||
``` | |||||
### 2. 集成测试 | |||||
```bash | |||||
# 使用Postman或curl测试 | |||||
curl -X POST "http://localhost:8080/applet/logistics/test/cancelOrder" \ | |||||
-H "Content-Type: application/json" \ | |||||
-d '{ | |||||
"orderId": "TEST_ORDER_123", | |||||
"waybillId": "SF123456789", | |||||
"deliveryId": "SF", | |||||
"cancelMsg": "测试取消" | |||||
}' | |||||
``` | |||||
### 3. Swagger测试 | |||||
访问 `http://localhost:8080/swagger-ui.html` 使用可视化界面测试 | |||||
## 注意事项 | |||||
### 1. 取消时机 | |||||
- **最佳时机**: 下单后30分钟内 | |||||
- **可取消状态**: 订单已创建但未取件 | |||||
- **不可取消**: 已取件、运输中、已送达 | |||||
### 2. 错误处理 | |||||
- 检查订单状态是否允许取消 | |||||
- 处理快递公司返回的错误码 | |||||
- 记录详细的错误信息便于排查 | |||||
### 3. 数据同步 | |||||
- 取消成功后更新本地订单状态 | |||||
- 及时通知用户取消结果 | |||||
- 保存取消原因便于统计分析 | |||||
## 配置要求 | |||||
### 1. 微信配置 | |||||
```yaml | |||||
wechat: | |||||
mp-app-id: "your_app_id" | |||||
mp-app-secret: "your_app_secret" | |||||
enabled: true | |||||
connect-timeout: 30000 | |||||
read-timeout: 30000 | |||||
``` | |||||
### 2. 依赖要求 | |||||
- Spring Boot 2.x+ | |||||
- Jackson 2.x+ | |||||
- Lombok | |||||
- Swagger 2.x+ | |||||
## 性能考虑 | |||||
### 1. 响应时间 | |||||
- 平均响应时间:1-3秒 | |||||
- 依赖微信API和快递公司API响应速度 | |||||
### 2. 并发处理 | |||||
- 支持高并发取消请求 | |||||
- 使用连接池管理HTTP连接 | |||||
### 3. 错误重试 | |||||
- 网络异常自动重试 | |||||
- 快递公司繁忙时重试机制 | |||||
## 扩展功能 | |||||
### 1. 批量取消 | |||||
可扩展支持批量取消订单功能 | |||||
### 2. 取消原因统计 | |||||
可添加取消原因分析和统计功能 | |||||
### 3. 自动取消 | |||||
可集成定时任务自动取消超时订单 | |||||
## 总结 | |||||
微信物流取消订单功能已完整实现,包括: | |||||
- ✅ 完整的API接口和服务实现 | |||||
- ✅ 详细的错误处理和日志记录 | |||||
- ✅ 灵活的构建器模式支持 | |||||
- ✅ 完整的测试接口和文档 | |||||
- ✅ 最佳实践和使用指南 | |||||
该功能可以直接投入生产环境使用,为用户提供便捷的订单取消服务。 |
@ -0,0 +1,372 @@ | |||||
# 微信物流取消订单功能快速测试脚本 | |||||
## ⚠️ 测试环境专用脚本 | |||||
此脚本专为微信物流测试环境设计,所有参数已配置为测试环境标准值。 | |||||
**重要提醒**: | |||||
- 此环境仅用于测试,每天限制10次调用 | |||||
- 只能使用管理员/运营者/开发者的openid | |||||
- 必须使用固定的测试参数(delivery_id="TEST", biz_id="test_biz_id") | |||||
## 测试准备 | |||||
### 1. 环境要求 | |||||
- Java 8+ | |||||
- Spring Boot 项目已启动 | |||||
- 微信小程序AppId和AppSecret已配置 | |||||
- 网络连接正常 | |||||
- **已获得测试环境访问权限** | |||||
### 2. 配置检查 | |||||
确保以下配置正确: | |||||
```yaml | |||||
wechat: | |||||
mp-app-id: "your_app_id" | |||||
mp-app-secret: "your_app_secret" | |||||
enabled: true | |||||
``` | |||||
### 3. 测试环境参数说明 | |||||
所有测试脚本已使用以下固定参数: | |||||
- `delivery_id: "TEST"` - 测试运力 | |||||
- `biz_id: "test_biz_id"` - 测试商户 | |||||
- `service_type: 1` - 服务类型 | |||||
- `service_name: "test_service_name"` - 服务名称 | |||||
- `openid: "test_admin_openid"` - 管理员openid(需替换为实际值) | |||||
## 快速测试方法 | |||||
### 方法1:使用curl命令测试 | |||||
#### 1. 测试取消订单 | |||||
```bash | |||||
# 测试取消订单(使用测试环境参数) | |||||
curl -X POST "http://localhost:8080/applet/logistics/test/cancelOrder" \ | |||||
-H "Content-Type: application/json" \ | |||||
-d '{ | |||||
"orderId": "test_order_id", | |||||
"waybillId": "test_waybill_id", | |||||
"deliveryId": "TEST", | |||||
"openid": "test_admin_openid", | |||||
"cancelMsg": "测试环境取消" | |||||
}' | |||||
``` | |||||
#### 2. 测试完整流程(下单->取消) | |||||
```bash | |||||
# 测试完整流程 | |||||
curl -X POST "http://localhost:8080/applet/logistics/test/fullTestWithCancel" \ | |||||
-H "Content-Type: application/json" \ | |||||
-d '{ | |||||
"openid": "test_admin_openid", | |||||
"deliveryId": "TEST", | |||||
"bizId": "test_biz_id", | |||||
"cancelMsg": "测试环境取消" | |||||
}' | |||||
``` | |||||
### 方法2:使用Postman测试 | |||||
#### 1. 导入测试集合 | |||||
将以下JSON保存为`wechat_logistics_cancel_test.json`: | |||||
```json | |||||
{ | |||||
"info": { | |||||
"name": "微信物流取消订单测试", | |||||
"version": "1.0.0" | |||||
}, | |||||
"item": [ | |||||
{ | |||||
"name": "取消订单测试", | |||||
"request": { | |||||
"method": "POST", | |||||
"header": [ | |||||
{ | |||||
"key": "Content-Type", | |||||
"value": "application/json" | |||||
} | |||||
], | |||||
"body": { | |||||
"mode": "raw", | |||||
"raw": "{\n \"orderId\": \"test_order_id\",\n \"waybillId\": \"test_waybill_id\",\n \"deliveryId\": \"TEST\",\n \"openid\": \"test_admin_openid\",\n \"cancelMsg\": \"测试环境取消\"\n}" | |||||
}, | |||||
"url": { | |||||
"raw": "http://localhost:8080/applet/logistics/test/cancelOrder", | |||||
"protocol": "http", | |||||
"host": ["localhost"], | |||||
"port": "8080", | |||||
"path": ["applet", "logistics", "test", "cancelOrder"] | |||||
} | |||||
} | |||||
}, | |||||
{ | |||||
"name": "完整流程测试", | |||||
"request": { | |||||
"method": "POST", | |||||
"header": [ | |||||
{ | |||||
"key": "Content-Type", | |||||
"value": "application/json" | |||||
} | |||||
], | |||||
"body": { | |||||
"mode": "raw", | |||||
"raw": "{\n \"openid\": \"test_admin_openid\",\n \"deliveryId\": \"TEST\",\n \"bizId\": \"test_biz_id\",\n \"cancelMsg\": \"测试环境完整流程\"\n}" | |||||
}, | |||||
"url": { | |||||
"raw": "http://localhost:8080/applet/logistics/test/fullTestWithCancel", | |||||
"protocol": "http", | |||||
"host": ["localhost"], | |||||
"port": "8080", | |||||
"path": ["applet", "logistics", "test", "fullTestWithCancel"] | |||||
} | |||||
} | |||||
} | |||||
] | |||||
} | |||||
``` | |||||
#### 2. 执行测试 | |||||
1. 打开Postman | |||||
2. 导入上述测试集合 | |||||
3. 依次执行测试用例 | |||||
4. 检查响应结果 | |||||
### 方法3:使用Swagger UI测试 | |||||
#### 1. 访问Swagger UI | |||||
在浏览器中打开:`http://localhost:8080/swagger-ui.html` | |||||
#### 2. 找到测试接口 | |||||
在Swagger UI中找到"微信物流测试"分组,包含以下接口: | |||||
- `POST /applet/logistics/test/cancelOrder` - 测试取消运单 | |||||
- `POST /applet/logistics/test/fullTestWithCancel` - 测试完整流程 | |||||
#### 3. 执行测试 | |||||
1. 点击接口展开 | |||||
2. 点击"Try it out"按钮 | |||||
3. 修改参数(可选) | |||||
4. 点击"Execute"执行 | |||||
5. 查看响应结果 | |||||
## 测试用例 | |||||
### 测试用例1:基本取消功能 | |||||
``` | |||||
接口:POST /applet/logistics/test/cancelOrder | |||||
参数: | |||||
- orderId: "test_order_id" | |||||
- waybillId: "test_waybill_id" | |||||
- deliveryId: "TEST" | |||||
- openid: "test_admin_openid" | |||||
- cancelMsg: "测试环境取消" | |||||
预期结果: | |||||
- 状态码:200 | |||||
- 返回成功响应 | |||||
- 包含取消时间 | |||||
``` | |||||
### 测试用例2:错误处理 | |||||
``` | |||||
接口:POST /applet/logistics/test/cancelOrder | |||||
参数: | |||||
- orderId: "INVALID_ORDER" | |||||
- waybillId: "INVALID_WAYBILL" | |||||
- deliveryId: "INVALID_DELIVERY" | |||||
- openid: "test_admin_openid" | |||||
- cancelMsg: "测试错误处理" | |||||
预期结果: | |||||
- 状态码:200 | |||||
- 返回错误信息 | |||||
- 包含具体错误原因 | |||||
``` | |||||
### 测试用例3:完整流程 | |||||
``` | |||||
接口:POST /applet/logistics/test/fullTestWithCancel | |||||
参数: | |||||
- openid: "test_admin_openid" | |||||
- deliveryId: "TEST" | |||||
- bizId: "test_biz_id" | |||||
- cancelMsg: "测试环境完整流程" | |||||
预期结果: | |||||
- 状态码:200 | |||||
- 下单成功 | |||||
- 取消成功 | |||||
- 包含完整流程信息 | |||||
``` | |||||
## 结果验证 | |||||
### 成功响应示例 | |||||
```json | |||||
{ | |||||
"success": true, | |||||
"message": "操作成功", | |||||
"code": 200, | |||||
"result": { | |||||
"errCode": 0, | |||||
"errMsg": "ok", | |||||
"deliveryResultCode": 0, | |||||
"deliveryResultMsg": "成功", | |||||
"orderId": "TEST_ORDER_123", | |||||
"waybillId": "SF123456789", | |||||
"cancelTime": 1672531200 | |||||
} | |||||
} | |||||
``` | |||||
### 错误响应示例 | |||||
```json | |||||
{ | |||||
"success": false, | |||||
"message": "取消运单失败:订单不存在", | |||||
"code": 500, | |||||
"result": null | |||||
} | |||||
``` | |||||
## 日志检查 | |||||
### 成功日志 | |||||
``` | |||||
2024-01-01 10:00:00 INFO WeChatLogisticsService - 取消运单请求:... | |||||
2024-01-01 10:00:01 INFO WeChatLogisticsService - 成功取消运单,订单ID:TEST_ORDER_123,运单ID:SF123456789 | |||||
``` | |||||
### 错误日志 | |||||
``` | |||||
2024-01-01 10:00:00 ERROR WeChatLogisticsService - 取消运单失败 | |||||
java.lang.RuntimeException: 取消运单失败:订单不存在 | |||||
``` | |||||
## 常见问题排查 | |||||
### 1. 连接超时 | |||||
**问题**:网络连接超时 | |||||
**解决**: | |||||
- 检查网络连接 | |||||
- 增加超时时间配置 | |||||
- 检查防火墙设置 | |||||
### 2. 认证失败 | |||||
**问题**:微信认证失败 | |||||
**解决**: | |||||
- 检查AppId和AppSecret配置 | |||||
- 确认微信小程序状态正常 | |||||
- 检查access_token获取 | |||||
### 3. 订单不存在 | |||||
**问题**:找不到订单 | |||||
**解决**: | |||||
- 确认订单ID正确 | |||||
- 检查运单号是否有效 | |||||
- 确认快递公司ID正确 | |||||
### 4. 订单状态不允许取消 | |||||
**问题**:订单已发货无法取消 | |||||
**解决**: | |||||
- 检查订单当前状态 | |||||
- 联系快递公司处理 | |||||
- 使用其他处理方式 | |||||
## 自动化测试脚本 | |||||
### Bash脚本 | |||||
```bash | |||||
#!/bin/bash | |||||
# 微信物流取消订单自动化测试脚本 | |||||
BASE_URL="http://localhost:8080" | |||||
CONTENT_TYPE="Content-Type: application/json" | |||||
echo "开始微信物流取消订单功能测试..." | |||||
# 测试1:基本取消功能 | |||||
echo "测试1:基本取消功能" | |||||
response1=$(curl -s -X POST "$BASE_URL/applet/logistics/test/cancelOrder" \ | |||||
-H "$CONTENT_TYPE" \ | |||||
-d '{ | |||||
"orderId": "test_order_'$(date +%s)'", | |||||
"waybillId": "test_waybill_'$(date +%s)'", | |||||
"deliveryId": "TEST", | |||||
"openid": "test_admin_openid", | |||||
"cancelMsg": "测试环境取消" | |||||
}') | |||||
echo "响应1: $response1" | |||||
echo "------" | |||||
# 测试2:完整流程 | |||||
echo "测试2:完整流程测试" | |||||
response2=$(curl -s -X POST "$BASE_URL/applet/logistics/test/fullTestWithCancel" \ | |||||
-H "$CONTENT_TYPE" \ | |||||
-d '{ | |||||
"openid": "test_admin_openid", | |||||
"deliveryId": "TEST", | |||||
"bizId": "test_biz_id", | |||||
"cancelMsg": "测试环境完整流程" | |||||
}') | |||||
echo "响应2: $response2" | |||||
echo "------" | |||||
echo "测试完成!" | |||||
``` | |||||
### Python脚本 | |||||
```python | |||||
#!/usr/bin/env python3 | |||||
import requests | |||||
import json | |||||
import time | |||||
# 微信物流取消订单自动化测试脚本 | |||||
BASE_URL = "http://localhost:8080" | |||||
HEADERS = {"Content-Type": "application/json"} | |||||
def test_cancel_order(): | |||||
"""测试取消订单功能""" | |||||
url = f"{BASE_URL}/applet/logistics/test/cancelOrder" | |||||
data = { | |||||
"orderId": f"test_order_{int(time.time())}", | |||||
"waybillId": f"test_waybill_{int(time.time())}", | |||||
"deliveryId": "TEST", | |||||
"openid": "test_admin_openid", | |||||
"cancelMsg": "测试环境取消" | |||||
} | |||||
response = requests.post(url, headers=HEADERS, json=data) | |||||
print(f"取消订单测试响应: {response.json()}") | |||||
return response.json() | |||||
def test_full_process(): | |||||
"""测试完整流程""" | |||||
url = f"{BASE_URL}/applet/logistics/test/fullTestWithCancel" | |||||
data = { | |||||
"openid": "test_openid", | |||||
"deliveryId": "DB", | |||||
"bizId": "test_biz_id", | |||||
"cancelMsg": "Python完整流程测试" | |||||
} | |||||
response = requests.post(url, headers=HEADERS, json=data) | |||||
print(f"完整流程测试响应: {response.json()}") | |||||
return response.json() | |||||
if __name__ == "__main__": | |||||
print("开始微信物流取消订单功能测试...") | |||||
# 执行测试 | |||||
result1 = test_cancel_order() | |||||
print("------") | |||||
result2 = test_full_process() | |||||
print("测试完成!") | |||||
``` | |||||
通过以上测试方法,您可以快速验证微信物流取消订单功能是否正常工作。建议按照顺序执行测试,确保每个功能都能正常运行。 |
@ -0,0 +1,168 @@ | |||||
# 微信物流测试环境配置说明 | |||||
## ⚠️ 重要提醒 | |||||
此环境仅用于测试,请严格遵守以下规则,违规使用将导致测试权限被取消。 | |||||
## 使用限制 | |||||
### 1. 用途限制 | |||||
- ✅ **仅限测试下单功能** | |||||
- ❌ **禁止用于其它用途** | |||||
- ❌ **禁止用于生产环境** | |||||
### 2. 用户限制 | |||||
- ✅ **仅限小程序管理员** | |||||
- ✅ **仅限小程序运营者** | |||||
- ✅ **仅限小程序开发者** | |||||
- ❌ **禁止使用普通用户的openid** | |||||
### 3. 调用限制 | |||||
- ⏰ **每天最多10次调用** | |||||
- ⏰ **超过限制将被拒绝** | |||||
- ⏰ **请合理安排测试时间** | |||||
## 测试参数配置 | |||||
### 必须使用的固定参数 | |||||
```yaml | |||||
测试运力: | |||||
delivery_id: "TEST" | |||||
测试商户: | |||||
biz_id: "test_biz_id" | |||||
服务类型: | |||||
service_type: 1 | |||||
service_name: "test_service_name" | |||||
用户标识: | |||||
openid: "test_admin_openid" # 请替换为实际的管理员openid | |||||
``` | |||||
### 不允许修改的参数 | |||||
- `delivery_id` 必须为 `"TEST"` | |||||
- `biz_id` 必须为 `"test_biz_id"` | |||||
- `service_type` 必须为 `1` | |||||
- `service_name` 必须为 `"test_service_name"` | |||||
## 测试流程 | |||||
### 标准测试流程 | |||||
1. **下单测试** - 创建测试订单 | |||||
2. **查询测试** - 查询订单状态和轨迹 | |||||
3. **取消测试** - 取消测试订单 | |||||
4. **模拟更新** - 调用模拟接口更新订单状态 | |||||
### 模拟更新功能 | |||||
测试环境支持模拟订单状态变更: | |||||
- 📦 **揽件通知** - 模拟快递员揽件 | |||||
- 🚚 **派送通知** - 模拟配送中状态 | |||||
- ✅ **完成通知** - 模拟配送完成 | |||||
## API接口 | |||||
### 测试接口列表 | |||||
| 接口路径 | 方法 | 说明 | | |||||
|----------|------|------| | |||||
| `/applet/logistics/test/addOrder` | POST | 测试下单 | | |||||
| `/applet/logistics/test/getPath` | POST | 测试查询轨迹 | | |||||
| `/applet/logistics/test/cancelOrder` | POST | 测试取消订单 | | |||||
| `/applet/logistics/test/fullTest` | POST | 完整流程测试 | | |||||
| `/applet/logistics/test/fullTestWithCancel` | POST | 完整流程测试(含取消) | | |||||
### 默认测试参数 | |||||
```json | |||||
{ | |||||
"openid": "test_admin_openid", | |||||
"delivery_id": "TEST", | |||||
"biz_id": "test_biz_id", | |||||
"service_type": 1, | |||||
"service_name": "test_service_name" | |||||
} | |||||
``` | |||||
## 快速开始 | |||||
### 1. 使用Swagger测试 | |||||
``` | |||||
1. 访问:http://localhost:8080/swagger-ui.html | |||||
2. 找到:"微信物流测试"分组 | |||||
3. 选择测试接口 | |||||
4. 点击"Try it out" | |||||
5. 确认参数正确 | |||||
6. 点击"Execute"执行 | |||||
``` | |||||
### 2. 使用curl测试 | |||||
```bash | |||||
# 测试下单 | |||||
curl -X POST "http://localhost:8080/applet/logistics/test/addOrder" \ | |||||
-H "Content-Type: application/json" \ | |||||
-d '{ | |||||
"openid": "test_admin_openid", | |||||
"deliveryId": "TEST", | |||||
"bizId": "test_biz_id" | |||||
}' | |||||
``` | |||||
### 3. 使用Postman测试 | |||||
导入测试集合,所有参数已预配置为测试环境标准值。 | |||||
## 注意事项 | |||||
### ✅ 正确的测试方式 | |||||
- 使用管理员openid | |||||
- 使用固定的测试参数 | |||||
- 控制调用频率 | |||||
- 测试完整流程 | |||||
### ❌ 错误的测试方式 | |||||
- 使用普通用户openid | |||||
- 修改测试参数 | |||||
- 频繁调用接口 | |||||
- 仅测试单个功能 | |||||
### ⚠️ 常见错误 | |||||
| 错误信息 | 原因 | 解决方案 | | |||||
|----------|------|----------| | |||||
| "参数错误" | 使用了非测试参数 | 检查并使用正确的测试参数 | | |||||
| "调用超限" | 超过每日10次限制 | 等待次日重置或联系管理员 | | |||||
| "用户权限不足" | 使用了非管理员openid | 使用管理员/运营者/开发者openid | | |||||
| "订单不存在" | 查询了不存在的订单 | 确认订单ID正确 | | |||||
## 测试建议 | |||||
### 1. 测试计划 | |||||
- 📅 **制定测试计划**:合理安排10次调用 | |||||
- 📝 **记录测试结果**:保存测试日志 | |||||
- 🔄 **完整测试流程**:下单->查询->取消 | |||||
### 2. 测试数据 | |||||
- 📦 **使用标准地址**:测试地址库中的地址 | |||||
- 📱 **使用测试手机**:避免骚扰真实用户 | |||||
- 💰 **使用小额保价**:测试保价功能 | |||||
### 3. 错误处理 | |||||
- 🐛 **记录错误信息**:保存错误日志 | |||||
- 🔍 **分析错误原因**:检查参数和配置 | |||||
- 📞 **及时反馈问题**:联系技术支持 | |||||
## 技术支持 | |||||
如果在测试过程中遇到问题: | |||||
1. 检查是否严格按照测试环境要求配置 | |||||
2. 查看错误日志和返回信息 | |||||
3. 确认未超过调用限制 | |||||
4. 联系技术支持获取帮助 | |||||
## 升级说明 | |||||
测试完成后,如需升级到生产环境: | |||||
1. 申请生产环境权限 | |||||
2. 配置真实的快递公司参数 | |||||
3. 使用真实的商户信息 | |||||
4. 遵守生产环境的使用规范 | |||||
--- | |||||
**再次提醒:严格遵守测试环境规则,确保测试的有效性和合规性!** |
@ -0,0 +1,212 @@ | |||||
# 微信物流取消订单问题解决方案 | |||||
## 🔍 问题诊断 | |||||
### 1. "order not exists" 错误 | |||||
**错误信息**: `取消运单失败:order not exists rid: 68691313-48c27f21-7ac12929` | |||||
**原因分析**: | |||||
- 使用了虚拟测试数据:`orderId=test_order_id`, `waybillId=test_waybill_id` | |||||
- 这些订单在微信物流系统中并不存在 | |||||
- 根据微信官方API,取消订单需要提供**真实存在的订单ID和运单ID** | |||||
### 2. HTTP 404错误 | |||||
**错误信息**: `HTTP Status 404 – Not Found` | |||||
**原因分析**: | |||||
- 应用设置了上下文路径:`context-path: /recycle-admin` | |||||
- 之前使用的接口路径缺少上下文路径前缀 | |||||
## ✅ 正确的解决方案 | |||||
### 1. 正确的接口路径 | |||||
应用运行在:`http://localhost:8002/recycle-admin` | |||||
正确的测试接口路径: | |||||
``` | |||||
- 下单: POST http://localhost:8002/recycle-admin/applet/logistics/test/addOrder | |||||
- 查询: POST http://localhost:8002/recycle-admin/applet/logistics/test/getPath | |||||
- 取消: POST http://localhost:8002/recycle-admin/applet/logistics/test/cancelOrder | |||||
- 完整流程: POST http://localhost:8002/recycle-admin/applet/logistics/test/fullTestWithCancel | |||||
``` | |||||
### 2. 正确的测试流程 | |||||
#### 方法1:完整流程测试(推荐) | |||||
```powershell | |||||
# 使用完整流程测试,先下单再取消 | |||||
Invoke-WebRequest -Uri "http://localhost:8002/recycle-admin/applet/logistics/test/fullTestWithCancel" ` | |||||
-Method POST ` | |||||
-Headers @{"Content-Type"="application/json"} ` | |||||
-Body '{"openid": "test_admin_openid", "deliveryId": "TEST", "bizId": "test_biz_id", "cancelMsg": "测试环境取消"}' | |||||
``` | |||||
#### 方法2:分步测试 | |||||
```powershell | |||||
# 步骤1:先下单 | |||||
$orderResponse = Invoke-WebRequest -Uri "http://localhost:8002/recycle-admin/applet/logistics/test/addOrder" ` | |||||
-Method POST ` | |||||
-Headers @{"Content-Type"="application/json"} ` | |||||
-Body '{"openid": "test_admin_openid", "deliveryId": "TEST", "bizId": "test_biz_id"}' | |||||
# 从响应中提取订单ID和运单ID | |||||
$orderData = $orderResponse.Content | ConvertFrom-Json | |||||
$orderId = $orderData.result.orderId | |||||
$waybillId = $orderData.result.waybillId | |||||
# 步骤2:使用真实订单ID取消订单 | |||||
Invoke-WebRequest -Uri "http://localhost:8002/recycle-admin/applet/logistics/test/cancelOrder" ` | |||||
-Method POST ` | |||||
-Headers @{"Content-Type"="application/json"} ` | |||||
-Body "{'orderId': '$orderId', 'waybillId': '$waybillId', 'deliveryId': 'TEST', 'openid': 'test_admin_openid', 'cancelMsg': '测试取消'}" | |||||
``` | |||||
### 3. 使用浏览器测试(最简单) | |||||
访问Swagger UI:`http://localhost:8002/recycle-admin/swagger-ui.html` | |||||
1. 找到"微信物流测试"分组 | |||||
2. 选择"测试完整流程(包含取消)"接口 | |||||
3. 点击"Try it out" | |||||
4. 点击"Execute"执行 | |||||
## 📋 测试环境参数说明 | |||||
### 必须使用的固定参数 | |||||
```json | |||||
{ | |||||
"openid": "test_admin_openid", // 需替换为实际管理员openid | |||||
"deliveryId": "TEST", // 测试运力(固定值) | |||||
"bizId": "test_biz_id", // 测试商户(固定值) | |||||
"cancelMsg": "测试环境取消" // 取消原因 | |||||
} | |||||
``` | |||||
### ⚠️ 重要提醒 | |||||
1. **每天最多10次调用** - 请合理安排测试 | |||||
2. **仅限管理员openid** - `test_admin_openid`需替换为实际值 | |||||
3. **使用固定测试参数** - 不要修改`TEST`和`test_biz_id` | |||||
4. **测试流程** - 必须先下单再取消,不能取消不存在的订单 | |||||
## 🧪 快速验证脚本 | |||||
### PowerShell脚本 | |||||
```powershell | |||||
# 微信物流取消订单测试脚本 | |||||
$baseUrl = "http://localhost:8002/recycle-admin" | |||||
$headers = @{"Content-Type"="application/json"} | |||||
Write-Host "开始微信物流取消订单测试..." -ForegroundColor Green | |||||
try { | |||||
# 测试完整流程(下单 -> 取消) | |||||
Write-Host "执行完整流程测试..." -ForegroundColor Yellow | |||||
$response = Invoke-WebRequest -Uri "$baseUrl/applet/logistics/test/fullTestWithCancel" ` | |||||
-Method POST ` | |||||
-Headers $headers ` | |||||
-Body '{"openid": "test_admin_openid", "deliveryId": "TEST", "bizId": "test_biz_id", "cancelMsg": "PowerShell测试"}' | |||||
$result = $response.Content | ConvertFrom-Json | |||||
if ($result.success) { | |||||
Write-Host "✅ 测试成功!" -ForegroundColor Green | |||||
Write-Host "订单ID: $($result.result.orderResponse.orderId)" -ForegroundColor Cyan | |||||
Write-Host "运单ID: $($result.result.orderResponse.waybillId)" -ForegroundColor Cyan | |||||
if ($result.result.cancelResponse) { | |||||
Write-Host "✅ 取消成功!" -ForegroundColor Green | |||||
Write-Host "取消时间: $($result.result.cancelResponse.cancelTime)" -ForegroundColor Cyan | |||||
} | |||||
} else { | |||||
Write-Host "❌ 测试失败: $($result.message)" -ForegroundColor Red | |||||
} | |||||
} catch { | |||||
Write-Host "❌ 请求失败: $($_.Exception.Message)" -ForegroundColor Red | |||||
Write-Host "请检查:" -ForegroundColor Yellow | |||||
Write-Host "1. 应用是否在 http://localhost:8002/recycle-admin 运行" -ForegroundColor White | |||||
Write-Host "2. 微信配置是否正确" -ForegroundColor White | |||||
Write-Host "3. 网络连接是否正常" -ForegroundColor White | |||||
} | |||||
Write-Host "测试完成!" -ForegroundColor Green | |||||
``` | |||||
### 保存并运行脚本 | |||||
1. 将上述脚本保存为 `test-logistics.ps1` | |||||
2. 在PowerShell中运行:`.\test-logistics.ps1` | |||||
## 🐛 常见问题排查 | |||||
### 1. 访问被拒绝 | |||||
**问题**: HTTP 403或认证失败 | |||||
**解决**: | |||||
- 检查微信AppId和AppSecret配置 | |||||
- 确认使用管理员openid | |||||
- 验证测试环境权限 | |||||
### 2. 参数错误 | |||||
**问题**: 参数验证失败 | |||||
**解决**: | |||||
- 确保使用固定测试参数:`deliveryId=TEST`, `bizId=test_biz_id` | |||||
- 检查JSON格式是否正确 | |||||
- 确认必填字段都已提供 | |||||
### 3. 连接超时 | |||||
**问题**: 网络连接超时 | |||||
**解决**: | |||||
- 检查应用是否正常运行 | |||||
- 验证端口8002是否开放 | |||||
- 确认防火墙设置 | |||||
### 4. 订单状态错误 | |||||
**问题**: 订单状态不允许取消 | |||||
**解决**: | |||||
- 在下单后立即取消(建议5分钟内) | |||||
- 检查订单当前状态 | |||||
- 使用完整流程测试确保订单存在 | |||||
## 📖 微信官方API参考 | |||||
根据微信官方文档,取消订单接口要求: | |||||
**接口地址**: `POST https://api.weixin.qq.com/cgi-bin/express/business/order/cancel?access_token=ACCESS_TOKEN` | |||||
**必填参数**: | |||||
- `order_id`: 订单ID(必须是真实存在的) | |||||
- `delivery_id`: 快递公司ID | |||||
- `waybill_id`: 运单ID(必须是真实存在的) | |||||
- `access_token`: 接口调用凭证 | |||||
**可选参数**: | |||||
- `openid`: 用户openid | |||||
## 🎯 成功测试的标志 | |||||
测试成功时,您应该看到类似以下的响应: | |||||
```json | |||||
{ | |||||
"success": true, | |||||
"message": "操作成功", | |||||
"code": 200, | |||||
"result": { | |||||
"orderResponse": { | |||||
"orderId": "TEST_ORDER_1234567890", | |||||
"waybillId": "TEST_WAYBILL_123", | |||||
"errCode": 0, | |||||
"errMsg": "ok" | |||||
}, | |||||
"cancelResponse": { | |||||
"errCode": 0, | |||||
"errMsg": "ok", | |||||
"orderId": "TEST_ORDER_1234567890", | |||||
"waybillId": "TEST_WAYBILL_123", | |||||
"cancelTime": 1672531200 | |||||
}, | |||||
"message": "完整流程测试成功(包含取消)" | |||||
} | |||||
} | |||||
``` | |||||
现在您可以使用正确的路径和方法来测试微信物流取消订单功能了! |
@ -0,0 +1,154 @@ | |||||
# 微信物流取消订单测试脚本 | |||||
# 使用正确的上下文路径:/recycle-admin | |||||
param( | |||||
[string]$openid = "test_admin_openid", | |||||
[string]$deliveryId = "TEST", | |||||
[string]$bizId = "test_biz_id", | |||||
[string]$cancelMsg = "PowerShell自动化测试" | |||||
) | |||||
$baseUrl = "http://localhost:8002/recycle-admin" | |||||
$headers = @{"Content-Type"="application/json"} | |||||
Write-Host "=" * 60 -ForegroundColor Green | |||||
Write-Host " 微信物流取消订单测试脚本" -ForegroundColor Green | |||||
Write-Host "=" * 60 -ForegroundColor Green | |||||
Write-Host "" | |||||
Write-Host "测试配置:" -ForegroundColor Yellow | |||||
Write-Host "- 服务地址: $baseUrl" -ForegroundColor White | |||||
Write-Host "- OpenID: $openid" -ForegroundColor White | |||||
Write-Host "- 快递公司: $deliveryId" -ForegroundColor White | |||||
Write-Host "- 商户ID: $bizId" -ForegroundColor White | |||||
Write-Host "- 取消原因: $cancelMsg" -ForegroundColor White | |||||
Write-Host "" | |||||
# 检查服务是否可用 | |||||
Write-Host "检查服务状态..." -ForegroundColor Yellow | |||||
try { | |||||
$healthCheck = Invoke-WebRequest -Uri "$baseUrl/actuator/health" -Method GET -TimeoutSec 5 | |||||
Write-Host "✅ 服务正常运行" -ForegroundColor Green | |||||
} catch { | |||||
Write-Host "⚠️ 无法访问健康检查端点,继续测试..." -ForegroundColor Yellow | |||||
} | |||||
Write-Host "" | |||||
Write-Host "开始执行完整流程测试(下单 -> 取消)..." -ForegroundColor Yellow | |||||
Write-Host "" | |||||
try { | |||||
# 构建请求体 | |||||
$requestBody = @{ | |||||
openid = $openid | |||||
deliveryId = $deliveryId | |||||
bizId = $bizId | |||||
cancelMsg = $cancelMsg | |||||
} | ConvertTo-Json | |||||
Write-Host "发送请求到: $baseUrl/applet/logistics/test/fullTestWithCancel" -ForegroundColor Cyan | |||||
Write-Host "请求数据: $requestBody" -ForegroundColor Gray | |||||
Write-Host "" | |||||
# 发送请求 | |||||
$response = Invoke-WebRequest -Uri "$baseUrl/applet/logistics/test/fullTestWithCancel" ` | |||||
-Method POST ` | |||||
-Headers $headers ` | |||||
-Body $requestBody ` | |||||
-TimeoutSec 30 | |||||
# 解析响应 | |||||
$result = $response.Content | ConvertFrom-Json | |||||
Write-Host "响应状态码: $($response.StatusCode)" -ForegroundColor Cyan | |||||
Write-Host "" | |||||
if ($result.success) { | |||||
Write-Host "🎉 测试成功!" -ForegroundColor Green | |||||
Write-Host "" | |||||
# 显示下单结果 | |||||
if ($result.result.orderResponse) { | |||||
Write-Host "📦 下单结果:" -ForegroundColor Yellow | |||||
Write-Host " 订单ID: $($result.result.orderResponse.orderId)" -ForegroundColor Cyan | |||||
Write-Host " 运单ID: $($result.result.orderResponse.waybillId)" -ForegroundColor Cyan | |||||
Write-Host " 错误码: $($result.result.orderResponse.errCode)" -ForegroundColor Cyan | |||||
Write-Host " 错误信息: $($result.result.orderResponse.errMsg)" -ForegroundColor Cyan | |||||
if ($result.result.orderResponse.waybillData) { | |||||
Write-Host " 运单数据: 已生成" -ForegroundColor Cyan | |||||
} | |||||
Write-Host "" | |||||
} | |||||
# 显示取消结果 | |||||
if ($result.result.cancelResponse) { | |||||
Write-Host "❌ 取消结果:" -ForegroundColor Yellow | |||||
Write-Host " 错误码: $($result.result.cancelResponse.errCode)" -ForegroundColor Cyan | |||||
Write-Host " 错误信息: $($result.result.cancelResponse.errMsg)" -ForegroundColor Cyan | |||||
if ($result.result.cancelResponse.cancelTime) { | |||||
$cancelTime = [DateTimeOffset]::FromUnixTimeSeconds($result.result.cancelResponse.cancelTime).ToString("yyyy-MM-dd HH:mm:ss") | |||||
Write-Host " 取消时间: $cancelTime" -ForegroundColor Cyan | |||||
} | |||||
Write-Host "" | |||||
} | |||||
# 显示总结信息 | |||||
Write-Host "📋 测试总结:" -ForegroundColor Yellow | |||||
Write-Host " $($result.result.message)" -ForegroundColor White | |||||
Write-Host "" | |||||
} else { | |||||
Write-Host "❌ 测试失败!" -ForegroundColor Red | |||||
Write-Host "错误信息: $($result.message)" -ForegroundColor Red | |||||
if ($result.result) { | |||||
Write-Host "详细信息: $($result.result)" -ForegroundColor Red | |||||
} | |||||
Write-Host "" | |||||
} | |||||
} catch { | |||||
Write-Host "❌ 请求失败!" -ForegroundColor Red | |||||
Write-Host "错误信息: $($_.Exception.Message)" -ForegroundColor Red | |||||
Write-Host "" | |||||
# 提供排查建议 | |||||
Write-Host "🔍 排查建议:" -ForegroundColor Yellow | |||||
Write-Host "1. 检查应用是否在 $baseUrl 运行" -ForegroundColor White | |||||
Write-Host "2. 检查微信配置是否正确" -ForegroundColor White | |||||
Write-Host "3. 确认网络连接正常" -ForegroundColor White | |||||
Write-Host "4. 验证测试环境权限" -ForegroundColor White | |||||
Write-Host "" | |||||
# 显示详细错误信息 | |||||
if ($_.Exception.Response) { | |||||
Write-Host "响应状态码: $($_.Exception.Response.StatusCode)" -ForegroundColor Red | |||||
Write-Host "响应状态: $($_.Exception.Response.StatusDescription)" -ForegroundColor Red | |||||
} | |||||
Write-Host "" | |||||
} | |||||
Write-Host "=" * 60 -ForegroundColor Green | |||||
Write-Host " 测试完成!" -ForegroundColor Green | |||||
Write-Host "=" * 60 -ForegroundColor Green | |||||
Write-Host "" | |||||
# 提供后续操作建议 | |||||
Write-Host "💡 后续操作建议:" -ForegroundColor Yellow | |||||
Write-Host "1. 如果测试成功,可以在实际应用中使用相同的逻辑" -ForegroundColor White | |||||
Write-Host "2. 记住每天最多只能调用10次,请合理安排测试" -ForegroundColor White | |||||
Write-Host "3. 在生产环境中,请替换为实际的openid和配置" -ForegroundColor White | |||||
Write-Host "4. 可以通过Swagger UI进行更详细的测试: $baseUrl/swagger-ui.html" -ForegroundColor White | |||||
Write-Host "" | |||||
# 参数说明 | |||||
Write-Host "📖 脚本参数说明:" -ForegroundColor Yellow | |||||
Write-Host "使用示例:" -ForegroundColor White | |||||
Write-Host " .\test-logistics.ps1" -ForegroundColor Gray | |||||
Write-Host " .\test-logistics.ps1 -openid 'your_openid' -cancelMsg '自定义取消原因'" -ForegroundColor Gray | |||||
Write-Host "" | |||||
Write-Host "按任意键退出..." -ForegroundColor Green | |||||
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | Out-Null |