Webhooks cho Thanh toán (trước đây là Cập nhật trong thời gian thực) là phương thức thiết yếu để thông báo cho bạn về những thay đổi đối với đơn đặt hàng được thực hiện qua dịch vụ Thanh toán trên Facebook trong ứng dụng của bạn. |
Webhooks là một hệ thống dựa trên gói đăng ký giữa Facebook và máy chủ của bạn. Ứng dụng của bạn đăng ký nhận thông tin cập nhật từ Facebook qua điểm cuối HTTPS đã chỉ định. Khi một đơn đặt hàng đã thực hiện trong ứng dụng của bạn được cập nhật, chúng tôi sẽ gửi yêu cầu HTTPS POST
đến điểm cuối đó nhằm thông báo cho máy chủ của bạn về sự thay đổi.
Có 3 trường hợp chính mà thông tin cập nhật sẽ được gửi đến máy chủ nhà phát triển của bạn:
Để đăng ký Webhooks cho Thanh toán, trước tiên, hãy tạo một URL điểm cuối công khai sẽ nhận cả HTTPS GET
để xác minh gói đăng ký và POST
để yêu cầu thay đổi dữ liệu. Cấu trúc của cả hai loại yêu cầu này được mô tả bên dưới. Tiếp theo, hãy thiết lập gói đăng ký đối tượng payment
của ứng dụng. Bạn có 2 cách để thực hiện việc này:
Trong cả hai trường hợp, điểm cuối của bạn sẽ nhận được cùng dữ liệu theo cùng một cách. Hãy xem Máy chủ gọi lại của bạn để biết thêm thông tin về nội dung mà máy chủ sẽ nhận được.
Cách dễ nhất để thiết lập ứng dụng nhằm nhận thông tin cập nhật từ Webhooks là sử dụng bảng điều khiển Thanh toán của Bảng điều khiển ứng dụng. Tìm ứng dụng của bạn trong bảng điều khiển, sau đó nhấp vào tab Payments
. Phần Webhooks sẽ nằm ngay dưới phần Cài đặt của công ty bạn.
Sau đó, màn hình này sẽ liệt kê trạng thái đăng ký của ứng dụng, cho dù đăng ký được thêm qua bảng điều khiển này hay qua API. Từ đây, bạn có thể thay đổi và thử nghiệm URL gọi lại gói đăng ký.
Trong trường "Gọi lại", bạn phải cung cấp điểm cuối máy chủ hợp lệ có thể truy cập công khai. Đây là địa chỉ mà chúng tôi sẽ dùng để xác minh gói đăng ký cũng như gửi thông tin cập nhật. Điểm cuối này cần phản hồi như được mô tả trong Máy chủ gọi lại của bạn.
Cuối cùng, hãy cung cấp "Mã xác minh". Mã này sẽ chỉ được gửi trong giai đoạn đăng ký để xác minh rằng bạn đang thực hiện đăng ký từ một vị trí an toàn. Mã này sẽ không được gửi khi có thông tin cập nhật thông thường từ Webhook.
Bạn phải thử nghiệm cài đặt gọi lại trước khi lưu gói đăng ký. Thao tác này sẽ gửi yêu cầu GET xác minh đến điểm cuối của bạn. Yêu cầu này chứa các thông số hub.mode
, hub.challenge
và hub.verify_token
, đồng thời đảm bảo rằng bạn xử lý chúng đúng cách. Ví dụ: bạn phải đảm bảo điểm cuối sẽ trả về hub.challenge
cho Facebook:
Sau khi nhập chi tiết gói đăng ký, hãy nhớ nhấp vào nút "Lưu thay đổi" ở cuối trang. Chỉnh sửa gói đăng ký là một thao tác đơn giản để sửa đổi nội dung trường, thử nghiệm lại rồi lưu lại mẫu.
Bạn cũng có thể thiết lập và liệt kê gói đăng ký theo lập trình thông qua API Đồ thị. Bạn sẽ cần access token
của ứng dụng. Bạn có thể lấy mã này trong Công cụ tạo mã truy cập hoặc qua điểm cuối /oauth
của API Đồ thị
API Đăng ký có sẵn trên điểm cuối https://graph.facebook.com/[APP_ID]/subscriptions
Với API này, bạn có thể thực hiện 3 tác vụ:
POST
)GET
)Để thiết lập gói đăng ký, hãy gửi POST
kèm theo thông số sau. Lưu ý rằng những thông số này tương ứng với các trường trong mẫu được mô tả ở trên:
object
- Giống như trên, đây là loại đối tượng bạn muốn nhận thông tin cập nhật. Chỉ định payments
.fields
- Danh sách các thuộc tính của loại đối tượng mà bạn muốn nhận thông tin cập nhật về thay đổi. Danh sách này được phân tách bằng dấu phẩy. Chỉ định "hành động" và "tranh chấp".callback_url
- Điểm cuối máy chủ hợp lệ và có thể truy cập công khai.verify_token
- Một chuỗi tùy ý được gửi đến điểm cuối của bạn khi xác minh gói đăng ký.Khi nhận được yêu cầu này, giống với cấu hình mẫu ở trên, chúng tôi sẽ gửi yêu cầu GET
đến điểm cuối gọi lại của bạn để đảm bảo rằng đăng ký hợp lệ và sẵn sàng nhận thông tin cập nhật. Cụ thể, bạn phải đảm bảo điểm cuối của mình trả về hub.challenge
cho Facebook.
Lưu ý rằng mỗi loại đối tượng của ứng dụng chỉ có thể có một gói đăng ký. Vì thế, nếu một gói đăng ký đã tồn tại cho loại đối tượng này thì dữ liệu mới đăng sẽ thay thế bất kỳ dữ liệu hiện có nào.
Việc gửi yêu cầu HTTP GET
đến API Đăng ký sẽ trả về nội dung được mã hóa JSON liệt kê các gói đăng ký của bạn. Ví dụ:
[ { "object": "payments", "callback_url": "https://www.friendsmash.com/rtu.php", "fields": ["actions", "disputes"], "active": true } ]
Bạn có thể sử dụng Trình khám phá đồ thị để thử nghiệm trực tiếp với API này, hãy nhớ sử dụng mã truy cập của ứng dụng.
Máy chủ gọi lại của bạn phải xử lý 2 loại yêu cầu. Hãy đảm bảo rằng máy chủ gọi lại đó nằm trên một URL công khai để chúng tôi có thể gửi thành công những yêu cầu này.
Trước tiên, máy chủ Facebook sẽ tạo một HTTPS GET
đến URL gọi lại của bạn khi bạn cố gắng thêm hoặc sửa đổi gói đăng ký. Một chuỗi truy vấn sẽ được thêm vào URL gọi lại của bạn kèm theo các thông số sau:
Thông số | Mô tả |
---|---|
| Chuỗi " |
| Chuỗi ngẫu nhiên |
| Giá trị |
Trước tiên, điểm cuối này phải xác minh hub.verify_token
. Việc này đảm bảo máy chủ của bạn biết rằng yêu cầu là do Facebook tạo và có liên quan đến gói đăng ký mà bạn vừa đặt cấu hình.
Sau đó, máy chủ sẽ chỉ trả về giá trị hub.challenge
, qua đó xác nhận với Facebook rằng máy chủ này được đặt cấu hình để chấp nhận các lệnh gọi lại và ngăn chặn lỗ hổng từ chối dịch vụ (DDoS).
Lưu ý dành cho nhà phát triển PHP: Trong PHP, các dấu chấm và dấu cách trong tên thông số truy vấn sẽ tự động được chuyển đổi thành dấu gạch chân. Do đó, bạn nên truy cập những thông số này thông qua $_GET['hub_mode']
,$_GET['hub_challenge']
và $_GET['hub_verify_token']
nếu đang ghi điểm cuối gọi lại trong PHP. Hãy xem lưu ý này trong hướng dẫn về ngôn ngữ PHP để biết thêm chi tiết.
Sau khi đăng ký thành công, chúng tôi sẽ tiếp tục gửi HTTPS POST
đến điểm cuối máy chủ của bạn mỗi khi có thay đổi (đối với các trường hoặc kết nối đã chọn). Bạn phải phản hồi yêu cầu này kèm theo mã HTTP 200
.
Lưu ý - chúng tôi xem bất kỳ phản hồi HTTP nào không phải 200
đều là lỗi. Trong những trường hợp này, chúng tôi sẽ tiếp tục thử gửi lại thông tin cập nhật từ webhook. Do đó, nếu không phản hồi đúng, bạn có thể nhận được cùng một thông tin cập nhật nhiều lần.
Yêu cầu sẽ có loại nội dung là application/json
và phần nội dung sẽ bao gồm chuỗi được mã hóa JSON chứa một hoặc nhiều thay đổi.
Lưu ý dành cho nhà phát triển PHP: Trong PHP, để nhận dữ liệu được mã hóa, bạn cần sử dụng mã sau:
$data = file_get_contents("php://input"); $json = json_decode($data);`
Lưu ý rằng bạn không thể gửi lại các thông số hub.mode
, hub.challenge
và hub.verify_token
sau khi gói đăng ký được xác nhận.
Dưới đây là ví dụ điển hình về lệnh gọi lại được tạo cho gói đăng ký đối tượng payments
:
{ "object": "payments", "entry": [ { "id": "296989303750203", "time": 1347996346, "changed_fields": [ "actions" ] } ] }
Cần lưu ý rằng thông tin cập nhật từ Webhook chỉ thông báo cho bạn về một khoản thanh toán cụ thể - được xác định bằng trường id
- đã được thay đổi. Sau khi nhận được thông tin cập nhật, bạn sẽ phải truy vấn API Đồ thị để biết chi tiết về giao dịch, nhằm xử lý thay đổi theo cách phù hợp.
Lưu ý - Mặc dù Webhooks cho các loại đối tượng khác có thể được tạo theo lô nhưng thông tin cập nhật về thanh toán sẽ không bao giờ được tạo theo lô.
Bạn chắc chắn sẽ nhận được thông tin cập nhật mới mỗi khi một giao dịch được cập nhật do hành động của người dùng hoặc hành động của nhà phát triển.
Nếu không gửi được thông tin cập nhật đến máy chủ của bạn, chúng tôi sẽ thử lại ngay rồi thử lại thêm vài lần nữa với tần suất giảm dần trong 24 giờ tiếp theo.
Với mọi yêu cầu, chúng tôi sẽ gửi tiêu đề HTTP X-Hub-Signature-256
chứa chữ ký SHA256 của phần tải dữ liệu yêu cầu bằng cách sử dụng khóa bí mật của ứng dụng làm khóa và có tiền tố là sha256=
. Điểm cuối gọi lại của bạn có thể xác minh chữ ký này để xác thực tính toàn vẹn và nguồn gốc của phần tải dữ liệu.
Sau khi máy chủ của bạn nhận được thông tin cập nhật, bạn cần truy vấn API Đồ thị bằng cách sử dụng trường id
để biết chi tiết về trạng thái mới của giao dịch. Sau đó, bạn cần thực hiện hành động tùy thuộc vào trạng thái.
Những phần sau liệt kê tất cả các thay đổi trạng thái có thể kích hoạt quá trình gửi thông tin cập nhật. Những thay đổi này nhìn chung được chia thành:
Mỗi đối tượng payment
chứa một mảng có tên là actions
. Mảng này chứa tập hợp các thay đổi trạng thái mà giao dịch đã trải qua. Mỗi mục nhập trong mảng actions
chứa thuộc tính có tên là type
mô tả loại hành động đã diễn ra. type
có thể có các giá trị sau: charge
, refund
,chargeback
, chargeback_reversal
và decline
- được giải thích đầy đủ tại đây.
Dưới đây là phản hồi mẫu từ API Đồ thị cho đối tượng thanh toán có các hành động được liên kết:
{ "id": "3603105474213890", "user": { "name": "Marco Alvarez", "id": "500535225" }, "application": { "name": "Friend Smash", "namespace": "friendsmashsample", "id": "241431489326925" }, "actions": [ { "type": "charge", "status": "completed", "currency": "USD", "amount": "0.99", "time_created": "2013-03-22T21:18:54+0000", "time_updated": "2013-03-22T21:18:55+0000" }, { "type": "refund", "status": "completed", "currency": "USD", "amount": "0.99", "time_created": "2013-03-23T21:18:54+0000", "time_updated": "2013-03-23T21:18:55+0000" } ], "refundable_amount": { "currency": "USD", "amount": "0.00" }, "items": [ { "type": "IN_APP_PURCHASE", "product": "https://www.friendsmash.com/og/friend_smash_bomb.html", "quantity": 1 } ], "country": "US", "created_time": "2013-03-22T21:18:54+0000", "payout_foreign_exchange_rate": 1,}`
Vì bạn đăng ký trường hành động khi đăng ký Webhooks, chúng tôi sẽ gửi thông tin cập nhật khi mảng này thay đổi như sau:
Ban đầu, tất cả các đơn đặt hàng đều chứa mục nhập phí có "status": "initiated"
. Khoản thanh toán đã bắt đầu biểu thị khoản thanh toán chỉ được tạo và chưa hoàn thành đầy đủ. Chúng tôi sẽ không gửi thông tin cập nhật về các khoản thanh toán ở trạng thái đã bắt đầu.
Khi hoàn tất thanh toán thành công, "status": "initiated"
sẽ được thay đổi thành "status": "completed"
và chúng tôi sẽ gửi thông tin cập nhật. Khi nhìn thấy thay đổi này, bạn nên kiểm tra hồ sơ thanh toán để xác minh xem đây là giao dịch mới hay cũ và phản hồi như sau:
initiated
thì bạn có thể tiếp tục thực hiện đơn đặt hàng, qua đó gửi mặt hàng hoặc đơn vị tiền tệ ảo được liên kết cho người tiêu dùng. Sau đó, bạn có thể yên tâm đánh dấu khoản thanh toán này là hoàn tất.Bạn cũng sẽ nhận được thông tin cập nhật về khoản thanh toán có "status": "failed"
. Những khoản thanh toán này sẽ không được thực hiện.
Mỗi khi hoàn tiền qua API Đồ thị, bạn sẽ nhận được thông tin cập nhật. Giống như với "type": "charge"
, quá trình hoàn tiền cũng có thể có trạng thái khác nhau mà bạn phải biết. Đáng chú ý nhất là quá trình hoàn tiền có thể không thực hiện được - thường là do lỗi kết nối hoặc xử lý - trong trường hợp này, bạn nên thử lại quá trình hoàn tiền.
Giống với tiền hoàn lại, bạn cũng sẽ nhận được thông báo khi có yêu cầu hoàn tiền, từ chối hoặc hủy bỏ yêu cầu hoàn tiền. Đối tượng yêu cầu hoàn tiền, từ chối hoặc hủy bỏ yêu cầu hoàn tiền sẽ được thêm vào mảng hành động của dữ liệu trả về API Đồ thị cho khoản thanh toán.
Chúng tôi sẽ thông báo cho bạn bằng cách gửi thông tin cập nhật khi có tranh chấp. Trong trường hợp này, bạn sẽ thấy mảng "disputes"
mới xuất hiện như là một phần của đối tượng payment
. Mảng này sẽ chứa thời gian phát sinh tranh chấp, lý do mà người tiêu dùng đưa ra trong phản hồi và địa chỉ email của người tiêu dùng. Bạn có thể dùng những thông tin này để liên hệ trực tiếp với người tiêu dùng nhằm giải quyết tranh chấp.
Dưới đây là phản hồi mẫu đầy đủ từ API Đồ thị cho giao dịch có tranh chấp:
{ "id": "990361254213890", "user": { "name": "Marco Alvarez", "id": "500535225" }, "application": { "name": "Friend Smash", "namespace": "friendsmashsample", "id": "241431489326925" }, "actions": [ { "type": "charge", "status": "completed", "currency": "USD", "amount": "0.99", "time_created": "2013-03-22T21:18:54+0000", "time_updated": "2013-03-22T21:18:55+0000" } ], "refundable_amount": { "currency": "USD", "amount": "0.99" }, "items": [ { "type": "IN_APP_PURCHASE", "product": "https://www.friendsmash.com/og/friend_smash_bomb.html", "quantity": 1 } ], "country": "US", "created_time": "2013-03-22T21:18:54+0000", "payout_foreign_exchange_rate": 1, "disputes": [ { "user_comment": "I didn't receive my item! I want a refund, please!", "time_created": "2013-03-24T18:21:02+0000", "user_email": "email\u0040domain.com", "status": "resolved", "reason": "refunded_in_cash" } ] }
Để biết thêm thông tin về cách phản hồi tranh chấp và tiến hành hoàn tiền, vui lòng xem Hướng dẫn về thanh toán: Xử lý tranh chấp và hoàn tiền.