15 рджрд┐рд╕ре░ 2024┬╖8 рдорд┐рдирдЯ рдкрдврд╝рдиреЗ рдореЗрдВ

рд╕реБрд░рдХреНрд╖рд┐рдд рдмрд┐рд▓рд┐рдВрдЧ рдЕрдкрдбреЗрдЯ рдХреЗ рд▓рд┐рдП рдЗрдбреЗрдореНрдкреЛрдЯреЗрдВрдЯ рдкреЗрдореЗрдВрдЯ рд╡реЗрдмрд╣реБрдХ рдЪреЗрдХрд▓рд┐рд╕реНрдЯ

рдЗрдбреЗрдореНрдкреЛрдЯреЗрдВрдЯ рдкреЗрдореЗрдВрдЯ рд╡реЗрдмрд╣реБрдХ рдЪреЗрдХрд▓рд┐рд╕реНрдЯ тАФ рдЗрд╡реЗрдВрдЯреНрд╕ рдХреЛ рдбреЗрдбреБрдк рдХрд░рдиреЗ, retries рд╕рдВрднрд╛рд▓рдиреЗ, рдФрд░ invoices, subscriptions, entitlements рдХреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗред

рд╕реБрд░рдХреНрд╖рд┐рдд рдмрд┐рд▓рд┐рдВрдЧ рдЕрдкрдбреЗрдЯ рдХреЗ рд▓рд┐рдП рдЗрдбреЗрдореНрдкреЛрдЯреЗрдВрдЯ рдкреЗрдореЗрдВрдЯ рд╡реЗрдмрд╣реБрдХ рдЪреЗрдХрд▓рд┐рд╕реНрдЯ

рдХреНрдпреЛрдВ рдкреЗрдореЗрдВрдЯ рд╡реЗрдмрд╣реБрдХ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдЕрдкрдбреЗрдЯ рдмрдирд╛рддреЗ рд╣реИрдВ

рдПрдХ рдкреЗрдореЗрдВрдЯ рд╡реЗрдмрд╣реБрдХ рд╡рд╣ рд╕рдВрджреЗрд╢ рд╣реИ рдЬреЛ рдЖрдкрдХрд╛ рдкреЗрдореЗрдВрдЯ рдкреНрд░реЛрд╡рд╛рдЗрдбрд░ рдЖрдкрдХреЗ рдмреИрдХрдПрдВрдб рдХреЛ рддрдм рднреЗрдЬрддрд╛ рд╣реИ рдЬрдм рдХреБрдЫ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реЛрддрд╛ рд╣реИтАФрдЬреИрд╕реЗ рдХрд┐ рдЪрд╛рд░реНрдЬ рд╕рдлрд▓ рд╣реЛ рдЧрдпрд╛, рдПрдХ invoice рдкреЗ рдХрд┐рдпрд╛ рдЧрдпрд╛, рд╕рдмреНрд╕рдХреНрд░рд┐рдкреНрд╢рди рд░рд┐рдиреНрдпреВ рд╣реБрдЖ, рдпрд╛ рд░рд┐рдлрдВрдб рдЬрд╛рд░реА рд╣реБрдЖред рдпрд╣ рдмреЗрд╕рд┐рдХрд▓реА рдкреНрд░реЛрд╡рд╛рдЗрдбрд░ рдХрд╣ рд░рд╣рд╛ рд╣реИ, тАЬрдпрд╣ рд╣реБрдЖред рдЕрдкрдиреЗ рд░рд┐рдХреЙрд░реНрдб рдЕрдкрдбреЗрдЯ рдХрд░реЛредтАЭ

рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдЗрд╕рд▓рд┐рдП рдЖрддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рд╡реЗрдмрд╣реБрдХ рдбрд┐рд▓реАрд╡рд░реА рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХреА рдЧрдИ рд╣реИ, "рдПрдХ рд╣реА рдмрд╛рд░" рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВред рдЕрдЧрд░ рдЖрдкрдХрд╛ рд╕рд░реНрд╡рд░ рдзреАрдорд╛ рд╣реИ, рдЯрд╛рдЗрдордЖрдЙрдЯ рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдПрд░рд░ рд▓реМрдЯрд╛ рд░рд╣рд╛ рд╣реИ, рдпрд╛ рдереЛрдбрд╝реА рджреЗрд░ рдХреЗ рд▓рд┐рдП рдЕрдирдЙрдкрд▓рдмреНрдз рд╣реИ, рддреЛ рдкреНрд░реЛрд╡рд╛рдЗрдбрд░ рдЖрдорддреМрд░ рдкрд░ рд╡рд╣реА рдЗрд╡реЗрдВрдЯ retries рдХрд░реЗрдЧрд╛ред рдЖрдк рдЕрдХреНрд╕рд░ рджреЛ рдЕрд▓рдЧ рдЗрд╡реЗрдВрдЯ рднреА рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдПрдХ рд╣реА рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХрд╛рд░реНрд░рд╡рд╛рдИ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реЛрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ invoice рдЗрд╡реЗрдВрдЯ рдФрд░ рдЙрд╕реА рднреБрдЧрддрд╛рди рд╕реЗ рдЬреБрдбрд╝рд╛ payment рдЗрд╡реЗрдВрдЯ)ред рдЗрд╡реЗрдВрдЯреНрд╕ рдЖрдЙрдЯ рдСрдлрд╝ рдСрд░реНрдбрд░ рднреА рдЖ рд╕рдХрддреЗ рд╣реИрдВ, рдЦрд╛рд╕рдХрд░ рд░рд┐рдлрдВрдб рдЬреИрд╕реЗ рддреНрд╡рд░рд┐рдд рдлреЙрд▓реЛ-рдЕрдкреНрд╕ рдХреЗ рд╕рд╛рдеред

рдЕрдЧрд░ рдЖрдкрдХрд╛ рд╣реИрдВрдбрд▓рд░ idempotent рдирд╣реАрдВ рд╣реИ, рддреЛ рд╡рд╣ рдПрдХ рд╣реА рдЗрд╡реЗрдВрдЯ рдХреЛ рджреЛ рдмрд╛рд░ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХрд╛ рдЕрд╕рд░ рдЧреНрд░рд╛рд╣рдХ рдФрд░ рдлрд╛рдЗрдиреЗрдВрд╕ рдЯреАрдо рддреБрд░рдВрдд рджреЗрдЦ рд▓реЗрдВрдЧреА:

  • рдПрдХ invoice рдХреЛ рджреЛ рдмрд╛рд░ paid рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рдирд╛, рдЬрд┐рд╕рд╕реЗ duplicate рдЕрдХрд╛рдЙрдВрдЯрд┐рдВрдЧ рдПрдВрдЯреНрд░реАрдЬрд╝ рдмрдирддреА рд╣реИрдВ
  • рд░рд┐рдиреНрдпреВрдЕрд▓ рджреЛ рдмрд╛рд░ рд▓рд╛рдЧреВ рд╣реЛрдирд╛, рдЬрд┐рд╕рд╕реЗ рдПрдХреНрд╕реЗрд╕ рдмрд╣реБрдд рдЖрдЧреЗ рдмрдврд╝ рдЬрд╛рдирд╛
  • Entitlements рджреЛ рдмрд╛рд░ рджреЗрдирд╛ (рдЕрддрд┐рд░рд┐рдХреНрдд рдХреНрд░реЗрдбрд┐рдЯреНрд╕, рд╕реАрдЯреНрд╕, рдпрд╛ рдлреАрдЪрд░реНрд╕)
  • рд░рд┐рдлрдВрдб рдпрд╛ рдЪрд╛рд░реНрдЬрдмреИрдХ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХреЛ рд╡рд╛рдкрд╕ рди рдХрд░ рдкрд╛рдирд╛

рдпрд╣ рд╕рд┐рд░реНрдлрд╝ "best practice" рдирд╣реАрдВ рд╣реИред рдпрд╣ рднрд░реЛрд╕реЗрдордВрдж рдмрд┐рд▓рд┐рдВрдЧ рдФрд░ рд╕рдкреЛрд░реНрдЯ рдЯрд┐рдХрдЯ рдкреИрджрд╛ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдмрд┐рд▓рд┐рдВрдЧ рдХреЗ рдмреАрдЪ рдХрд╛ рдлрд░реНрдХ рд╣реИред

рдЗрд╕ рдЪреЗрдХрд▓рд┐рд╕реНрдЯ рдХрд╛ рд▓рдХреНрд╖реНрдп рд╕рд░рд▓ рд╣реИ: рд╣рд░ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдЗрд╡реЗрдВрдЯ рдХреЛ "рдЕрдзрд┐рдХрддрдо рдПрдХ рдмрд╛рд░ рд▓рд╛рдЧреВ рдХрд░реЗрдВ" рдХреА рддрд░рд╣ рд╣рд╛рде рдореЗрдВ рд░рдЦреЗрдВред рдЖрдк рд╣рд░ рдЗрд╡реЗрдВрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдерд┐рд░ рдкрд╣рдЪрд╛рди рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдВрдЧреЗ, retries рдХреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рд╣реИрдВрдбрд▓ рдХрд░реЗрдВрдЧреЗ, рдФрд░ invoices, subscriptions, рдФрд░ entitlements рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рддрд░реАрдХреЗ рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВрдЧреЗред рдЕрдЧрд░ рдЖрдк рдмреИрдХрдПрдВрдб рдХреЛ рдХреЛрдИ-рдХреЛрдб рдЯреВрд▓ рдЬреИрд╕реЗ AppMaster рдореЗрдВ рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рд╡рд╣реА рдирд┐рдпрдо рд▓рд╛рдЧреВ рд╣реЛрддреЗ рд╣реИрдВ: рдЖрдкрдХреЛ рдПрдХ рд╕рд╛рдлрд╝ рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдФрд░ рдПрдХ рджреЛрд╣рд░рд╛рдиреЗ рдпреЛрдЧреНрдп рд╣реИрдВрдбрд▓рд░ рдлрд╝реНрд▓реЛ рдЪрд╛рд╣рд┐рдП рдЬреЛ retries рдХреЗ рджреМрд░рд╛рди рднреА рд╕рд╣реА рд░рд╣реЗред

рд╡реЗрдмрд╣реБрдХреНрд╕ рдкрд░ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдпреЛрдЧреНрдп idempotency рдХреЗ рдмреЗрд╕рд┐рдХреНрд╕

Idempotency рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдПрдХ рд╣реА рдЗрдирдкреБрдЯ рдХреЛ рдПрдХ рд╕реЗ рдЬреНрдпрд╛рджрд╛ рдмрд╛рд░ рдкреНрд░реЛрд╕реЗрд╕ рдХрд░рдиреЗ рдкрд░ рдЕрдВрддрд┐рдо рд╕реНрдерд┐рддрд┐ рд╕рдорд╛рди рд░рд╣рддреА рд╣реИред рдмрд┐рд▓рд┐рдВрдЧ рднрд╛рд╖рд╛ рдореЗрдВ: рдПрдХ invoice рдПрдХ рдмрд╛рд░ рд╣реА paid рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдПрдХ subscription рдПрдХ рдмрд╛рд░ рдЕрдкрдбреЗрдЯ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдПрдХреНрд╕реЗрд╕ рдПрдХ рдмрд╛рд░ рд╣реА granted рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рднрд▓реЗ рд╣реА рд╡реЗрдмрд╣реБрдХ рджреЛ рдмрд╛рд░ рдбрд┐рд▓реАрд╡рд░ рд╣реЛред

рдкреНрд░реЛрд╡рд╛рдЗрдбрд░ рддрдм retries рдХрд░рддреЗ рд╣реИрдВ рдЬрдм рдЖрдкрдХреЗ endpoint рдХреЛ рдПрдХ рддреЗрдЬрд╝ рд╕рдлрд▓ response рдирд╣реАрдВ рдорд┐рд▓рддрд╛тАФрдЯрд╛рдЗрдордЖрдЙрдЯ, 5xx, рдпрд╛ рдиреЗрдЯрд╡рд░реНрдХ рдбреНрд░реЙрдкред рд╡реЗ рдПрдХ рд╣реА рдЗрд╡реЗрдВрдЯ рд░рд┐рдкреАрдЯ рдХрд░реЗрдВрдЧреЗред рдпрд╣ рдЕрд▓рдЧ рд╣реИ рдЙрди рдЕрд▓рдЧ рдЗрд╡реЗрдВрдЯреНрд╕ рд╕реЗ рдЬреЛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдмрджрд▓рд╛рд╡ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ рдХреБрдЫ рджрд┐рдиреЛрдВ рдмрд╛рдж рдЖрдпрд╛ refundред рдирдП рдЗрд╡реЗрдВрдЯреНрд╕ рдХреЗ рдЕрд▓рдЧ IDs рд╣реЛрддреЗ рд╣реИрдВуАВ

рдЗрд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рд▓рд╛рдпрдХ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рджреЛ рдЪреАрдЬрд╝реЛрдВ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ: рд╕реНрдерд┐рд░ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ (stable identifiers) рдФрд░ рдЬрд┐рд╕ рдЪреАрдЬрд╝ рдХрд╛ рдЖрдкрдиреЗ рдкрд╣рд▓реЗ рд╣реА рд╕рд╛рдордирд╛ рдХрд┐рдпрд╛ рд╣реИ рдЙрд╕рдХрд╛ рдЫреЛрдЯрд╛ тАЬрдореЗрдореЛрд░реАтАЭред

рдХреМрди рд╕реЗ IDs рдорд╛рдпрдиреЗ рд░рдЦрддреЗ рд╣реИрдВ (рдФрд░ рдХреНрдпрд╛ рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ)

рдЬрд╝реНрдпрд╛рджрд╛рддрд░ рдкреЗрдореЗрдВрдЯ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдПрдХ рдЗрд╡реЗрдВрдЯ ID рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рд╡реЗрдмрд╣реБрдХ рдЗрд╡реЗрдВрдЯ рдХреЗ рд▓рд┐рдП рдпреВрдирд┐рдХ рд╣реЛрддрд╛ рд╣реИред рдХреБрдЫ payload рдХреЗ рдЕрдВрджрд░ request ID, idempotency key, рдпрд╛ рдХреЛрдИ рдпреВрдирд┐рдХ payment object ID (рдЬреИрд╕реЗ charge рдпрд╛ payment intent) рднреА рджреЗрддреЗ рд╣реИрдВред

рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ рдЬреЛ рдЖрдкрдХреЛ рдПрдХ рд╕рд╡рд╛рд▓ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗ: тАЬрдХреНрдпрд╛ рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рд╣реА рдпрд╣реА рдареАрдХ рд╡рд╣реА рдЗрд╡реЗрдВрдЯ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИ?тАЭ

рдПрдХ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдиреНрдпреВрдирддрдо рд╕реВрдЪреА:

  • Event ID (unique key)
  • Event type (рдбрд┐рдмрдЧрд┐рдВрдЧ рдореЗрдВ рдорджрдж рдХреЗ рд▓рд┐рдП)
  • Received timestamp
  • Processing status (processed/failed)
  • рдкреНрд░рднрд╛рд╡рд┐рдд customer, invoice, рдпрд╛ subscription рдХрд╛ рд╕рдВрджрд░реНрдн

рдореБрдЦреНрдп рдХрджрдо рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╡реЗрдВрдЯ ID рдХреЛ рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдпреВрдирд┐рдХ constraint рдХреЗ рд╕рд╛рде рд╕реНрдЯреЛрд░ рдХрд░реЗрдВред рдлрд┐рд░ рдЖрдкрдХрд╛ рд╣реИрдВрдбрд▓рд░ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдпрд╣ рдХрд░ рд╕рдХрддрд╛ рд╣реИ: рдкрд╣рд▓реЗ event ID insert рдХрд░реЗрдВ; рдЕрдЧрд░ рд╡рд╣ рдкрд╣рд▓реЗ рд╕реЗ рдореМрдЬреВрдж рд╣реИ, рддреЛ рд░реБрдХ рдЬрд╛рдПрдБ рдФрд░ 200 рд▓реМрдЯрд╛рдПрдБред

рдбреЗрдбреБрдк рд░рд┐рдХреЙрд░реНрдб рдХрд┐рддрдиреЗ рд╕рдордп рддрдХ рд░рдЦреЗрдВ

рд▓реЗрдЯ retries рдФрд░ рд╕рдкреЛрд░реНрдЯ рдЬрд╛рдВрдЪ рдХреЗ рд▓рд┐рдП рдбреЗрдбреБрдк рд░рд┐рдХреЙрд░реНрдб рдкрд░реНрдпрд╛рдкреНрдд рд╕рдордп рддрдХ рд░рдЦреЗрдВред рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рдВрдбреЛ 30 рд╕реЗ 90 рджрд┐рди рд╣реИред рдЕрдЧрд░ рдЖрдк chargebacks, disputes, рдпрд╛ рд▓рдВрдмреА subscription cycles рд╕реЗ рдирд┐рдкрдЯрддреЗ рд╣реИрдВ, рддреЛ рдЗрдиреНрд╣реЗрдВ рд▓рдВрдмрд╛ рд░рдЦреЗрдВ (6 рд╕реЗ 12 рдорд╣реАрдиреЗ), рдФрд░ рдкреБрд░рд╛рдиреА rows purge рдХрд░рддреЗ рд░рд╣реЗрдВ рддрд╛рдХрд┐ рддрд╛рд▓рд┐рдХрд╛ рддреЗрдЬрд╝ рд░рд╣реЗред

Generated рдмреИрдХрдПрдВрдб рдЬреИрд╕реЗ AppMaster рдореЗрдВ рдпрд╣ рд╕рд╛рдлрд╝ рддреМрд░ рдкрд░ WebhookEvents рдореЙрдбрд▓ рдмрди рдХрд░ рдЖрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ event ID рдкрд░ unique рдлреАрд▓реНрдб рд╣реЛ, рдФрд░ рдПрдХ рдмрд┐рдЬрдиреЗрд╕ рдкреНрд░реЛрд╕реЗрд╕ рдЬреЛ duplicate рдорд┐рд▓рдиреЗ рдкрд░ рдЬрд▓реНрджреА рдмрд╛рд╣рд░ рдирд┐рдХрд▓ рдЬрд╛рдПред

рдЗрд╡реЗрдВрдЯреНрд╕ рдХреЗ рдбреЗрдбреБрдк рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд░реЗрдВ

рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡реЗрдмрд╣реБрдХ рд╣реИрдВрдбрд▓рд░ рдЬреНрдпрд╛рджрд╛рддрд░ рдбреЗрдЯрд╛ рдХреА рд╕рдорд╕реНрдпрд╛ рд╣реИред рдЕрдЧрд░ рдЖрдк рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░реЛрд╡рд╛рдЗрдбрд░ рдЗрд╡реЗрдВрдЯ рдХреЛ рд╕рдЯреАрдХ рд░реВрдк рд╕реЗ рдПрдХ рдмрд╛рд░ рд░рд┐рдХреЙрд░реНрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рдЖрдЧреЗ рдХреА рд╣рд░ рдЪреАрдЬрд╝ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реЛ рдЬрд╛рддреА рд╣реИред

рдПрдХ рд░рд┐рд╕реАрдЯ-рд▓реЙрдЧ рдХреА рддрд░рд╣ рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВред PostgreSQL рдореЗрдВ (рдФрд░ AppMaster рдХреЗ Data Designer рдореЗрдВ modeled рдХрд░рддреЗ рд╕рдордп), рдЗрд╕реЗ рдЫреЛрдЯрд╛ рдФрд░ рд╕рдЦреНрдд рд░рдЦреЗрдВ рддрд╛рдХрд┐ duplicates рдЬрд▓реНрджреА рдлреЗрд▓ рд╣реЛрдВред

рдиреНрдпреВрдирддрдо рдЬрд░реВрд░рдд

webhook_events рдЯреЗрдмрд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдмреЗрд╕рд▓рд╛рдЗрди:

  • provider (text, рдЬреИрд╕реЗ "stripe")
  • provider_event_id (text, required)
  • status (text, рдЬреИрд╕реЗ "received", "processed", "failed")
  • processed_at (timestamp, nullable)
  • raw_payload (jsonb рдпрд╛ text)

(provider, provider_event_id) рдкрд░ рдПрдХ unique constraint рдЬреЛрдбрд╝реЗрдВред рдпрд╣реА рдЖрдкрдХрд╛ рдореБрдЦреНрдп рдбреЗрдбреБрдк рдЧрд╛рд░реНрдбрд░реЗрд▓ рд╣реИред

рдЖрдкрдХреЛ рдЙрди рдмрд┐рдЬрдиреЗрд╕ IDs рдХреА рднреА рдЬрд╝рд░реВрд░рдд рд╣реЛрдЧреА рдЬрд┐рдирдХрд╛ рдЖрдк рдЙрдкрдпреЛрдЧ рд░рд┐рдХреЙрд░реНрдбреНрд╕ рдХреЛ locate рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддреЗ рд╣реИрдВред рдпреЗ webhook event ID рд╕реЗ рдЕрд▓рдЧ рд╣реЛрддреЗ рд╣реИрдВред

рдЖрдо рдЙрджрд╛рд╣рд░рдг: customer_id, invoice_id, рдФрд░ subscription_idред рдЗрдиреНрд╣реЗрдВ text рд░рдЦреЗрдВ рдХреНрдпреЛрдВрдХрд┐ рдкреНрд░рджрд╛рддрд╛ рдЕрдХреНрд╕рд░ non-numeric IDs рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░рддреЗ рд╣реИрдВред

raw payload vs parsed fields

рдбрд┐рдмрдЧ рдФрд░ рдмрд╛рдж рдореЗрдВ reprocess рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП raw payload рд╕реНрдЯреЛрд░ рдХрд░реЗрдВред parsed fields рдХреНрд╡реЗрд░реА рдФрд░ рд░рд┐рдкреЛрд░реНрдЯрд┐рдВрдЧ рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рд╡рд╣реА рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ рдЬрд┐рдирдХрд╛ рдЖрдк рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред

рд╕рд░рд▓ рджреГрд╖реНрдЯрд┐рдХреЛрдг:

  • рд╣рдореЗрд╢рд╛ raw_payload рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ
  • рд╕рд╛рде рдореЗрдВ рдХреБрдЫ parsed IDs рд░рдЦреЗрдВ рдЬрд┐рдирдХреА рдЖрдк рдЕрдХреНрд╕рд░ рдХреНрд╡реЗрд░реА рдХрд░рддреЗ рд╣реИрдВ (customer, invoice, subscription)
  • рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП normalized event_type (text) рд░рдЦреЗрдВ

