Webhook — тойм¶
Төлбөр амжилттай болох, барьцаа (hold) тавигдах, хүн QR уншуулах, буцаалт дуусах зэрэг үйл явдлыг Gerege таны
серверт POST хүсэлтээр мэдэгдэнэ. Энэ хуудсыг уншаад та webhook endpoint-оо нэмж, secret-ээ хадгалж, хэсгийн
бусад хуудсыг хаана хэрэглэхээ мэдэнэ.
- Хугацаа: 10–15 минут (endpoint нэмэх + гарын үсэг шалгах handler).
- Хэрэгтэй: хөгжүүлэгчийн консолд бүртгэлтэй апп (mini app эсвэл худалдагч), нийтийн интернетээс хүрэх https хаяг, secret-ийг хадгалах газар (environment variable, secret manager — репо биш).
Заавал
payments scope-той апп ба бүх худалдагч review-д илгээхээс өмнө, мөн батлагдах үед идэвхтэй live webhook
endpoint-тэй байх ёстой — endpoint №1 (webhook URL) эсвэл бусад аль нэг; унтраасан, автоматаар унтарсан endpoint
тооцогдохгүй. Submit нь ийм endpoint-гүй апп-ыг 400 not_ready (path webhook_url) гэж буцаана.
1. Хэсгийн хуудсууд¶
| Хуудас | Юу |
|---|---|
| Гарын үсэг шалгах | Gerege-Signature толгой, алгоритм, Node/Go/Python/PHP код, тест вектор |
| Хүргэлт ба давталт | Endpoint бүрийн хүргэлт, шууд оролдлого, retry хуваарь, автомат унтраалт, дараалал |
| Idempotent handler | Давхардлыг арилгах, хурдан 2xx, объектыг дахин унших — жишээ код |
| Event-ийн лавлах | 12 event тус бүр: хэзээ, data.object, жишээ payload |
| Events API | GET /events — алдсан event-ээ татах, webhook-гүй тулгах |
2. Endpoint¶
Event-ийг хүлээн авах хаягийг endpoint гэнэ. Апп-ын орчин бүрт (test, live) 5 хүртэл endpoint; endpoint бүр өөрийн URL, тайлбар (≤ 200), event-ийн шүүлтүүр, өөрийн secret, хүргэлтийн лог, төлөвтэй.
- Endpoint №1 нь апп-ын анхны
webhook_url— хоёр орчинд хоёуланд нь нэг URL, нэг secret (legacy: true). Консолын апп-ын «Webhook» хэсэг баPOST /api/v1/miniapp/dev/apps/{id}/webhook {"url"}нь үүнийг тохируулна. Review-д илгээхэд заавал. - Нэмэлт endpoint — консолоос (
/dev/apps/{id}/webhook-endpoints, орчныг сонгоно) эсвэл таны серверээс/webhook-endpointsAPI-аар (тухайн түлхүүрийн орчинд, доор §6). - Эрх (консол, 1.13.0): бичилт бүр
miniapp.develop; live endpoint-ийн URL, secret солих, устгах (endpoint №1 болонPOST …/webhook— хоёр орчных тул)miniapp.keys.liveба сүүлийн 10 минутын нэвтрэлт (403 fresh_sign_in_required). Тайлбар, шүүлтүүр, унтраах нь step-up шаардахгүй. Шүүж болох event-ийн жагсаалт mn/en нэртэйгээ:GET /api/v1/miniapp/dev/webhook-event-types. - Шүүлтүүр
event_types: хоосон = бүх event; эсвэл ≤ 20 төрөл (давхардалгүй,webhook.test-ээс бусад). Шүүлтүүр event үүсэх агшинд шалгагдана — дараа нь өөрчилсөн ч өмнөх event-ийн хүргэлт өөрчлөгдөхгүй. - Төлөв
status:active(хүлээн авна),disabled(та унтраасан),auto_disabled(5 хоног амжилтгүй тул платформ унтраасан — Хүргэлт). Идэвхгүй endpoint-д шинэ event хуваарилагдахгүй. - URL нь
https://, ≤ 2048 тэмдэгт. Хүргэх үед хаягийг DNS-ийн дараа шалгана: дотоод сүлжээ, loopback, link-local хаяг руу хэзээ ч илгээхгүй — production-д endpoint нийтийн IP-тэй байна. Локал машин дээр туршихдаа tunnel ашигла (Локал webhook). - Test endpoint зөвхөн test event, live endpoint зөвхөн live event авна. Endpoint №1 хоёр орчинд нэг URL тул тэнд
ирсэн event-ийг
livemode-оор ялга; test event-ээр бараа олгохгүй.
Endpoint үүсгэх (консол):
POST /api/v1/miniapp/dev/apps/{id}/webhook-endpoints
Content-Type: application/json
{"environment": "live", "url": "https://api.example.mn/webhooks/gerege",
"description": "ERP", "event_types": ["payment_intent.succeeded", "refund.succeeded"]}
{"endpoint": {"id": "we_…", "object": "webhook_endpoint", "environment": "live", "livemode": true,
"url": "https://api.example.mn/webhooks/gerege", "description": "ERP",
"event_types": ["payment_intent.succeeded", "refund.succeeded"], "status": "active", "disabled_reason": null,
"legacy": false, "previous_secret_until": null, "failing_since": null, "last_success_at": null,
"created_at": "…", "updated_at": "…"},
"webhook_secret": "whsec_…", "notice": "Энэ secret-ийг дахин харуулахгүй — одоо хадгална уу"}
webhook_secret (whsec_…) зөвхөн энэ хариунд нэг удаа харагдана (Cache-Control: no-store). Платформ түүнийг
битүүмжилж хадгалдаг — алдвал солино (§5). Жагсаалт (GET …/webhook-endpoints[?environment=])
endpoint бүрийн сүүлийн 24 цагийн deliveries_24h {delivered, failing}-ийг нэмж харуулна. Endpoint-ийн алдааны
кодууд — Алдааны код.
3. Хүсэлт ямар харагдах¶
POST /webhooks/gerege HTTP/1.1
Content-Type: application/json
User-Agent: GeregeApp-Webhooks/1
Gerege-Event-Id: evt_Vec0000000000000000000001
Gerege-Signature: t=1792659600,v1=aab41441cf937428aac0a577ff2e0236b4e487b82c8a725afd2b1791cc2c9821
OpenPay-Event-Id: evt_Vec0000000000000000000001
OpenPay-Signature: t=1792659600,v1=aab41441cf937428aac0a577ff2e0236b4e487b82c8a725afd2b1791cc2c9821
{"id":"evt_Vec0000000000000000000001","type":"payment_intent.succeeded","created_at":"2026-10-22T09:00:00Z",
"livemode":true,"app":"esim","data":{"object":{"id":"pi_4fQ2mX8kLp0aZr7TbN3cVw9E","object":"payment_intent", …}}}
OpenPay-* толгойнууд нь OMAS стандартын нэрээр ижил утга — OMAS-д бичсэн backend өөрчлөлтгүй шалгана.
data.object нь API-ийн хариутай яг ижил хэлбэр (жишээ нь GET /payment-intents/{id}-ийнх). Нэг event хэд хэдэн
endpoint руу очвол body нь ижил, гарын үсэг нь endpoint бүрийн secret-ээр.
Таны хийх гурван зүйл:
- Гарын үсгийг шалга — түүхий body дээр, тухайн endpoint-ийн secret-ээр (Гарын үсэг шалгах).
- 10 секундэд 2xx буцаа, ажлыг queue-д хий;
id-аар давхардлыг арилга (Idempotent handler). - Бараа олгох, захиалга хаахаас өмнө объектыг API-аас дахин унш — webhook бол дохио, эцсийн үнэн нь API.
4. Event-ууд¶
Товч жагсаалт; event бүрийн нөхцөл, data.object, жишээ payload — Event-ийн лавлах.
type |
Хэзээ | data.object |
|---|---|---|
payment_intent.succeeded |
Төлбөр амжилттай (automatic: баталгаажуулсны дараа; manual: capture-ийн дараа) | PaymentIntent |
payment_intent.requires_capture |
Manual intent-ийн мөнгө барьцаалагдсан — capture эсвэл cancel хий | PaymentIntent |
payment_intent.canceled |
Цуцлагдсан; app intent-ийн хугацаа дуусахад ч (status: "expired") |
PaymentIntent |
payment_intent.failed |
Баталгаажуулалт эсвэл capture амжилтгүй (failure_code) |
PaymentIntent |
payment_intent.claimed |
Хүн claimless (qr/redirect/terminal) intent-ийг өөртөө авсан |
PaymentIntent |
payment_intent.expired |
Claimless intent-ийн хугацаа дууссан | PaymentIntent |
refund.succeeded · refund.failed |
Буцаалт дууссан / татгалзсан | Refund |
app.status_changed |
Апп-ын status эсвэл review_status өөрчлөгдсөн |
AppStatus |
consent.revoked |
Хүн апп-аа салгасан | Consent |
settlement.paid |
Тооцоо payout данс руу шилжсэн (үргэлж live) | Settlement |
webhook.test |
Консолоос тест илгээлт (үргэлж test) | WebhookTest |
Мэдэхгүй type-д 2xx хариулж үл тоомсорло — minor хувилбар шинэ event нэмж болно.
5. Secret ба солих¶
| Үйлдэл | Юу болох |
|---|---|
POST …/webhook-endpoints/{eid}/rotate-secret |
Тухайн endpoint-д шинэ secret (хариунд нэг удаа). Хуучин нь 24 цаг хамт гарын үсэг зурна: event бүрт хоёр v1 — эхэнд шинэ, дараа нь хуучин. Endpoint-ийн previous_secret_until хэзээ дуусахыг хэлнэ. Тэр хугацаанд шинэ secret-ээ deploy хий — нэг ч event алдагдахгүй. |
Endpoint №1: url-тэй POST …/webhook (URL өөрчлөөгүй ч) |
№1-д шинэ secret, хуучин нь 24 цаг хамт (хоёр орчинд хоёуланд). |
DELETE …/webhook-endpoints/{eid} · №1-д {"url": null} |
Endpoint, түүний secret устна; хүлээгдэж байсан хүргэлтүүд нь хамт устна. Event өөрөө Events API-д үлдэнэ. |
- URL, secret нь хүргэх агшинд уншигдана — өөрчлөлт хуучин event-ийн дараагийн retry-д ч хэрэгжинэ.
- Шилжилтийн үед хүлээн авагч талд
[шинэ, хуучин]хоёуланг нь зөвшөөр (SDK-ууд secret-ийн жагсаалт авна), deploy дууссаны дараа хуучныг хас. Endpoint тус бүрийн secret өөр — хоёр endpoint нэг handler-т ирдэг бол хоёуланг нь зөвшөөр. - Түдгэлзсэн (
suspended) апп-ын endpoint-ийг өөрчлөх боломжгүй (409 suspended); review-д буй апп-ын endpoint №1-ийн URL, secret-ийг ч (409 locked_for_review). - Суулгацад secret битүүмжлэх түлхүүр тохируулаагүй бол
503 no_secret_key— secret хэзээ ч ил хадгалагдахгүй. - Өөрчлөлт бүр апп-ын audit-д бичигдэнэ; secret өөрөө хэзээ ч биш.
6. Таны серверээс удирдах — /webhook-endpoints¶
IaC, deploy script-ээс endpoint-оо тохируулахад: https://geregeapp.mn/api/v1/miniapp/webhook-endpoints,
Basic (API түлхүүр), scope webhooks:write — энэ scope зөвхөн live түлхүүрт олгогддог; test түлхүүр
403 live_only авна (test endpoint-ийг консолоос). Түлхүүр зөвхөн өөрийн орчны endpoint-ийг харж, үүсгэнэ
(environment-ийг орхи, эсвэл түлхүүрийнхтэй ижил; өөр бол 403 environment_mismatch).
| Method | Зам | |
|---|---|---|
| GET · POST | /webhook-endpoints |
{"data": [WebhookEndpoint], "next_cursor": null} · 201 {endpoint, webhook_secret, notice} |
| GET · PATCH · DELETE | /webhook-endpoints/{eid} |
PATCH: url, description, event_types, status (active | disabled) · DELETE → 204 |
| POST | /webhook-endpoints/{eid}/rotate-secret |
200 {endpoint, webhook_secret, notice} |
| POST | /webhook-endpoints/{eid}/test |
Гарын үсэгтэй webhook.test-ийг тэр endpoint руу одоо илгээж үр дүнг хариулна (20/мин) |
Консол ижил үйлдлүүдийг /dev/apps/{id}/webhook-endpoints… дор аль ч орчинд хийнэ. auto_disabled endpoint-ийг
PATCH {"status": "active"}-ээр асаана (алдсан event-ээ Events API-аас татсаны дараа). Түлхүүр ба
scope — Аюулгүй байдлын загвар, бүх route — API-ийн нийтлэг дүрэм.