API DocsCreate Ticket

Webhook 配置

通过 Webhook 实时接收发货状态更新。

什么是 Webhook?

Webhook 是在事件发生时,由 atoship 自动推送到你服务器的消息通知,例如:

  • 已创建面单
  • 包裹已发货
  • 派送状态发生变化
  • 出现异常

优势

  • 实时更新(无需轮询)
  • 触发自动化流程
  • 即时同步你的系统
  • 提升客户体验

可用事件

发货事件

事件触发时机使用场景
shipment.created已购买面单更新库存
shipment.cancelled面单已作废恢复库存
shipment.delivered包裹已签收发送评价邀请
shipment.returned已收到退货处理退款
shipment.exception派送异常通知客服

物流跟踪事件

事件触发时机使用场景
tracking.in_transit承运商首次扫描通知客户
tracking.out_for_delivery已上派送车当日提醒
tracking.delivered确认签收关闭订单
tracking.failed_attempt派送尝试失败提醒客户
tracking.exception出现问题排查处理

订单事件

事件触发时机使用场景
order.imported订单已同步开始履约
order.updated订单已修改更新记录
order.cancelled订单已取消停止履约

账户事件

事件触发时机使用场景
balance.low钱包余额低于阈值充值提醒
billing.adjustment承运商费用调整复核账单

配置指南

第 1 步:创建接收端点

你的端点必须:

  • 接受 POST 请求
  • 使用 HTTPS(生产环境必需)
  • 在 5 秒内返回 200 状态码
  • 以幂等方式处理重试

端点示例(Node.js/Express):

const express = require('express');
const app = express();

app.post('/webhooks/atoship', express.json(), (req, res) => {
  // Acknowledge immediately
  res.status(200).send('OK');

  // Process asynchronously
  processWebhook(req.body).catch(console.error);
});

async function processWebhook(event) {
  switch (event.type) {
    case 'shipment.delivered':
      await markOrderDelivered(event.data.order_id);
      await sendDeliveryEmail(event.data);
      break;
    case 'tracking.exception':
      await alertCustomerService(event.data);
      break;
    // Handle other events...
  }
}

第 2 步:注册 Webhook

  1. 进入 设置 > Webhooks
  2. 点击 添加 Webhook 端点
  3. 输入你的 URL:https://yoursite.com/webhooks/atoship
  4. 选择要接收的事件
  5. 点击 保存

第 3 步:复制 Webhook 密钥

保存后:

  1. 点击你的 Webhook
  2. 复制 签名密钥(Signing Secret)
  3. 妥善保管(存入环境变量)

第 4 步:验证签名

重要提示:请务必验证 Webhook 签名,以防止伪造请求。

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expectedSig = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

  // Use timing-safe comparison
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expectedSig, 'hex')
  );
}

app.post('/webhooks/atoship', express.json(), (req, res) => {
  const signature = req.headers['x-atoship-signature'];
  const secret = process.env.ATOSHIP_WEBHOOK_SECRET;

  if (!verifySignature(req.body, signature, secret)) {
    console.error('Invalid webhook signature');
    return res.status(401).send('Invalid signature');
  }

  // Signature valid, process event
  res.status(200).send('OK');
  processWebhook(req.body);
});

事件载荷(Payload)结构

标准格式

{
  "id": "evt_1234567890abcdef",
  "type": "shipment.delivered",
  "created_at": "2024-01-15T10:30:00Z",
  "data": {
    "shipment_id": "shp_abc123",
    "tracking_number": "9400111899223456789012",
    "carrier": "USPS",
    "service": "Priority Mail",
    "order_id": "order_xyz789",
    "order_reference": "ORD-12345",
    "delivered_at": "2024-01-15T10:28:00Z",
    "delivery_location": "Front door",
    "signed_by": "RESIDENT"
  },
  "metadata": {
    "organization_id": "org_xxxxx",
    "attempt": 1
  }
}

重试机制

自动重试

如果你的端点返回非 2xx 状态码或超时:

尝试次数延迟时间
1立即
21 分钟
35 分钟
430 分钟
52 小时
66 小时

连续失败 6 次后,该 Webhook 将被标记为失败。

处理重试

幂等性至关重要

const processedEvents = new Map(); // Use Redis in production

async function processWebhook(event) {
  // Check if already processed
  if (processedEvents.has(event.id)) {
    console.log('Event ' + event.id + ' already processed, skipping');
    return;
  }

  // Mark as processing
  processedEvents.set(event.id, { status: 'processing', timestamp: Date.now() });

  try {
    // Process event
    await handleEvent(event);
    processedEvents.set(event.id, { status: 'completed', timestamp: Date.now() });
  } catch (error) {
    processedEvents.set(event.id, { status: 'failed', error: error.message });
    throw error; // Let retry happen
  }
}

测试 Webhook

发送测试事件

  1. 进入 设置 > Webhooks
  2. 点击你的端点
  3. 点击 发送测试事件
  4. 选择事件类型
  5. 查看响应结果

本地开发

使用 ngrok 进行本地测试:

# Install ngrok
npm install -g ngrok

# Expose local port
ngrok http 3000

# Use provided URL
# https://abc123.ngrok.io/webhooks/atoship

Webhook 日志

查看推送尝试记录:

  1. 进入 Webhook 设置
  2. 点击 推送日志(Delivery Logs)
  3. 查看请求 / 响应详情
  4. 重新推送失败的记录

最佳实践

响应时间

尽快返回 200

// Good - Acknowledge immediately, process async
app.post('/webhooks', (req, res) => {
  res.status(200).send('OK');
  queue.add('process-webhook', req.body);
});

// Bad - Blocking response
app.post('/webhooks', async (req, res) => {
  await processWebhook(req.body); // May timeout
  res.status(200).send('OK');
});

监控

跟踪 Webhook 运行状况:

  • 推送成功率
  • 平均响应时间
  • 失败的事件类型
  • 重试频率

故障排查

收不到 Webhook

请检查

  1. 端点 URL 是否正确
  2. 是否已启用 HTTPS
  3. 防火墙是否放行 atoship 的 IP
  4. 是否已订阅相应事件
  5. Webhook 是否已启用

签名验证失败

常见原因

  • 使用了已解析的 JSON,而非原始请求体(raw body)
  • Webhook 密钥错误
  • 编码不一致

超时错误

如果 Webhook 超时:

  1. 立即返回 200
  2. 异步处理业务逻辑
  3. 使用消息队列
  4. 检查服务器性能

需要帮助?

  • API 文档:完整的 Webhook 参考
  • 开发者聊天:技术支持
  • 邮箱[email protected]
  • 客服支持:前往 /dashboard/support 创建工单

Was this article helpful?