рдЕрдЧрд░ рдПрдХ invoice.paid рдЗрд╡реЗрдВрдЯ рджреЛ рдмрд╛рд░ рдЖрддрд╛ рд╣реИ, рддреЛ рдЖрдкрдХрд╛ unique constraint рджреВрд╕рд░реА insert рдХреЛ рдмреНрд▓реЙрдХ рдХрд░ рджреЗрдЧрд╛ред рдЖрдкрдХреЗ рдкрд╛рд╕ рдСрдбрд┐рдЯ рдХреЗ рд▓рд┐рдП raw payload рд░рд╣реЗрдЧрд╛, рдФрд░ parsed invoice ID рд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдкрд╣рд▓рд╛ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ invoice рд░рд┐рдХреЙрд░реНрдб рдорд┐рд▓ рдЬрд╛рдПрдЧрд╛ред

рдЪрд░рдг-рджрд░-рдЪрд░рдг: рдПрдХ рд╕реБрд░рдХреНрд╖рд┐рдд рд╡реЗрдмрд╣реБрдХ рд╣реИрдВрдбрд▓рд░ рдлреНрд▓реЛ

рдПрдХ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИрдВрдбрд▓рд░ рдЬрд╛рдирдмреВрдЭрдХрд░ рдиреАрд░рд╕ рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рд╣рд░ рдмрд╛рд░ рдПрдХ рдЬреИрд╕рд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддрд╛ рд╣реИ, рднрд▓реЗ рд╣реА рдкреНрд░реЛрд╡рд╛рдЗрдбрд░ рд╡рд╣реА рдЗрд╡реЗрдВрдЯ retries рдХрд░реЗ рдпрд╛ рдЗрд╡реЗрдВрдЯреНрд╕ рдЖрдЙрдЯ рдСрдлрд╝ рдСрд░реНрдбрд░ рдЖрдПрдВред

рд╣рд░ рдмрд╛рд░ рдкрд╛рд▓рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП 5-рд╕реНрдЯреЗрдк рдлреНрд▓реЛ

  1. рд╕рд┐рдЧреНрдиреЗрдЪрд░ рд╡реЗрд░рд┐рдлрд╝рд╛рдИ рдХрд░реЗрдВ рдФрд░ payload рдкрд╛рд░реНрд╕ рдХрд░реЗрдВред рдЬреЛ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ рд╕рд┐рдЧреНрдиреЗрдЪрд░ рдЪреЗрдХ рдлреЗрд▓ рдХрд░рддреА рд╣реИрдВ, рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рдЗрд╡реЗрдВрдЯ рдЯрд╛рдЗрдк рд╣реЛрддреА рд╣реИрдВ, рдпрд╛ рдкрд╛рд░реНрд╕ рдирд╣реАрдВ рд╣реЛ рдкрд╛ рд░рд╣реАрдВ, рдЙрдиреНрд╣реЗрдВ reject рдХрд░реЗрдВред

  2. рдмрд┐рд▓рд┐рдВрдЧ рдбреЗрдЯрд╛ рдЫреВрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЗрд╡реЗрдВрдЯ рд░рд┐рдХреЙрд░реНрдб рд▓рд┐рдЦреЗрдВред provider event ID, type, created time, рдФрд░ raw payload (рдпрд╛ рдЙрд╕рдХрд╛ hash) рд╕реЗрд╡ рдХрд░реЗрдВред рдЕрдЧрд░ event ID рдкрд╣рд▓реЗ рд╕реЗ рдореМрдЬреВрдж рд╣реИ, рддреЛ рдЗрд╕реЗ duplicate рдорд╛рдиреЗрдВ рдФрд░ рд░реБрдХреЗрдВред

  3. рдЗрд╡реЗрдВрдЯ рдХреЛ рдПрдХ single тАЬownerтАЭ рд░рд┐рдХреЙрд░реНрдб рд╕реЗ рдореИрдк рдХрд░реЗрдВред рддрдп рдХрд░реЗрдВ рдЖрдк рдХреНрдпрд╛ рдЕрдкрдбреЗрдЯ рдХрд░ рд░рд╣реЗ рд╣реИрдВ: invoice, subscription, рдпрд╛ customerред рдЕрдкрдиреЗ рд░рд┐рдХреЙрд░реНрдбреНрд╕ рдкрд░ external IDs рд╕реНрдЯреЛрд░ рд░рдЦреЗрдВ рддрд╛рдХрд┐ рдЖрдк рдЙрдиреНрд╣реЗрдВ рд╕реАрдзреЗ lookup рдХрд░ рд╕рдХреЗрдВред

  4. рдПрдХ рд╕реБрд░рдХреНрд╖рд┐рдд state change рд▓рд╛рдЧреВ рдХрд░реЗрдВред рдХреЗрд╡рд▓ рд╕реНрдЯреЗрдЯ рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛рдПрдБред рдПрдХ late "invoice.updated" рдХреЗ рдЖрдиреЗ рдкрд░ paid рд╣реБрдП invoice рдХреЛ undo рди рдХрд░реЗрдВред рдЬреЛ рдЖрдк рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ рдЙрд╕рдХрд╛ рд░рд┐рдХреЙрд░реНрдб рд░рдЦреЗрдВ (old state, new state, timestamp, event ID) рддрд╛рдХрд┐ audit рд╣реЛ рд╕рдХреЗред

  5. рддреЗрдЬрд╝реА рд╕реЗ рдЬрд╡рд╛рдм рджреЗрдВ рдФрд░ outcome рд▓реЙрдЧ рдХрд░реЗрдВред рдЗрд╡реЗрдВрдЯ рдХреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рд╕реНрдЯреЛрд░ рдХрд░ рд▓реЗрдиреЗ рдФрд░ рдпрд╛ рддреЛ рдкреНрд░реЛрд╕реЗрд╕ рдпрд╛ рдЗрдЧреНрдиреЛрд░ рдХрд░ рджреЗрдиреЗ рдХреЗ рдмрд╛рдж success рд▓реМрдЯрд╛рдПрдБред рд▓реЙрдЧ рдХрд░реЗрдВ рдХреНрдпрд╛ рдкреНрд░реЛрд╕реЗрд╕ рд╣реБрдЖ, deduped рд╣реБрдЖ, рдпрд╛ reject рд╣реБрдЖ, рдФрд░ рдХреНрдпреЛрдВред

AppMaster рдореЗрдВ рдпрд╣ рдЕрдХреНрд╕рд░ webhook events рдХреЗ рд▓рд┐рдП рдПрдХ DB рдЯреЗрдмрд▓ рдФрд░ рдПрдХ Business Process рдмрдирдХрд░ рдЖрддрд╛ рд╣реИ рдЬреЛ тАЬseen event ID?тАЭ рдЪреЗрдХ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рдиреНрдпреВрдирддрдо рдЕрдкрдбреЗрдЯ рд╕реНрдЯреЗрдкреНрд╕ рдЪрд▓рд╛рддрд╛ рд╣реИред

Retries, timeouts, рдФрд░ out of order delivery рдХреЛ рд╣реИрдВрдбрд▓ рдХрд░рдирд╛

Avoid duplicate access grants
Use drag-and-drop logic to keep invoice, subscription, and entitlement updates in sync.
Try AppMaster

рдкреНрд░реЛрд╡рд╛рдЗрдбрд░ рд╡реЗрдмрд╣реБрдХ рддрдм retries рдХрд░рддреЗ рд╣реИрдВ рдЬрдм рдЙрдиреНрд╣реЗрдВ рддреЗрдЬрд╝ success response рдирд╣реАрдВ рдорд┐рд▓рддрд╛ред рд╡реЗ рдЗрд╡реЗрдВрдЯреНрд╕ рдХреЛ рдЖрдЙрдЯ рдСрдлрд╝ рдСрд░реНрдбрд░ рднреА рднреЗрдЬ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдкрдХрд╛ рд╣реИрдВрдбрд▓рд░ рддрдм рднреА рд╕реБрд░рдХреНрд╖рд┐рдд рд░рд╣рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрдм рд╡рд╣реА рдЕрдкрдбреЗрдЯ рджреЛ рдмрд╛рд░ рдЖрдП, рдпрд╛ рдмрд╛рдж рд╡рд╛рд▓рд╛ рдЕрдкрдбреЗрдЯ рдкрд╣рд▓реЗ рдЖ рдЬрд╛рдПред

рдПрдХ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдирд┐рдпрдо: рддреЗрдЬрд╝реА рд╕реЗ рдЬрд╡рд╛рдм рджреЗрдВ, рднрд╛рд░реА рдХрд╛рдо рдмрд╛рдж рдореЗрдВ рдХрд░реЗрдВред рд╡реЗрдмрд╣реБрдХ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ рдХреЛ рдПрдХ рд░рд┐рд╕реАрдЯ рдХреА рддрд░рд╣ рдЯреНрд░реАрдЯ рдХрд░реЗрдВ, рди рдХрд┐ рднрд╛рд░реА рд▓реЙрдЬрд┐рдХ рдЪрд▓рд╛рдиреЗ рдХреА рдЬрдЧрд╣ред рдпрджрд┐ рдЖрдк рддреАрд╕рд░реЗ-рдкрдХреНрд╖ APIs рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, PDFs рдЬрдирд░реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдпрд╛ рдЕрдиреБрд░реЛрдз рдХреЗ рднреАрддрд░ рдЕрдХрд╛рдЙрдВрдЯреНрд╕ рдлрд┐рд░ рд╕реЗ рдХреИрд▓реНрдХреБрд▓реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЯрд╛рдЗрдордЖрдЙрдЯ рдмрдврд╝рд╛рддреЗ рд╣реИрдВ рдФрд░ рдФрд░ retries рдЯреНрд░рд┐рдЧрд░ рдХрд░рддреЗ рд╣реИрдВред

Out of order: рд╕рдмрд╕реЗ рдирдпрд╛ рд╕рдЪ рд░рдЦреЗрдВ

рдЖрдЙрдЯ-рдСрдл-рдСрд░реНрдбрд░ рдбрд┐рд▓реАрд╡рд░реА рд╕рд╛рдорд╛рдиреНрдп рд╣реИред рдХреЛрдИ рднреА рдмрджрд▓рд╛рд╡ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рджреЛ рдЪреЗрдХ рдХрд░реЗрдВ:

  • рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ: рдХреЗрд╡рд▓ рд╡рд╣реА рдЗрд╡реЗрдВрдЯ рд▓рд╛рдЧреВ рдХрд░реЗрдВ рдЬреЛ рдЙрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ (invoice, subscription, entitlement) рдХреЗ рд▓рд┐рдП рдЖрдкрдиреЗ рдкрд╣рд▓реЗ рд╕реНрдЯреЛрд░ рдХрд┐рдП рдЧрдП рд╕реЗ рдирдпрд╛ рд╣реЛред
  • рдЬрдм рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдХреНрд▓реЛрдЬрд╝ рдпрд╛ рдЕрд╕реНрдкрд╖реНрдЯ рд╣реЛрдВ рддреЛ рд╕реНрдерд┐рддрд┐ рдкреНрд░рд╛рдпреЛрд░рд┐рдЯреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ: paid, open рдХреЗ рдКрдкрд░ рд╣реИ; canceled active рд╕реЗ рдКрдкрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ; refunded рдХрд╛ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ paid рдкрд░ рд╣реЛред

