Հոդվածի ֆոկուսը
Սկզբնական խնդիր. մեկ contract պատվերի և provider-ի միջև
Backend-ը չպետք է provider-ին փոխանցի browser-ից կամայական գումար կամ փոխի պատվերը առանց ստուգելի payment state-ի:
Սերվերը վավերացնում է պատվերը, գումարը, արժույթը և թույլատրելի գործողությունը, ապա ստեղծում է payment attempt ներքին id-ով և idempotency key-ով: Միայն դրանից հետո է ձևավորվում անվտանգ checkout URL:
Ներքին order id-ն, payment attempt id-ն և provider payment id-ն պահվում են միասին: Սա անվտանգ է դարձնում կրկնվող հարցումները և հեշտացնում է աջակցման ու հաշվառման որոնումը:
- Frontend-ից եկած վերջնական գումարին չվստահել:
- Order-ը, payment attempt-ը և refund-ը պահել առանձին էություններ:
- Արժույթն ու կլորացման կանոնները ֆիքսել backend-ում:
- Նույն idempotency key-ի համար վերադարձնել նույն create-payment արդյունքը:
Լուծումը. state machine և idempotent webhook handler-ներ
Webhook-ը կարող է գալ մի քանի անգամ, return URL-ից հետո կամ այլ հերթականությամբ, ուստի բիզնես վիճակը փոխվում է միայն թույլատրելի անցումներով:
Backend-ը ստուգում է ստորագրությունը, գումարը, արժույթը, correlation id-ն և աղբյուրը, ապա որոշում է՝ արդյոք ստացված անցումը թույլատրելի է: Ուշացած failed callback-ը չի կարող փոխարինել paid-ին, իսկ կրկնվող paid-ը չի կարող կրկին մատուցել պատվերը:
Laravel job-ը կամ Django worker-ը երկրորդային գործողությունները կարող է կատարել ասինխրոն՝ ծանուցում, CRM sync, ֆիսկալ գործողություն կամ հասանելիության բացում: Կրիտիկական webhook պատասխանը մնում է արագ:
- Պահել raw event-ը և նորմալացված ստուգման արդյունքը:
- Webhook ընդունումը առանձնացնել ծանր ֆոնային գործողություններից:
- Չլուծված անհամապատասխանությունների համար կիրառել retry policy և manual review:
- Հաստատված paid-ից առաջ անդառնալի գործողություն չկատարել:
Գործարկումից հետո. վերադարձներ, դիտարկելիություն և հաշտեցում
Թիմին անհրաժեշտ է payment attempts-ի, refunds-ի, retries-ի և provider report-ի տարբերությունների գրանցամատյան:
Վերադարձը սկսվում է սկզբնական վճարման, հասանելի գումարի և օպերատորի դերի ստուգումից: Request-ից հետո backend-ը ստեղծում է առանձին refund record և վերջնական արդյունքը հաստատում է նույն անվտանգ կարգավիճակի մեխանիզմով:
Կառուցվածքային լոգերը, հերթերի մետրիկաները և provider report-ի ամենօրյա հաշտեցումը բացահայտում են ոչ միայն API սխալները, այլ նաև provider-ում անցած, սակայն ներքին համակարգ չհասած վճարումները:
- Չլոգավորել քարտային տվյալներ կամ գաղտնիքներ:
- Օպերատորին տալ որոնում ըստ order id-ի, payment id-ի և correlation id-ի:
- Առանձնացնել նախաձեռնված և հաստատված վերադարձները:
- Webhook retries-ն ու manual review խնդիրները դիտարկել առանձին:
FAQ
Արդյո՞ք պետք է payment attempt, եթե պատվերն արդեն կա:
Այո: Պատվերն ու payment attempt-ը տարբեր կյանքի ցիկլեր ունեն. մեկ պատվերը կարող է ունենալ մի քանի փորձ, չեղարկում կամ վերադարձ:
Ինչպե՞ս մշակել կրկնվող webhook-ը:
Ստուգել ստորագրությունն ու event id-ն, պահել այն audit-ի համար, ապա կիրառել միայն թույլատրելի idempotent state transition:
Կարելի՞ է CRM sync-ը կատարել webhook-ի ներսում:
Ավելի լավ է արագ ընդունել և ստուգել իրադարձությունը, իսկ CRM sync-ը կատարել կայուն հերթով retry և error logging մեխանիզմով: