Webhooks สำหรับการชำระเงิน (เดิมเรียกว่า "การอัพเดตแบบเรียลไทม์") เป็นวิธีการสำคัญที่จะแจ้งให้คุณทราบถึงการเปลี่ยนแปลงในคำสั่งซื้อที่ดำเนินการผ่านการชำระเงินบน Facebook ภายในแอพของคุณ |
Webhooks เป็นระบบที่อิงตามการสมัครรับข้อมูลระหว่าง Facebook กับเซิร์ฟเวอร์ของคุณ ซึ่งแอพของคุณจะสมัครรับข้อมูลอัพเดตต่างๆ จาก Facebook ผ่านตำแหน่งข้อมูล HTTPS ที่ระบุ เมื่อคำสั่งซื้อในแอพมีการอัพเดต เราจะออกคำขอ HTTPS POST
ให้กับตำแหน่งข้อมูลดังกล่าว โดยแจ้งให้เซิร์ฟเวอร์ของคุณทราบถึงการเปลี่ยนแปลง
ระบบจะส่งการอัพเดตไปยังเซิร์ฟเวอร์ของผู้พัฒนาใน 3 สถานการณ์หลักต่อไปนี้
หากต้องการสมัครรับข้อมูล Webhooks สำหรับการชำระเงิน อันดับแรกให้สร้าง URL ตำแหน่งข้อมูลเป็นแบบสาธารณะที่รับทั้ง HTTPS GET
สำหรับการตรวจสอบยืนยันการสมัครรับข้อมูล และ POST
สำหรับคำขอข้อมูลการเปลี่ยนแปลง ซึ่งโครงสร้างของคำขอทั้ง 2 ประเภทนี้มีคำอธิบายที่ด้านล่าง จากนั้น ตั้งค่าการสมัครรับข้อมูลให้กับอ็อบเจ็กต์ payment
ในแอพของคุณ โดยสามารถทำได้ 2 วิธี ดังนี้
ซึ่งไม่ว่าจะเป็นกรณีใด ตำแหน่งข้อมูลของคุณก็จะได้รับข้อมูลเดียวกันนี้ในรูปแบบเดียวกัน โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่เซิร์ฟเวอร์ของคุณจะได้รับที่เซิร์ฟเวอร์การเรียกกลับของคุณ
วิธีที่ง่ายที่สุดในการตั้งค่าแอพเพื่อรับการอัพเดต Webhooks คือการใช้แผงการชำระเงินในแดชบอร์ดของแอพ โดยค้นหาแอพของคุณในแดชบอร์ด แล้วคลิกที่แท็บ Payments
ซึ่งส่วนของ Webhooks จะอยู่ถัดจากส่วน "การตั้งค่า" ของบริษัทลงไปด้านล่าง
จากนั้น หน้าจอนี้จะแสดงรายการสถานะการสมัครรับข้อมูลของแอพ ไม่ว่าคุณจะเพิ่มการสมัครรับข้อมูลนั้นผ่านแผงนี้หรือผ่าน API ก็ตาม จากตรงนี้ คุณสามารถเปลี่ยนแปลง URL การเรียกกลับของการสมัครรับข้อมูลและทดสอบ URL ดังกล่าวได้
ในช่อง "การเรียกกลับ" คุณต้องระบุตำแหน่งข้อมูลของเซิร์ฟเวอร์ที่เข้าถึงได้แบบสาธารณะและถูกต้อง นี่คือที่อยู่ที่เราจะใช้ตรวจสอบยืนยันการสมัครรับข้อมูลและส่งการอัพเดต และจำเป็นต้องตอบกลับตามที่อธิบายไว้ในเซิร์ฟเวอร์การเรียกกลับของคุณ
ขั้นตอนสุดท้าย ให้ระบุ "โทเค็นการตรวจสอบยืนยัน" โดยระบบจะส่งโทเค็นนี้เฉพาะในระหว่างช่วงการลงทะเบียน เพื่อตรวจสอบยืนยันว่าการสมัครรับข้อมูลมาจากตำแหน่งที่ปลอดภัยเท่านั้น ซึ่งระบบจะไม่ส่งโทเค็นนี้ในการอัพเดต Webhook ตามปกติ
คุณควรทดสอบการตั้งค่าการเรียกกลับก่อนที่จะบันทึกการสมัครรับข้อมูล ซึ่งระบบจะออกคำขอ GET การตรวจสอบยืนยันให้กับตำแหน่งข้อมูลของคุณ โดยจะประกอบด้วยพารามิเตอร์ hub.mode
, hub.challenge
และ hub.verify_token
และจะรับรองว่าคุณได้จัดการอย่างถูกต้องแล้ว ตัวอย่างเช่น คุณต้องแน่ใจได้ว่าตำแหน่งข้อมูลของคุณสะท้อน hub.challenge
กลับมาที่ Facebook
เมื่อคุณป้อนรายละเอียดการสมัครรับข้อมูลแล้ว โปรดตรวจสอบให้แน่ใจว่าคุณได้คลิกปุ่ม "บันทึกการเปลี่ยนแปลง" ที่ด้านล่างของหน้าแล้ว ส่วนการแก้ไขการสมัครรับข้อมูลก็สามารถทำได้ง่ายๆ เพียงปรับเปลี่ยนเนื้อหาในช่อง ทดสอบซ้ำ และบันทึกแบบฟอร์มอีกครั้ง
นอกจากนี้คุณยังสามารถตั้งค่าและลงรายการการสมัครรับข้อมูลด้วยโปรแกรมผ่าน API กราฟได้อีกด้วย โดยคุณจะต้องมี access token
ของแอพ ซึ่งจะพร้อมใช้งานจากเครื่องมือสร้างโทเค็นการเข้าถึง หรือโดยการใช้ตำแหน่งข้อมูล /oauth
ของ API กราฟ
API การสมัครรับข้อมูลมีให้ใช้งานที่ตำแหน่งข้อมูล https://graph.facebook.com/[APP_ID]/subscriptions
ซึ่งคุณสามารถใช้ในการทำงาน 3 อย่างต่อไปนี้
POST
)GET
)ในการตั้งค่าการสมัครรับข้อมูล ให้ส่ง POST
พร้อมพารามิเตอร์ต่อไปนี้ โปรดทราบว่าพารามิเตอร์เหล่านี้จะสอดคล้องกับช่องต่างๆ ในแบบฟอร์มที่อธิบายไว้ข้างต้น ดังนี้
object
- ประเภทอ็อบเจ็กต์ที่คุณต้องการรับข้อมูลอัพเดตดังที่ระบุไว้ข้างต้น ให้ระบุ payments
fields
- รายการคุณสมบัติของประเภทอ็อบเจ็กต์ที่คั่นด้วยเครื่องหมายจุลภาคที่คุณต้องการรับข้อมูลอัพเดตเกี่ยวกับการเปลี่ยนแปลง ให้ระบุ "actions" และ "disputes"callback_url
- ตำแหน่งข้อมูลของเซิร์ฟเวอร์ที่เข้าถึงได้แบบสาธารณะและถูกต้องverify_token
- สตริงแบบกำหนดเองซึ่งส่งไปยังตำแหน่งข้อมูลของคุณเมื่อมีการตรวจสอบยืนยันการสมัครรับข้อมูลเมื่อเราได้รับคำขอนี้ เราจะดำเนินการ GET
ไปที่การเรียกกลับของคุณเช่นเดียวกับการกำหนดค่าแบบฟอร์มข้างต้น เพื่อให้แน่ใจว่าคำขอนั้นถูกต้องและพร้อมรับการอัพเดต โดยเฉพาะอย่างยิ่ง คุณต้องแน่ใจได้ว่าตำแหน่งข้อมูลของคุณสะท้อน hub.challenge
กลับมาที่ Facebook
โปรดทราบว่า เนื่องจากแอพหนึ่งๆ สามารถมีการสมัครรับข้อมูลอ็อบเจ็กต์แต่ละประเภทได้เพียง 1 รายการ หากมีการสมัครรับข้อมูลอ็อบเจ็กต์ประเภทนี้อยู่แล้ว ข้อมูลที่โพสต์ใหม่จะแทนที่ข้อมูลใดๆ ก็ตามที่มีอยู่
การออก HTTP GET
ให้กับ API การสมัครรับข้อมูลจะส่งกลับเนื้อหาที่เข้ารหัสแบบ JSON ซึ่งแสดงรายการการสมัครรับข้อมูลของคุณ ตัวอย่างเช่น
[ { "object": "payments", "callback_url": "https://www.friendsmash.com/rtu.php", "fields": ["actions", "disputes"], "active": true } ]
คุณสามารถใช้ Graph Explorer เพื่อทดลองกับ API นี้ได้โดยตรง โดยอย่าลืมใช้โทเค็นการเข้าถึงของแอพ
เซิร์ฟเวอร์การเรียกกลับของคุณต้องจัดการกับคำขอ 2 ประเภท โปรดตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์อยู่บน URL สาธารณะ เพื่อให้เราสามารถสร้างคำขอเหล่านี้ได้สำเร็จ
อันดับแรก เซิร์ฟเวอร์ Facebook จะสร้าง HTTPS GET
แบบเดี่ยวไปที่ URL การเรียกกลับกลับเมื่อคุณพยายามเพิ่มหรือแก้ไขการสมัครรับข้อมูล ซึ่งระบบจะนำสตริงการสืบค้นมาต่อท้าย URL การเรียกกลับของคุณโดยมีพารามิเตอร์ต่อไปนี้
พารามิเตอร์ | คำอธิบาย |
---|---|
| ระบบจะส่งสตริง " |
| สตริงแบบสุ่ม |
| ค่า |
ตำแหน่งข้อมูลควรตรวจสอบยืนยัน hub.verify_token
เป็นอันดับแรก ซึ่งจะช่วยให้แน่ใจได้ว่าเซิร์ฟเวอร์ของคุณรู้ว่า Facebook เป็นผู้สร้างคำขอและคำขอนั้นเกี่ยวข้องกับการสมัครรับข้อมูลที่คุณเพิ่งกำหนดค่าไป
จากนั้น ตำแหน่งข้อมูลควรสะท้อนกลับเฉพาะค่า hub.challenge
ซึ่งจะเป็นการยืนยันกับ Facebook ว่าเซิร์ฟเวอร์นี้ได้รับการกำหนดค่าให้ยอมรับการเรียกกลับ และป้องกันช่องโหว่การปฏิเสธบริการ (DDoS) แล้ว
หมายเหตุสำหรับผู้พัฒนา PHP: ระบบจะแปลงจุดและการเว้นวรรคในชื่อพารามิเตอร์การสืบค้นเป็นเครื่องหมายขีดล่างโดยอัตโนมัติในภาษา PHP ดังนั้น คุณควรเข้าถึงพารามิเตอร์เหล่านี้โดยใช้ $_GET['hub_mode']
, $_GET['hub_challenge']
และ $_GET['hub_verify_token']
หากคุณเขียนตำแหน่งข้อมูลการเรียกกลับในภาษา PHP โปรดดูรายละเอียดเพิ่มเติมที่บันทึกนี้ในคู่มือภาษา PHP
หลังจากที่สมัครรับข้อมูลสำเร็จแล้ว เราจะออก HTTPS POST
ไปยังตำแหน่งข้อมูลเซิร์ฟเวอร์ของคุณในทุกๆ ครั้งที่มีการเปลี่ยนแปลง (ต่อช่องหรือการเชื่อมต่อที่เลือกไว้) คุณต้องตอบกลับคำขอนี้ด้วยรหัส HTTP 200
หมายเหตุ - เราจะถือว่าการตอบกลับแบบ HTTP ใดๆ ก็ตามที่ไม่ใช่ 200
เป็นข้อผิดพลาด ซึ่งในสถานการณ์เหล่านี้ เราจะยังพยายามส่งการอัพเดต Webhooks อีกครั้งต่อไป หากคุณไม่ตอบกลับอย่างถูกต้อง คุณอาจได้รับการอัพเดตเดิมซ้ำกันหลายครั้ง
คำขอจะมีเนื้อหาประเภท application/json
และเนื้อความจะประกอบด้วยสตริงที่เข้ารหัสแบบ JSON ที่มีการเปลี่ยนแปลง 1 รายการขึ้นไป
หมายเหตุสำหรับผู้พัฒนา 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" ] } ] }
คุณจำเป็นต้องทราบว่าการอัพเดต Webhook จะแจ้งให้คุณทราบเมื่อการชำระเงินที่เฉพาะเจาะจงซึ่งระบุโดยช่อง id
มีการเปลี่ยนแปลงเท่านั้น หลังจากที่รับการอัพเดตแล้ว คุณจะต้องสืบค้น API กราฟเพื่อดูรายละเอียดของธุรกรรม เพื่อจัดการกับการเปลี่ยนแปลงนั้นอย่างเหมาะสม
หมายเหตุ - ในขณะที่ Webhooks สำหรับอ็อบเจ็กต์ประเภทอื่นๆ สามารถรวมเป็นแบตช์ได้ แต่การอัพเดตการชำระเงินจะไม่รวมเป็นแบตช์โดยเด็ดขาด
เรารับประกันว่าคุณจะได้รับการอัพเดตใหม่ในทุกครั้งที่มีการอัพเดตธุรกรรม ไม่ว่าจะเป็นการดำเนินการของผู้ใช้หรือการดำเนินการของผู้พัฒนาก็ตาม
หากการอัพเดตไปยังเซิร์ฟเวอร์ของคุณล้มเหลว เราจะลองส่งอีกครั้งทันที จากนั้นจะลองส่งอีก 2-3 ครั้ง โดยจะลดความถี่ลงในช่วง 24 ชั่วโมงหลังจากนั้น
ในทุกคำขอ เราส่งส่วนหัว HTTP X-Hub-Signature-256
ซึ่งประกอบด้วยลายเซ็น SHA256 ของเพย์โหลดคำขอ โดยใช้ข้อมูลลับของแอพเป็นคีย์และขึ้นต้นด้วย sha256=
ตำแหน่งข้อมูลการเรียกกลับของคุณสามารถตรวจสอบยืนยันลายเซ็นนี้เพื่อยืนยันความถูกต้องสมบูรณ์และต้นทางของเพย์โหลดได้
หลังจากเซิร์ฟเวอร์ของคุณได้รับการอัพเดต คุณควรสืบค้น API กราฟโดยใช้ช่อง id
เพื่อดูรายละเอียดเกี่ยวกับสถานะใหม่ของธุรกรรม จากนั้นคุณควรดำเนินการตามสถานะของธุรกรรมนั้น
ส่วนต่อไปนี้จะแจกแจงการเปลี่ยนแปลงสถานะทั้งหมดที่อาจเกิดขึ้นได้ซึ่งจะทริกเกอร์ให้ระบบส่งการอัพเดต โดยจะมีการแบ่งแบบกว้างๆ ได้ดังนี้
แต่ละอ็อบเจ็กต์ payment
จะมีอาร์เรย์ที่มีชื่อว่า actions
ซึ่งประกอบด้วยคอลเลกชั่นการเปลี่ยนแปลงสถานะต่างๆ ที่เกิดขึ้นในระหว่างทำธุรกรรม โดยแต่ละรายการในอาร์เรย์ actions
จะมีคุณสมบัติที่ชื่อ type
ซึ่งอธิบายประเภทของการดำเนินการที่เกิดขึ้น ทั้งนี้ type
ดังกล่าวอาจมีค่าต่างๆ ดังนี้ ได้แก่ charge
, refund
, chargeback
, chargeback_reversal
และ decline
ซึ่งเราได้อธิบายไว้อย่างครบถ้วนที่นี่
ตัวอย่างการตอบกลับจาก 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,}`
เนื่องจากคุณได้สมัครรับข้อมูลช่อง actions เมื่อลงทะเบียน Webhooks เราจะออกการอัพเดตเมื่ออาร์เรย์มีการเปลี่ยนแปลงดังนี้
โดยเริ่มต้นแล้ว คำสั่งซื้อทั้งหมดจะมี "status": "initiated"
อยู่ในรายการเก็บค่าบริการ การชำระเงินที่เริ่มต้นแล้วเป็นการกำหนดว่าการชำระเงินดังกล่าวได้เริ่มต้นขึ้นแล้วเท่านั้นและยังดำเนินการไม่เสร็จสมบูรณ์ ซึ่งเราจะไม่ส่งการอัพเดตสำหรับการชำระเงินที่มีสถานะเป็น "initiated"
เมื่อดำเนินการชำระเงินเสร็จสมบูรณ์แล้ว "status": "initiated"
จะเปลี่ยนเป็น "status": "completed"
จากนั้นเราจะออกการอัพเดต เมื่อเห็นการเปลี่ยนแปลงนี้ คุณควรตรวจสอบบันทึกการชำระเงินเพื่อตรวจสอบยืนยันว่าการชำระเงินนี้เป็นธุรกรรมใหม่หรือเป็นธุรกรรมที่มีอยู่แล้ว และตอบกลับดังนี้
initiated
คุณจะสามารถดำเนินการตามคำสั่งซื้อได้โดยออกสกุลเงินหรือรายการเสมือนที่เกี่ยวข้องให้กับผู้บริโภค จากนั้น คุณจะสามารถทำเครื่องหมายว่าการชำระเงินนี้เสร็จสิ้นแล้วได้อย่างปลอดภัยนอกจากนี้ คุณจะได้รับการอัพเดตสำหรับการชำระเงินที่มี "status": "failed"
อีกด้วย ซึ่งคุณไม่ควรดำเนินการกับการชำระเงินเหล่านี้ต่อ
คุณจะได้รับการอัพเดตทุกครั้งที่คุณออกการคืนเงินผ่าน API กราฟ ซึ่งการคืนเงินอาจมีสถานะต่างๆ ที่คุณจะต้องทราบเช่นเดียวกับ "type": "charge"
อีกด้วย โดยเฉพาะอย่างยิ่ง การคืนเงินอาจมีความเป็นไปได้ที่จะไม่สำเร็จ ซึ่งมักเกิดจากข้อผิดพลาดในการประมวลผลหรือการเชื่อมต่อ ซึ่งในกรณีนี้คุณควรพยายามออกการคืนเงินอีกครั้ง
คุณจะได้รับการแจ้งเตือนเมื่อมีการออกการคืนยอดเงิน รวมถึงการเปลี่ยนคำตัดสินหรือการปฏิเสธการคืนยอดเงินเช่นเดียวกับการคืนเงินอีกด้วย โดยระบบจะเพิ่มอ็อบเจ็กต์การคืนยอดเงิน การเปลี่ยนคำตัดสิน หรือการปฏิเสธการคืนยอดเงินไปยังอาร์เรย์ "actions" ของข้อมูลการส่งคืน API กราฟสำหรับการชำระเงิน
เราจะแจ้งให้คุณทราบโดยการออกข้อมูลอัพเดตเมื่อมีข้อโต้แย้งเริ่มต้นขึ้น ในกรณีนี้ คุณจะเห็นอาร์เรย์ "disputes"
ใหม่ปรากฏเป็นส่วนหนึ่งของอ็อบเจ็กต์ payment
ซึ่งอาร์เรย์นี้จะประกอบด้วยเวลาที่เริ่มข้อโต้แย้ง เหตุผลของผู้บริโภคในการเริ่มดำเนินการตอบกลับ และอีเมลของผู้บริโภค ซึ่งคุณสามารถใช้ติดต่อกับผู้บริโภคได้โดยตรงเพื่อระงับข้อโต้แย้งนั้น
ตัวอย่างการตอบกลับที่ครบถ้วนจาก 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" } ] }
โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีตอบกลับข้อโต้แย้งและออกการคืนเงินที่คู่มือการชำระเงิน: การจัดการกับข้อโตแย้งและการคืนเงิน