### Webhook概述 Webhook 是一种在特定事件发生时自动向指定 URL 发送 HTTP POST 请求的机制,用于实现应用程序之间的数据传递和交互。通常情况下,Webhook 由接收方提供一个 URL 和相关配置参数,并在某一事件触发时向该 URL 发送包含相应信息的 HTTP POST 请求。 Webhook 可以被用于多种场景,例如实时通知、自动更新、数据同步等。它可以让第三方应用程序、服务或者系统在事件发生时及时获取到信息,并根据需要进行处理和响应。Webhook 可以与 RESTful API 配合使用,提供更加灵活和可定制化的数据传输方式,也可以用于处理异步任务、实现消息队列等。 ### 设置Webhook 使用自己的DP账号登录DP系统,进入到页面‘个人中心>账户管理>API对接信息’设置webhook地址 ### 推送策略 - 推送由队列控制发送,建议您使用队列处理接收到的信息; - 每次推送通知包含一个物流单号的全量信息; - 接收推送的 Webhook URL 返回 HTTP状态码 200 表示推送成功; - HTTP状态码非 200 都判断为推送失败; - 推送失败后会自动重试 5 次,如果仍无法推送,将放弃推送此单号,等待下一次推送重试再进行。所有重试都失败,要等到下次自动跟踪再进行推送; - 重试方式具体如下: 尝试次数 | 重试次数 | 发送前延迟(秒) | 累计延迟(秒) | 描述 ---|---|---|---|--- 1 | 0 | 0 | 0 | 无 2 | 1 | 180 | 180 | 第3分钟发起 3 | 2 | 180 | 360 | 第6分钟发起 4 | 3 | 180 | 540 | 第9分钟发起 5 | 4 | 180 | 720 | 第12分钟发起 6 | 5 | 180 | 900 | 第15分钟发起 ### Webhook数据及签名 #### 数据格式 名称 | 类型 | 描述 ---|---|--- data | JSON Object | 发送的数据 -order_number | String | 订单号 -reference_number | String | 参考号 -tracking_number | String | 追踪单号 -tracking_status | 枚举 | 订单轨迹状态 -tracking_event_status | 枚举 | 订单轨迹子状态 -created_at | String | 订单下单时间 -last_track_info | String | 末条轨迹内容 -track_infos | JSON Array | 全量轨迹内容 --create_time | String | 轨迹发生的时间 --tracking_status | 枚举 | 轨迹状态 --location | String | 轨迹发生的位置 --description | String | 轨迹描述 --event_code | String | 轨迹子状态 Event code verify | JSON Object | 签名验证 -signature | String | 签名 -timestamp | Long | 时间戳 ### Webhook 签名验证 为了确保消息的来源身份是 DP,你可以选择对 POST 数据的来源进行安全认证。 ( 不验证,直接解析 POST 的数据也可以 ) 安全认证的方法如下: 解析出 POST 数据中的 timestamp 和 signature 这两个参数。 使用你的 DP 用户编码(鉴权信息中的API Key) 和 timestamp (明文) 生成签名 signature, 与 POST 数据中的 signature 进行校验 ( 签名算法: PHP:SHA256、JAVA:HmacSHA256) **备注:使用附带的Jave和Php示例代码来验证DP数据,当验证您自己的数据请替换SIGNATURE,TIMESTAMP 和 ACCOUNT。** #### Java ``` import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; public class Main { public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException { String signature = "a0bf09322c134d77ead26c8e50124c52e5cb710117fd7c03ef463dc0de035e18"; String timestamp = "1680577815864"; String account = "YS2204205"; Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(account.getBytes(), "HmacSHA256"); sha256_HMAC.init(secret_key); byte[] bytes = sha256_HMAC.doFinal(timestamp.getBytes()); StringBuilder new_signature = new StringBuilder(); for (byte item : bytes) { new_signature.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); } System.out.println(new_signature.toString()); System.out.println(new_signature.toString().equals(signature)); } } ``` #### Php ``` $signature = 'a0bf09322c134d77ead26c8e50124c52e5cb710117fd7c03ef463dc0de035e18'; $timestamp = '1680577815864'; $account = 'YS2204205'; $new_signature = hash_hmac('sha256', $timestamp, $account); var_dump($signature == $new_signature , $new_signature); ``` #### 物流状态枚举参考: 枚举值 | 描述 ---|--- NOT_ONLINE | 未上网 TAKE_DELIVERY | 仓库收货 TAKE_OFF | 离港 LANDING | 到港 CLEARANCE | 清关中 IN_TRANSIT | 运输中 WAIT_TO_PICKUP | 到达待取 POSSIBLE_ABNORMALITY | 可能异常 FOREIGN_RETURN | 国外退件 SIGNING_SUCCESS | 已签收 OTHER | 其他 #### 物流子状态枚举参考: 枚举值 | Event code | Event 描述 ---|---|--- CUSTOMS_CLEARANCE_DONE | customs_clearance_done | Customs Clearance Done ORIGIN_SCAN_EXPIRED | origin_scan_expired | Possible Origin Scan Expired ORIGIN_SCAN | origin_scan | Origin Scan DELIVERY_EXPIRED | delivery_expired | Possible Delivery Expired ATTEMPT_REDELIVERY | attempt_redelivery | Attempt Redelivery FAILURE_ADDRESS_ERROR | failure_address_error | Failure Address Error FAILURE_NO_BODY | failure_no_body | Failure No Body FAILURE_REJECTED | failure_rejected | Failure Rejected FAILURE_OTHER | failure_other | Failure Other INSPECTION | inspection | Inspection AVAILABLE_FOR_PICKUP | available_for_pickup | Available For Pickup EXCEPTION_LOST | exception_lost | Exception Lost EXCEPTION_DESTROYED | exception_destroyed | Exception Destroyed EXCEPTION_OTHER | exception_other | Exception Other INVESTIGATION | investigation | Investigation CLAIM | claim | Claim DELIVERY_FAILED | delivery_failed | Delivery Failed RETURN_TO_SENDER | return_to_sender | Return To Sender RETURNING_TO_SENDER | returning_to_sender | Returning To Sender RETURNED_TO_SENDER | returned_to_sender | Returned To Sender ### Webhook请求示例 ``` { "data": { "order_number": "DPAYQ0003737121YQ", "reference_number": "FEILO1722333950YQ", "tracking_number": "1Z6676E86894283690", "tracking_status": "FOREIGN_RETURN", "tracking_event_status": "returning_to_sender", "created_at": "2022-12-23 13:57:00", "last_track_info": "2023-02-04 09:00:00 PRATO,59100,IT, Delivered", "track_infos": [ { "create_time": "2023-02-04 09:00:00", "tracking_status": "SIGNING_SUCCESS", "location": "PRATO,59100,IT", "description": "Delivered", "event_code": "" }, { "create_time": "2023-02-03 15:51:10", "tracking_status": "WAIT_TO_PICKUP", "location": "IT", "description": "The receiving business was closed at the time of the final delivery attempt." }, { "create_time": "2023-02-03 10:23:32", "tracking_status": "IN_TRANSIT", "location": "Prato,IT", "description": "The package has been rescheduled for a future delivery date." }, { "create_time": "2023-02-03 07:31:00", "tracking_status": "FOREIGN_RETURN", "location": "Prato,IT", "description": "Processing at UPS Facility", "event_code": "returning_to_sender" }, { "create_time": "2023-02-03 07:30:00", "tracking_status": "IN_TRANSIT", "location": "Prato,IT", "description": "Arrived at Facility" }, { "create_time": "2023-02-03 05:15:00", "tracking_status": "IN_TRANSIT", "location": "Carpi,IT", "description": "Departed from Facility" }, { "create_time": "2023-02-02 22:19:00", "tracking_status": "IN_TRANSIT", "location": "Carpi,IT", "description": "Arrived at Facility" }, { "create_time": "2023-02-02 03:35:00", "tracking_status": "IN_TRANSIT", "location": "Herne-Boernig,DE", "description": "Departed from Facility" }, { "create_time": "2023-02-01 22:34:00", "tracking_status": "IN_TRANSIT", "location": "Herne-Boernig,DE", "description": "Arrived at Facility" }, { "create_time": "2023-02-01 20:14:00", "tracking_status": "IN_TRANSIT", "location": "Lummen,BE", "description": "Departed from Facility" }, { "create_time": "2023-02-01 17:07:45", "tracking_status": "IN_TRANSIT", "location": "Lummen,BE", "description": "Origin Scan" }, { "create_time": "2023-01-30 10:27:21", "tracking_status": "IN_TRANSIT", "location": "BE", "description": "Shipper created a label, UPS has not received the package yet." } ] }, "verify": { "timestamp": 1680577815864, "signature": "a0bf09322c134d77ead26c8e50124c52e5cb710117fd7c03ef463dc0de035e18" } } ```