рдЕрдЧрд░ рдЖрдкрдиреЗ рдкрд╣рд▓реЗ рд╣реА рдХрд┐рд╕реА invoice рдХреЛ paid рд░рд┐рдХреЙрд░реНрдб рдХрд┐рдпрд╛ рд╣реИ рдФрд░ рдПрдХ рд▓реЗрдЯ "open" рдЗрд╡реЗрдВрдЯ рдЖрддрд╛ рд╣реИ, рддреЛ рдЙрд╕реЗ рдЗрдЧреНрдиреЛрд░ рдХрд░реЗрдВред рдЕрдЧрд░ рдЖрдкрдиреЗ "canceled" рд░рд┐рдХреЙрд░реНрдб рдХрд┐рдпрд╛ рдФрд░ рдмрд╛рдж рдореЗрдВ рдХреЛрдИ рдкреБрд░рд╛рдирд╛ "active" рдЕрдкрдбреЗрдЯ рдЖрддрд╛ рд╣реИ, рддреЛ canceled рд░рдЦреЗрдВред

Ignore рдмрдирд╛рдо queue

рдЬрдм рдЖрдк рд╕рд╛рдмрд┐рдд рдХрд░ рд╕рдХреЗрдВ рдХрд┐ рдЗрд╡реЗрдВрдЯ stale рд╣реИ рдпрд╛ рдкрд╣рд▓реЗ рд╕реЗ рд▓рд╛рдЧреВ рд╣реИ (same event ID, older timestamp, lower status priority) рддреЛ рдЗрдЧреНрдиреЛрд░ рдХрд░реЗрдВред рдЬрдм рдЗрд╡реЗрдВрдЯ рдРрд╕реЗ рдбреЗрдЯрд╛ рдкрд░ рдирд┐рд░реНрднрд░ рд╣реЛ рдЬреЛ рдЕрднреА рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИ (рдЬреИрд╕реЗ subscription рдЕрдкрдбреЗрдЯ рдЙрд╕ рд╕реЗ рдкрд╣рд▓реЗ рдЖрдирд╛ рдЬрдм customer рд░рд┐рдХреЙрд░реНрдб рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИ) рддреЛ queue рдХрд░реЗрдВред

рдПрдХ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдкреИрдЯрд░реНрди:

  • рдЗрд╡реЗрдВрдЯ рдХреЛ рддреБрд░рдВрдд processing state рдХреЗ рд╕рд╛рде рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ (received, processing, done, failed)
  • рдЕрдЧрд░ dependencies рдЧрд╛рдпрдм рд╣реИрдВ, рддреЛ рдЙрд╕реЗ waiting рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рд░реНрдХ рдХрд░реЗрдВ рдФрд░ рдмреИрдХрдЧреНрд░рд╛рдЙрдВрдб рдореЗрдВ retry рдХрд░реЗрдВ
  • retry рд▓рд┐рдорд┐рдЯ рд╕реЗрдЯ рдХрд░реЗрдВ рдФрд░ рдмрд╛рд░-рдмрд╛рд░ рд╡рд┐рдлрд▓рддрд╛рдУрдВ рдХреЗ рдмрд╛рдж рдЕрд▓рд░реНрдЯ рдХрд░реЗрдВ

AppMaster рдореЗрдВ, рдпрд╣ рдПрдХ webhook events рддрд╛рд▓рд┐рдХрд╛ рдФрд░ рдПрдХ Business Process рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛ рдлрд┐рдЯ рд╣реИ рдЬреЛ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ рдХреЛ рдЬрд▓реНрджреА acknowledge рдХрд░рддрд╛ рд╣реИ рдФрд░ queued рдЗрд╡реЗрдВрдЯреНрд╕ рдХреЛ рдЕрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рддрд░реАрдХреЗ рд╕реЗ рдкреНрд░реЛрд╕реЗрд╕ рдХрд░рддрд╛ рд╣реИред

рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ invoices, subscriptions, рдФрд░ entitlements рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛

рдбреЗрдбреБрдкреНрд▓рд┐рдХреЗрд╢рди рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рдмрд╛рдж рдЕрдЧрд▓рд╛ рдЬреЛрдЦрд┐рдо split billing state рд╣реИ: invoice рдХрд╣рддрд╛ рд╣реИ paid, рдкрд░ subscription рдЕрднреА рднреА past due рд╣реИ, рдпрд╛ рдПрдХреНрд╕реЗрд╕ рджреЛ рдмрд╛рд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рдФрд░ рдХрднреА revoke рдирд╣реАрдВ рд╣реБрдЖред рд╣рд░ рд╡реЗрдмрд╣реБрдХ рдХреЛ рдПрдХ state transition рдХреЗ рд░реВрдк рдореЗрдВ рдЯреНрд░реАрдЯ рдХрд░реЗрдВ рдФрд░ рдЙрд╕реЗ рдПрдХ atomic рдЕрдкрдбреЗрдЯ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░реЗрдВред

Invoices: status changes рдХреЛ monotonic рдмрдирд╛рдПрдВ

Invoices paid, voided, рдФрд░ refunded рдЬреИрд╕реА рд╕реНрдЯреЗрдЯреНрд╕ рд╕реЗ рдЧреБрдЬрд░рддреЗ рд╣реИрдВред рдЖрдк partial payments рднреА рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рдХрд┐рд╕реА рднреА рдЗрд╡реЗрдВрдЯ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ invoice рдХреЛ рдмрджрд▓рддреЗ рд╡рдХреНрдд рдЙрд╕реЗ toggle рди рдХрд░реЗрдВред current status рдФрд░ key totals (amount_paid, amount_refunded) рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ рдФрд░ рдХреЗрд╡рд▓ рдЖрдЧреЗ-рд╕реБрд░рдХреНрд╖рд┐рдд transitions рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВред

рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдирд┐рдпрдо:

  • рдПрдХ invoice рдХреЛ рдХреЗрд╡рд▓ рдкрд╣рд▓реА рдмрд╛рд░ paid рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рд░реНрдХ рдХрд░реЗрдВ рдЬрдм рдЖрдк paid рдЗрд╡реЗрдВрдЯ рдкрд╣рд▓реА рдмрд╛рд░ рджреЗрдЦреЗрдВред
  • refunds рдХреЗ рд▓рд┐рдП, amount_refunded рдХреЛ invoice рдХреБрд▓ рддрдХ рдмрдврд╝рд╛рдПрдБ; рдХрднреА рдШрдЯрд╛рдПрдБ рдирд╣реАрдВред
  • рдЕрдЧрд░ рдХреЛрдИ invoice voided рд╣реИ, рддреЛ fulfillment actions рдмрдВрдж рдХрд░ рджреЗрдВ, рдкрд░ рд░рд┐рдХреЙрд░реНрдб audit рдХреЗ рд▓рд┐рдП рд░рдЦреЗрдВред
  • partial payments рдХреЗ рд▓рд┐рдП, amounts рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ рдкрд░ тАЬfully paidтАЭ рд▓рд╛рдн рди рджреЗрдВ рдЬрдм рддрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреВрд░реНрдг рднреБрдЧрддрд╛рди рди рд╣реЛред

Subscriptions рдФрд░ entitlements: рдПрдХ рдмрд╛рд░ рджреЗрдирд╛, рдПрдХ рдмрд╛рд░ рд╣рдЯрд╛рдирд╛

Subscriptions рдореЗрдВ renewals, cancellations, рдФрд░ grace periods рдЖрддреЗ рд╣реИрдВред subscription status рдФрд░ рдЕрд╡рдзрд┐ рдХреА рд╕реАрдорд╛рдПрдБ (current_period_start/end) рд░рдЦреЗрдВ, рдФрд░ рдЙрди рдбреЗрдЯрд╛ рд╕реЗ entitlement windows рдирд┐рдХрд╛рд▓реЗрдВред Entitlements рд╕реНрдкрд╖реНрдЯ рд░рд┐рдХреЙрд░реНрдб рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП, рди рдХрд┐ рд╕рд┐рд░реНрдлрд╝ рдПрдХ booleanред

рдПрдХреНрд╕реЗрд╕ рдХрдВрдЯреНрд░реЛрд▓ рдХреЗ рд▓рд┐рдП:

  • рдкреНрд░рддрд┐ user рдкреНрд░рддрд┐ product рдкреНрд░рддрд┐ period рдПрдХ entitlement grant
  • рдЬрдм рдПрдХреНрд╕реЗрд╕ рдЦрд╝рддреНрдо рд╣реЛ (cancellation, refund, chargeback) рддреЛ рдПрдХ revocation рд░рд┐рдХреЙрд░реНрдб
  • рдПрдХ audit trail рдЬреЛ рд░рд┐рдХреЙрд░реНрдб рдХрд░реЗ рдХрд┐ рдХрд┐рд╕ webhook рдЗрд╡реЗрдВрдЯ рдиреЗ рд╣рд░ рдмрджрд▓рд╛рд╡ рдХрд┐рдпрд╛

рд╡рд┐рднрд╛рдЬрди рд╕реНрдерд┐рддрд┐ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЯреНрд░рд╛рдВрдЬрд╝реИрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ

Invoice, subscription, рдФрд░ entitlement рдЕрдкрдбреЗрдЯ рдПрдХ рд╣реА рдбреЗрдЯрд╛рдмреЗрд╕ рдЯреНрд░рд╛рдВрдЬрд╝реИрдХреНрд╢рди рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рд╡рд░реНрддрдорд╛рди rows рдкрдврд╝реЗрдВ, рдЪреЗрдХ рдХрд░реЗрдВ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдЗрд╡реЗрдВрдЯ рдкрд╣рд▓реЗ рд╕реЗ рд▓рд╛рдЧреВ рд╣реИ, рдлрд┐рд░ рд╕рднреА рдЪреЗрдВрдЬреЗрдЬрд╝ рдПрдХ рд╕рд╛рде рд▓рд┐рдЦреЗрдВред рдЕрдЧрд░ рдХреБрдЫ рдлреЗрд▓ рд╣реЛрддрд╛ рд╣реИ, рддреЛ roll back рдХрд░реЗрдВ рддрд╛рдХрд┐ рдЖрдк тАЬpaid invoice рдкрд░ рдХреЛрдИ рдПрдХреНрд╕реЗрд╕ рдирд╣реАрдВтАЭ рдпрд╛ рдЙрд▓реНрдЯрд╛ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рди рдЖрдПрдБред

AppMaster рдореЗрдВ, рдпрд╣ рдЕрдХреНрд╕рд░ рдПрдХ Business Process рдлреНрд▓реЛ рдХреЗ рд░реВрдк рдореЗрдВ рдореЙрдбрд▓ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ PostgreSQL рдХреЛ рдПрдХ рдирд┐рдпрдВрддреНрд░рд┐рдд рдкрде рдореЗрдВ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдмрд┐рдЬрдиреЗрд╕ рдЪреЗрдВрдЬ рдХреЗ рд╕рд╛рде рдПрдХ audit entry рд▓рд┐рдЦрддрд╛ рд╣реИред

