{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-@l10n/zh-CN/develop/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Webhook 回调","description":"YouCam API documentation by Perfect Corp. Learn how to use Skin analysis API, Virtual try-on API, Image editing API, and Video generative AI APIs.","siteUrl":"https://docs.perfectcorp.com","keywords":"AI Skin Analysis, AI Clothes, AI Hairstyle, AI Outfits","image":"/assets/favicon.cd6fa4d833b2a573b3c6dae68386b293da205b203402cb0c97b80bd2acc07ea2.8351e24f.png"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"webhook-回调","__idx":0},"children":["Webhook 回调"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Webhook 让您可以异步收到通知：AI 任务跑完，状态是 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["success"]}," 还是 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error"]},"，都会推送给您指定的 HTTP 端点。通知遵循 ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://github.com/standard-webhooks/standard-webhooks/blob/main/spec/standard-webhooks.md"},"children":["Standard Webhooks 规范"]},"。"]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"webhook-密钥","__idx":1},"children":["Webhook 密钥"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"webhook-密钥是怎么构成的","__idx":2},"children":["Webhook 密钥是怎么构成的"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["我们采用 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["HMAC-SHA256"]}," 签名方案的 webhook 密钥。密钥经 base64 编码，并加上 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["whsec_"]}," 前缀，方便一眼认出。"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["webhook 密钥示例："]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["whsec_NDQzMzYxNzkzMzE0NjYyNDM6OTIxOTcwNDIxODQ"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"用-standard-webhooks-官方库实现-webhook","__idx":3},"children":["用 Standard Webhooks 官方库实现 Webhook"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["我们强烈建议使用 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Standard Webhooks Library"]}," 的官方实现，签名校验的细节就不用您操心了。"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["用官方实现还能保证签名校验既安全又正确。"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://github.com/standard-webhooks/standard-webhooks/tree/main?tab=readme-ov-file#reference-implementations"},"children":["https://github.com/standard-webhooks/standard-webhooks/tree/main?tab=readme-ov-file#reference-implementations"]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"自己实现-webhook","__idx":4},"children":["自己实现 Webhook"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["请先弄懂 webhook 密钥的构成，参见",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://github.com/standard-webhooks/standard-webhooks/blob/main/spec/standard-webhooks.md#signature-scheme"},"children":["签名方案"]},"中的对称密钥部分。"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["给签名输入内容做签名时，请去掉 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["whsec_"]}," 前缀，再把剩下的字符串做 base64 解码，得到密钥的真实字节，用它来做 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["HMAC-SHA256"]}," 哈希。"]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"webhook-请求示例","__idx":5},"children":["Webhook 请求示例"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"http","header":{"controls":{"copy":{}}},"source":"POST https://yourdomain.com/webhook-endpoint\nContent-Type: application/json\nwebhook-id: msg_1eWPv9cWJCnEP99UJncmVJ6KjK_xVXRhZPe_eSGnRNbLlXEPjiG3gb3Usg9le3_4:1761112848\nwebhook-timestamp: 1761112900\nwebhook-signature: v1,vyVNWrjoZcBK1JXrFGkdDKK2slo5+Q5yfzpkHmqO5R0=\n","lang":"http"},"children":[]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"created_at\": 1761112848,\n  \"data\": {\n    \"task_id\": \"1eWPv9cWJCnEP99UJncmVJ6KjK_xVXRhZPe_eSGnRNbLlXEPjiG3gb3Usg9le3_4\",\n    \"task_status\": \"success\"\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"http-请求头","__idx":6},"children":["HTTP 请求头"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"webhook-id","__idx":7},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["webhook-id"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["这次 webhook 投递的唯一标识。"," ","重试时这个值保持不变，可以拿来做幂等处理。"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"webhook-timestamp","__idx":8},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["webhook-timestamp"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["webhook 发出时的 Unix 时间戳（秒）。"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"webhook-signature","__idx":9},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["webhook-signature"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["'v1'，一个逗号（,），再跟上 base64 编码后的 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["HMAC-SHA256"]}," 签名。"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["'v1' 表示签名方案的版本，目前只支持这一个版本。"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["base64 编码后的 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["HMAC-SHA256"]}," 签名，是用您的 webhook 密钥对签名输入内容签名后的结果。"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["签名输入的格式："]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"{webhook-id}.{webhook-timestamp}.{raw-minified-json-body}\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["签名内容示例："]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"msg_1eWPv9cWJCnEP99UJncmVJ6KjK_xVXRhZPe_eSGnRNbLlXEPjiG3gb3Usg9le3_4:1761112848.1761112900.{\"created_at\":1761112848,\"data\":{\"task_id\":\"1eWPv9cWJCnEP99UJncmVJ6KjK_xVXRhZPe_eSGnRNbLlXEPjiG3gb3Usg9le3_4\",\"task_status\":\"success\"}}\n"},"children":[]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"请求体","__idx":10},"children":["请求体"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"created_at","__idx":11},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["created_at"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Unix 时间戳（秒），表示任务完成的时间。"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"data","__idx":12},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["事件的具体内容。"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"字段"},"children":["字段"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"说明"},"children":["说明"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["task_id"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["创建任务时返回的任务标识。用它查询任务的最终结果。"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["task_status"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["任务完成状态。取值有：",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["success"]},"、",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error"]},"。"]}]}]}]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"集成指南","__idx":13},"children":["集成指南"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"webhook-集成指南","__idx":14},"children":["Webhook 集成指南"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["在您的服务器上准备好一个 webhook 接收端点。"]}," ","该端点要能接受 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST"]}," 请求，并且可以通过 HTTPS 访问。"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["在 API 控制台里创建一个 webhook。"]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["跑一个 AI 任务，记下 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["task_id"]},"。"]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["处理 webhook 通知，用 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["task_id"]}," 取回任务结果。"]}]}]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"创建-webhook-接收端点","__idx":15},"children":["创建 Webhook 接收端点"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["进入 API 控制台的 Webhook 管理页："]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://yce.makeupar.com/api-console/en/webhook/"},"children":["https://yce.makeupar.com/api-console/en/webhook/"]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"1-找到-webhook-区块","__idx":16},"children":["1. 找到 Webhook 区块"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"img","attributes":{"src":"https://bcw-media.s3.ap-northeast-1.amazonaws.com/strapi/assets/webhook_main_bae171663b.png","alt":""},"children":[]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"2-新建一个-webhook-接收端点","__idx":17},"children":["2. 新建一个 Webhook 接收端点"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"img","attributes":{"src":"https://bcw-media.s3.ap-northeast-1.amazonaws.com/strapi/assets/webhook_create_cd28e68fa3.png","alt":""},"children":[]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["最多可以同时配置 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["10 个 webhook 接收端点"]},"。"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"3-保管好您的-webhook-密钥","__idx":18},"children":["3. 保管好您的 Webhook 密钥"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["webhook 密钥用来校验 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["webhook-signature"]},"。"," ","请务必妥善保存，切勿公开外泄。"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"img","attributes":{"src":"https://bcw-media.s3.ap-northeast-1.amazonaws.com/strapi/assets/webhook_secret_key_6fe757a7de.png","alt":""},"children":[]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"4-管理已有的-webhook","__idx":19},"children":["4. 管理已有的 Webhook"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"img","attributes":{"src":"https://bcw-media.s3.ap-northeast-1.amazonaws.com/strapi/assets/webhook_manage_endpoints_3bed715de9.png","alt":""},"children":[]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"验证签名","__idx":20},"children":["验证签名"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"在服务器上处理-webhook-请求","__idx":21},"children":["在服务器上处理 Webhook 请求"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["我们建议使用 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Standard Webhooks Library"]}," 的官方实现："]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://github.com/standard-webhooks/standard-webhooks/tree/main?tab=readme-ov-file#reference-implementations"},"children":["https://github.com/standard-webhooks/standard-webhooks/tree/main?tab=readme-ov-file#reference-implementations"]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["这样能保证签名校验既安全又正确。"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["您也可以用 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Standard Webhooks Simulator"]}," 来测试或调试推送内容："]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.standardwebhooks.com/simulate"},"children":["https://www.standardwebhooks.com/simulate"]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"校验-webhook-签名","__idx":22},"children":["校验 Webhook 签名"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["来看这个 webhook 请求示例："]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"http","header":{"controls":{"copy":{}}},"source":"POST https://yourdomain.com/webhook-endpoint\nContent-Type: application/json\nwebhook-id: msg_1eWPv9cWJCnEP99UJncmVJ6KjK_xVXRhZPe_eSGnRNbLlXEPjiG3gb3Usg9le3_4:1761112848\nwebhook-timestamp: 1761112900\nwebhook-signature: v1,vyVNWrjoZcBK1JXrFGkdDKK2slo5+Q5yfzpkHmqO5R0=\n","lang":"http"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["请求体："]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"created_at\": 1761112848,\n  \"data\": {\n    \"task_id\": \"1eWPv9cWJCnEP99UJncmVJ6KjK_xVXRhZPe_eSGnRNbLlXEPjiG3gb3Usg9le3_4\",\n    \"task_status\": \"success\"\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["签名输入格式如下："]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"{webhook-id}.{webhook-timestamp}.{raw-minified-json-body}\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["签名内容示例："]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"msg_1eWPv9cWJCnEP99UJncmVJ6KjK_xVXRhZPe_eSGnRNbLlXEPjiG3gb3Usg9le3_4:1761112848.1761112900.{\"created_at\":1761112848,\"data\":{\"task_id\":\"1eWPv9cWJCnEP99UJncmVJ6KjK_xVXRhZPe_eSGnRNbLlXEPjiG3gb3Usg9le3_4\",\"task_status\":\"success\"}}\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["用您的 webhook 密钥，对签名内容做 HMAC-SHA256 运算，再与收到的 webhook-signature 比对。"," ","示例："]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"v1,vyVNWrjoZcBK1JXrFGkdDKK2slo5+Q5yfzpkHmqO5R0=\n"},"children":[]}]},"headings":[{"value":"Webhook 回调","id":"webhook-回调","depth":1},{"value":"Webhook 密钥","id":"webhook-密钥","depth":4},{"value":"Webhook 密钥是怎么构成的","id":"webhook-密钥是怎么构成的","depth":5},{"value":"用 Standard Webhooks 官方库实现 Webhook","id":"用-standard-webhooks-官方库实现-webhook","depth":5},{"value":"自己实现 Webhook","id":"自己实现-webhook","depth":5},{"value":"Webhook 请求示例","id":"webhook-请求示例","depth":4},{"value":"HTTP 请求头","id":"http-请求头","depth":4},{"value":"webhook-id","id":"webhook-id","depth":5},{"value":"webhook-timestamp","id":"webhook-timestamp","depth":5},{"value":"webhook-signature","id":"webhook-signature","depth":5},{"value":"请求体","id":"请求体","depth":4},{"value":"created_at","id":"created_at","depth":5},{"value":"data","id":"data","depth":5},{"value":"集成指南","id":"集成指南","depth":2},{"value":"Webhook 集成指南","id":"webhook-集成指南","depth":3},{"value":"创建 Webhook 接收端点","id":"创建-webhook-接收端点","depth":4},{"value":"1. 找到 Webhook 区块","id":"1-找到-webhook-区块","depth":5},{"value":"2. 新建一个 Webhook 接收端点","id":"2-新建一个-webhook-接收端点","depth":5},{"value":"3. 保管好您的 Webhook 密钥","id":"3-保管好您的-webhook-密钥","depth":5},{"value":"4. 管理已有的 Webhook","id":"4-管理已有的-webhook","depth":5},{"value":"验证签名","id":"验证签名","depth":2},{"value":"在服务器上处理 Webhook 请求","id":"在服务器上处理-webhook-请求","depth":4},{"value":"校验 Webhook 签名","id":"校验-webhook-签名","depth":4}],"frontmatter":{"seo":{"title":"Webhook 回调"}},"lastModified":"2026-10-30T07:26:32.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/zh-cn/develop/webhook","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}