发货 API 测试
本指南以通用的 API 测试 原则为基础,为 Equinix Shipments API 提供具体的测试方法和示例。
发货 API 概述
Shipments API 允许您以编程方式安排和管理进出 Equinix IBX 数据中心的货物运输,包括:
- 安排入库货物(接收包裹)
- 安排出货(寄送包裹)
- 更新发货详情
- 管理货运跟踪信息
- 处理承运商信息和跟踪号码
重要提示: 所有入库和出库货物必须提前 24 小时安排。Equinix API 是一个生产系统,会创建真实的货运请求。请务必遵循这些测试最佳实践,以确保不会产生意外的运维工作。
发货测试工作流程
在测试 Shipments API 之前,请确保您已具备以下条件:
- 具有发货订单权限的有效 API 凭证
- 可前往设有笼位的 Equinix IBX 地点
- 您的发货地点的有效笼号编号
- 了解承运商要求和跟踪号码格式
创建入库发货请求
import requests
import json
from datetime import datetime, timedelta
# Setup authentication
auth_url = "https://api.equinix.com/oauth2/v1/token"
auth_payload = {
"grant_type": "client_credentials",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
}
auth_response = requests.post(auth_url, data=auth_payload)
token = auth_response.json()["access_token"]
# Test creating an inbound shipment request
base_url = "https://api.equinix.com/colocations/v2"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
# Calculate delivery date (24+ hours in advance as required)
delivery_date = (datetime.utcnow() + timedelta(days=2)).isoformat() + "Z"
# Example: Create an inbound shipment request
inbound_payload = {
"type": "INBOUND",
"requestedDateTime": delivery_date,
"cageId": "SV1:01:001MC3",
"customerReferenceId": "SHIP-REF-12345",
"description": "Server hardware delivery for data center expansion project",
"details": {
"carrier": "DHL",
"carrierTrackingNumbers": [
"1234567890123",
"1234567890124"
],
"numberOfBoxes": 2,
"accountNumber": "12345"
},
"purchaseOrder": {
"type": "EXISTING",
"number": "PO-789456"
},
"attachments": [
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"name": "packing_list.pdf"
}
],
"contacts": [
{
"type": "TECHNICAL",
"registeredUsers": ["tech.admin@example.com"],
"availability": "WORK_HOURS",
"timezone": "America/New_York"
},
{
"type": "NOTIFICATION",
"registeredUsers": ["notifications@example.com"]
}
]
}
create_response = requests.post(
f"{base_url}/orders/shipments",
headers=headers,
data=json.dumps(inbound_payload)
)
# Verify response
assert create_response.status_code == 201, f"Failed to create shipment: {create_response.text}"
# Extract order ID from Location header
order_number = create_response.json()["OrderNumber"]
print(f"Successfully created inbound shipment with order ID: {order_number}")
创建出库发货请求
# Example: Create an outbound shipment request
outbound_payload = {
"type": "OUTBOUND",
"requestedDateTime": delivery_date,
"cageId": "SV1:01:001MC3",
"customerReferenceId": "OUT-SHIP-67890",
"description": "Returning defective network equipment to vendor",
"details": {
"carrier": "FEDEX",
"carrierTrackingNumbers": [
"987654321098"
],
"numberOfBoxes": 1,
"pickupLocation": "Main cage entrance",
"specialInstructions": "Handle with care - contains sensitive electronic equipment"
},
"purchaseOrder": {
"type": "EXEMPTED"
},
"contacts": [
{
"type": "TECHNICAL",
"registeredUsers": ["shipping@example.com"],
"availability": "ANYTIME"
}
]
}
outbound_response = requests.post(
f"{base_url}/orders/shipments",
headers=headers,
data=json.dumps(outbound_payload)
)
assert outbound_response.status_code == 201, f"Failed to create outbound shipment: {outbound_response.text}"
order_number = outbound_response.json()["OrderNumber"]
print("Successfully created outbound shipment request with order ID: {order_number}")
测试错误场景
务必对 API 实现中的错误处理进行测试:
# Test with invalid carrier
invalid_carrier_payload = {
"type": "INBOUND",
"requestedDateTime": delivery_date,
"cageId": "SV1:01:001MC3",
"details": {
"carrier": "INVALID_CARRIER", # Invalid carrier
"carrierTrackingNumbers": ["1234567890"],
"numberOfBoxes": 1
},
"contacts": [
{
"type": "TECHNICAL",
"registeredUsers": ["test@example.com"]
}
]
}
error_response = requests.post(
f"{base_url}/orders/shipments",
headers=headers,
data=json.dumps(invalid_carrier_payload)
)
# Verify error response
assert error_response.status_code == 400, f"Expected error but got: {error_response.status_code}"
error_data = error_response.json()
assert any("carrier" in error["errorMessage"].lower() for error in error_data), "Expected carrier validation error"
# Test with insufficient advance notice (less than 24 hours)
insufficient_time_payload = {
"type": "INBOUND",
"requestedDateTime": (datetime.utcnow() + timedelta(hours=12)).isoformat() + "Z", # Only 12 hours advance
"cageId": "SV1:01:001MC3",
"details": {
"carrier": "DHL",
"carrierTrackingNumbers": ["1234567890"],
"numberOfBoxes": 1
},
"contacts": [
{
"type": "TECHNICAL",
"registeredUsers": ["test@example.com"]
}
]
}
time_error_response = requests.post(
f"{base_url}/orders/shipments",
headers=headers,
data=json.dumps(insufficient_time_payload)
)
assert time_error_response.status_code == 400, f"Expected time validation error but got: {time_error_response.status_code}"
发货 API 测试最佳实践
- 提前24小时安排规则:务必至少提前24小时安排发货。
- 有效的追踪号码:请使用适用于各承运商的实际追踪号码格式。
- 正确的联系信息:请确保在送货时间段内联系人畅通。
- 笼具访问:测试前请核实笼具编号和访问权限
- 国际货运:请考虑国际货运的海关要求。
- 特殊说明:请在各种特殊操作要求下进行测试
- 文件附件:测试上传装箱单和特殊说明的附件
- 时区:正确处理时区转换,以便进行日程安排。
- 采购订单:测试不同的采购订单类型(新建、现有、豁免)
自动化考量
在围绕发货 API 构建自动化流程时:
- 实施针对提前24小时排班要求的验证
- 针对跟踪号码格式构建运营商特定的验证机制
- 针对运营商可用性和容量问题,制定适当的错误处理方案
- 实现用于接收发货状态更新的 webhook 接收器
- 为所有货运交易建立审计日志
- 创建请求前,请验证笼子访问权限和权限。
- 确保正确处理国际地点的时区。