рд╡реЗрдмрд╣реБрдХ endpoints рдХреЗ рд▓рд┐рдП рд╕реБрд░рдХреНрд╖рд╛ рдФрд░ рдбреЗрдЯрд╛ рд╕реБрд░рдХреНрд╖рд╛ рдЪреЗрдХ

Keep billing states consistent
Set up monotonic invoice statuses and refund handling that stays correct under replays.
Start Now

рд╡реЗрдмрд╣реБрдХ рд╕реБрд░рдХреНрд╖рд╛ correctness рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред рдЕрдЧрд░ рдХреЛрдИ attacker рдЖрдкрдХреЗ endpoint рдХреЛ рд╣рд┐рдЯ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рддреЛ рд╡рд╣ рдирдХрд▓реА тАЬpaidтАЭ рд╕реНрдЯреЗрдЯреНрд╕ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рднрд▓реЗ рд╣реА рдбреЗрдбреБрдкреНрд▓рд┐рдХреЗрд╢рди рд╣реЛ, рдЖрдкрдХреЛ рдЗрд╡реЗрдВрдЯ рдЕрд╕рд▓реА рд╣реИ рдпрд╣ рд╕рд╛рдмрд┐рдд рдХрд░рдирд╛ рдФрд░ рдЧреНрд░рд╛рд╣рдХ рдбреЗрдЯрд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░рдЦрдирд╛ рдЬрд╝рд░реВрд░реА рд╣реИред

рдмрд┐рд▓рд┐рдВрдЧ рдбреЗрдЯрд╛ рдЫреВрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рднреЗрдЬрдиреЗ рд╡рд╛рд▓реЗ рдХреА рд╕рддреНрдпрддрд╛ рдЬрд╛рдБрдЪреЗрдВ

рд╣рд░ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ рдкрд░ рд╕рд┐рдЧреНрдиреЗрдЪрд░ рд╡реЗрд░рд┐рдлрд╝рд╛рдИ рдХрд░реЗрдВред Stripe рдХреЗ рд▓рд┐рдП рдпрд╣ рдЖрдо рддреМрд░ рдкрд░ Stripe-Signature рд╣реЗрдбрд░ рдЪреЗрдХ рдХрд░рдиреЗ, raw request body (рди рдХрд┐ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдпреА рдЧрдИ JSON) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ, рдФрд░ рдкреБрд░рд╛рдиреЗ timestamp рд╡рд╛рд▓реЗ рдЗрд╡реЗрдВрдЯреНрд╕ рдХреЛ reject рдХрд░рдиреЗ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рддрд╛ рд╣реИред рдорд┐рд╕рд┐рдВрдЧ рд╣реЗрдбрд░реНрд╕ рдХреЛ рд╣рд╛рд░реНрдб рдлрд╝реЗрд▓ рдорд╛рдиреЗрдВред

рд╢реБрд░реВ рдореЗрдВ рдмреЗрд╕рд┐рдХреНрд╕ рд╡реИрд░рд┐рдлрд╝рд╛рдИ рдХрд░реЗрдВ: рд╕рд╣реА HTTP method, Content-Type, рдФрд░ required fields (event id, type, рдФрд░ рд╡рд╣ object id рдЬрд┐рд╕рдХрд╛ рдЖрдк invoice рдпрд╛ subscription рдвреВрдБрдврдиреЗ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ)ред рдЕрдЧрд░ рдЖрдк рдЗрд╕реЗ AppMaster рдореЗрдВ рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВ, рддреЛ signing secret рдХреЛ environment variables рдпрд╛ secure config рдореЗрдВ рд░рдЦреЗрдВ, рдХрднреА DB рдпрд╛ client code рдореЗрдВ рди рд░рдЦреЗрдВред

рдПрдХ рддреНрд╡рд░рд┐рдд рд╕реБрд░рдХреНрд╖рд╛ рдЪреЗрдХрд▓рд┐рд╕реНрдЯ:

  • рд╡реИрдз рд╕рд┐рдЧреНрдиреЗрдЪрд░ рдФрд░ рддрд╛рдЬрд╝рд╛ timestamp рдХреЗ рдмрд┐рдирд╛ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ reject рдХрд░реЗрдВ
  • рдЕрдкреЗрдХреНрд╖рд┐рдд рд╣реЗрдбрд░реНрд╕ рдФрд░ content type рдХреА рдорд╛рдБрдЧ рдХрд░реЗрдВ
  • webhook handler рдХреЗ рд▓рд┐рдП least-privilege DB access рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
  • secrets рдХреЛ рдЯреЗрдмрд▓реНрд╕ рдХреЗ рдмрд╛рд╣рд░ рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ (env/config), рдФрд░ рдЖрд╡рд╢реНрдпрдХрддрд╛рдиреБрд╕рд╛рд░ rotate рдХрд░реЗрдВ
  • рдХреЗрд╡рд▓ рддрдм 2xx рд▓реМрдЯрд╛рдПрдБ рдЬрдм рдЖрдкрдиреЗ рдЗрд╡реЗрдВрдЯ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ persist рдХрд░ рд▓рд┐рдпрд╛ рд╣реЛ

рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рдЬрд╛рдирдХрд╛рд░реА рд▓реАрдХ рдХрд┐рдП рдмрд┐рдирд╛ рд▓реЙрдЧреНрд╕ рдЙрдкрдпреЛрдЧреА рд░рдЦреЗрдВ

Retries рдФрд░ рд╡рд┐рд╡рд╛рджреЛрдВ рдХреЛ рдбрд┐рдмрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд▓реЙрдЧ рд░рдЦреЗрдВ, рдкрд░ рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рдорд╛рди рди рд░рдЦреЗрдВред PII рдХрд╛ рдПрдХ рд╕реБрд░рдХреНрд╖рд┐рдд subset рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ: provider customer ID, internal user ID, рдФрд░ рд╢рд╛рдпрдж рдПрдХ masked email (рдЬреИрд╕реЗ a***@domain.com)ред рдХрднреА рднреА рдкреВрд░рд╛ рдХрд╛рд░реНрдб рдбреЗрдЯрд╛, рдкреВрд░рд╛ рдкрддрд╛, рдпрд╛ raw authorization headers рд╕реНрдЯреЛрд░ рди рдХрд░реЗрдВред

рд▓реЙрдЧ рд░рдЦреЗрдВ рдЬреЛ рдЖрдкрдХреЛ рдШрдЯрдирд╛ reconstruct рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗ:

  • Provider event id, type, created time
  • Verification result (signature ok/failed) рдмрд┐рдирд╛ signature рд╕реНрдЯреЛрд░ рдХрд┐рдП
  • Dedupe рдирд┐рд░реНрдгрдп (рдирдпрд╛ рдмрдирд╛рдо рдкрд╣рд▓реЗ рд╕реЗ рдкреНрд░реЛрд╕реЗрд╕ рдХрд┐рдпрд╛ рд╣реБрдЖ)
  • рдкреНрд░рднрд╛рд╡рд┐рдд internal record IDs (invoice/subscription/entitlement)
  • Error reason рдФрд░ retry count (рдЕрдЧрд░ рдЖрдк retries queue рдХрд░рддреЗ рд╣реИрдВ)

рдмреБрдирд┐рдпрд╛рджреА abuse protection рдЬреЛрдбрд╝реЗрдВ: IP рджреНрд╡рд╛рд░рд╛ rate limit рдХрд░реЗрдВ рдФрд░ (рдЬрдм рд╕рдВрднрд╡ рд╣реЛ) customer ID рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рднреА rate limit рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ, рдФрд░ рдЕрдЧрд░ рдЖрдкрдХреА рд╕реЗрдЯрдЕрдк рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ рддреЛ рдХреЗрд╡рд▓ рдЬреНрдЮрд╛рдд provider IP ranges рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдирд╛ рд╕реЛрдЪреЗрдВред

рдбрдмрд▓ рдЪрд╛рд░реНрдЬ рдпрд╛ рдбрдмрд▓ рдПрдХреНрд╕реЗрд╕ рдХрд╛ рдХрд╛рд░рдг рдмрдирдиреЗ рд╡рд╛рд▓реА рдЖрдо рдЧрд▓рддрд┐рдпрд╛рдБ

Ship a secure webhook endpoint
Verify signatures first, store events, then apply one atomic state change.
Build Flow

рдЬрд╝реНрдпрд╛рджрд╛рддрд░ рдмрд┐рд▓рд┐рдВрдЧ рдмрдЧреНрд╕ рдЧрдгрд┐рдд рдХреА рд╡рдЬрд╣ рд╕реЗ рдирд╣реАрдВ рд╣реЛрддреЗред рд╡реЗ рддрдм рд╣реЛрддреЗ рд╣реИрдВ рдЬрдм рдЖрдк рд╡реЗрдмрд╣реБрдХ рдбрд┐рд▓реАрд╡рд░реА рдХреЛ рдПрдХ рдПрдХрд▓, рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд╕рдВрджреЗрд╢ рдХреА рддрд░рд╣ рдорд╛рди рд▓реЗрддреЗ рд╣реИрдВред

рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдЕрдкрдбреЗрдЯреНрд╕ рдХрд╛ рд╕рдмрд╕реЗ рдЖрдо рдХрд╛рд░рдг рдмрдирдиреЗ рд╡рд╛рд▓реА рдЧрд▓рддрд┐рдпрд╛рдБ:

  • рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдпрд╛ рд░рд╛рд╢рд┐ рд╕реЗ рдбреЗрдбреБрдк рдХрд░рдирд╛ рдмрдЬрд╛рдп event ID рдХреЗред рдЕрд▓рдЧ рдЗрд╡реЗрдВрдЯреНрд╕ рдореЗрдВ рд╡рд╣реА рд░рд╛рд╢рд┐ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдФрд░ retries рдорд┐рдирдЯ рдмрд╛рдж рдЖ рд╕рдХрддреЗ рд╣реИрдВред рдкреНрд░рджрд╛рддрд╛ рдХреЗ unique event ID рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
  • рд╕рд┐рдЧреНрдиреЗрдЪрд░ рд╡реЗрд░рд┐рдлрд╝рд╛рдИ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ DB рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ред рдкрд╣рд▓реЗ рд╡реЗрд░рд┐рдлрд╝рд╛рдИ рдХрд░реЗрдВ, рдлрд┐рд░ рдкрд╛рд░реНрд╕ рдХрд░реЗрдВ, рдлрд┐рд░ рдПрдХреНрдЯ рдХрд░реЗрдВред
  • рд╣рд░ рдЗрд╡реЗрдВрдЯ рдХреЛ рд╕рддреНрдп рдХреЗ рд╕реНрд░реЛрдд рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирдирд╛ рдмрд┐рдирд╛ current state рдЪреЗрдХ рдХрд┐рдПред рдЕрдЧрд░ invoice рдкрд╣рд▓реЗ рд╕реЗ paid, refunded, рдпрд╛ void рд╣реИ рддреЛ рдЙрд╕реЗ рдЕрдВрдзрд╛рдзреБрдВрдз paid рди рдорд╛рд░реНрдХ рдХрд░реЗрдВред
  • рдПрдХ рд╣реА рдЦрд░реАрдж рдХреЗ рд▓рд┐рдП рдХрдИ entitlements рдмрдирд╛рдирд╛ред Retries duplicate rows рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рдПрдХ upsert рдЕрдкрдирд╛рдПрдБ рдЬреИрд╕реЗ тАЬensure entitlement exists for subscription_idтАЭ, рдлрд┐рд░ dates/limits рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВред
  • рд╡реЗрдмрд╣реБрдХ fail рдХрд░ рдЬрд╛рдирд╛ рдХреНрдпреЛрдВрдХрд┐ notification service рдбрд╛рдЙрди рд╣реИред рдИрдореЗрд▓, SMS, Slack, рдпрд╛ Telegram рдмрд┐рд▓рд┐рдВрдЧ рдХреЛ рдмреНрд▓реЙрдХ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдиреЛрдЯрд┐рдлрд╝рд┐рдХреЗрд╢рдВрд╕ рдХреЛ queue рдХрд░реЗрдВ рдФрд░ core billing changes рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рд╕реНрдЯреЛрд░ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж success рд▓реМрдЯрд╛рдПрдБред

рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЙрджрд╛рд╣рд░рдг: рдПрдХ renewal рдЗрд╡реЗрдВрдЯ рджреЛ рдмрд╛рд░ рдЖрддрд╛ рд╣реИред рдкрд╣рд▓реА рдбрд┐рд▓реАрд╡рд░реА entitlement row рдмрдирд╛рддреА рд╣реИред retry рджреВрд╕рд░реА row рдмрдирд╛ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдЖрдкрдХреА рдРрдк тАЬрджреЛ active entitlementsтАЭ рджреЗрдЦрдХрд░ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реАрдЯреНрд╕ рдпрд╛ рдХреНрд░реЗрдбрд┐рдЯ рджреЗ рджреЗрддреА рд╣реИред

AppMaster рдореЗрдВ, рдлрд┐рдХреНрд╕ рдЕрдзрд┐рдХрддрд░ рдлреНрд▓реЛ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реЛрддрд╛ рд╣реИ: рдкрд╣рд▓реЗ verify рдХрд░реЗрдВ, unique constraint рдХреЗ рд╕рд╛рде event рд░рд┐рдХреЙрд░реНрдб insert рдХрд░реЗрдВ, state checks рдХреЗ рд╕рд╛рде billing updates рд▓рд╛рдЧреВ рдХрд░реЗрдВ, рдФрд░ side effects (рдЗрдореЗрд▓, рд░рд╕реАрджреЗрдВ) рдХреЛ async рд╕реНрдЯреЗрдкреНрд╕ рдореЗрдВ рдбрд╛рд▓реЗрдВ рддрд╛рдХрд┐ рд╡реЗ retry storm рди рдЯреНрд░рд┐рдЧрд░ рдХрд░ рд╕рдХреЗрдВред

рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЙрджрд╛рд╣рд░рдг: duplicate renewal + рдмрд╛рдж рдореЗрдВ refund

рдпрд╣ рдкреИрдЯрд░реНрди рдбрд░рд╛рд╡рдирд╛ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ, рдкрд░ рдЕрдЧрд░ рдЖрдкрдХрд╛ рд╣реИрдВрдбрд▓рд░ рджреЛрдмрд╛рд░рд╛ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИ рддреЛ рдпрд╣ рд╕рдВрднрд╛рд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдПрдХ рдЧреНрд░рд╛рд╣рдХ рдорд╛рд╕рд┐рдХ рдкреНрд▓рд╛рди рдкрд░ рд╣реИред Stripe рдПрдХ renewal рдЗрд╡реЗрдВрдЯ рднреЗрдЬрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, invoice.paid)ред рдЖрдкрдХрд╛ рд╕рд░реНрд╡рд░ рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ, рдбреЗрдЯрд╛рдмреЗрд╕ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИ, рдкрд░ 200 рд▓реМрдЯрд╛рдиреЗ рдореЗрдВ рдмрд╣реБрдд рд╕рдордп рд▓реЗрддрд╛ рд╣реИ (cold start, рд╡реНрдпрд╕реНрдд DB)ред Stripe рдЗрд╕реЗ рдлреЗрд▓ рдорд╛рдирдХрд░ рд╡рд╣реА рдЗрд╡реЗрдВрдЯ retry рдХрд░ рджреЗрддрд╛ рд╣реИред

рдкрд╣рд▓реА рдбрд┐рд▓реАрд╡рд░реА рдкрд░ рдЖрдк рдПрдХреНрд╕реЗрд╕ рджреЗ рджреЗрддреЗ рд╣реИрдВред retry рдкрд░ рдЖрдк рдкрд╣рдЪрд╛рди рд▓реЗрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рд╡рд╣реА рдЗрд╡реЗрдВрдЯ рд╣реИ рдФрд░ рдХреБрдЫ рдирд╣реАрдВ рдХрд░рддреЗред рдмрд╛рдж рдореЗрдВ, рдПрдХ refund рдЗрд╡реЗрдВрдЯ рдЖрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, charge.refunded) рдФрд░ рдЖрдк рдПрдХ рдмрд╛рд░ рдПрдХреНрд╕реЗрд╕ revoke рдХрд░ рджреЗрддреЗ рд╣реИрдВред

рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╕реНрдЯреЗрдЯ рдореЙрдбрд▓ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╕рд░рд▓ рддрд░реАрдХрд╛ (AppMaster Data Designer рдореЗрдВ рдмрдирд╛рдиреЗ рдпреЛрдЧреНрдп рддрд╛рд▓рд┐рдХрд╛рдПрдБ):

  • webhook_events(event_id UNIQUE, type, processed_at, status)
  • invoices(invoice_id UNIQUE, subscription_id, status, paid_at, refunded_at)
  • entitlements(customer_id, product, active, valid_until, source_invoice_id)

рд╣рд░ рдЗрд╡реЗрдВрдЯ рдХреЗ рдмрд╛рдж рдбреЗрдЯрд╛рдмреЗрд╕ рдХреИрд╕рд╛ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП

Event A (renewal, рдкрд╣рд▓реА рдбрд┐рд▓реАрд╡рд░реА) рдХреЗ рдмрд╛рдж: webhook_events рдореЗрдВ event_id=evt_123 рдХреЗ рд▓рд┐рдП рдПрдХ рдирдИ row status=processed рдХреЗ рд╕рд╛рдеред invoices рдХреЛ paid рдорд╛рд░реНрдХ рдХрд┐рдпрд╛ рдЧрдпрд╛ред entitlements.active=true рдФрд░ valid_until рдПрдХ рдмрд┐рд▓рд┐рдВрдЧ рдкреАрд░рд┐рдпрдб рдЖрдЧреЗ рдЪрд▓рд╛ рдЧрдпрд╛ред

Event A рдлрд┐рд░ рд╕реЗ (renewal, retry) рдХреЗ рдмрд╛рдж: webhook_events рдореЗрдВ insert рдлреЗрд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ (unique event_id) рдпрд╛ рдЖрдкрдХрд╛ рд╣реИрдВрдбрд▓рд░ рджреЗрдЦрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рдкреНрд░реЛрд╕реЗрд╕ рдХрд┐рдпрд╛ рдЬрд╛ рдЪреБрдХрд╛ рд╣реИред invoices рдпрд╛ entitlements рдореЗрдВ рдХреЛрдИ рдкрд░рд┐рд╡рд░реНрддрди рдирд╣реАрдВ рд╣реЛрддрд╛ред

Event B (refund) рдХреЗ рдмрд╛рдж: webhook_events рдореЗрдВ event_id=evt_456 рдХреЗ рд▓рд┐рдП рдирдИ rowред invoices.refunded_at рд╕реЗрдЯ рд╣реЛрддрд╛ рд╣реИ рдФрд░ status=refundedред entitlements.active=false (рдпрд╛ valid_until рдЕрдм) рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ source_invoice_id рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд╣реА рдПрдХреНрд╕реЗрд╕ рдПрдХ рдмрд╛рд░ revoke рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ dedupe рдЪреЗрдХ рдХрд┐рд╕реА рднреА grant рдпрд╛ revoke рд▓рд┐рдЦрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╣реЛрддрд╛ рд╣реИред

рдкреНрд░реА-рд▓реЙрдиреНрдЪ рддреНрд╡рд░рд┐рдд рдЪреЗрдХрд▓рд┐рд╕реНрдЯ

Handle retries the right way
Create a backend that can handle retries without double updates or split billing states.
Create Backend

рд▓рд╛рдЗрд╡ рд╡реЗрдмрд╣реБрдХ рдЪрд╛рд▓реВ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЖрдк рдпрд╣ рдкреНрд░рдорд╛рдгрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗ рдХрд┐ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╡рд░реНрд▓реНрдб рдЗрд╡реЗрдВрдЯ рдмрд┐рд▓рд┐рдВрдЧ рд░рд┐рдХреЙрд░реНрдбреНрд╕ рдХреЛ рдареАрдХ рдПрдХ рдмрд╛рд░ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИ, рднрд▓реЗ рд╣реА рдкреНрд░реЛрд╡рд╛рдЗрдбрд░ рдЙрд╕реЗ рджреЛ рдмрд╛рд░ (рдпрд╛ рджрд╕ рдмрд╛рд░) рднреЗрдЬ рджреЗред

рдЗрд╕ рдЪреЗрдХрд▓рд┐рд╕реНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдкрдиреЗ рд╕реЗрдЯрдЕрдк рдХреЛ end-to-end validate рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░реЗрдВ:

  • рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рд╣рд░ рдЖрдиреЗ рд╡рд╛рд▓рд╛ рдЗрд╡реЗрдВрдЯ рдкрд╣рд▓реЗ рд╕реЗрд╡ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (raw payload, event id, type, created time, рдФрд░ signature verification result), рднрд▓реЗ рд╣реА рдмрд╛рдж рдХреЗ рд╕реНрдЯреЗрдк рдлреЗрд▓ рд╣реЛрдВред
  • рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░реЗрдВ рдХрд┐ duplicates рдЬрд▓реНрджреА рдкрд╣рдЪрд╛рдиреЗ рдЬрд╛рддреЗ рд╣реИрдВ (same provider event id) рдФрд░ рд╣реИрдВрдбрд▓рд░ рдмрд┐рдирд╛ invoices, subscriptions, рдпрд╛ entitlements рдмрджрд▓реЗ рдирд┐рдХрд▓ рдЬрд╛рддрд╛ рд╣реИред
  • рд╕рд╛рдмрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдмрд┐рдЬрдиреЗрд╕ рдЕрдкрдбреЗрдЯ рдПрдХ-рдмрд╛рд░ рд╣реА рд╣реИ: рдПрдХ invoice status change, рдПрдХ subscription state change, рдПрдХ entitlement grant рдпрд╛ revokeред
  • рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдлреЗрд▓реНрдпрд░реНрд╕ рдЗрддрдиреЗ рдбрд┐рдЯреЗрд▓ рдХреЗ рд╕рд╛рде рд░рд┐рдХреЙрд░реНрдб рд╣реЛрдВ рдХрд┐ рдЙрдиреНрд╣реЗрдВ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ replay рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ (error message, failed step, retry status)ред
  • рдЯреЗрд╕реНрдЯ рдХрд░реЗрдВ рдХрд┐ рдЖрдкрдХрд╛ рд╣реИрдВрдбрд▓рд░ рддреЗрдЬрд╝реА рд╕реЗ рд░рд┐рд╕реНрдкреЙрдиреНрдб рдХрд░рддрд╛ рд╣реИ: рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд░рд┐рд╕реАрдЯ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░реЗрдВ, рдФрд░ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ рдХреЗ рдЕрдВрджрд░ рдзреАрдорд╛ рдХрд╛рдо рдХрд░рдиреЗ рд╕реЗ рдмрдЪреЗрдВред

