付款專用 Webhooks(前稱「即時更新」)是一種很重要的方法,我們會透過這種方式通知您應用程式內 Facebook 付款發生的訂單變更。 |
Webhooks 是 Facebook 與您伺服器之間的訂閱式系統。訂閱後,您的應用程式會透過指定 HTTPS 端點接收來自 Facebook 的更新項目。如果您應用程式內的訂單有所更新,我們就會向該端點發出 HTTPS POST
要求,以通知您的伺服器相關變更項目。
在以下 3 種主要情況下,我們會將更新項目傳送到您的開發人員伺服器:
如要訂閱付款 Webhooks,請先建立公開端點網址以接收 HTTPS GET
及 POST
,分別用於訂閱驗證和變更資料要求。有關這兩種要求類型的結構,請見下文說明。然後,設定訂閱應用程式的 payment
物件。如要執行此操作,可以採用以下 2 種方式:
無論採用哪種方式,您的端點都會以相同方式收到相同的資料。請查看回呼伺服器部分,進一步了解您伺服器會收到的內容。
如要設定應用程式以接收 Webhooks 更新資訊,最簡單的方法就是使用應用程式管理中心的「付款」面板。在管理中心找出應用程式,然後點擊 Payments
分頁。「Webhooks」區塊位於公司「設定」區塊的正下方。
然後,這個畫面會列出應用程式的訂閱狀態,供您了解此為透過此面板加入還是透過 API 加入。您可以在此變更訂閱回呼網址並對其進行測試。
在「回呼」欄位中,您必須提供有效且可公開存取的伺服器端點。這是我們用來驗證訂閱與傳送更新的網址,而此網址需要以回呼伺服器部分中所述的方式作出回應。
最後,請提供「驗證憑證」。這個憑證只會在註冊階段時傳送,用來驗證訂閱是否來源於安全的地點。此憑證不會透過一般 Webhook 更新項目傳送。
儲存訂閱前,請先測試回呼設定。此操作會向您的端點傳送驗證 GET 要求,其中包含 hub.mode
、hub.challenge
及 hub.verify_token
參數,並確保您以正確方式完成處理。舉例來說,您必須確保端點會向 Facebook 回應 hub.challenge
:
輸入訂閱詳情後,請記得點擊頁面下方的「儲存變更」按鈕。編輯訂閱相當簡單,只需修改欄位內容、重新測試,然後再次儲存表格即可。
您也可以透過 Graph API 設定訂閱,並以程式輔助方式列出訂閱清單。您需要應用程式的 access token
,此憑證可透過存取憑證工具或使用 Graph API 的 /oauth
端點取得
訂閱 API 可從 https://graph.facebook.com/[APP_ID]/subscriptions
端點取得
您可以透過此 API 執行 3 種任務:
POST
要求)GET
要求)如要設定訂閱,請傳送包含以下參數的 POST
。請注意,這些參數對應上述表格中的欄位:
object
:如上所述,此為您想接收相關更新的物件類型。指定 payments
。fields
:逗號分隔清單,其中列出您想接收相關變更更新通知的物件類型屬性。指定「actions」及「disputes」。callback_url
:有效且可公開存取的伺服器端點。verify_token
:在訂閱經驗證後向您端點傳送的任何字串。我們接收到這個要求及上述表格配置後,便會向您的回呼執行 GET
,以確保回呼有效且已準備好接收更新項目。請特別留意,您必須確保端點會向 Facebook 回應 hub.challenge
。
請注意,應用程式每一種物件類型只能有一個訂閱,因此如果這種物件類型已有訂閱存在,新發佈的資料便將取代現有的所有資料。
如果向訂閱 API 傳送 HTTP GET
,系統將會傳回 JSON 編碼內容,當中列有您的訂閱。例如:
[ { "object": "payments", "callback_url": "https://www.friendsmash.com/rtu.php", "fields": ["actions", "disputes"], "active": true } ]
您的回呼伺服器必須處理 2 類要求。請確保回呼伺服器位於公開網址,這樣我們才能成功發出這些要求。
首先,當您嘗試新增或修改訂閱時,Facebook 伺服器會向您的回呼網址發出單獨的 HTTPS GET
。查詢字串會連同以下參數一同附加至回呼網址:
參數 | 說明 |
---|---|
| 「 |
| 隨機字串 |
| 您在建立訂閱時指定的 |
端點應先驗證 hub.verify_token
,以確保您的伺服器知道此要求是由 Facebook 發出,且與您剛才配置的訂閱有關。
然後,伺服器應只回應 hub.challenge
值,以向 Facebook 確認此伺服器已配置為可接收回呼,並預防出現阻斷服務攻擊 (DDoS) 漏洞。
PHP 開發人員注意事項:在 PHP 中,查詢參數名稱中的圓點和空格會自動轉換為底線。因此,如果您在 PHP 中撰寫回呼端點,應該使用 $_GET['hub_mode']
、$_GET['hub_challenge']
和 $_GET['hub_verify_token']
來存取這些參數。如要了解詳情,請參閱 PHP 語言手冊中的注意事項。
訂閱成功後,當您所選欄位或連結有所變更,我們就會向您的伺服器端點傳送 HTTPS POST
。您必須以 HTTP 代碼 200
回應此要求。
注意:我們會將 200
以外的所有 HTTP 回應視為錯誤。在這些情況下,我們會繼續重新嘗試傳送 Webhooks 更新。如果您仍未以正確方式作出回應,就可能會多次收到相同的更新。
要求會是 application/json
內容類型,其正文由 JSON 編碼字串組成,當中包含一個或多個變更項目。
PHP 開發人員注意事項:在 PHP 中,如要取得已編碼的資料,需要使用以下代碼:
$data = file_get_contents("php://input"); $json = json_decode($data);`
請注意,一旦確認訂閱,系統不會再次傳送 hub.mode
、hub.challenge
及 hub.verify_token
參數。
以下為向 payments
物件訂閱執行回呼的常見範例:
{ "object": "payments", "entry": [ { "id": "296989303750203", "time": 1347996346, "changed_fields": [ "actions" ] } ] }
請特別注意,Webhooks 更新只會通知您某個特定付款(由 id
欄位識別)有所變更。收到更新後,您接下來需要查詢 Graph API 以了解交易詳情,以妥善處理變更。
注意:其他物件類型的 Webhooks 可作批次處理,但付款更新項目絕對無法作批次處理。
我們可確保每當交易有所更新時,您都一定會收到新的更新項目,無論更新是由用戶還是開發人員操作也是如此。
如果更新無法送至您的伺服器,我們將立即重試,然後在接下來的 24 小時內再重試幾次,但重試頻率會下降。
在每個要求中,我們都會以應用程式密鑰作為密鑰來傳送 X-Hub-Signature-256
HTTP 頁首,其中包含要求裝載的 SHA256 簽章,首碼為 sha256=
。回呼端點可以驗證此簽章,從而驗證裝載的完整性及來源。
伺服器收到更新後,您應該使用 id
欄位查詢 Graph API,以了解交易新狀態的詳情。然後,您應根據狀態採取相應行動。
以下部分列出了所有會觸發傳送更新項目的狀態變更項目,大致可分為兩類:
每個 payment
物件都包含一個名為 actions
的陣列,其中包含一系列交易已處理完的狀態變更項目。actions
陣列中的每個條目都有一個名為 type
的屬性,用於說明已發生的動作之類型。type
可以是以下的值:charge
、refund
、chargeback
、chargeback_reversal
及 decline
(詳見此處)。
以下為 Graph API 連同相關動作對付款物件發出的回應範例:
{ "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,}`
由於您在註冊 Webhook 時已訂閱動作欄位,因此當陣列發生以下變更時,我們會發出更新:
一開始,所有訂單都包含一個帶有 "status": "initiated"
的收費條目。「已發起的付款」表示付款只是有人發起,尚未完成。我們不會為處於「已發起」狀態的付款傳送更新。
成功完成付款後,"status": "initiated"
會變更為 "status": "completed"
,我們會為此傳送更新。看見此變更項目後,您應該查看付款記錄,以確認此為新交易還是現有的交易,並按以下方式作出回應:
initiated
狀態,則您可以繼續完成訂單,並向消費者傳送相關虛擬商品或貨幣。之後,此次付款可順利被標記為完成。此外,您亦會收到付款為 "status": "failed"
的更新。請勿完成此類訂單。
每當您透過 Graph API 發起退款,就會收到更新。與 "type": "charge"
一樣,退款也有不同狀態,需要多加注意。其中最重要的一點就是,退款可能會失敗,這通常是處理或連線出錯所致。如果發生這種情況,您應重新發起退款。
與退款一樣,如有買家要求退款、取消退款與拒絕退款,您也會收到通知。買家要求退款、取消退款與拒絕退款物件會新增至 Graph API 付款傳回資料中的動作陣列。
如有發起異議,我們會傳送更新項目通知您。在這種情況下,您會看到 payment
物件中出現新的 "disputes"
陣列。此陣列會包含發起異議的時間、消費者提出回應的原因,以及消費者的電郵地址,以便您透過此電郵地址直接聯絡消費者解決異議。
以下為 Graph API 對有異議交易發出的完整回應範例:
{ "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" } ] }
如需進一步了解如何回應異議及發起退款,請參閱付款操作說明:處理異議和退款。