Bài 18: Tương tác với dịch vụ bên ngoài qua webhook
Webhook là một hàm callback dựa trên HTTP mà một dịch vụ bên ngoài gọi để thông báo về một sự kiện, kèm theo một payload dữ liệu. Webhook cho phép các ứng dụng web và dịch vụ khác nhau giao tiếp với nhau.
Một số ví dụ về các dịch vụ gọi webhook bao gồm:
- GitHub, khi một commit được đẩy vào repository
- Dropbox, khi một tài liệu được cập nhật
- WooCommerce, khi một đơn hàng được thêm vào
- Microsoft Teams, để nhận tin nhắn văn bản định dạng phong phú và đăng lên các kênh công khai
- ConvertKit, khi một người đăng ký được kích hoạt
Với Gato GraphQL, chúng ta có thể tạo Persisted Queries hoạt động như webhook:
- Vì Persisted Query được hiển thị dưới URL riêng của nó, nó có thể được sử dụng làm đích cho webhook
- Mỗi Persisted Query có thể xử lý riêng một webhook cụ thể
Trong bài học hướng dẫn này, chúng ta sẽ tạo một Persisted Query để tương tác với ConvertKit.
Xem tài liệu webhook
Bước đầu tiên là đọc tài liệu của trang web và hiểu dữ liệu nào được gửi qua payload.
Phân tích webhook trong ConvertKit, các sự kiện liên quan đến người đăng ký sẽ gửi yêu cầu POST đến URL của chúng ta với một payload JSON như sau:
{
"subscriber": {
"id": 1,
"first_name": "John",
"email_address": "John@example.com",
"state": "active",
"created_at": "2018-02-15T19:40:24.913Z",
"fields": {
"My Custom Field": "Value"
}
}
}Trích xuất dữ liệu từ payload
Vì yêu cầu được gửi qua POST, chúng ta phải trích xuất dữ liệu từ phần thân của yêu cầu HTTP (được hỗ trợ qua tiện ích mở rộng HTTP Request via Schema).
Nếu yêu cầu HTTP được thực hiện qua GET, thì Persisted Query có thể trực tiếp lấy các mục dữ liệu từ các tham số URL.
GraphQL query này lấy phần thân của yêu cầu và chuyển đổi nó thành một đối tượng JSON. Sau đó nó trích xuất các mục "subscriber.first_name" và "subscriber.email_address" từ đối tượng JSON, và xuất chúng dưới dạng các biến động:
query ExtractPayloadData {
body: _httpRequestBody
bodyJSONObject: _strDecodeJSONObject(string: $__body)
subscriberFirstName: _objectProperty(
object: $__bodyJSONObject,
by: { path: "subscriber.first_name" }
)
@export(as: "subscriberFirstName")
subscriberEmail: _objectProperty(
object: $__bodyJSONObject,
by: { path: "subscriber.email_address" }
)
@export(as: "subscriberEmail")
}Tiện ích mở rộng HTTP Request via Schema cho phép chúng ta lấy tất cả dữ liệu yêu cầu HTTP hiện tại, thông qua các trường sau:
_httpRequestBody: Phần thân của yêu cầu HTTP_httpRequestClientHost: Host của client_httpRequestClientIP: Địa chỉ IP của client (hoặcnullnếu máy chủ không được cấu hình đúng)_httpRequestCookie: Giá trị cookie của yêu cầu_httpRequestCookies: Cookie của yêu cầu_httpRequestDomain: Tên miền của URL được yêu cầu_httpRequestFullURL: URL được yêu cầu (bao gồm các tham số query)_httpRequestHasCookie: Yêu cầu có chứa một cookie nhất định không?_httpRequestHasHeader: Yêu cầu có chứa một header nhất định không?_httpRequestHasParam: Yêu cầu có chứa một tham số nhất định không?_httpRequestHeader: Giá trị header của yêu cầu_httpRequestHeaders: Các header của yêu cầu_httpRequestHost: Host của URL được yêu cầu_httpRequestMethod: Phương thức yêu cầu_httpRequestStringParam: Giá trị của một tham số (được truyền qua POST hoặc GET) kiểu?param=value_httpRequestStringListParam: Giá trị của một tham số (được truyền qua POST hoặc GET) kiểu?param[]=value1¶m[]=value2_httpRequestParams: Các tham số được truyền qua POST hoặc qua query URL_httpRequestProtocol: Giao thức của yêu cầu_httpRequestQuery: Chuỗi tham số query_httpRequestReferer: Referer của yêu cầu_httpRequestRequestTime: Dấu thời gian bắt đầu yêu cầu_httpRequestScheme: Scheme của URL được yêu cầu_httpRequestServerIP: Địa chỉ IP của máy chủ_httpRequestURL: URL được yêu cầu (không có tham số query)_httpRequestURLPath: Đường dẫn tuyệt đối (bắt đầu bằng "/") của URL được yêu cầu_httpRequestUserAgent: User agent
Thực hiện một hành động với dữ liệu
Sau khi trích xuất dữ liệu từ payload, chúng ta có thể thực hiện một hành động với nó.
GraphQL query này xử lý sự kiện subscriber.subscriber_unsubscribe, để gửi email đến người đã hủy đăng ký, yêu cầu phản hồi.
query CreateEmailMessage
@depends(on: "ExtractPayloadData")
{
emailMessageTemplate: _strConvertMarkdownToHTML(
text: """
Hey {$subscriberFirstName}, it's sad to let you go!
Please be welcome to complete [this form](https://forms.gle/FpXNromWAsZYC1zB8) and let us know if there is anything we can do better.
Thanks. Hope to see you back!
"""
)
emailMessage: _strReplaceMultiple(
search: ["{$subscriberFirstName}"],
replaceWith: [$subscriberFirstName],
in: $__emailMessageTemplate
)
@export(as: "emailMessage")
}
mutation SendEmail @depends(on: "CreateEmailMessage") {
_sendEmail(
input: {
to: $subscriberEmail
subject: "Would you like to give us feedback on how we can improve?"
messageAs: {
html: $emailMessage
}
}
) {
status
}
}