рдЖрдкрдХреЛ рдмрдбрд╝реА observability рд╕реЗрдЯрдЕрдк рдХреА рдЬрд╝рд░реВрд░рдд рдирд╣реАрдВ рд╣реИ, рдкрд░ рд╕рдВрдХреЗрдд рдЪрд╛рд╣рд┐рдПред рд▓реЙрдЧреНрд╕ рдпрд╛ рд╕рд░рд▓ рдбреИрд╢рдмреЛрд░реНрдб рд╕реЗ рдпреЗ рдЯреНрд░реИрдХ рдХрд░реЗрдВ:

  • duplicate deliveries рдореЗрдВ spike (рдЖрдо рд╣реИ, рдкрд░ рдмрдбрд╝реЗ рдЙрдЫрд╛рд▓ timeouts рдпрд╛ рдкреНрд░реЛрд╡рд╛рдЗрдбрд░ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рд╕рдВрдХреЗрдд рджреЗ рд╕рдХрддреЗ рд╣реИрдВ)
  • event type рджреНрд╡рд╛рд░рд╛ рдЙрдЪреНрдЪ error rate (рдЙрджрд╛рд╣рд░рдг: invoice payment failed)
  • retries рдореЗрдВ рдлрдБрд╕реЗ рдЗрд╡реЗрдВрдЯреНрд╕ рдХрд╛ рдмрдврд╝рддрд╛ backlog
  • mismatch checks (paid invoice рдкрд░ missing entitlement, revoked subscription рдкрд░ рдЕрднреА рднреА active access)
  • processing time рдореЗрдВ рдЕрдЪрд╛рдирдХ рд╡реГрджреНрдзрд┐

рдЕрдЧрд░ рдЖрдк AppMaster рдореЗрдВ рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдЗрд╡реЗрдВрдЯ рд╕рдВрдЧреНрд░рд╣рдг рдХреЛ Data Designer рдореЗрдВ рдПрдХ рд╕рдорд░реНрдкрд┐рдд рдЯреЗрдмрд▓ рдореЗрдВ рд░рдЦреЗрдВ рдФрд░ тАЬmark processedтАЭ рдХреЛ рдЕрдкрдиреЗ Business Process рдореЗрдВ рдПрдХ рд╕рд┐рдВрдЧрд▓, рдПрдЯреЙрдорд┐рдХ рдирд┐рд░реНрдгрдп рдмрд┐рдВрджреБ рдмрдирд╛рдПрдВред

рдЖрдЧреЗ рдХреЗ рдХрджрдо: рдЯреЗрд╕реНрдЯ рдХрд░реЗрдВ, рдореЙрдирд┐рдЯрд░ рдХрд░реЗрдВ, рдФрд░ рдЗрд╕реЗ рдиреЛ-рдХреЛрдб рдмреИрдХрдПрдВрдб рдореЗрдВ рдмрдирд╛рдПрдВ

рдЯреЗрд╕реНрдЯрд┐рдВрдЧ рд╡рд╣ рдЬрдЧрд╣ рд╣реИ рдЬрд╣рд╛рдБ idempotency рдЦреБрдж рдХреЛ рд╕рд╛рдмрд┐рдд рдХрд░рддреА рд╣реИред рдХреЗрд╡рд▓ happy path рди рдЪрд▓рд╛рдПрдБред рдПрдХ рд╣реА рдЗрд╡реЗрдВрдЯ рдХреЛ рдХрдИ рдмрд╛рд░ replay рдХрд░реЗрдВ, рдЗрд╡реЗрдВрдЯреНрд╕ рдХреЛ рдЖрдЙрдЯ рдСрдлрд╝ рдСрд░реНрдбрд░ рднреЗрдЬреЗрдВ, рдФрд░ timeouts рдлреЛрд░реНрд╕ рдХрд░реЗрдВ рддрд╛рдХрд┐ рдЖрдкрдХрд╛ рдкреНрд░реЛрд╡рд╛рдЗрдбрд░ retries рдХрд░реЗред рджреВрд╕рд░реА, рддреАрд╕рд░реА, рдФрд░ рджрд╕рд╡реАрдВ рдбрд┐рд▓реАрд╡рд░реА рдХреБрдЫ рднреА рдирд╣реАрдВ рдмрджрд▓рдиреА рдЪрд╛рд╣рд┐рдПред

рдмреИрдХрдлрд╝рд┐рд▓рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдЬрд▓реНрджреА рд╕реЗ рдпреЛрдЬрдирд╛ рдмрдирд╛рдПрдВред рдХрд┐рд╕реА рдмрдЧ рдлрд┐рдХреНрд╕, рд╕реНрдХреАрдорд╛ рдмрджрд▓рд╛рд╡, рдпрд╛ рдкреНрд░реЛрд╡рд╛рдЗрдбрд░ рдШрдЯрдирд╛ рдХреЗ рдмрд╛рдж рдЖрдкрдХреЛ рдкреБрд░рд╛рдиреЗ рдЗрд╡реЗрдВрдЯреНрд╕ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкреНрд░реЛрд╕реЗрд╕ рдХрд░рдирд╛ рдкрдбрд╝ рд╕рдХрддрд╛ рд╣реИред рдЕрдЧрд░ рдЖрдкрдХрд╛ рд╣реИрдВрдбрд▓рд░ рд╕рдЪрдореБрдЪ idempotent рд╣реИ, рддреЛ backfilling рдХрд╛ рдЕрд░реНрде рд╣реЛрддрд╛ рд╣реИ тАЬрдЙрд╕реА рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╡реЗрдВрдЯреНрд╕ рдХреЛ replay рдХрд░рдирд╛тАЭ рдмрд┐рдирд╛ duplicates рдмрдирд╛рдПред

рд╕рдкреЛрд░реНрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯрд╛ рд░рдирдмреБрдХ рд░рдЦреЗрдВ рддрд╛рдХрд┐ рд╕рдорд╕реНрдпрд╛рдПрдБ рдЕрдиреБрдорд╛рди рдкрд░ рди рдЯрд┐рдХреА рд░рд╣реЗрдВ:

  • рдЗрд╡реЗрдВрдЯ ID рдЦреЛрдЬреЗрдВ рдФрд░ рдЬрд╛рдБрдЪреЗрдВ рдХрд┐ рдХреНрдпрд╛ рд╡рд╣ processed рдХреЗ рд░реВрдк рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рд╣реИ
  • invoice рдпрд╛ subscription рд░рд┐рдХреЙрд░реНрдб рджреЗрдЦреЗрдВ рдФрд░ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╕реНрдерд┐рддрд┐ рдФрд░ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░реЗрдВ
  • entitlement рд░рд┐рдХреЙрд░реНрдб рджреЗрдЦреЗрдВ (рдХрдм рдФрд░ рдХреНрдпреЛрдВ рдПрдХреНрд╕реЗрд╕ рджрд┐рдпрд╛ рдЧрдпрд╛)
  • рдЬрд░реВрд░рдд рдкрдбрд╝реЗ рддреЛ рд╕реБрд░рдХреНрд╖рд┐рдд reprocess рдореЛрдб рдореЗрдВ рд╕рд┐рд░реНрдлрд╝ рдЙрд╕реА single event ID рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдлрд┐рд░ рд╕реЗ рдЪрд▓рд╛рдПрдБ
  • рдЕрдЧрд░ рдбреЗрдЯрд╛ inconsistent рд╣реИ, рддреЛ рдПрдХ corrective action рд▓рд╛рдЧреВ рдХрд░реЗрдВ рдФрд░ рдЙрд╕реЗ рд░рд┐рдХреЙрд░реНрдб рдХрд░реЗрдВ

рдЕрдЧрд░ рдЖрдк рдмрд┐рдирд╛ рдмрд╣реБрдд boilerplate рд▓рд┐рдЦреЗ рдпрд╣ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ AppMaster (appmaster.io) рдЖрдкрдХреЛ core рдЯреЗрдмрд▓реНрд╕ рдореЙрдбрд▓ рдХрд░рдиреЗ рдФрд░ рд╡реЗрдмрд╣реБрдХ рдлреНрд▓реЛ рдХреЛ рдПрдХ рд╡рд┐рдЬрд╝реБрдЕрд▓ Business Process рдореЗрдВ рдмрдирд╛рдиреЗ рджреЗрддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рдмреИрдХрдПрдВрдб рдХреЗ рд▓рд┐рдП рдЕрд╕рд▓реА рд╕реНрд░реЛрдд рдХреЛрдб рднреА рдЬрдирд░реЗрдЯ рдХрд░рддрд╛ рд╣реИред

рдкреВрд░рд╛ рд╡реЗрдмрд╣реБрдХ рд╣реИрдВрдбрд▓рд░ end-to-end рдПрдХ рдиреЛ-рдХреЛрдб generated рдмреИрдХрдПрдВрдб рдореЗрдВ рдмрдирд╛рдХрд░ рдкрд╣рд▓реЗ рд╣реА рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░ рд▓реЗрдВ рдХрд┐ retries рдХреЗ рджреМрд░рд╛рди рдпрд╣ рд╕реБрд░рдХреНрд╖рд┐рдд рд░рд╣рддрд╛ рд╣реИ, рддрдм рд╣реА рдЖрдк рдЯреНрд░реИрдлрд╝рд┐рдХ рдФрд░ рд░реЗрд╡рдиреНрдпреВ рдмрдбрд╝реЗ рдкреИрдорд╛рдиреЗ рдкрд░ рд▓реЗ рдЬрд╛рдПрдБред

рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рд╢реНрди

Why does my payment provider send the same webhook more than once?

рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд╡реЗрдмрд╣реБрдХ рдбрд┐рд▓реАрд╡рд░рд┐рдпрд╛рдБ рд╕рд╛рдорд╛рдиреНрдп рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдкреНрд░рджрд╛рддрд╛ рдХрдо рд╕реЗ рдХрдо рдПрдХ рдмрд╛рд░ рдбрд┐рд▓реАрд╡рд░реА рдХреЗ рдкрдХреНрд╖ рдореЗрдВ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝ рдХрд░рддреЗ рд╣реИрдВред рдЕрдЧрд░ рдЖрдкрдХрд╛ endpoint рдЯрд╛рдЗрдордЖрдЙрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, 5xx рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдпрд╛ рдХрдиреЗрдХреНрд╢рди рдереЛрдбрд╝реА рджреЗрд░ рдХреЗ рд▓рд┐рдП рдЯреВрдЯ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдкреНрд░рджрд╛рддрд╛ рд╡рд╣реА рдЗрд╡реЗрдВрдЯ рдлрд┐рд░ рд╕реЗ рднреЗрдЬ рджреЗрдЧрд╛ рдЬрдм рддрдХ рдЙрд╕реЗ рд╕рдлрд▓ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд╣реАрдВ рдорд┐рд▓рддреАред

WhatтАЩs the best way to dedupe webhook events?

рдкреНрд░рджрд╛рддрд╛ рдХреЗ рдпреВрдирд┐рдХ event ID рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ (рд╡реЗрдмрд╣реБрдХ рдЗрд╡реЗрдВрдЯ рдЖрдЗрдбреЗрдВрдЯрд┐рдлрд╛рдпрд░), рди рдХрд┐ рд░рд╛рд╢рд┐, рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк, рдпрд╛ рдЧреНрд░рд╛рд╣рдХ рдИрдореЗрд▓ред рдЙрд╕ event ID рдХреЛ unique constraint рдХреЗ рд╕рд╛рде рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ рддрд╛рдХрд┐ retry рддреБрд░рдВрдд рдкрддрд╛ рдЪрд▓ рд╕рдХреЗ рдФрд░ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдирдЬрд╝рд░рдЕрдВрджрд╛рдЬрд╝ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред

Should I save the event before updating billing records?

рдЗрд╡реЗрдВрдЯ рд░рд┐рдХреЙрд░реНрдб рдХреЛ рдкрд╣рд▓реЗ рдбрд╛рд▓реЗрдВ, рдЙрд╕рдХреЗ рдмрд╛рдж рд╣реА invoices, subscriptions, рдпрд╛ entitlements рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВред рдЕрдЧрд░ insert рдЙрд╕реАрд▓рд┐рдП рдлреЗрд▓ рд╣реЛрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╡рд╣реА event ID рдкрд╣рд▓реЗ рд╕реЗ рдореМрдЬреВрдж рд╣реИ, рддреЛ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рд░реЛрдХреЗрдВ рдФрд░ success рд▓реМрдЯрд╛рдПрдБ рддрд╛рдХрд┐ retries рдбрдмрд▓ рдЕрдкрдбреЗрдЯ рди рдХрд░реЗрдВред

How long should I keep webhook dedupe records?

рджреЗрд░ рд╕реЗ retries рдФрд░ рдЬрд╛рдВрдЪ рдХреЗ рд▓рд┐рдП рдХрд╛рдлрд╝реА рд╕рдордп рддрдХ рд░рдЦреЗрдВред рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ 30тАУ90 рджрд┐рди рд╣реИ; рдЕрдЧрд░ рдЖрдк рд╡рд┐рд╡рд╛рдж, рдЪрд╛рд░реНрдЬрдмреИрдХ, рдпрд╛ рд▓рдВрдмреЗ рд╕рдмреНрд╕рдХреНрд░рд┐рдкреНрд╢рди рдЪрдХреНрд░ рд╕реЗ рдирд┐рдкрдЯрддреЗ рд╣реИрдВ рддреЛ рдЗрд╕реЗ 6тАУ12 рдорд╣реАрдиреЗ рддрдХ рдмрдврд╝рд╛рдПрдБред рдкреБрд░рд╛рдиреЗ рд░рд┐рдХреЙрд░реНрдбреНрд╕ рдХреЛ рд╕рдордп-рд╕рдордп рдкрд░ purge рдХрд░реЗрдВ рддрд╛рдХрд┐ рдХреНрд╡реЗрд░реА рддреЗрдЬрд╝ рд░рд╣реЗрдВред

Do I really need signature verification if I already dedupe events?

рдмрд┐рд▓рд┐рдВрдЧ рдбреЗрдЯрд╛ рдЫреВрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╕рд┐рдЧреНрдиреЗрдЪрд░ рд╡реЗрд░рд┐рдлрд╝рд╛рдИ рдХрд░реЗрдВ, рдлрд┐рд░ рдкрд╛рд░реНрд╕ рдФрд░ рдЖрд╡рд╢реНрдпрдХ рдлрд╝реАрд▓реНрдб рд╡реИрд▓рд┐рдбреЗрдЯ рдХрд░реЗрдВред рдЕрдЧрд░ рд╕рд┐рдЧреНрдиреЗрдЪрд░ рд╡реЗрд░рд┐рдлрд╝рд┐рдХреЗрд╢рди рдлреЗрд▓ рд╣реЛ рдЬрд╛рдП рддреЛ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ reject рдХрд░реЗрдВ рдФрд░ рдмрд┐рд▓рд┐рдВрдЧ рдЪреЗрдВрдЬ рди рд▓рд┐рдЦреЗрдВ тАФ рдХреНрдпреЛрдВрдХрд┐ рдбреЗрдбреБрдкрд┐рдВрдЧ рдирдХрд▓реА тАЬpaidтАЭ рдЗрд╡реЗрдВрдЯ рд╕реЗ рдЖрдкрдХреЛ рдмрдЪрд╛рдПрдЧрд╛ рдирд╣реАрдВред

How do I handle webhook timeouts without creating duplicates?

рдЗрд╡реЗрдВрдЯ рдХреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж рд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рд▓реЗрдВ, рдФрд░ рднрд╛рд░реА рдХрд╛рдо рдмреИрдХрдЧреНрд░рд╛рдЙрдВрдб рдореЗрдВ рд╢реЗрдбреНрдпреВрд▓ рдХрд░реЗрдВред рдзреАрдореЗ рд╣реИрдВрдбрд▓рд░ рдЕрдзрд┐рдХ рдЯрд╛рдЗрдордЖрдЙрдЯ рдмрдврд╝рд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ retries рдмрдврд╝рддреА рд╣реИрдВ рдФрд░ рдбреБрдкреНрд▓реАрдХреЗрдЯ рдЕрдкрдбреЗрдЯ рдХрд╛ рдЬреЛрдЦрд┐рдо рдмрдврд╝рддрд╛ рд╣реИред

What should I do when events arrive out of order?

рд╕рд┐рд░реНрдлрд╝ рд╡рд╣реА рдмрджрд▓рд╛рд╡ рд▓рд╛рдЧреВ рдХрд░реЗрдВ рдЬреЛ рд╕реНрдЯреЗрдЯ рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛рдП тАФ рд╕реНрдЯреЗрд▓ рдЗрд╡реЗрдВрдЯреНрд╕ рдХреЛ рдЗрдЧреНрдиреЛрд░ рдХрд░реЗрдВред рдЙрдкрд▓рдмреНрдз рд╣реЛрдиреЗ рдкрд░ рдЗрд╡реЗрдВрдЯ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рдФрд░ рдПрдХ рд╕рд░рд▓ рд╕реНрдерд┐рддрд┐ рдкреНрд░рд╛рдпреЛрд░рд┐рдЯреА рд▓рд╛рдЧреВ рдХрд░реЗрдВ (рдЙрджрд╛рд╣рж░ржг: refunded рдХреЛ paid рдкрд░ overwrite рди рд╣реЛрдиреЗ рджреЗрдВ, canceled рдХреЛ active рдкрд░)ред

How can I avoid granting access twice when a renewal webhook is retried?

рд╣рд░ рдЗрд╡реЗрдВрдЯ рдкрд░ рдирдИ entitlement рд░реЛ рдмрдирд╛рдХрд░ рди рджреЗрдВред рдПрдХ upsert-рд╕реНрдЯрд╛рдЗрд▓ рдирд┐рдпрдо рдЕрдкрдирд╛рдПрдБ рдЬреИрд╕реЗ тАЬрдПрдХ entitlement рдкреНрд░рддрд┐ user/product/period (рдпрд╛ рдкреНрд░рддрд┐ subscription) рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВтАЭ, рдлрд┐рд░ dates/limits рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ рдФрд░ рдХрд┐рд╕ event ID рдиреЗ рдкрд░рд┐рд╡рд░реНрддрди рдХрд┐рдпрд╛ рдпрд╣ audit рдХреЗ рд▓рд┐рдП рд░рд┐рдХреЙрд░реНрдб рдХрд░реЗрдВред

Why should invoice and entitlement updates be in one transaction?

Invoice, subscription, рдФрд░ entitlement рдЪреЗрдВрдЬреЗрдЬрд╝ рдХреЛ рдПрдХ рд╣реА DB рдЯреНрд░рд╛рдВрдЬрд╝реИрдХреНрд╢рди рдореЗрдВ рд▓рд┐рдЦреЗрдВ рддрд╛рдХрд┐ рд╡реЗ рд╕рд╛рде рдореЗрдВ рд╕рдлрд▓ рд╣реЛрдВ рдпрд╛ рдЕрд╕рдлрд▓ рд╣реЛрдВред рдЗрд╕рд╕реЗ split states рдЬреИрд╕реЗ тАЬinvoice paid рдкрд░ access рдирд╣реАрдВтАЭ рдпрд╛ тАЬaccess revoked рдкрд░ refund рд░рд┐рдХреЙрд░реНрдб рдирд╣реАрдВтАЭ рд╕реЗ рдмрдЪрд╛рд╡ рд╣реЛрддрд╛ рд╣реИред

Can I implement this safely in AppMaster without writing custom backend code?

рд╣рд╛рдБред рдЕрдЪреНрдЫрд╛ рдлрд╝рд┐рдЯ рд╣реИ: рдПрдХ WebhookEvents рдореЙрдбрд▓ рдмрдирд╛рдЗрдП рдЬрд┐рд╕рдореЗрдВ unique event ID рд╣реЛ, рдлрд┐рд░ рдПрдХ Business Process рдмрдирд╛рдЗрдП рдЬреЛ тАЬрдкрд╣рд▓реЗ рджреЗрдЦрд╛ рдЧрдпрд╛?тАЭ рдЪреЗрдХ рдХрд░реЗ рдФрд░ рдЬрд▓реНрджреА рдмрд╛рд╣рд░ рдирд┐рдХрд▓ рдЬрд╛рдПред invoices/subscriptions/entitlements рдХреЛ Data Designer рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдореЙрдбрд▓ рдХрд░реЗрдВ рддрд╛рдХрд┐ retries рдФрд░ replays duplicate rows рди рдмрдирд╛рдПрдБред

рд╢реБрд░реВ рдХрд░рдирд╛ рдЖрд╕рд╛рди
рдХреБрдЫ рдмрдирд╛рдПрдВ рдЕрджреНрднреБрдд

рдлреНрд░реА рдкреНрд▓рд╛рди рдХреЗ рд╕рд╛рде рдРрдкрдорд╛рд╕реНрдЯрд░ рдХреЗ рд╕рд╛рде рдкреНрд░рдпреЛрдЧ рдХрд░реЗрдВред
рдЬрдм рдЖрдк рддреИрдпрд╛рд░ рд╣реЛрдВрдЧреЗ рддрдм рдЖрдк рдЙрдЪрд┐рдд рд╕рджрд╕реНрдпрддрд╛ рдЪреБрди рд╕рдХрддреЗ рд╣реИрдВред

рд╢реБрд░реВ рд╣реЛ рдЬрд╛рдУ
рд╕реБрд░рдХреНрд╖рд┐рдд рдмрд┐рд▓рд┐рдВрдЧ рдЕрдкрдбреЗрдЯ рдХреЗ рд▓рд┐рдП рдЗрдбреЗрдореНрдкреЛрдЯреЗрдВрдЯ рдкреЗрдореЗрдВрдЯ рд╡реЗрдмрд╣реБрдХ рдЪреЗрдХрд▓рд┐рд╕реНрдЯ | AppMaster