{"id":23746,"date":"2026-05-10T09:30:22","date_gmt":"2026-05-10T09:30:22","guid":{"rendered":"https:\/\/umang.pk\/2026\/05\/10\/%d9%be%d9%b9%db%8c%d8%8c-%d9%88%db%8c%d8%a8-%db%81%da%a9%d8%b3%d8%8c-%d8%a7%d9%88%d8%b1-%d8%a7%db%8c-%d9%85%db%8c%d9%84-%d8%a7%d8%b7%d9%84%d8%a7%d8%b9%d8%a7%d8%aa-%da%a9%d8%a7-%d8%a7%d8%b3%d8%aa%d8%b9\/"},"modified":"2026-05-10T09:30:36","modified_gmt":"2026-05-10T09:30:36","slug":"%d9%be%d9%b9%db%8c%d8%8c-%d9%88%db%8c%d8%a8-%db%81%da%a9%d8%b3%d8%8c-%d8%a7%d9%88%d8%b1-%d8%a7%db%8c-%d9%85%db%8c%d9%84-%d8%a7%d8%b7%d9%84%d8%a7%d8%b9%d8%a7%d8%aa-%da%a9%d8%a7-%d8%a7%d8%b3%d8%aa%d8%b9","status":"publish","type":"post","link":"https:\/\/umang.pk\/en_us\/2026\/05\/10\/%d9%be%d9%b9%db%8c%d8%8c-%d9%88%db%8c%d8%a8-%db%81%da%a9%d8%b3%d8%8c-%d8%a7%d9%88%d8%b1-%d8%a7%db%8c-%d9%85%db%8c%d9%84-%d8%a7%d8%b7%d9%84%d8%a7%d8%b9%d8%a7%d8%aa-%da%a9%d8%a7-%d8%a7%d8%b3%d8%aa%d8%b9\/","title":{"rendered":"\u067e\u0679\u06cc\u060c \u0648\u06cc\u0628 \u06c1\u06a9\u0633\u060c \u0627\u0648\u0631 \u0627\u06cc \u0645\u06cc\u0644 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u06cc\u06a9 \u0645\u06a9\u0645\u0644 SaaS \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0627 \u0628\u06c1\u0627\u0624 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2"},"content":{"rendered":"\n<div id=\"\">\n<p>\u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u067e\u0679\u06cc \u0648\u0627\u0644\u06d2 \u0633\u0628\u0642 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0635\u0641\u062d\u06c1 \u067e\u0631 \u062e\u062a\u0645 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062c\u0628 \u06a9\u0648\u0626\u06cc \u0635\u0627\u0631\u0641 &quot;\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc&#8221; \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0628\u0644\u0646\u06af \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u0627 \u062c\u0634\u0646 \u0645\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0644\u06cc\u06a9\u0646 \u06cc\u06c1 \u0627\u0635\u0644 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0646\u0638\u0627\u0645 \u06a9\u0627 \u0635\u0631\u0641 \u067e\u06c1\u0644\u0627 10% \u06c1\u06d2\u06d4<\/p>\n<p>\u06af\u0627\u06c1\u06a9 \u06a9\u06cc \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u06a9\u06cc\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u061f \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0648 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0631\u0646\u0627 \u06c1\u0648\u06af\u0627\u060c \u0627\u06cc\u06a9 \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u060c \u0627\u0648\u0631 \u067e\u0631\u0648\u0688\u06a9\u0679 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u06cc\u06ba (GitHub \u0631\u06cc\u067e\u0648\u0632\u0679\u0631\u06cc \u062f\u0639\u0648\u062a\u060c API \u06a9\u0644\u06cc\u062f\u060c \u0644\u0627\u0626\u0633\u0646\u0633 \u0641\u0627\u0626\u0644)\u06d4 \u0628\u0637\u0648\u0631 \u0645\u06cc\u0646\u06cc\u062c\u0631\u060c \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0622\u067e \u06a9\u0648 \u0628\u062a\u0627\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u0622\u067e \u06a9\u0648 2 \u06c1\u0641\u062a\u0648\u06ba \u06a9\u06d2 \u0628\u0639\u062f \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u062c\u0627\u0631\u06cc \u06a9\u0631\u0646\u06cc \u06c1\u0648\u06af\u06cc \u0627\u0648\u0631 \u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u062a\u0631\u06a9 \u06a9\u0631\u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u0628\u0627\u0632\u06cc\u0627\u0628\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u0646\u0627 \u06c1\u0648\u06af\u0627\u06d4<\/p>\n<p>\u06cc\u06c1 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc\u0648\u06ba \u06a9\u0627 \u067e\u0648\u0631\u0627 \u0644\u0627\u0626\u0641 \u0633\u0627\u0626\u06cc\u06a9\u0644 \u06c1\u06d2 \u0627\u0648\u0631 \u06cc\u06c1\u06cc\u06ba \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 SaaS \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646\u0632 \u0679\u0648\u0679 \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0645\u0636\u0645\u0648\u0646 \u0622\u067e \u06a9\u0648 &quot;\u062e\u0631\u06cc\u062f\u06cc\u06ba&#8221; \u06a9\u06d2 \u0628\u0679\u0646 \u0633\u06d2 \u0644\u06d2 \u06a9\u0631 &quot;\u062e\u0648\u0634 \u0622\u0645\u062f\u06cc\u062f&#8221; \u0627\u06cc \u0645\u06cc\u0644 \u062a\u06a9\u060c \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u06a9\u06cc \u06c1\u0631 \u0686\u06cc\u0632 \u062a\u06a9 \u0644\u06d2 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 \u062a\u0645\u0627\u0645 \u06a9\u0648\u0688 \u06a9\u06cc \u0645\u062b\u0627\u0644\u06cc\u06ba \u0627\u06cc\u06a9 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0627\u06cc\u067e\u0644\u06cc \u06a9\u06cc\u0634\u0646 \u0633\u06d2 \u0622\u062a\u06cc \u06c1\u06cc\u06ba \u062c\u0648 \u0627\u0635\u0644 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc\u0648\u06ba \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u06c1\u0645 \u062f\u06cc\u06a9\u06be\u06cc\u06ba \u06af\u06d2 \u06a9\u06c1 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u060c \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u067e\u0631\u0648\u0688\u06a9\u0679\u0633 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u0626\u06cc\u06ba\u060c \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u060c \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc\u0648\u06ba \u06a9\u0648 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u067e\u0631\u0648\u0633\u06cc\u0633 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u060c \u0631\u06cc\u0641\u0646\u0688\u0632 \u067e\u0631 \u0639\u0645\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u060c \u0686\u06be\u0648\u0691\u06cc \u06c1\u0648\u0626\u06cc \u06af\u0627\u0691\u06cc\u0648\u06ba \u06a9\u0648 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u060c \u0627\u0648\u0631 \u0644\u06cc\u0646 \u062f\u06cc\u0646 \u06a9\u06cc \u0627\u06cc \u0645\u06cc\u0644\u0632 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1\u0627\u06ba \u0622\u067e \u06a9\u06cc\u0627 \u0633\u06cc\u06a9\u06be\u06cc\u06ba \u06af\u06d2:<\/p>\n<ul>\n<li>\n<p>\u0627\u06cc\u06a9 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u062c\u0648 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06d2 \u06c1\u0631 \u0642\u062f\u0645 \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u0648\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0633\u0679\u0631\u0627\u0626\u067e \u067e\u0631\u0648\u0688\u06a9\u0679\u0633 \u0627\u0648\u0631 \u0642\u06cc\u0645\u062a\u06cc\u06ba \u067e\u0631\u0648\u06af\u0631\u0627\u0645 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u0626\u06cc\u06ba<\/p>\n<\/li>\n<li>\n<p>\u06a9\u0627\u0645\u06cc\u0627\u0628\u06cc\/\u0645\u0646\u0633\u0648\u062e\u06cc \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0627 \u0628\u06c1\u0627\u0624 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u062f\u0633\u062a\u062e\u0637\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06a9\u06cc\u0633\u06d2 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u06a9\u06cc \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u0648 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631\u060c \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u0634\u062f\u06c1 \u0645\u0631\u0627\u062d\u0644 \u0645\u06cc\u06ba \u06a9\u06cc\u0633\u06d2 \u062a\u0642\u0633\u06cc\u0645 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0631\u0633\u0627\u0626\u06cc \u06a9\u06d2 \u062d\u0642\u0648\u0642 \u06a9\u06cc \u062e\u0648\u062f\u06a9\u0627\u0631 \u0648\u0627\u067e\u0633\u06cc \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u0645\u06a9\u0645\u0644 \u0627\u0648\u0631 \u062c\u0632\u0648\u06cc \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u06cc\u0633\u06d2 \u06a9\u06cc \u062c\u0627\u0626\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0644\u0627\u0648\u0627\u0631\u062b \u0686\u06cc\u06a9 \u0622\u0624\u0679\u0633 \u0633\u06d2 \u0631\u06cc\u0648\u06cc\u0646\u06cc\u0648 \u06a9\u06cc \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0631\u06cc \u0627\u06cc\u06a9\u0679 \u0627\u06cc \u0645\u06cc\u0644 \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u06be\u06cc\u062c \u06a9\u0631 \u0679\u0631\u0627\u0646\u0632\u06cc\u06a9\u0634\u0646\u0644 \u0627\u06cc \u0645\u06cc\u0644 \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679\u0633 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u0626\u06cc\u06ba<\/p>\n<\/li>\n<li>\n<p>\u0627\u0633\u0679\u0631\u0627\u0626\u067e CLI \u0627\u0648\u0631 Ingest \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u067e\u0648\u0631\u06d2 \u0628\u06c1\u0627\u0624 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<h2 id=\"heading-table-of-contents\">\u0627\u0646\u0688\u06cc\u06a9\u0633<\/h2>\n<h2 id=\"heading-prerequisites\">\u0634\u0631\u0637\u06cc\u06ba<\/h2>\n<p>\u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u06cc\u06c1\u0627\u06ba \u0622\u067e \u06a9\u0648 \u062c\u0627\u0646\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2:<\/p>\n<ul>\n<li>\n<p>TypeScript \u0627\u0648\u0631 Node.js<\/p>\n<\/li>\n<li>\n<p>SQL \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 (\u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 PostgreSQL \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2)<\/p>\n<\/li>\n<li>\n<p>\u0631\u062f \u0639\u0645\u0644 \u06a9\u0631\u06cc\u06ba (\u0627\u06cc \u0645\u06cc\u0644 \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2)<\/p>\n<\/li>\n<li>\n<p>\u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u062a\u0641\u06c1\u06cc\u0645<\/p>\n<\/li>\n<\/ul>\n<p>\u06a9\u0633\u06cc \u0645\u062e\u0635\u0648\u0635 \u0644\u0627\u0626\u0628\u0631\u06cc\u0631\u06cc \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0633\u06cc \u067e\u06cc\u0634\u06af\u06cc \u062a\u062c\u0631\u0628\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06cc\u06c1 \u06a9\u062a\u0627\u0628\u0686\u06c1 \u06c1\u0631 \u0645\u0648\u0636\u0648\u0639 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-what-you-need-installed\">\u0622\u067e \u06a9\u0648 \u062c\u0633 \u0686\u06cc\u0632 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2 \u0627\u0646\u0633\u0679\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u06a9\u0648\u0688 \u06a9\u06cc \u0645\u062b\u0627\u0644\u0648\u06ba \u06a9\u0648 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u062f\u0631\u062c \u0630\u06cc\u0644 \u067e\u06cc\u06a9\u06cc\u062c\u0632 \u0627\u0646\u0633\u0679\u0627\u0644 \u06a9\u0631\u06cc\u06ba:<\/p>\n<pre><code class=\"language-bash\">bun add stripe drizzle-orm @neondatabase\/serverless inngest resend @react-email\/components\n<\/code><\/pre>\n<p>\u0622\u067e \u06a9\u0648 \u0628\u06be\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648 \u06af\u06cc:<\/p>\n<h3 id=\"heading-environment-variables\">\u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0645\u062a\u063a\u06cc\u0631\u0627\u062a<\/h3>\n<p>\u062f\u0631\u062c \u0630\u06cc\u0644 \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u06a9\u0648 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba: <code>.env<\/code> \u0641\u0627\u0626\u0644:<\/p>\n<pre><code class=\"language-bash\"># Database\nDATABASE_URL=postgresql:\/\/...\n\n# Stripe\nSTRIPE_SECRET_KEY=sk_test_...\nSTRIPE_WEBHOOK_SECRET=whsec_...\nSTRIPE_PRO_PRICE_ID=price_...\n\n# Email\nRESEND_API_KEY=re_...\nEMAIL_FROM=\"Your App <noreply>\"\nADMIN_EMAIL=you@yourapp.com\n\n# App\nBETTER_AUTH_URL=http:\/\/localhost:3000\n<\/noreply><\/code><\/pre>\n<h2 id=\"heading-how-to-design-the-payment-database-schema\">\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc\u0648\u06ba \u06a9\u0627 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u06cc\u0633\u06d2 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0627\u0633\u0679\u0631\u0627\u0626\u067e \u06a9\u0648\u0688 \u0644\u06a9\u06be\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2 \u062c\u0648 \u0627\u0646 \u06a9\u06d2 \u0644\u0627\u0626\u0641 \u0633\u0627\u0626\u06cc\u06a9\u0644 \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u0645\u0631\u0627\u062d\u0644 \u0645\u06cc\u06ba \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc\u0648\u06ba \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631 \u0633\u06a9\u06d2: \u062a\u062e\u0644\u06cc\u0642\u060c \u062a\u06a9\u0645\u06cc\u0644\u060c \u062c\u0632\u0648\u06cc \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc\u060c \u0627\u0648\u0631 \u0645\u06a9\u0645\u0644 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc\u06d4<\/p>\n<p>\u0622\u067e \u06a9\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u0627\u0633 \u0637\u0631\u062d \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u06cc \u06c1\u06d2: <code>pending<\/code> \u062c\u0628 \u0635\u0627\u0631\u0641 &#8216;\u062e\u0631\u06cc\u062f\u0627\u0631\u06cc&#8217; \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u067e\u06be\u0631 \u0627\u0633 \u067e\u0631 \u0645\u0646\u062a\u0642\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2: <code>completed<\/code>. \u0648\u06c1\u0627\u06ba \u0633\u06d2 \u0622\u067e \u0622\u06af\u06d2 \u0628\u0691\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba: <code>refunded<\/code> \u06cc\u0627 <code>partially_refunded<\/code>. \u0646\u0627\u0645\u06a9\u0645\u0644 \u0632\u06cc\u0631 \u0627\u0644\u062a\u0648\u0627\u0621 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc\u0648\u06ba \u06a9\u06cc \u0645\u06cc\u0639\u0627\u062f 24 \u06af\u06be\u0646\u0679\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u062e\u062a\u0645 \u06c1\u0648 \u062c\u0627\u062a\u06cc \u06c1\u06d2 (\u062a\u0631\u06a9 \u0634\u062f\u06c1 \u06a9\u0627\u0631\u0679)\u06d4<\/p>\n<p>\u0630\u06cc\u0644 \u0645\u06cc\u06ba \u0648\u06c1 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06c1\u06d2 \u062c\u0633\u06d2 \u06c1\u0645 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0645\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u0633 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a Drizzle ORM \u0633\u06d2 \u06a9\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4 \u0627\u0633 \u0645\u0636\u0645\u0648\u0646 \u06a9\u06cc \u062a\u0645\u0627\u0645 \u0645\u062b\u0627\u0644\u06cc\u06ba \u0627\u0633 \u0645\u062e\u0635\u0648\u0635 \u067e\u0631\u0648\u0688\u06a9\u0679 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u0641\u0631\u0648\u062e\u062a \u06a9\u0631\u062f\u06c1 \u0646\u062c\u06cc GitHub \u0630\u062e\u06cc\u0631\u06c1 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>&quot;\u06af\u0631\u0627\u0646\u0679 \u0627\u06cc\u06a9\u0633\u06cc\u0633&#8221; \u06a9\u06d2 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0645\u062e\u062a\u0644\u0641 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba: \u0635\u0627\u0631\u0641 \u06a9\u0648 \u067e\u0631\u0648 \u067e\u0644\u0627\u0646 \u0645\u06cc\u06ba \u0627\u067e \u06af\u0631\u06cc\u0688 \u06a9\u0631\u06cc\u06ba\u060c API \u06a9\u0631\u06cc\u0688\u0679\u0633 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u06cc\u06ba\u060c \u06a9\u0648\u0631\u0633 \u06a9\u06d2 \u0645\u0648\u0627\u062f \u06a9\u0648 \u063a\u06cc\u0631 \u0645\u0642\u0641\u0644 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0633\u0628\u0633\u06a9\u0631\u067e\u0634\u0646 \u06a9\u0648 \u0686\u0627\u0644\u0648 \u06a9\u0631\u06cc\u06ba\u06d4 \u0633\u06a9\u06cc\u0645\u0627 \u0641\u06cc\u0644\u0688\u0632 \u0627\u0648\u0631 \u0645\u0631\u062d\u0644\u06c1 \u0648\u0627\u0631 \u0645\u0646\u0637\u0642 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644\u06cc\u060c \u0644\u06cc\u06a9\u0646 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u0627 \u0637\u0631\u06cc\u0642\u06c1 \u0648\u06c1\u06cc \u0631\u06c1\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/lib\/db\/schema.ts\nimport {\n  boolean,\n  integer,\n  pgEnum,\n  pgTable,\n  text,\n  timestamp,\n  varchar,\n} from \"drizzle-orm\/pg-core\";\n\nexport const purchaseTierEnum = pgEnum(\"purchase_tier\", [\"pro\"]);\nexport const purchaseStatusEnum = pgEnum(\"purchase_status\", [\n  \"completed\",\n  \"partially_refunded\",\n  \"refunded\",\n]);\n\nexport const users = pgTable(\"users\", {\n  id: text(\"id\").primaryKey(),\n  email: varchar(\"email\", { length: 255 }).notNull().unique(),\n  emailVerified: boolean(\"email_verified\").notNull().default(false),\n  name: text(\"name\"),\n  image: text(\"image\"),\n  githubUsername: text(\"github_username\"),\n  createdAt: timestamp(\"created_at\").notNull().defaultNow(),\n  updatedAt: timestamp(\"updated_at\").notNull().defaultNow(),\n});\n\nexport const purchases = pgTable(\"purchases\", {\n  id: text(\"id\")\n    .primaryKey()\n    .$defaultFn(() => crypto.randomUUID()),\n  userId: text(\"user_id\")\n    .notNull()\n    .references(() => users.id, { onDelete: \"cascade\" }),\n  stripeCheckoutSessionId: text(\"stripe_checkout_session_id\")\n    .notNull()\n    .unique(),\n  stripeCustomerId: text(\"stripe_customer_id\"),\n  stripePaymentIntentId: text(\"stripe_payment_intent_id\"),\n  tier: purchaseTierEnum(\"tier\").notNull(),\n  status: purchaseStatusEnum(\"status\").notNull().default(\"completed\"),\n  githubAccessGranted: boolean(\"github_access_granted\")\n    .notNull()\n    .default(false),\n  githubInvitationId: text(\"github_invitation_id\"),\n  amount: integer(\"amount\").notNull(),\n  currency: text(\"currency\").notNull().default(\"usd\"),\n  purchasedAt: timestamp(\"purchased_at\").notNull().defaultNow(),\n  createdAt: timestamp(\"created_at\").notNull().defaultNow(),\n  updatedAt: timestamp(\"updated_at\").notNull().defaultNow(),\n});\n\nexport type Purchase = typeof purchases.$inferSelect;\nexport type NewPurchase = typeof purchases.$inferInsert;\n<\/code><\/pre>\n<p>\u0622\u0626\u06cc\u06d2 \u0627\u0633 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u06d2 \u067e\u06cc\u0686\u06be\u06d2 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06d2 \u0641\u06cc\u0635\u0644\u0648\u06ba \u067e\u0631 \u0627\u06cc\u06a9 \u0646\u0638\u0631 \u0688\u0627\u0644\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-why-three-stripe-id-columns\">\u0622\u067e \u06a9\u0648 3 \u0627\u0633\u0679\u0631\u0627\u0626\u067e ID \u06a9\u0627\u0644\u0645\u0632 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06a9\u06cc\u0648\u06ba \u06c1\u06d2\u061f<\/h3>\n<p>\u06a9\u06c1 <code>purchases<\/code> \u0679\u06cc\u0628\u0644 \u062a\u06cc\u0646 \u0639\u0644\u06cc\u062d\u062f\u06c1 \u067e\u0679\u06cc \u0634\u0646\u0627\u062e\u062a \u06a9\u0646\u0646\u062f\u06af\u0627\u0646 \u06a9\u0648 \u0627\u0633\u0679\u0648\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>stripeCheckoutSessionId<\/code>\u060c <code>stripeCustomerId<\/code>\u0627\u0648\u0631 <code>stripePaymentIntentId<\/code>.<\/p>\n<p>\u06c1\u0631 \u0627\u06cc\u06a9 \u0645\u062e\u062a\u0644\u0641 \u0645\u0642\u0635\u062f \u06a9\u06cc \u062e\u062f\u0645\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06c1 <strong>\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u0633\u06cc\u0634\u0646 ID<\/strong> \u06cc\u06c1 \u067e\u06c1\u0644\u06cc \u0686\u06cc\u0632 \u06c1\u06d2 \u062c\u0648 \u0622\u067e \u06a9\u0648 \u0645\u0644\u062a\u06cc \u06c1\u06d2\u06d4 \u062c\u0628 \u06a9\u0648\u0626\u06cc \u0635\u0627\u0631\u0641 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u0634\u0631\u0648\u0639 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0627\u06cc\u06a9 \u0633\u06cc\u0634\u0646 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06cc\u06c1 ID \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0645 \u0627\u0633\u06d2 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u06a9\u06d2 \u06c1\u0648\u0633\u0679\u0646\u06af \u0686\u06cc\u06a9 \u0622\u0624\u0679 \u0635\u0641\u062d\u06c1 \u0633\u06d2 \u06a9\u0633\u0679\u0645\u0631 \u06a9\u06d2 \u0648\u0627\u067e\u0633 \u0622\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u0627\u0646 \u06a9\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0627 \u062f\u0639\u0648\u06cc \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06a9\u06c1 <code>unique()<\/code> \u0627\u0633 \u06a9\u0627\u0644\u0645 \u06a9\u06cc \u0631\u06a9\u0627\u0648\u0679 \u0627\u06cc\u06a9 \u063a\u06cc\u0631\u0645\u0639\u0645\u0648\u0644\u06cc \u0645\u062d\u0627\u0641\u0638 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u0627\u06cc\u06a9 \u06c1\u06cc \u0633\u06cc\u0634\u0646 \u06a9\u06cc \u062f\u0648 \u0628\u0627\u0631 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u062f\u0648\u0633\u0631\u06cc \u062f\u0627\u062e\u0644 \u06a9\u0648 \u0645\u0633\u062a\u0631\u062f \u06a9\u0631 \u062f\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u06a9\u06c1 <strong>\u06a9\u0633\u0679\u0645\u0631 ID<\/strong> \u062e\u0631\u06cc\u062f\u0627\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0679\u06cc \u06a9\u0627 \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u0634\u0646\u0627\u062e\u062a \u06a9\u0646\u0646\u062f\u06c1\u06d4 \u0622\u067e \u06a9\u0648 \u0627\u0633 \u0645\u0639\u0644\u0648\u0645\u0627\u062a \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0627\u067e\u0646\u06d2 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0645\u06cc\u06ba \u0627\u067e\u0646\u06d2 \u06a9\u0633\u0679\u0645\u0631 \u06a9\u06cc \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06cc \u0633\u0631\u06af\u0632\u0634\u062a \u062f\u06cc\u06a9\u06be\u0646\u06d2 \u0627\u0648\u0631 \u0628\u0644\u0646\u06af \u06a9\u06cc \u0645\u0639\u0644\u0648\u0645\u0627\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0633\u062a\u0642\u0628\u0644 \u0645\u06cc\u06ba \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0633\u06cc\u0634\u0646 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06c1\u0648 \u06af\u06cc\u06d4<\/p>\n<p>\u06a9\u06c1 <strong>\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0627 \u0627\u0631\u0627\u062f\u06c1 ID<\/strong> \u0631\u06cc\u0641\u0646\u0688 \u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0648\u0646\u0679 \u0645\u06cc\u06ba \u0633\u0679\u0631\u0627\u0626\u067e \u06cc\u06c1\u06cc \u0628\u06be\u06cc\u062c\u062a\u06cc \u06c1\u06d2\u06d4 \u062c\u0628 <code>charge.refunded<\/code> \u062c\u0628 \u06a9\u0648\u0626\u06cc \u0648\u0627\u0642\u0639\u06c1 \u067e\u06cc\u0634 \u0622\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0627\u0631\u0627\u062f\u06d2 \u06a9\u06cc ID \u0634\u0627\u0645\u0644 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0633\u06cc\u0634\u0646 \u06a9\u06cc ID \u0634\u0627\u0645\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0627\u0633 \u0641\u06cc\u0644\u0688 \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u06a9\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u0631\u06cc\u0641\u0646\u0688\u0632 \u06a9\u0648 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc\u0648\u06ba \u0633\u06d2 \u0645\u0644\u0627\u0646\u06d2 \u06a9\u0627 \u06a9\u0648\u0626\u06cc \u0637\u0631\u06cc\u0642\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-why-track-access-state-in-your-database\">\u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u0631\u0633\u0627\u0626\u06cc \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u06a9\u0648 \u06a9\u06cc\u0648\u06ba \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u06a9\u06c1 <code>githubAccessGranted<\/code> \u0627\u0648\u0631 <code>githubInvitationId<\/code> \u0645\u06cc\u062f\u0627\u0646 \u063a\u06cc\u0631 \u0636\u0631\u0648\u0631\u06cc \u0645\u0639\u0644\u0648\u0645 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u067e GitHub \u06a9\u0627 API \u0686\u06cc\u06a9 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u0622\u067e \u06a9\u0648 \u0631\u0633\u0627\u0626\u06cc \u062d\u0627\u0635\u0644 \u06c1\u06d2\u06d4 \u062a\u0627\u06c1\u0645\u060c \u06c1\u0631 \u0628\u0627\u0631 \u062c\u0628 \u0622\u067e \u06a9\u0648 \u06a9\u0633\u06cc \u0635\u0627\u0631\u0641 \u06a9\u06cc \u0631\u0633\u0627\u0626\u06cc \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u0686\u06cc\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648 \u062a\u0648 \u06a9\u0633\u06cc \u0628\u06cc\u0631\u0648\u0646\u06cc API \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u0631\u0646\u0627 \u0633\u0633\u062a\u060c \u0631\u0641\u062a\u0627\u0631 \u0633\u06d2 \u0645\u062d\u062f\u0648\u062f\u060c \u0627\u0648\u0631 \u0646\u0627\u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0628\u0627\u0631 \u06c1\u06d2\u06d4<\/p>\n<p>\u0622\u067e \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u0631\u0633\u0627\u0626\u06cc \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u06a9\u0627 \u0633\u0631\u0627\u063a \u0644\u06af\u0627\u0646\u0627 \u0622\u067e \u06a9\u0648 \u0627\u0633 \u0633\u0648\u0627\u0644 \u06a9\u0627 \u062c\u0648\u0627\u0628 \u062f\u06cc\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u060c &quot;\u06a9\u06cc\u0627 \u0627\u0633 \u0635\u0627\u0631\u0641 \u06a9\u0648 \u0631\u0633\u0627\u0626\u06cc \u062d\u0627\u0635\u0644 \u06c1\u06d2\u061f&#8221; \u0627\u06cc\u06a9 \u0627\u0646\u0688\u06cc\u06a9\u0633 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u06d4 \u0622\u067e \u06cc\u06c1 \u0628\u06be\u06cc \u062c\u0627\u0646 \u0644\u06cc\u06ba \u06af\u06d2 \u06a9\u06c1 \u0631\u0633\u0627\u0626\u06cc \u062f\u06cc \u06af\u0626\u06cc \u06c1\u06d2 \u06cc\u0627 \u0646\u06c1\u06cc\u06ba\u060c \u062c\u0648 \u06a9\u06c1 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06a9\u06cc \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06c1\u062a \u0627\u06c1\u0645 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 <code>githubAccessGranted<\/code> \u06c1\u06d2 <code>false<\/code>\u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u062d\u0627\u0635\u0644 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a \u0622\u067e \u06a9\u0648 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0645\u0646\u0633\u0648\u062e \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-why-a-status-enum-with-three-values\">\u06c1\u0645\u06cc\u06ba \u062a\u06cc\u0646 \u0642\u06cc\u0645\u062a\u06cc \u0631\u06cc\u0627\u0633\u062a\u06cc \u06af\u0646\u062a\u06cc \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06a9\u06cc\u0648\u06ba \u06c1\u06d2\u061f<\/h3>\n<p>\u06a9\u06c1 <code>purchaseStatusEnum<\/code> \u062a\u06cc\u0646 \u0642\u062f\u0631\u06cc\u06ba \u06c1\u06cc\u06ba: <code>completed<\/code>\u060c <code>partially_refunded<\/code>\u0627\u0648\u0631 <code>refunded<\/code>.<\/p>\n<p>\u06cc\u06c1 \u0688\u0627\u0624\u0646 \u0627\u0633\u0679\u0631\u06cc\u0645 \u0645\u0646\u0637\u0642 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06c1\u0645 \u06c1\u06d2\u06d4 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688\u0632\u060c \u062a\u062c\u0632\u06cc\u0627\u062a\u060c \u0633\u067e\u0648\u0631\u0679 \u0679\u0648\u0644\u0632\u060c \u0627\u0648\u0631 \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628 \u0633\u0628\u06be\u06cc \u06a9\u0648 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u0635\u062d\u06cc\u062d \u062d\u06cc\u062b\u06cc\u062a \u062c\u0627\u0646\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u062c\u0632\u0648\u06cc \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u0627\u0628 \u0628\u06be\u06cc \u0631\u0633\u0627\u0626\u06cc \u062d\u0627\u0635\u0644 \u06c1\u0648\u06af\u06cc\u060c \u062c\u0628\u06a9\u06c1 \u0645\u06a9\u0645\u0644 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u0646\u06c1\u06cc\u06ba \u0645\u0644\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0635\u0631\u0641 \u0628\u0648\u0644\u06cc\u0646 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 &quot;\u0631\u06cc\u0641\u0646\u0688&#8221; \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u0646\u0627 \u062c\u0632\u0648\u06cc \u0627\u0648\u0631 \u0645\u06a9\u0645\u0644 \u0631\u06cc\u0641\u0646\u0688\u0632 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0631\u0642 \u06a9\u0648 \u062e\u062a\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u062e\u062a\u0644\u0627\u0641\u0627\u062a \u0627\u0633 \u0628\u0627\u062a \u067e\u0631 \u0627\u062b\u0631 \u0627\u0646\u062f\u0627\u0632 \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u067e\u0631\u0648\u0688\u06a9\u0679 \u062a\u06a9 \u0622\u067e \u06a9\u06cc \u0631\u0633\u0627\u0626\u06cc \u0645\u0646\u0633\u0648\u062e \u06a9\u0631 \u062f\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-how-to-generate-and-run-migrations\">\u06c1\u062c\u0631\u062a \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/h3>\n<p>\u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0627\u06cc\u06a9 \u0645\u0646\u062a\u0642\u0644\u06cc \u0641\u0627\u0626\u0644 \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u067e\u0631 \u0644\u0627\u06af\u0648 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\"># Generate migration SQL from schema changes\nbun run drizzle-kit generate\n\n# Push schema directly (development only)\nbun run drizzle-kit push\n\n# Run migrations (production)\nbun run drizzle-kit migrate\n<\/code><\/pre>\n<p>Drizzle Kit \u0622\u067e \u06a9\u06d2 TypeScript \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u0627 \u0622\u067e \u06a9\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0633\u06d2 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0631\u06a9\u0627\u0631 SQL \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062f\u06c1 \u0645\u0646\u062a\u0642\u0644\u06cc \u0641\u0627\u0626\u0644 \u06a9\u0648 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u0686\u0644\u0627\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633 \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06cc\u06ba\u06d4 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u0627\u0646 \u0686\u0646\u062f \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc\u0648\u06ba \u0645\u06cc\u06ba \u0633\u06d2 \u0627\u06cc\u06a9 \u06c1\u06cc\u06ba \u062c\u0646\u06c1\u06cc\u06ba \u0622\u0633\u0627\u0646\u06cc \u0633\u06d2 \u06a9\u0627\u0644\u0639\u062f\u0645 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627\u06d4<\/p>\n<p>\u062a\u0631\u0642\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2\u060c <code>drizzle-kit push<\/code> \u06cc\u06c1 \u062a\u06cc\u0632 \u062a\u0631 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0645\u0646\u062a\u0642\u0644\u06cc \u0641\u0627\u0626\u0644 \u0628\u0646\u0627\u0626\u06d2 \u0628\u063a\u06cc\u0631 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u062a\u0628\u062f\u06cc\u0644\u06cc\u0648\u06ba \u06a9\u0627 \u0627\u0637\u0644\u0627\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u06d2 \u06c1\u0645\u06cc\u0634\u06c1 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>drizzle-kit generate<\/code> \u067e\u06be\u0631 <code>drizzle-kit migrate<\/code> \u0644\u06c1\u0630\u0627 \u06c1\u0631 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u06d2 \u0644\u0626\u06d2 \u0627\u06cc\u06a9 \u0648\u0631\u0698\u0646 \u06a9\u06cc \u062a\u0627\u0631\u06cc\u062e \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-how-to-create-stripe-products-and-prices\">\u067e\u0679\u06cc \u06a9\u06cc \u0645\u0635\u0646\u0648\u0639\u0627\u062a \u0627\u0648\u0631 \u0642\u06cc\u0645\u062a\u0648\u06ba \u06a9\u0627 \u062a\u0639\u06cc\u0646 \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0627\u06af\u0631\u0686\u06c1 \u0622\u067e \u0633\u0679\u0631\u0627\u0626\u067e \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0679\u0633 \u0627\u0648\u0631 \u0642\u06cc\u0645\u062a\u06cc\u06ba \u0628\u0646\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0644\u06cc\u06a9\u0646 \u062a\u0648\u0644\u06cc\u062f\u06cc \u0635\u0644\u0627\u062d\u06cc\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0646 \u06a9\u0627 \u067e\u0631\u0648\u06af\u0631\u0627\u0645 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u0627\u0646\u062a\u0638\u0627\u0645 \u06a9\u0631\u0646\u0627 \u0628\u06c1\u062a\u0631 \u06c1\u06d2\u06d4 \u06cc\u06c1\u0627\u06ba \u0627\u06cc\u06a9 \u0628\u06cc\u062c \u0627\u0633\u06a9\u0631\u067e\u0679 \u06c1\u06d2 \u062c\u0648 \u0622\u067e \u06a9\u0648 \u062f\u0631\u06a9\u0627\u0631 \u06c1\u0631 \u0686\u06cc\u0632 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/lib\/payments\/seed.ts\nimport { stripe } from \".\/index\";\n\nconst PRODUCTS = [\n  {\n    name: \"My SaaS Product\",\n    description: \"Full access, one-time purchase\",\n    features: [\n      \"Full source code access\",\n      \"Production-ready infrastructure\",\n      \"Lifetime updates\",\n    ],\n    metadata: { tier: \"pro\" },\n    prices: [\n      {\n        lookupKey: \"pro_one_time\",\n        unitAmount: 19900, \/\/ $199.00 in cents\n        currency: \"usd\",\n        nickname: \"Pro One-Time\",\n      },\n    ],\n  },\n];\n\nasync function main() {\n  console.log(\"Seeding Stripe products and prices...n\");\n\n  for (const config of PRODUCTS) {\n    \/\/ Create or find product\n    const products = await stripe.products.list({ active: true, limit: 100 });\n    let product = products.data.find((p) => p.name === config.name);\n\n    if (!product) {\n      product = await stripe.products.create({\n        name: config.name,\n        description: config.description,\n        marketing_features: config.features.map((f) => ({ name: f })),\n        metadata: config.metadata,\n      });\n      console.log(`Created product \"({config.name}\" (){product.id})`);\n    }\n\n    \/\/ Create prices\n    for (const priceConfig of config.prices) {\n      const existing = await stripe.prices.list({\n        lookup_keys: [priceConfig.lookupKey],\n        active: true,\n        limit: 1,\n      });\n\n      if (existing.data[0]) {\n        console.log(`Price \"${priceConfig.lookupKey}\" already exists`);\n        continue;\n      }\n\n      const price = await stripe.prices.create({\n        product: product.id,\n        unit_amount: priceConfig.unitAmount,\n        currency: priceConfig.currency,\n        nickname: priceConfig.nickname,\n        lookup_key: priceConfig.lookupKey,\n        transfer_lookup_key: true,\n      });\n\n      console.log(`Created price \"({priceConfig.lookupKey}\" (){price.id})`);\n    }\n  }\n\n  console.log(\"nDone! Add the price ID to your .env as STRIPE_PRO_PRICE_ID\");\n}\n\nmain().catch(console.error);\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0686\u0644\u0627\u0626\u06cc\u06ba <code>bun run src\/lib\/payments\/seed.ts<\/code>.<\/p>\n<p>\u0686\u0646\u062f \u0628\u0627\u062a\u06cc\u06ba \u0642\u0627\u0628\u0644 \u062a\u0648\u062c\u06c1 \u06c1\u06cc\u06ba\u06d4<\/p>\n<ul>\n<li>\n<p><strong>\u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba<\/strong> <code>lookup_key<\/code> <strong>\u0642\u06cc\u0645\u062a \u06a9\u06cc ID \u06a9\u0648 \u06c1\u0627\u0631\u0688 \u06a9\u0648\u0688\u0646\u06af \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2:<\/strong> \u0679\u06cc\u0633\u0679 \u0645\u0648\u0688 \u0627\u0648\u0631 \u0644\u0627\u0626\u06cc\u0648 \u0645\u0648\u0688 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0642\u06cc\u0645\u062a IDs \u0645\u062e\u062a\u0644\u0641 \u06c1\u06cc\u06ba\u06d4 \u062a\u0644\u0627\u0634 \u06a9\u06cc \u0686\u0627\u0628\u06cc\u0627\u06ba \u0622\u067e \u06a9\u0648 \u0646\u0627\u0645 \u0633\u06d2 \u0642\u06cc\u0645\u062a\u0648\u06ba \u06a9\u0627 \u062d\u0648\u0627\u0644\u06c1 \u062f\u06cc\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u06cc \u06c1\u06cc\u06ba (<code>pro_one_time<\/code>) \u067e\u0679\u06cc \u0633\u06d2 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062f\u06c1 ID \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 (<code>price_1P...<\/code>)\u06d4  <\/p>\n<p>\u06a9\u06c1 <code>transfer_lookup_key: true<\/code> \u0622\u067e\u0634\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u060c \u0627\u0633\u06cc \u062a\u0644\u0627\u0634 \u06a9\u06cc \u06a9\u0644\u06cc\u062f \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0646\u0626\u06cc \u0642\u06cc\u0645\u062a \u0628\u0646\u0627\u0646\u06d2 \u0633\u06d2 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u067e\u0631\u0627\u0646\u06cc \u0642\u06cc\u0645\u062a \u0628\u062f\u0644 \u062c\u0627\u0626\u06d2 \u06af\u06cc\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0642\u06cc\u0645\u062a\u06cc\u06ba \u0633\u06cc\u0646\u0679 \u0645\u06cc\u06ba \u06c1\u06cc\u06ba:<\/strong> Stripe&#8217;s API \u06a9\u0631\u0646\u0633\u06cc \u06a9\u06cc \u0633\u0628 \u0633\u06d2 \u0686\u06be\u0648\u0679\u06cc \u0627\u06a9\u0627\u0626\u06cc \u0645\u06cc\u06ba \u0631\u0642\u0645 \u06a9\u06cc \u062a\u0648\u0642\u0639 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 USD \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2\u06d4 <code>19900<\/code> $199.00 \u06a9\u06cc \u0646\u0645\u0627\u0626\u0646\u062f\u06af\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4  <\/p>\n<p>\u06cc\u06c1 \u06a9\u06cc\u0691\u06d2 \u06a9\u06cc \u0627\u06cc\u06a9 \u0639\u0627\u0645 \u0648\u062c\u06c1 \u06c1\u06d2\u06d4 \u0627\u067e\u0646\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u0631\u0642\u0645 \u06a9\u0648 \u06c1\u0645\u06cc\u0634\u06c1 \u0633\u06cc\u0646\u0679 \u0645\u06cc\u06ba \u0631\u06a9\u06be\u06cc\u06ba \u0627\u0648\u0631 \u0635\u0631\u0641 \u0688\u0633\u067e\u0644\u06d2 \u0644\u06cc\u0626\u0631 \u0645\u06cc\u06ba \u0688\u0627\u0644\u0631 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0628\u06cc\u062c\u0648\u06ba \u06a9\u06d2 \u0627\u0633\u06a9\u0631\u067e\u0679 \u0628\u06d2 \u0636\u0645\u06cc\u0631 \u06c1\u06cc\u06ba\u06d4<\/strong> \u0622\u067e \u0627\u0633\u06d2 \u06a9\u0626\u06cc \u0628\u0627\u0631 \u0645\u062d\u0641\u0648\u0638 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0686\u0644\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0646\u0626\u06cc \u0645\u0635\u0646\u0648\u0639\u0627\u062a \u0628\u0646\u0627\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0645\u0635\u0646\u0648\u0639\u0627\u062a \u0627\u0648\u0631 \u0642\u06cc\u0645\u062a\u06cc\u06ba \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-how-to-set-up-the-stripe-client\">\u0627\u0633\u0679\u0631\u0627\u0626\u067e \u06a9\u0644\u0627\u0626\u0646\u0679 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/h3>\n<p>\u0627\u06af\u0631 \u0645\u0627\u0688\u06cc\u0648\u0644 \u0644\u0648\u0688 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a API \u06a9\u0644\u06cc\u062f \u063a\u0627\u0626\u0628 \u06c1\u0648 \u062a\u0648 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u06a9\u0644\u0627\u0626\u0646\u0679 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u0648 \u0631\u0648\u06a9\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u0633\u062a \u0627\u0628\u062a\u062f\u0627\u0621 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u062a\u0639\u0645\u06cc\u0631\u0627\u062a\u06cc \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u0627\u06c1\u0645 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u0633\u06cc\u0679 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/lib\/payments\/index.ts\nimport Stripe from \"stripe\";\n\nlet stripeClient: Stripe | null = null;\n\nfunction getStripe(): Stripe {\n  if (!stripeClient) {\n    const secretKey = process.env.STRIPE_SECRET_KEY;\n    if (!secretKey) {\n      throw new Error(\"STRIPE_SECRET_KEY is not set\");\n    }\n    stripeClient = new Stripe(secretKey);\n  }\n  return stripeClient;\n}\n\nexport const stripe = new Proxy({} as Stripe, {\n  get(_, prop) {\n    return Reflect.get(getStripe(), prop);\n  },\n});\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>Proxy<\/code> \u0631\u06cc\u067e\u0631 \u06cc\u06c1\u0627\u06ba \u06a9\u0644\u06cc\u062f\u06cc \u0646\u0645\u0648\u0646\u06c1 \u06c1\u06d2\u06d4 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06cc \u062f\u0631\u0622\u0645\u062f \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u06a9\u0648\u0688 <code>stripe<\/code> \u0627\u0648\u0631 \u067e\u06be\u0631 \u062f\u0631\u062c \u0630\u06cc\u0644 \u0637\u0631\u06cc\u0642\u06c1 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u06cc\u06ba: <code>stripe.checkout.sessions.create(...)<\/code>. \u067e\u0631\u0627\u06a9\u0633\u06cc \u062a\u0645\u0627\u0645 \u067e\u0631\u0627\u067e\u0631\u0679\u06cc \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u06a9\u0648 \u0631\u0648\u06a9\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0646\u06c1\u06cc\u06ba \u0633\u0633\u062a \u0634\u0631\u0648\u0639 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u0644\u0627\u0626\u0646\u0679 \u062a\u06a9 \u067e\u06c1\u0646\u0686\u0627\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u0627\u0633\u0679\u0631\u0627\u0626\u067e SDK \u0635\u0631\u0641 \u0627\u0633 \u0648\u0642\u062a \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u0622\u067e \u0627\u0635\u0644 \u0645\u06cc\u06ba \u0645\u0627\u0688\u06cc\u0648\u0644 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0646\u06c1 \u06a9\u06c1 \u062c\u0628 \u0622\u067e \u0627\u0633\u06d2 \u062f\u0631\u0622\u0645\u062f \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-how-to-build-the-checkout-flow\">\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0627 \u0628\u06c1\u0627\u0624 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/h2>\n<p>\u0686\u06cc\u06a9 \u0622\u0624\u0679 \u0641\u0644\u0648 \u062a\u06cc\u0646 \u062d\u0635\u0648\u06ba \u067e\u0631 \u0645\u0634\u062a\u0645\u0644 \u06c1\u06d2: \u0633\u06cc\u0634\u0646 \u062a\u062e\u0644\u06cc\u0642\u060c \u06a9\u0633\u0679\u0645\u0631 \u0631\u06cc \u0688\u0627\u0626\u0631\u06cc\u06a9\u0634\u0646\u060c \u0627\u0648\u0631 \u0631\u06cc\u0679\u0631\u0646 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af\u06d4<\/p>\n<h3 id=\"heading-how-to-create-a-checkout-session\">\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0627 \u0633\u06cc\u0634\u0646 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/h3>\n<p>\u0648\u06c1 \u0641\u0646\u06a9\u0634\u0646 \u062c\u0648 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u06a9\u06cc \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0686\u06cc\u06a9 \u0622\u0624\u0679 \u0633\u06cc\u0634\u0646 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/lib\/payments\/index.ts\nexport async function createOneTimeCheckoutSession(params: {\n  priceId: string;\n  successUrl: string;\n  cancelUrl: string;\n  metadata: Record<string string=\"\">;\n  customerEmail?: string;\n  couponId?: string;\n}) {\n  const client = getStripe();\n\n  const session = await client.checkout.sessions.create({\n    mode: \"payment\",\n    line_items: [{ price: params.priceId, quantity: 1 }],\n    success_url: params.successUrl,\n    cancel_url: params.cancelUrl,\n    metadata: params.metadata,\n    ...(params.customerEmail && {\n      customer_email: params.customerEmail,\n    }),\n    ...(params.couponId\n      ? { discounts: [{ coupon: params.couponId }] }\n      : { allow_promotion_codes: true }),\n  });\n\n  return session;\n}\n<\/string><\/code><\/pre>\n<p>\u06cc\u06c1\u0627\u06ba \u062a\u06cc\u0646 \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u0627\u06c1\u0645 \u06c1\u06cc\u06ba\u06d4<\/p>\n<ul>\n<li>\n<p><strong>\u06a9\u06c1<\/strong> <code>mode: \"payment\"<\/code> <strong>\u062a\u0631\u062a\u06cc\u0628 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u06a9\u0648 \u0628\u062a\u0627\u062a\u06cc \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0686\u0627\u0631\u062c \u06c1\u06d2\u06d4<\/strong>\u06cc\u06c1 \u0633\u0628\u0633\u06a9\u0631\u067e\u0634\u0646 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0633\u0628\u0633\u06a9\u0631\u067e\u0634\u0646\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba: <code>mode: \"subscription\"<\/code>. \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u067e\u0679\u06cc \u0628\u06be\u06cc\u062c\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u0648 \u0645\u0648\u0688 \u0645\u062a\u0627\u062b\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u06a9\u06c1<\/strong> <code>metadata<\/code> <strong>\u0641\u06cc\u0644\u0688\u0632 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0633\u06cc\u0634\u0646 \u06a9\u0648 \u0622\u067e \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0633\u06d2 \u0645\u0646\u0633\u0644\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0627\u06cc\u06a9 \u0637\u0631\u06cc\u0642\u06c1 \u06c1\u06cc\u06ba\u06d4<\/strong> \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u0639\u062f\u060c \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u067e\u0631\u0648\u0688\u06a9\u0679 \u06a9\u06d2 \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc\u060c \u0635\u0627\u0631\u0641 \u06a9\u06cc \u0634\u0646\u0627\u062e\u062a \u06cc\u0627 \u062f\u06cc\u06af\u0631 \u0645\u0637\u0644\u0648\u0628\u06c1 \u0688\u06cc\u0679\u0627 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u067e\u0627\u0633 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0627\u0633 \u0645\u06cc\u0679\u0627 \u0688\u06cc\u0679\u0627 \u06a9\u0648 \u0627\u0633\u0679\u0648\u0631 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0648\u0646\u0679\u0633 \u0627\u0648\u0631 API \u062c\u0648\u0627\u0628\u0627\u062a \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u06a9\u06c1<\/strong> <code>allow_promotion_codes: true<\/code> <strong>\u0686\u06cc\u06a9 \u0622\u0624\u0679 \u067e\u06cc\u062c \u067e\u0631 \u067e\u0631\u0648\u0645\u0648 \u06a9\u0648\u0688 \u0641\u06cc\u0644\u0688 \u06a9\u0648 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0622\u067e\u0634\u0646\u06d4<\/strong> \u0627\u06af\u0631 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062e\u0635\u0648\u0635 \u06a9\u0648\u067e\u0646 \u06c1\u06d2 (\u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0644\u06cc\u0646\u0688\u0646\u06af \u067e\u06cc\u062c \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631 \u0645\u06cc\u06ba)\u060c \u062a\u0648 \u0627\u0633\u06d2 \u0628\u0630\u0631\u06cc\u0639\u06c1 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba: <code>discounts<\/code> \u0627\u0633 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u06d4 \u0622\u067e \u062f\u0648\u0646\u0648\u06ba \u06a9\u0648 \u0628\u06cc\u06a9 \u0648\u0642\u062a \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u0631 \u0633\u06a9\u062a\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-how-to-create-the-checkout-api-endpoint\">\u0686\u06cc\u06a9 \u0622\u0624\u0679 API \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/h3>\n<p>API \u06a9\u0627 \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u06c1 \u062c\u0648 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0627 \u0633\u06cc\u0634\u0646 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 URL \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062f\u0631\u062c \u0630\u06cc\u0644 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/server\/api.ts\napp.post(\"\/api\/payments\/checkout\", async ({ set }) => {\n  const priceId = process.env.STRIPE_PRO_PRICE_ID;\n\n  if (!priceId) {\n    set.status = 500;\n    return { error: \"Price not configured\" };\n  }\n\n  const baseUrl = process.env.BETTER_AUTH_URL ?? \"http:\/\/localhost:3000\";\n  const tier = \"pro\";\n\n  const checkoutSession = await createOneTimeCheckoutSession({\n    priceId,\n    successUrl: `${baseUrl}\/dashboard?purchase=success&session_id={CHECKOUT_SESSION_ID}`,\n    cancelUrl: `${baseUrl}\/pricing`,\n    metadata: { tier },\n  });\n\n  return { url: checkoutSession.url };\n});\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>{CHECKOUT_SESSION_ID}<\/code> \u06a9\u0627\u0645\u06cc\u0627\u0628\u06cc \u06a9\u06d2 URL \u06a9\u06d2 \u067e\u0644\u06cc\u0633 \u06c1\u0648\u0644\u0688\u0631\u0632 \u0633\u0679\u0631\u0627\u0626\u067e \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679 \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u06c1\u06cc\u06ba\u06d4 \u06a9\u0633\u0679\u0645\u0631 \u06a9\u0648 \u0631\u06cc \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0627\u0633\u06d2 \u0627\u0635\u0644 \u0633\u06cc\u0634\u0646 ID \u0633\u06d2 \u0628\u062f\u0644 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u0633\u06d2 \u0641\u0631\u0646\u0679 \u0627\u06cc\u0646\u0688 \u06a9\u0648 \u0645\u0639\u0644\u0648\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u0627 \u0633\u06cc\u0634\u0646 \u0627\u0628\u06be\u06cc \u0645\u06a9\u0645\u0644 \u06c1\u0648\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-how-to-claim-the-purchase-after-checkout\">\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u0627\u067e\u0646\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0627 \u0628\u0644 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u0626\u06cc\u06ba<\/h3>\n<p>\u062c\u0628 \u06af\u0627\u06c1\u06a9 \u06a9\u0627\u0645\u06cc\u0627\u0628\u06cc \u06a9\u06d2 URL\u060c \u0641\u0631\u0646\u0679 \u0627\u06cc\u0646\u0688 \u067e\u0631 \u0648\u0627\u067e\u0633 \u0622\u062a\u0627 \u06c1\u06d2\u06d4 <code>session_id<\/code> \u0627\u0633\u06d2 URL \u0645\u06cc\u06ba &quot;\u062f\u0639\u0648\u06d2&#8221; \u06a9\u06d2 \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u06c1 \u067e\u0631 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u06c1 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0627 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/server\/api.ts\napp.post(\n  \"\/api\/purchases\/claim\",\n  async ({ body, request, set }) => {\n    const session = await auth.api.getSession({\n      headers: request.headers,\n    });\n\n    if (!session) {\n      set.status = 401;\n      return { error: \"Unauthorized\" };\n    }\n\n    const { sessionId } = body;\n\n    \/\/ Check if this session was already claimed\n    const existing = await db\n      .select()\n      .from(purchases)\n      .where(eq(purchases.stripeCheckoutSessionId, sessionId))\n      .limit(1);\n\n    if (existing[0]) {\n      return { success: true, alreadyClaimed: true, tier: existing[0].tier };\n    }\n\n    \/\/ Retrieve the Stripe checkout session to verify payment\n    const stripeSession = await retrieveCheckoutSession(sessionId);\n\n    if (stripeSession.payment_status !== \"paid\") {\n      set.status = 400;\n      return { error: \"Payment not completed\" };\n    }\n\n    const tier = (stripeSession.metadata?.tier ?? \"pro\") as PaymentTier;\n\n    \/\/ Create purchase record\n    await db.insert(purchases).values({\n      userId: session.user.id,\n      stripeCheckoutSessionId: sessionId,\n      stripeCustomerId:\n        typeof stripeSession.customer === \"string\"\n          ? stripeSession.customer\n          : stripeSession.customer?.id ?? null,\n      stripePaymentIntentId:\n        typeof stripeSession.payment_intent === \"string\"\n          ? stripeSession.payment_intent\n          : stripeSession.payment_intent?.id ?? null,\n      tier,\n      status: \"completed\",\n      amount: stripeSession.amount_total ?? 0,\n      currency: stripeSession.currency ?? \"usd\",\n    });\n\n    \/\/ Trigger background processing\n    await inngest.send({\n      name: \"purchase\/completed\",\n      data: {\n        userId: session.user.id,\n        tier,\n        sessionId,\n      },\n    });\n\n    return { success: true, tier };\n  },\n  {\n    body: t.Object({\n      sessionId: t.String(),\n    }),\n  }\n);\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u06c1 \u062a\u0631\u062a\u06cc\u0628 \u0645\u06cc\u06ba \u0686\u0627\u0631 \u06a9\u0627\u0645 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2:<\/p>\n<ol>\n<li>\n<p><strong>\u067e\u06c1\u0644\u06d2 \u06c1\u0645 \u0686\u06cc\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u0633\u06cc\u0634\u0646 \u06a9\u06cc \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4<\/strong> \u06a9\u06c1 <code>unique()<\/code> \u0641\u0627\u0631\u0645\u0627\u0633\u06cc\u0648\u0679\u06cc\u06a9\u0644 <code>stripeCheckoutSessionId<\/code> \u0622\u067e \u06a9\u06d2 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u0645\u06cc\u06ba \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0631\u06cc\u06a9\u0627\u0631\u0688\u0632 \u06a9\u0648 \u0631\u0648\u06a9\u0646\u0627\u060c \u0644\u06cc\u06a9\u0646 \u067e\u06c1\u0644\u06d2 \u0686\u06cc\u06a9 \u06a9\u0631\u0646\u0627\u060c \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u06cc \u063a\u0644\u0637\u06cc\u0648\u06ba \u06a9\u0648 \u067e\u06a9\u0691\u06d2 \u0628\u063a\u06cc\u0631 \u0635\u0627\u0641 \u062c\u0648\u0627\u0628 \u062f\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u062f\u0648\u0633\u0631\u0627\u060c \u06c1\u0645 \u067e\u0679\u06cc \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba.<\/strong> \u06a9\u0644\u0627\u0626\u0646\u0679 \u06a9\u06d2 \u0688\u06cc\u0679\u0627 \u067e\u0631 \u06a9\u0628\u06be\u06cc \u0628\u06be\u0631\u0648\u0633\u06c1 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4 \u0641\u0631\u0646\u0679 \u0627\u06cc\u0646\u0688 \u0633\u06cc\u0634\u0646 \u0622\u0626\u06cc \u0688\u06cc \u06a9\u0648 \u067e\u0627\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0622\u067e \u06a9\u0648 \u0627\u0633 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u06a9\u06d2 API \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 <code>payment_status<\/code> \u06c1\u06d2 <code>\"paid\"<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>\u062a\u06cc\u0633\u0631\u0627\u060c \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0627 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/strong> \u0627\u0633\u06d2 \u06a9\u06cc\u0633\u06d2 \u0646\u06a9\u0627\u0644\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0633 \u067e\u0631 \u062a\u0648\u062c\u06c1 \u062f\u06cc\u06ba\u06d4 <code>customer<\/code> \u0627\u0648\u0631 <code>payment_intent<\/code> \u067e\u0679\u06cc \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba\u06d4 \u0622\u067e \u06a9\u06cc \u0627\u0633\u0679\u0631\u0627\u0626\u067e API \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628\u0627\u062a \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u062f\u0648\u0646\u0648\u06ba \u0641\u06cc\u0644\u0688\u0632 \u06a9\u0648 \u0633\u0679\u0631\u0646\u06af\u0632 \u06cc\u0627 \u062a\u0648\u0633\u06cc\u0639\u06cc \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0648\u0627\u067e\u0633 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0679\u0631\u0646\u0631\u06cc \u062f\u0648\u0646\u0648\u06ba \u0635\u0648\u0631\u062a\u0648\u06ba \u06a9\u0648 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0686\u0648\u062a\u06be\u0627\u060c \u062f\u0631\u062c \u0630\u06cc\u0644 \u0628\u06be\u06cc\u062c\u06cc\u06ba:<\/strong> <code>purchase\/completed<\/code> <strong>\u06cc\u06c1 Ingest \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0648\u0627\u0642\u0639\u06c1 \u06c1\u06d2\u06d4<\/strong> \u06cc\u06c1 \u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u0641\u0644\u0648 \u06a9\u0648 \u0645\u062a\u062d\u0631\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0627\u06cc \u0645\u06cc\u0644\u0632\u060c \u06af\u0631\u0627\u0646\u0679\u0633 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc\u060c \u062a\u062c\u0632\u06cc\u0627\u062a\u060c \u0627\u0648\u0631 \u0641\u0627\u0644\u0648 \u0627\u067e \u0634\u06cc\u0688\u0648\u0644\u0646\u06af \u06a9\u0648 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 API \u06a9\u0627 \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u06c1 \u0639\u0645\u0644 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u0648\u0627\u067e\u0633 \u0622\u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>{ success: true }<\/code> \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631<\/p>\n<\/li>\n<\/ol>\n<p>\u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u0631\u06cc\u06a9\u0627\u0631\u0688\u0646\u06af \u0627\u0648\u0631 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u06cc\u06c1 \u0639\u0644\u06cc\u062d\u062f\u06af\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u06c1\u06d2\u06d4 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u06d2 \u0627\u0646\u062f\u0631\u0627\u062c \u062a\u06cc\u0632 \u0627\u0648\u0631 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u06c1\u06cc\u06ba\u06d4 \u0688\u0627\u0624\u0646 \u0627\u0633\u0679\u0631\u06cc\u0645 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af (\u0627\u06cc \u0645\u06cc\u0644\u0632\u060c API \u06a9\u0627\u0644\u0632\u060c \u062a\u062c\u0632\u06cc\u0627\u062a) \u0633\u0633\u062a \u0627\u0648\u0631 \u0646\u0627\u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0628\u0627\u0631 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u06a9\u0648 \u062a\u0642\u0633\u06cc\u0645 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0635\u0627\u0631\u0641\u06cc\u0646 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0627\u0645\u06cc\u0627\u0628\u06cc \u06a9\u06d2 \u062c\u0648\u0627\u0628\u0627\u062a \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0628\u06a9\u06c1 \u067e\u0633 \u0645\u0646\u0638\u0631 \u06a9\u06d2 \u06a9\u0627\u0645 \u062c\u0627\u0631\u06cc \u0631\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-how-to-handle-webhooks-securely\">\u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06a9\u06cc\u0633\u06d2 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0646\u0679\u0631\u06cc \u067e\u0648\u0627\u0626\u0646\u0679 \u06c1\u06d2 \u062c\u0648 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u0633\u06d2 \u0628\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u06cc\u0633\u06d2 \u0631\u06cc\u0641\u0646\u0688\u0632\u060c \u0645\u06cc\u0639\u0627\u062f \u062e\u062a\u0645 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0633\u06cc\u0634\u0646\u0632 \u0627\u0648\u0631 \u062a\u0646\u0627\u0632\u0639\u0627\u062a\u06d4<\/p>\n<h3 id=\"heading-how-to-verify-webhook-signatures\">\u0648\u06cc\u0628 \u06c1\u06a9 \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0645\u06cc\u06ba \u0645\u0648\u062c\u0648\u062f \u062a\u0645\u0627\u0645 \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u062f\u0633\u062a\u062e\u0637\u06cc \u06c1\u06cc\u0688\u0631 \u0634\u0627\u0645\u0644 \u06c1\u06d2\u06d4 \u0627\u06cc\u0648\u0646\u0679 \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0622\u067e \u06a9\u0648 \u0627\u0633 \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u0646\u06cc \u06c1\u0648\u06af\u06cc\u06d4 \u0627\u06af\u0631 \u0686\u06cc\u06a9 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u0648\u060c \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0622\u067e \u06a9\u06d2 \u0648\u06cc\u0628 \u06c1\u06a9 URL \u067e\u0631 \u062c\u0639\u0644\u06cc \u0648\u0627\u0642\u0639\u0627\u062a \u0628\u06be\u06cc\u062c \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/lib\/payments\/index.ts\nexport async function constructWebhookEvent(\n  payload: string | Buffer,\n  signature: string\n) {\n  const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;\n  if (!webhookSecret) {\n    throw new Error(\"STRIPE_WEBHOOK_SECRET is not set\");\n  }\n  const client = getStripe();\n  return client.webhooks.constructEventAsync(payload, signature, webhookSecret);\n}\n<\/code><\/pre>\n<p>\u0627\u06cc\u06a9 \u0627\u06c1\u0645 \u062a\u0641\u0635\u06cc\u0644 \u06cc\u06c1 \u06c1\u06d2: <strong>\u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba<\/strong> <code>constructEventAsync<\/code> <strong>\u0627\u0633 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2<\/strong> <code>constructEvent<\/code><strong>.<\/strong> \u063a\u06cc\u0631 \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u0648\u0631\u0698\u0646 Web Crypto API \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0648 \u06a9\u06c1 Bun \u0627\u0648\u0631 Cloudflare \u0648\u0631\u06a9\u0631\u0632 \u062c\u06cc\u0633\u06d2 \u062c\u062f\u06cc\u062f \u0631\u0646 \u0679\u0627\u0626\u0645\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0637\u0627\u0628\u0642\u062a \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0645 \u0648\u0642\u062a \u0633\u0627\u0632 \u0648\u0631\u0698\u0646 Node.js \u067e\u0631 \u0645\u0646\u062d\u0635\u0631 \u06c1\u06d2\u06d4 <code>crypto<\/code> \u0645\u0627\u0688\u06cc\u0648\u0644 \u06c1\u0631 \u062c\u06af\u06c1 \u062f\u0633\u062a\u06cc\u0627\u0628 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0627\u0648\u0631 \u0627\u06c1\u0645 \u062a\u0641\u0635\u06cc\u0644: <strong>\u062e\u0627\u0645 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06d2 \u0628\u0627\u0688\u06cc \u06a9\u0648 \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642 \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0627\u06af\u0631 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u0627\u0633 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0628\u0627\u0688\u06cc \u06a9\u0648 JSON \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u0627\u0631\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u06cc\u06d4 \u062f\u0633\u062a\u062e\u0637\u0648\u06ba \u06a9\u0627 \u062d\u0633\u0627\u0628 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06d2 \u062e\u0627\u0645 \u0628\u0627\u0626\u0679\u0633 \u0633\u06d2 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u062c\u0632\u06cc\u06c1 \u06a9\u0631\u062f\u06c1 JSON \u0633\u06d2 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-how-to-build-the-webhook-endpoint\">\u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/h3>\n<p>\u06cc\u06c1\u0627\u06ba \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u06c1\u06d2: \u0627\u0633 \u06a9\u0627 \u0648\u0627\u062d\u062f \u06a9\u0627\u0645 \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642 \u06a9\u0631\u0646\u0627 \u0627\u0648\u0631 \u0627\u0646\u06c1\u06cc\u06ba \u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u0679\u0627\u0633\u06a9 \u0633\u0633\u0679\u0645 \u062a\u06a9 \u067e\u06c1\u0646\u0686\u0627\u0646\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/server\/api.ts\napp.post(\"\/api\/payments\/webhook\", async ({ request, set }) => {\n  const body = await request.text();\n  const sig = request.headers.get(\"stripe-signature\");\n\n  if (!sig) {\n    set.status = 400;\n    return { error: \"Missing signature\" };\n  }\n\n  try {\n    const event = await constructWebhookEvent(body, sig);\n    console.log(`[Webhook] Received ${event.type}`);\n\n    if (event.type === \"charge.refunded\") {\n      const charge = event.data.object as {\n        id: string;\n        payment_intent: string;\n        amount: number;\n        amount_refunded: number;\n        currency: string;\n      };\n      await inngest.send({\n        name: \"stripe\/charge.refunded\",\n        data: {\n          chargeId: charge.id,\n          paymentIntentId: charge.payment_intent,\n          amountRefunded: charge.amount_refunded,\n          originalAmount: charge.amount,\n          currency: charge.currency,\n        },\n      });\n    }\n\n    if (event.type === \"checkout.session.expired\") {\n      const session = event.data.object as {\n        id: string;\n        customer_email: string | null;\n      };\n      await inngest.send({\n        name: \"stripe\/checkout.session.expired\",\n        data: {\n          sessionId: session.id,\n          customerEmail: session.customer_email,\n        },\n      });\n    }\n\n    return { received: true };\n  } catch (error) {\n    console.error(\"[Webhook] Stripe verification failed:\", error);\n    set.status = 400;\n    return { error: \"Webhook verification failed\" };\n  }\n});\n<\/code><\/pre>\n<p>\u06cc\u06c1 &quot;\u067e\u062a\u0644\u06cc \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631&#8221; \u067e\u06cc\u0679\u0631\u0646 \u06c1\u06d2\u06d4 \u0646\u0648\u0679 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u06cc\u06c1 \u06a9\u06cc\u0627 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <strong>~ \u0646\u06c1\u06cc\u06ba<\/strong> \u06a9\u06cc\u0627 \u06a9\u0631\u06cc\u06ba: \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u06cc \u0645\u06cc\u0644\u0632 \u0646\u06c1 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u060c \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u06cc\u06ba\u060c \u06cc\u0627 \u0628\u06cc\u0631\u0648\u0646\u06cc \u062e\u062f\u0645\u0627\u062a \u06a9\u0648 \u06a9\u0627\u0644 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4 \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0645\u0637\u0644\u0648\u0628\u06c1 \u0641\u06cc\u0644\u0688\u0632 \u06a9\u0648 \u0646\u06a9\u0627\u0644\u0646\u06d2\u060c \u0627\u0648\u0631 \u062f\u0627\u062e\u0644 \u06a9\u0631\u062f\u06c1 \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u0648 Ingest \u067e\u0631 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u06d4<\/p>\n<p>\u067e\u0648\u0631\u0627 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0645\u0644\u06cc \u0633\u06cc\u06a9\u0646\u0688 \u0645\u06cc\u06ba \u0645\u06a9\u0645\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2\u061f \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u06a9\u0648 \u062a\u0648\u0642\u0639 \u06c1\u06d2 \u06a9\u06c1 \u0648\u06cc\u0628 \u06c1\u06a9 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b 20 \u0633\u06cc\u06a9\u0646\u0688 \u0645\u06cc\u06ba 2xx \u062c\u0648\u0627\u0628 \u062f\u06d2 \u06af\u0627\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u0627 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0628\u06c1\u062a \u0632\u06cc\u0627\u062f\u06c1 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 (\u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u060c API \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u06cc\u06ba)\u060c \u062a\u0648 \u0627\u0633 \u0633\u06d2 \u0648\u0642\u062a \u062e\u062a\u0645 \u06c1\u0648\u0646\u06d2 \u06a9\u0627 \u062e\u0637\u0631\u06c1 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u067e\u0679\u06cc \u0627\u0633\u06d2 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0646\u0634\u0627\u0646 \u0632\u062f \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u067e\u0648\u0631\u06d2 \u0627\u06cc\u0648\u0646\u0679 \u06a9\u06cc \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u062c\u0632\u0648\u06cc \u062a\u06a9\u0645\u06cc\u0644 \u0627\u0648\u0631 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u0627\u0628 \u0645\u06a9\u0645\u0644 \u06c1\u0648 \u0686\u06a9\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0633\u06cc\u0646 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0627\u0633\u06d2 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0648\u062b\u06cc\u0642 \u06a9\u0631\u06cc\u06ba\u060c \u0642\u0637\u0627\u0631 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u060c \u0648\u0627\u067e\u0633 \u062c\u0627\u0626\u06cc\u06ba\u06d4 \u062a\u0645\u0627\u0645 \u0627\u0635\u0644 \u06a9\u0627\u0645 \u0627\u06cc\u06a9 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u067e\u0633 \u0645\u0646\u0638\u0631 \u06a9\u06d2 \u0641\u0646\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u0645\u062a\u0636\u0627\u062f \u0637\u0648\u0631 \u067e\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0622\u067e \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0627\u06cc\u0648\u0646\u0679\u0633 \u0633\u06d2 \u06a9\u0686\u06be \u0641\u06cc\u0644\u0688\u0632 \u0646\u06a9\u0627\u0644\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0646\u06c1\u06cc\u06ba Ingest \u067e\u0631 \u0628\u06be\u06cc\u062c\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">await inngest.send({\n  name: \"stripe\/charge.refunded\",\n  data: {\n    chargeId: charge.id,\n    paymentIntentId: charge.payment_intent,\n    amountRefunded: charge.amount_refunded,\n    originalAmount: charge.amount,\n    currency: charge.currency,\n  },\n});\n<\/code><\/pre>\n<p>\u06a9\u06cc\u0627 \u06c1\u0648\u06af\u0627 \u0627\u06af\u0631 \u06c1\u0645 \u067e\u0648\u0631\u06d2 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0627\u06cc\u0648\u0646\u0679 \u06a9\u0648 \u0622\u06af\u06d2 \u0628\u06be\u06cc\u062c \u062f\u06cc\u06ba\u061f \u062f\u0648 \u0648\u062c\u0648\u06c1\u0627\u062a\u06d4<\/p>\n<p>\u0633\u0628 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0633\u0679\u0631\u0627\u0626\u067e \u0627\u06cc\u0648\u0646\u0679 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0628\u0691\u06d2 \u0627\u0648\u0631 \u06af\u06c1\u0631\u06d2 \u06af\u06be\u0648\u0646\u0633\u0644\u06d2 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0635\u0631\u0641 5 \u0641\u06cc\u0644\u0688\u0632 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u067e\u0648\u0631\u06cc \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06cc\u06a9 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0641\u0646\u06a9\u0634\u0646 \u06c1\u0631 \u0686\u0648\u06a9\u06cc \u067e\u0631 \u0627\u06cc\u06a9 \u0628\u0691\u0627 \u067e\u06d2 \u0644\u0648\u0688 \u0630\u062e\u06cc\u0631\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u06af\u0631 \u0622\u067e \u0627\u0633\u06d2 \u06c1\u0632\u0627\u0631\u0648\u06ba \u0628\u0627\u0631 \u0686\u0644\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0627\u0633 \u0645\u06cc\u06ba \u0627\u0636\u0627\u0641\u06c1 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062f\u0648\u0633\u0631\u0627\u060c \u0628\u0627\u0624\u0646\u0688\u0631\u06cc \u0633\u06d2 \u0641\u06cc\u0644\u0688\u0632 \u0646\u06a9\u0627\u0644\u0646\u06d2 \u0633\u06d2 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0627\u0648\u0631 \u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0648\u0627\u0636\u062d \u0645\u0639\u0627\u06c1\u062f\u06c1 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u067e\u0679\u06cc \u0645\u0633\u062a\u0642\u0628\u0644 \u06a9\u06d2 API \u0648\u0631\u0698\u0646 \u0645\u06cc\u06ba \u0627\u06cc\u0648\u0646\u0679 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06a9\u06cc \u0638\u0627\u06c1\u0631\u06cc \u0634\u06a9\u0644 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u06a9\u0648 \u0635\u0631\u0641 \u0627\u067e\u0646\u06d2 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0645\u06cc\u06ba \u0646\u06a9\u0627\u0644\u0646\u06d2 \u06a9\u06cc \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u067e\u0633 \u0645\u0646\u0638\u0631 \u06a9\u06cc \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u0631\u06c1\u06cc\u06ba \u06af\u06cc \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0648\u06c1 \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u062f\u0627\u062e\u0644 \u06a9\u0631\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u06a9\u06cc \u0634\u06a9\u0644 \u067e\u0631 \u0627\u0646\u062d\u0635\u0627\u0631 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba \u0646\u06c1 \u06a9\u06c1 \u067e\u0679\u06cc \u067e\u0631\u06d4<\/p>\n<h3 id=\"heading-how-to-set-up-webhooks-in-production\">\u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/h3>\n<p>\u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0645\u06cc\u06ba \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u06a9\u0648 \u06a9\u0646\u0641\u06cc\u06af\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<ol>\n<li>\n<p>\u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688\u060c \u0688\u0648\u06cc\u0644\u067e\u0631\u0632\u060c \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u067e\u0631 \u062c\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u067e\u0646\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 URL \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0627\u06cc\u06a9 \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u06c1 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>https:\/\/yourapp.com\/api\/payments\/webhook<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0648\u06c1 \u0627\u06cc\u0648\u0646\u0679 \u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u06cc\u06ba \u062c\u0633\u06d2 \u0622\u067e \u0648\u0635\u0648\u0644 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba: <code>charge.refunded<\/code> \u0627\u0648\u0631 <code>checkout.session.expired<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u062f\u0633\u062a\u062e\u0637 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0631\u0627\u0632 \u06a9\u0648 \u06a9\u0627\u067e\u06cc \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0627\u067e\u0646\u06d2 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0645\u0627\u062d\u0648\u0644 \u06a9\u06d2 \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u0645\u06cc\u06ba \u062f\u0631\u062c \u0630\u06cc\u0644 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba: <code>STRIPE_WEBHOOK_SECRET<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u067e\u0631 \u062f\u0633\u062a\u062e\u0637 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0631\u0627\u0632 \u0627\u0633 \u0631\u0627\u0632 \u0633\u06d2 \u0645\u062e\u062a\u0644\u0641 \u06c1\u06d2 \u062c\u0648 \u0633\u0679\u0631\u0627\u0626\u067e CLI \u0645\u0642\u0627\u0645\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba \u06a9\u06c1 \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u06c1\u0631 \u0645\u0627\u062d\u0648\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0631\u0633\u062a \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0633\u06cc\u0679 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-which-webhook-events-to-listen-for\">\u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0648\u0646\u0679\u0633 \u0648\u0635\u0648\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2<\/h3>\n<p>\u0645\u06a9\u0645\u0644 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0622\u067e \u06a9\u0648 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0645\u06cc\u06ba \u062f\u0631\u062c \u0630\u06cc\u0644 \u0648\u06cc\u0628 \u06c1\u064f\u06a9 \u0627\u06cc\u0648\u0646\u0679 \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u06d4<\/p>\n<table>\n<thead>\n<tr>\n<th>\u0648\u0627\u0642\u0639\u06c1<\/th>\n<th>\u0627\u06af\u0631 \u0622\u06af \u0644\u06af \u062c\u0627\u0626\u06d2\u06d4<\/th>\n<th>\u0622\u067e \u06a9\u06cc\u0627 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>charge.refunded<\/code><\/td>\n<td>\u06a9\u0633\u0679\u0645\u0631 \u0631\u06cc\u0641\u0646\u0688 \u0648\u0635\u0648\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<td>\u0631\u0633\u0627\u0626\u06cc \u0645\u0646\u0633\u0648\u062e \u06a9\u0631\u06cc\u06ba (\u0645\u06a9\u0645\u0644 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc) \u06cc\u0627 \u0627\u0633\u0679\u06cc\u0679\u0633 \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u06cc\u06ba (\u062c\u0632\u0648\u06cc)<\/td>\n<\/tr>\n<tr>\n<td><code>checkout.session.expired<\/code><\/td>\n<td>\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0633\u06cc\u0634\u0646 \u06a9\u0627 \u0679\u0627\u0626\u0645 \u0622\u0624\u0679 (24 \u06af\u06be\u0646\u0679\u06d2)<\/td>\n<td>\u062a\u0631\u06a9 \u0634\u062f\u06c1 \u06a9\u0627\u0631\u0679 \u0631\u06cc\u06a9\u0648\u0631\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u0633\u0628\u0633\u06a9\u0631\u067e\u0634\u0646 \u067e\u0631 \u0645\u0628\u0646\u06cc \u0628\u0644\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0622\u067e \u06cc\u06c1 \u0628\u06be\u06cc \u062d\u0627\u0635\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba: <code>customer.subscription.updated<\/code>\u060c <code>customer.subscription.deleted<\/code>\u0627\u0648\u0631 <code>invoice.payment_failed<\/code>. \u0686\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0645\u0636\u0645\u0648\u0646 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u06a9\u06cc \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc\u0648\u06ba \u06a9\u0627 \u0627\u062d\u0627\u0637\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0645\u062b\u0627\u0644 \u0627\u0648\u067e\u0631 \u06a9\u06d2 \u062f\u0648 \u0648\u0627\u0642\u0639\u0627\u062a \u067e\u0631 \u0645\u0631\u06a9\u0648\u0632 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06c1 <code>checkout.session.completed<\/code> \u0648\u0627\u0642\u0639\u0627\u062a \u0646\u0645\u0627\u06cc\u0627\u06ba \u0637\u0648\u0631 \u067e\u0631 \u063a\u0627\u0626\u0628 \u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u06a9\u06cc \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0622\u067e \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u0648\u06cc\u0628 \u06c1\u06a9 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 &quot;\u0628\u0644\u0646\u06af&#8221; \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679 (\u067e\u0686\u06be\u0644\u06d2 \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u062f\u06a9\u06be\u0627\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2) \u0645\u06cc\u06ba \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0648 \u06a9\u0633\u06cc \u0627\u06a9\u0627\u0624\u0646\u0679 \u0633\u06d2 \u0645\u0646\u0633\u0644\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0645\u0633\u062a\u0646\u062f \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u0633\u06cc\u0634\u0646 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-how-to-process-purchases-with-durable-background-jobs\">\u0627\u06cc\u06a9 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u067e\u0633 \u0645\u0646\u0638\u0631 \u06a9\u06d2 \u06a9\u0627\u0645 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc\u0648\u06ba \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u06cc\u06c1 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u06a9\u0627 \u062f\u0644 \u06c1\u06d2\u06d4 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0627 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f <code>purchase\/completed<\/code> \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062c\u0628 \u0627\u06cc\u0648\u0646\u0679 \u0628\u06be\u06cc\u062c \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0627\u06cc\u06a9 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0641\u0646\u06a9\u0634\u0646 \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0645\u06a9\u0645\u0644 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u0648\u0631\u06a9 \u0641\u0644\u0648 \u06a9\u0648 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u06c1\u0631 \u0642\u062f\u0645 \u06a9\u0648 \u0627\u0646\u0641\u0631\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 \u062c\u0627\u0646\u0686\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0645\u0631\u062d\u0644\u06c1 5 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648\u060c \u0645\u0631\u062d\u0644\u06c1 1 \u0633\u06d2 4 \u062a\u06a9 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0646\u06c1\u06cc\u06ba \u0686\u0644\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 \u0645\u0631\u062d\u0644\u06c1 5 \u062e\u0648\u062f \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u06af\u0631 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 6 \u0633\u06d2 9 \u062a\u06a9 \u06a9\u06d2 \u0645\u0631\u0627\u062d\u0644 \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be\u06cc\u06ba\u06d4<\/p>\n<p>&quot;\u0645\u0633\u0644\u0633\u0644 \u067e\u06be\u0627\u0646\u0633\u06cc&#8221; \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06cc\u06c1\u06cc \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0646\u0638\u0627\u0645 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0631\u0642 \u06c1\u06d2 \u062c\u0648 \u062a\u0631\u0642\u06cc\u0627\u062a\u06cc \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0646\u0638\u0627\u0645 \u0645\u06cc\u06ba \u062c\u0648 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0645\u06cc\u06ba \u0627\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 Ingest \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u0648\u06ba\u06d4 \u06cc\u06c1 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u06a9 \u0627\u06cc\u0648\u0646\u0679 \u0633\u06d2 \u0686\u0644\u0646\u06d2 \u0648\u0627\u0644\u0627\u060c \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0639\u0645\u0644\u062f\u0631\u0622\u0645\u062f \u067e\u0644\u06cc\u0679 \u0641\u0627\u0631\u0645 \u06c1\u06d2 \u062c\u0648 \u0645\u0631\u062d\u0644\u06c1 \u0648\u0627\u0631 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06cc\u06ba: <code>step.run()<\/code> \u0628\u0644\u0627\u06a9\u0646\u06af \u0627\u0648\u0631 \u0627\u0646\u062c\u0633\u0679 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0645\u0646\u0637\u0642\u060c \u0631\u06cc\u0627\u0633\u062a \u06a9\u06cc \u0627\u0633\u062a\u0642\u0627\u0645\u062a\u060c \u0627\u0648\u0631 \u0645\u0634\u0627\u06c1\u062f\u06d2 \u06a9\u0648 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0646\u062c\u0633\u0679 \u06a9\u0644\u0627\u0626\u0646\u0679 \u0633\u06cc\u0679 \u0627\u067e \u06a9\u0645 \u0633\u06d2 \u06a9\u0645 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/lib\/jobs\/client.ts\nimport { Inngest } from \"inngest\";\n\nexport const inngest = new Inngest({\n  id: \"my-app\",\n});\n<\/code><\/pre>\n<p>\u0627\u067e\u0646\u06d2 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 Ingest subhandler \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0631\u062c\u0633\u0679\u0631 \u06a9\u0631\u06cc\u06ba \u062a\u0627\u06a9\u06c1 \u0622\u067e \u06a9\u0627 \u0688\u0648\u06cc\u0644\u067e\u0645\u0646\u0679 \u0633\u0631\u0648\u0631 (\u0627\u0648\u0631 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646) \u0627\u0633\u06d2 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u0631 \u0633\u06a9\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">import { serve } from \"inngest\/bun\";\nimport { inngest } from \"@\/lib\/jobs\/client\";\nimport { stripeFunctions } from \"@\/lib\/jobs\/functions\/stripe\";\n\nconst inngestHandler = serve({\n  client: inngest,\n  functions: [...stripeFunctions],\n});\n\n\/\/ Mount on your API\napp.all(\"\/api\/inngest\", async (ctx) => {\n  return inngestHandler(ctx.request);\n});\n<\/code><\/pre>\n<p>\u0645\u06a9\u0645\u0644 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/lib\/jobs\/functions\/stripe.ts\nimport { eq } from \"drizzle-orm\";\nimport { createElement } from \"react\";\n\nimport { inngest } from \"..\/client\";\nimport { trackServerEvent } from \"@\/lib\/analytics\/server\";\nimport { brand } from \"@\/lib\/brand\";\nimport { db, purchases, users } from \"@\/lib\/db\";\nimport {\n  sendEmail,\n  PurchaseConfirmationEmail,\n  AdminPurchaseNotificationEmail,\n  RepoAccessGrantedEmail,\n} from \"@\/lib\/email\";\nimport { addCollaborator } from \"@\/lib\/github\";\n\nexport const handlePurchaseCompleted = inngest.createFunction(\n  { id: \"purchase-completed\", triggers: [{ event: \"purchase\/completed\" }] },\n  async ({ event, step }) => {\n    const { userId, tier, sessionId } = event.data as {\n      userId: string;\n      tier: string;\n      sessionId: string;\n    };\n\n    \/\/ Step 1: Look up user and purchase details\n    const { user, purchase } = await step.run(\n      \"lookup-user-and-purchase\",\n      async () => {\n        const userResult = await db\n          .select({\n            id: users.id,\n            email: users.email,\n            name: users.name,\n            githubUsername: users.githubUsername,\n          })\n          .from(users)\n          .where(eq(users.id, userId))\n          .limit(1);\n\n        const foundUser = userResult[0];\n        if (!foundUser) {\n          throw new Error(`User not found: ${userId}`);\n        }\n\n        const purchaseResult = await db\n          .select({\n            amount: purchases.amount,\n            currency: purchases.currency,\n            stripePaymentIntentId: purchases.stripePaymentIntentId,\n          })\n          .from(purchases)\n          .where(eq(purchases.stripeCheckoutSessionId, sessionId))\n          .limit(1);\n\n        const foundPurchase = purchaseResult[0];\n\n        return {\n          user: foundUser,\n          purchase: foundPurchase ?? {\n            amount: 0,\n            currency: \"usd\",\n            stripePaymentIntentId: null,\n          },\n        };\n      }\n    );\n\n    \/\/ Step 2: Track purchase in analytics\n    await step.run(\"track-purchase-to-posthog\", async () => {\n      try {\n        await trackServerEvent(userId, \"purchase_completed_server\", {\n          tier,\n          amount_cents: purchase.amount,\n          currency: purchase.currency,\n          stripe_session_id: sessionId,\n          stripe_payment_intent_id: purchase.stripePaymentIntentId,\n        });\n      } catch (error) {\n        console.error(`Failed to track to PostHog:`, error);\n      }\n    });\n\n    \/\/ Step 3: Send purchase confirmation to customer\n    await step.run(\"send-purchase-confirmation\", async () => {\n      await sendEmail({\n        to: user.email,\n        subject: `Your ${brand.name} purchase is confirmed!`,\n        template: createElement(PurchaseConfirmationEmail, {\n          amount: purchase.amount,\n          currency: purchase.currency,\n          customerEmail: user.email,\n        }),\n      });\n    });\n\n    \/\/ Step 4: Send admin notification\n    await step.run(\"send-admin-notification\", async () => {\n      const adminEmail = process.env.ADMIN_EMAIL;\n      if (!adminEmail) return;\n\n      await sendEmail({\n        to: adminEmail,\n        subject: `New template sale: ${user.email}`,\n        template: createElement(AdminPurchaseNotificationEmail, {\n          amount: purchase.amount,\n          currency: purchase.currency,\n          customerEmail: user.email,\n          customerName: user.name,\n          stripeSessionId: purchase.stripePaymentIntentId ?? sessionId,\n        }),\n      });\n    });\n\n    \/\/ Early return if user has no GitHub username\n    if (!user.githubUsername) {\n      return { success: true, userId, tier, githubAccessGranted: false };\n    }\n\n    \/\/ Step 5: Grant GitHub repository access\n    const collaboratorResult = await step.run(\n      \"add-github-collaborator\",\n      async () => {\n        return addCollaborator(user.githubUsername!);\n      }\n    );\n\n    \/\/ Step 6: Track GitHub access granted\n    await step.run(\"track-github-access\", async () => {\n      await trackServerEvent(userId, \"github_access_granted\", {\n        tier,\n        github_username: user.githubUsername,\n        invitation_status: collaboratorResult.status,\n      });\n    });\n\n    \/\/ Step 7: Update purchase record\n    await step.run(\"update-purchase-record\", async () => {\n      await db\n        .update(purchases)\n        .set({\n          githubAccessGranted: true,\n          githubInvitationId: collaboratorResult.status,\n          updatedAt: new Date(),\n        })\n        .where(eq(purchases.stripeCheckoutSessionId, sessionId));\n    });\n\n    \/\/ Step 8: Send repo access email\n    await step.run(\"send-repo-access-email\", async () => {\n      const repoUrl = brand.social.github;\n      await sendEmail({\n        to: user.email,\n        subject: `Your ${brand.name} repository access is ready!`,\n        template: createElement(RepoAccessGrantedEmail, { repoUrl }),\n      });\n    });\n\n    \/\/ Step 9: Schedule follow-up email sequence\n    await step.run(\"schedule-follow-up\", async () => {\n      const purchaseRecord = await db\n        .select({ id: purchases.id })\n        .from(purchases)\n        .where(eq(purchases.stripeCheckoutSessionId, sessionId))\n        .limit(1);\n\n      if (purchaseRecord[0]) {\n        await inngest.send({\n          name: \"purchase\/follow-up.scheduled\",\n          data: {\n            userId,\n            purchaseId: purchaseRecord[0].id,\n            tier,\n          },\n        });\n      }\n    });\n\n    return { success: true, userId, tier, githubAccessGranted: true };\n  }\n);\n<\/code><\/pre>\n<p>\u0628\u06c1\u062a \u0632\u06cc\u0627\u062f\u06c1 \u06a9\u0648\u0688 \u06c1\u06d2\u06d4 \u0622\u0626\u06cc\u06d2 \u0627\u0633 \u06a9\u0648 \u062a\u0648\u0691\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u06c1\u0631 \u0642\u062f\u0645 \u06a9\u06cc\u0648\u06ba \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u06d2 \u06a9\u06cc\u0648\u06ba \u0627\u0644\u06af \u06a9\u06cc\u0627 \u062c\u0627\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2\u06d4<\/p>\n<h3 id=\"heading-step-1-look-up-user-and-purchase\">\u0645\u0631\u062d\u0644\u06c1 1: \u0635\u0627\u0631\u0641 \u06a9\u06cc \u0627\u0646\u06a9\u0648\u0627\u0626\u0631\u06cc \u0627\u0648\u0631 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc<\/h3>\n<pre><code class=\"language-typescript\">const { user, purchase } = await step.run(\n  \"lookup-user-and-purchase\",\n  async () => {\n    \/\/ Database queries for user and purchase records\n    return { user: foundUser, purchase: foundPurchase };\n  }\n);\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0645\u0631\u062d\u0644\u06c1 \u0635\u0627\u0631\u0641 \u0627\u0648\u0631 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0645\u0627\u0645 \u0628\u0639\u062f \u06a9\u06d2 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0627\u0646 \u0627\u0642\u062f\u0627\u0631 \u067e\u0631 \u0645\u0646\u062d\u0635\u0631 \u06c1\u06cc\u06ba: \u0635\u0627\u0631\u0641 \u06a9\u0627 \u0627\u06cc \u0645\u06cc\u0644\u060c \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u0631\u0642\u0645\u060c \u0627\u0648\u0631 \u0635\u0627\u0631\u0641 \u06a9\u0627 GitHub \u0635\u0627\u0631\u0641 \u0646\u0627\u0645\u06d4<\/p>\n<p>\u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0627\u0633 \u0637\u0631\u062d \u067e\u06cc\u06a9 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 <code>step.run()<\/code>\u0648\u0627\u067e\u0633\u06cc \u06a9\u06cc \u0642\u06cc\u0645\u062a Ingest \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u06a9\u06cc\u0634 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0628\u0639\u062f \u06a9\u0627 \u0645\u0631\u062d\u0644\u06c1 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0641\u0646\u06a9\u0634\u0646 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u0645\u0631\u062d\u0644\u06c1 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0646\u06c1\u06cc\u06ba \u0686\u0644\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u06a9\u06cc\u0634 \u0634\u062f\u06c1 \u0627\u0642\u062f\u0627\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u0626\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0635\u0627\u0631\u0641 \u0688\u06cc\u0679\u0627\u0628\u06cc\u0633 \u0645\u06cc\u06ba \u0645\u0648\u062c\u0648\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u0645\u0631\u062d\u0644\u06c1 \u0627\u06cc\u06a9 \u063a\u0644\u0637\u06cc \u067e\u06be\u06cc\u0646\u06a9 \u062f\u06d2 \u06af\u0627 \u062c\u0648 \u067e\u0648\u0631\u06d2 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u0631\u0648\u06a9 \u062f\u06d2 \u06af\u0627\u06d4 \u0627\u06af\u0631 \u0635\u0627\u0631\u0641 \u0646\u06c1 \u0645\u0644 \u0633\u06a9\u06d2 \u062a\u0648 \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be\u0646\u06d2 \u06a9\u0627 \u06a9\u0648\u0626\u06cc \u0641\u0627\u0626\u062f\u06c1 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-step-2-track-analytics\">\u0645\u0631\u062d\u0644\u06c1 2: \u0627\u067e\u0646\u06d2 \u062a\u062c\u0632\u06cc\u0627\u062a \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<pre><code class=\"language-typescript\">await step.run(\"track-purchase-to-posthog\", async () => {\n  try {\n    await trackServerEvent(userId, \"purchase_completed_server\", {\n      tier,\n      amount_cents: purchase.amount,\n      currency: purchase.currency,\n    });\n  } catch (error) {\n    console.error(`Failed to track to PostHog:`, error);\n  }\n});\n<\/code><\/pre>\n<p>\u0686\u0648\u0646\u06a9\u06c1 \u062a\u062c\u0632\u06cc\u0627\u062a\u06cc \u062e\u062f\u0645\u0627\u062a \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0637\u0631\u06cc\u0642\u06d2 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u062a\u062c\u0632\u06cc\u0627\u062a\u06cc \u0679\u0631\u06cc\u06a9\u0646\u06af \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u0645\u0631\u0627\u062d\u0644 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 PostHog \u0645\u06cc\u06ba \u0631\u0641\u062a\u0627\u0631 \u06a9\u06cc \u062d\u062f \u06cc\u0627 \u0639\u0627\u0631\u0636\u06cc \u0637\u0648\u0631 \u067e\u0631 \u063a\u06cc\u0631 \u062f\u0633\u062a\u06cc\u0627\u0628 \u06a9\u0646\u06a9\u0634\u0646 \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0627\u06cc\u0633\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u0646\u06c1\u06cc\u06ba \u0686\u0627\u06c1\u062a\u06d2 \u06a9\u06c1 \u0622\u067e \u06a9\u0627 \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u0644\u0627\u06a9 \u06c1\u0648 \u062c\u0627\u0626\u06d2\u06d4<\/p>\n<p>\u0679\u0631\u0627\u0626\u06cc \u06a9\u06cc\u0686 \u067e\u0631 \u062a\u0648\u062c\u06c1 \u062f\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 \u0679\u0631\u06cc\u0633 \u06a9\u06cc \u0646\u0627\u06a9\u0627\u0645\u06cc \u0627\u06cc\u06a9 \u063a\u0644\u0637\u06cc \u06a9\u0648 \u0644\u0627\u06af \u0627\u0646 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u0644\u06cc\u06a9\u0646 \u0641\u0639\u0627\u0644\u06cc\u062a \u06a9\u0648 \u0631\u0648\u06a9\u062a\u06cc \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u062a\u062c\u0632\u06cc\u0627\u062a\u06cc \u0688\u06cc\u0679\u0627 \u0642\u06cc\u0645\u062a\u06cc \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u06cc\u06c1 \u0622\u067e \u06a9\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06c1\u0645 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-steps-3-and-4-email-notifications\">\u0645\u0631\u062d\u0644\u06c1 3 \u0627\u0648\u0631 4: \u0627\u06cc \u0645\u06cc\u0644 \u0627\u0637\u0644\u0627\u0639\u0627\u062a<\/h3>\n<p>\u06af\u0627\u06c1\u06a9 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u0627\u0648\u0631 \u0645\u0646\u062a\u0638\u0645 \u06a9\u06cc \u0627\u0637\u0644\u0627\u0639 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u06a9\u0627\u0645 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633 \u0644\u06cc\u06d2 \u0627\u0644\u06af \u0627\u0644\u06af \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u06c1\u06cc\u06ba\u06d4 \u0627\u06cc\u0688\u0645\u0646 \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u062a\u06d2 \u0648\u0642\u062a\u060c \u0635\u0627\u0631\u0641 \u06a9\u0648 \u0627\u06cc\u06a9 \u062a\u0635\u062f\u06cc\u0642\u06cc \u067e\u06cc\u063a\u0627\u0645 \u0645\u0648\u0635\u0648\u0644 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2 \u0686\u0627\u06c1\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u0633\u06d2 500 \u0648\u0627\u067e\u0633 \u0622\u0626\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">\/\/ Step 3: Customer confirmation\nawait step.run(\"send-purchase-confirmation\", async () => {\n  await sendEmail({\n    to: user.email,\n    subject: `Your ${brand.name} purchase is confirmed!`,\n    template: createElement(PurchaseConfirmationEmail, {\n      amount: purchase.amount,\n      currency: purchase.currency,\n      customerEmail: user.email,\n    }),\n  });\n});\n\n\/\/ Step 4: Admin notification\nawait step.run(\"send-admin-notification\", async () => {\n  const adminEmail = process.env.ADMIN_EMAIL;\n  if (!adminEmail) return;\n\n  await sendEmail({\n    to: adminEmail,\n    subject: `New template sale: ${user.email}`,\n    template: createElement(AdminPurchaseNotificationEmail, {\n      \/\/ ... admin-specific fields\n    }),\n  });\n});\n<\/code><\/pre>\n<p>\u0627\u06cc\u0688\u0645\u0646\u0633\u0679\u0631\u06cc\u0679\u0631 \u0646\u0648\u0679\u06cc\u0641\u06a9\u06cc\u0634\u0646 \u0645\u0631\u062d\u0644\u06d2 \u0645\u06cc\u06ba \u06af\u0627\u0631\u0688\u0632 \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba\u06d4 <code>ADMIN_EMAIL<\/code> \u0627\u06af\u0631 \u0633\u06cc\u0679 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u062a\u0648\u060c \u062c\u0644\u062f \u0648\u0627\u067e\u0633 \u0622\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0626\u06d2 \u06af\u0627 \u06a9\u06c1 \u0622\u067e \u06a9\u0627 \u0641\u0646\u06a9\u0634\u0646 \u0622\u067e \u06a9\u06d2 \u062a\u0631\u0642\u06cc\u0627\u062a\u06cc \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u062a\u0645\u0627\u0645 \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-step-5-grant-product-access\">\u0645\u0631\u062d\u0644\u06c1 5: \u0645\u0635\u0646\u0648\u0639\u0627\u062a \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<pre><code class=\"language-typescript\">if (!user.githubUsername) {\n  return { success: true, userId, tier, githubAccessGranted: false };\n}\n\nconst collaboratorResult = await step.run(\n  \"add-github-collaborator\",\n  async () => {\n    return addCollaborator(user.githubUsername!);\n  }\n);\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0648\u06c1 \u0642\u062f\u0645 \u06c1\u06d2 \u062c\u0633 \u06a9\u06d2 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u0646\u06d2 \u06a9\u0627 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u0645\u06a9\u0627\u0646 \u06c1\u06d2\u06d4 GitHub \u06a9\u06d2 API \u0645\u06cc\u06ba \u0634\u0631\u062d \u06a9\u06cc \u062d\u062f\u06cc\u06ba \u06c1\u06cc\u06ba\u060c \u0648\u0642\u062a \u062e\u062a\u0645 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0622\u067e \u06a9\u0627 GitHub \u0635\u0627\u0631\u0641 \u0646\u0627\u0645 \u063a\u0644\u0637 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0622\u067e \u0627\u0633\u06d2 \u0627\u067e\u0646\u0627 \u0645\u0631\u062d\u0644\u06c1 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 GitHub API \u06a9\u06cc \u062e\u0631\u0627\u0628\u06cc\u0627\u06ba \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u06cc \u0645\u06cc\u0644 (\u0645\u0631\u062d\u0644\u06c1 3) \u06cc\u0627 \u0645\u0646\u062a\u0638\u0645 \u06a9\u06cc \u0627\u0637\u0644\u0627\u0639 (\u0645\u0631\u062d\u0644\u06c1 4) \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0645\u062a\u062d\u0631\u06a9 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u06cc\u06ba \u06af\u06cc\u06d4 \u0627\u0646\u06c1\u06cc\u06ba \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0645\u0631\u062d\u0644\u06c1 5 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u062c\u0644\u062f \u0648\u0627\u067e\u0633 \u0622\u0646\u0627 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u067e\u0627\u0633 \u06a9\u0648\u0626\u06cc \u0645\u0646\u0633\u0644\u06a9 GitHub \u0635\u0627\u0631\u0641 \u0646\u0627\u0645 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u062a\u0648 \u0641\u0646\u06a9\u0634\u0646 \u0645\u0631\u062d\u0644\u06c1 4 \u06a9\u06d2 \u0628\u0639\u062f \u0648\u0627\u067e\u0633 \u0622\u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 \u0628\u0627\u0642\u06cc \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0635\u0631\u0641 \u0627\u0633 \u0635\u0648\u0631\u062a \u0645\u06cc\u06ba \u0686\u0644\u06cc\u06ba \u06af\u06d2 \u062c\u0628 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u0631\u0633\u0627\u0626\u06cc \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 GitHub \u0627\u06a9\u0627\u0624\u0646\u0679 \u06c1\u0648\u06d4<\/p>\n<h3 id=\"heading-steps-6-7-track-and-update\">\u0645\u0631\u062d\u0644\u06c1 6-7: \u0679\u0631\u06cc\u06a9 \u0627\u0648\u0631 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>GitHub \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0641\u0646\u06a9\u0634\u0646 \u062a\u062c\u0632\u06cc\u0627\u062a (\u0645\u0631\u062d\u0644\u06c1 6) \u0645\u06cc\u06ba \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 (\u0645\u0631\u062d\u0644\u06c1 7) \u0645\u06cc\u06ba \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06d2 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0627\u067e \u0688\u06cc\u0679\u0633 \u06a9\u0648 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 GitHub API \u06a9\u0627\u0644\u0632 \u06a9\u06d2 \u0628\u0639\u062f \u0622\u0631\u0688\u0631 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u067e \u0646\u06d2 \u0627\u0628\u06be\u06cc \u0633\u06cc\u0679 \u06a9\u06cc\u0627 <code>githubAccessGranted: true<\/code> \u062f\u0639\u0648\u062a \u0627\u0635\u0644 \u0645\u06cc\u06ba \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u06d4 \u0627\u06af\u0631 \u0622\u067e \u067e\u06c1\u0644\u06d2 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 GitHub \u0645\u0631\u062d\u0644\u06c1 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u06c1\u06d2 \u06af\u0627 \u06a9\u06c1 \u0631\u0633\u0627\u0626\u06cc \u062f\u06cc \u06af\u0626\u06cc \u06c1\u06d2 \u0627\u06af\u0631\u0686\u06c1 \u06cc\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-step-8-send-access-email\">\u0645\u0631\u062d\u0644\u06c1 8: \u0631\u0633\u0627\u0626\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4<\/h3>\n<pre><code class=\"language-typescript\">await step.run(\"send-repo-access-email\", async () => {\n  const repoUrl = brand.social.github;\n  await sendEmail({\n    to: user.email,\n    subject: `Your ${brand.name} repository access is ready!`,\n    template: createElement(RepoAccessGrantedEmail, { repoUrl }),\n  });\n});\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0627\u06cc \u0645\u06cc\u0644 \u0622\u067e \u06a9\u06d2 GitHub \u062f\u0639\u0648\u062a \u0646\u0627\u0645\u06d2 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u06d2 \u0628\u0639\u062f \u06c1\u06cc \u0628\u06be\u06cc\u062c\u06cc \u062c\u0627\u0626\u06d2 \u06af\u06cc\u06d4 \u06c1\u062c\u06d2 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u062f\u0639\u0648\u062a \u0646\u0627\u0645\u06c1 \u0646\u06c1\u06cc\u06ba \u0628\u06be\u06cc\u062c\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u0645\u0637\u0644\u0639 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u06a9\u06c1 &quot;\u0631\u0633\u0627\u0626\u06cc \u062a\u06cc\u0627\u0631 \u06c1\u06d2\u06d4&#8221;<\/p>\n<h3 id=\"heading-step-9-schedule-follow-up-sequence\">\u0645\u0631\u062d\u0644\u06c1 9: \u0641\u0627\u0644\u0648 \u0627\u067e \u062a\u0631\u062a\u06cc\u0628 \u06a9\u0627 \u0634\u06cc\u0688\u0648\u0644 \u0628\u0646\u0627\u0626\u06cc\u06ba<\/h3>\n<pre><code class=\"language-typescript\">await step.run(\"schedule-follow-up\", async () => {\n  const purchaseRecord = await db\n    .select({ id: purchases.id })\n    .from(purchases)\n    .where(eq(purchases.stripeCheckoutSessionId, sessionId))\n    .limit(1);\n\n  if (purchaseRecord[0]) {\n    await inngest.send({\n      name: \"purchase\/follow-up.scheduled\",\n      data: {\n        userId,\n        purchaseId: purchaseRecord[0].id,\n        tier,\n      },\n    });\n  }\n});\n<\/code><\/pre>\n<p>\u0622\u062e\u0631\u06cc \u0645\u0631\u062d\u0644\u06c1 \u0627\u06cc\u06a9 \u0639\u0644\u06cc\u062d\u062f\u06c1 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u0645\u062a\u062d\u0631\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0641\u0627\u0644\u0648 \u0627\u067e \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628 \u06a9\u0648 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: \u062f\u0646 7 \u06a9\u0648 \u0622\u0646 \u0628\u0648\u0631\u0688\u0646\u06af \u0679\u067e\u0633\u060c \u062f\u0646 14 \u067e\u0631 \u0641\u06cc\u0688 \u0628\u06cc\u06a9 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u060c \u0627\u0648\u0631 30\u0648\u06cc\u06ba \u062f\u0646 \u062a\u0634\u062e\u06cc\u0635 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0627\u06cc\u0648\u0646\u0679 \u067e\u0631 \u0645\u0628\u0646\u06cc \u0633\u0644\u0633\u0644\u06c1 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0641\u0646\u06a9\u0634\u0646 \u0645\u06a9\u0645\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u0648\u0633\u0631\u0627 \u0641\u0646\u06a9\u0634\u0646 \u0645\u062a\u062d\u0631\u06a9 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062c\u0627\u0646\u0634\u06cc\u0646 \u0641\u0646\u06a9\u0634\u0646 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>step.sleep()<\/code> \u06a9\u0645\u067e\u06cc\u0648\u0679\u0646\u06af \u0648\u0633\u0627\u0626\u0644 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u0627\u06cc \u0645\u06cc\u0644\u0632 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u0646\u0627:<\/p>\n<pre><code class=\"language-typescript\">export const handlePurchaseFollowUp = inngest.createFunction(\n  {\n    id: \"purchase-follow-up\",\n    triggers: [{ event: \"purchase\/follow-up.scheduled\" }],\n    cancelOn: [\n      {\n        event: \"purchase\/follow-up.cancelled\",\n        match: \"data.purchaseId\",\n      },\n    ],\n  },\n  async ({ event, step }) => {\n    await step.sleep(\"wait-7-days\", \"7d\");\n    await step.run(\"send-day-7-email\", async () => {\n      \/\/ Send onboarding tips\n    });\n\n    await step.sleep(\"wait-14-days\", \"7d\");\n    await step.run(\"send-day-14-email\", async () => {\n      \/\/ Send feedback request\n    });\n  }\n);\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>cancelOn<\/code> \u0627\u062e\u062a\u06cc\u0627\u0631\u0627\u062a \u0642\u0627\u0628\u0644 \u062a\u0648\u062c\u06c1 \u06c1\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0648 \u0648\u0627\u067e\u0633 \u06a9\u0631 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u06d4 <code>purchase\/follow-up.cancelled<\/code> \u0627\u06cc\u06a9 \u0648\u0627\u0642\u0639\u06c1 \u0631\u0648\u0646\u0645\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f \u06a9\u0627 \u067e\u0648\u0631\u0627 \u0639\u0645\u0644 \u0631\u06a9 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u067e\u0631\u0627\u0646\u06d2 \u0627\u06cc \u0645\u06cc\u0644\u0632 \u0627\u0646 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u0646\u06c1\u06cc\u06ba \u0628\u06be\u06cc\u062c\u06d2 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2 \u062c\u0646\u06c1\u0648\u06ba \u0646\u06d2 \u0627\u067e\u0646\u06cc \u0631\u0642\u0645 \u0648\u0627\u067e\u0633 \u06a9\u0631 \u062f\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-the-rule-for-step-separation\">\u0645\u0631\u062d\u0644\u06c1 \u0639\u0644\u06cc\u062d\u062f\u06af\u06cc \u06a9\u06d2 \u0642\u0648\u0627\u0639\u062f<\/h3>\n<p>\u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0622\u067e\u0631\u06cc\u0634\u0646 \u062c\u0648 \u0627\u06cc\u06a9 \u0628\u06cc\u0631\u0648\u0646\u06cc \u0633\u0631\u0648\u0633 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06cc\u0627 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0633 \u06a9\u0627 \u0627\u067e\u0646\u0627 \u0645\u0631\u062d\u0644\u06c1 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u06d2 \u0633\u0648\u0627\u0644\u0627\u062a \u0627\u06cc\u06a9 \u0642\u062f\u0645 \u06c1\u06cc\u06ba \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0639\u0627\u0631\u0636\u06cc \u0637\u0648\u0631 \u067e\u0631 \u062f\u0633\u062a\u06cc\u0627\u0628 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u0646\u0627 \u06cc\u0627 API \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u0627 \u0627\u06cc\u06a9 \u0642\u062f\u0645 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0648\u06c1 \u062e\u062f\u0645\u0627\u062a \u063a\u0644\u0637\u06cc\u0627\u06ba \u0648\u0627\u067e\u0633 \u06a9\u0631 \u0633\u06a9\u062a\u06cc \u06c1\u06cc\u06ba \u06cc\u0627 \u0634\u0631\u062d \u06a9\u06cc \u062d\u062f \u062a\u06a9 \u067e\u06c1\u0646\u0686 \u0633\u06a9\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u062f\u0648 \u06a9\u0627\u0645 \u06c1\u0645\u06cc\u0634\u06c1 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u06cc\u0627 \u0646\u0627\u06a9\u0627\u0645 \u0631\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0648\u06c1 \u0642\u062f\u0645 \u0628\u0627\u0646\u0679 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0644\u06cc\u06a9\u0646 \u062c\u0628 \u0634\u06a9 \u06c1\u0648 \u062a\u0648 \u0627\u0633\u06d2 \u0627\u0644\u06af \u06a9\u0631 \u062f\u06cc\u06ba\u06d4 \u0627\u0648\u0648\u0631 \u06c1\u06cc\u0688 \u0646\u06c1 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0631\u0627\u0628\u0631 \u06c1\u06d2 \u0627\u0648\u0631 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0628\u06c1\u062a\u0631\u06cc \u0646\u0645\u0627\u06cc\u0627\u06ba \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-how-to-handle-refunds\">\u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u06cc\u0633\u06d2 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4<\/h2>\n<p>\u0631\u06cc\u0641\u0646\u0688 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0646\u0638\u0627\u0645 \u06a9\u0627 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0646\u0638\u0631 \u0627\u0646\u062f\u0627\u0632 \u06a9\u06cc\u0627 \u062c\u0627\u0646\u06d2 \u0648\u0627\u0644\u0627 \u062d\u0635\u06c1 \u06c1\u06d2\u06d4 \u0622\u067e \u06a9\u0648 \u062f\u0648 \u0645\u0639\u0627\u0645\u0644\u0627\u062a \u06a9\u0648 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2: \u0645\u06a9\u0645\u0644 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc (\u0631\u0633\u0627\u0626\u06cc \u0645\u0646\u0633\u0648\u062e \u06a9\u0631\u06cc\u06ba) \u0627\u0648\u0631 \u062c\u0632\u0648\u06cc \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc (\u0631\u0633\u0627\u0626\u06cc \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u06cc\u06ba\u060c \u062d\u0627\u0644\u062a \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u06cc\u06ba)\u06d4<\/p>\n<p>\u0645\u06a9\u0645\u0644 \u0631\u06cc\u0641\u0646\u0688 \u067e\u0631\u0648\u0633\u06cc\u0633\u0631 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/lib\/jobs\/functions\/stripe.ts\nexport const handleRefund = inngest.createFunction(\n  { id: \"refund-processed\", triggers: [{ event: \"stripe\/charge.refunded\" }] },\n  async ({ event, step }) => {\n    const data = event.data as {\n      chargeId: string;\n      paymentIntentId: string;\n      amountRefunded: number;\n      originalAmount: number;\n      currency: string;\n    };\n\n    const chargeId = data.chargeId;\n    const paymentIntentId = data.paymentIntentId;\n    const currency = data.currency;\n    const amountRefunded = data.amountRefunded;\n    const originalAmount = data.originalAmount;\n    const isFullRefund = amountRefunded >= originalAmount;\n\n    \/\/ Step 1: Look up the purchase and user\n    const { user, purchase } = await step.run(\n      \"lookup-purchase-by-payment-intent\",\n      async () => {\n        const purchaseResult = await db\n          .select({\n            id: purchases.id,\n            userId: purchases.userId,\n            stripePaymentIntentId: purchases.stripePaymentIntentId,\n            githubAccessGranted: purchases.githubAccessGranted,\n          })\n          .from(purchases)\n          .where(eq(purchases.stripePaymentIntentId, paymentIntentId))\n          .limit(1);\n\n        const foundPurchase = purchaseResult[0];\n        if (!foundPurchase) {\n          return { user: null, purchase: null };\n        }\n\n        const userResult = await db\n          .select({\n            id: users.id,\n            email: users.email,\n            name: users.name,\n            githubUsername: users.githubUsername,\n          })\n          .from(users)\n          .where(eq(users.id, foundPurchase.userId))\n          .limit(1);\n\n        return { user: userResult[0] ?? null, purchase: foundPurchase };\n      }\n    );\n\n    if (!purchase || !user) {\n      return { success: false, reason: \"no_matching_purchase\" };\n    }\n\n    let accessRevoked = false;\n\n    \/\/ Step 2: Revoke GitHub access (only for full refunds)\n    if (isFullRefund && user.githubUsername && purchase.githubAccessGranted) {\n      const revokeResult = await step.run(\n        \"revoke-github-access\",\n        async () => {\n          return removeCollaborator(user.githubUsername!);\n        }\n      );\n      accessRevoked = revokeResult.success;\n    }\n\n    \/\/ Step 3: Update purchase status\n    await step.run(\"update-purchase-status\", async () => {\n      if (isFullRefund) {\n        await db\n          .update(purchases)\n          .set({\n            status: \"refunded\",\n            githubAccessGranted: false,\n            updatedAt: new Date(),\n          })\n          .where(eq(purchases.id, purchase.id));\n      } else {\n        await db\n          .update(purchases)\n          .set({\n            status: \"partially_refunded\",\n            updatedAt: new Date(),\n          })\n          .where(eq(purchases.id, purchase.id));\n      }\n    });\n\n    \/\/ Step 4: Track refund in analytics\n    await step.run(\"track-refund-event\", async () => {\n      try {\n        await trackServerEvent(user.id, \"refund_processed\", {\n          charge_id: chargeId,\n          payment_intent_id: paymentIntentId,\n          amount_cents: amountRefunded,\n          original_amount_cents: originalAmount,\n          currency,\n          is_full_refund: isFullRefund,\n          github_access_revoked: accessRevoked,\n        });\n      } catch (error) {\n        console.error(`Failed to track to PostHog:`, error);\n      }\n    });\n\n    \/\/ Step 5: Notify customer\n    await step.run(\"send-customer-notification\", async () => {\n      if (isFullRefund) {\n        await sendEmail({\n          to: user.email,\n          subject: `Your ${brand.name} refund has been processed`,\n          template: createElement(AccessRevokedEmail, {\n            customerEmail: user.email,\n            refundAmount: amountRefunded,\n            currency,\n          }),\n        });\n      } else {\n        await sendEmail({\n          to: user.email,\n          subject: `Your ${brand.name} partial refund has been processed`,\n          template: createElement(PartialRefundEmail, {\n            customerEmail: user.email,\n            refundAmount: amountRefunded,\n            originalAmount,\n            currency,\n          }),\n        });\n      }\n    });\n\n    \/\/ Step 6: Notify admin\n    await step.run(\"send-admin-notification\", async () => {\n      const adminEmail = process.env.ADMIN_EMAIL;\n      if (!adminEmail) return;\n\n      await sendEmail({\n        to: adminEmail,\n        subject: `({isFullRefund ? \"Full\" : \"Partial\"} refund processed: ){user.email}`,\n        template: createElement(AdminRefundNotificationEmail, {\n          customerEmail: user.email,\n          customerName: user.name,\n          githubUsername: user.githubUsername,\n          refundAmount: amountRefunded,\n          originalAmount,\n          currency,\n          stripeChargeId: chargeId,\n          accessRevoked,\n          isPartialRefund: !isFullRefund,\n        }),\n      });\n    });\n\n    return { success: true, accessRevoked, isFullRefund, userId: user.id };\n  }\n);\n<\/code><\/pre>\n<h3 id=\"heading-how-full-refunds-differ-from-partial-refunds\">\u0645\u06a9\u0645\u0644 \u0627\u0648\u0631 \u062c\u0632\u0648\u06cc \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0631\u0642<\/h3>\n<p>\u06cc\u06c1 \u0641\u0646\u06a9\u0634\u0646 \u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u062f\u0648\u0646\u0648\u06ba \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0631\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">const isFullRefund = amountRefunded >= originalAmount;\n<\/code><\/pre>\n<p>\u06a9\u06d2 \u0644\u06cc\u06d2 <strong>\u0645\u06a9\u0645\u0644 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc\u06d4<\/strong>\u062a\u06cc\u0646 \u0686\u06cc\u0632\u06cc\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba:<\/p>\n<ol>\n<li>\n<p>GitHub \u0631\u0633\u0627\u0626\u06cc \u0645\u0646\u0633\u0648\u062e \u06a9\u0631 \u062f\u06cc \u06af\u0626\u06cc ( <code>removeCollaborator<\/code> \u06a9\u0627\u0644 \u06a9\u0631\u06cc\u06ba)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u0627\u0633 \u067e\u0631 \u0633\u06cc\u0679 \u06c1\u06d2: <code>\"refunded\"<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u06af\u0627\u06c1\u06a9 <code>AccessRevokedEmail<\/code> \u06cc\u06c1 \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0631\u0633\u0627\u0626\u06cc \u06a9\u06d2 \u062d\u0642\u0648\u0642 \u06a9\u0648 \u06c1\u0679\u0627 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ol>\n<p>\u06a9\u06d2 \u0644\u06cc\u06d2 <strong>\u062c\u0632\u0648\u06cc \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc\u06d4<\/strong>\u06af\u0627\u06c1\u06a9 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2:<\/p>\n<ol>\n<li>\n<p>GitHub \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u06c1\u06d2\u06d4 <strong>~ \u0646\u06c1\u06cc\u06ba<\/strong> \u0645\u0646\u0633\u0648\u062e<\/p>\n<\/li>\n<li>\n<p>\u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u0627\u0633 \u067e\u0631 \u0633\u06cc\u0679 \u06c1\u06d2: <code>\"partially_refunded\"<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u06af\u0627\u06c1\u06a9 <code>PartialRefundEmail<\/code> \u0622\u067e \u06a9\u0648 \u0648\u0627\u067e\u0633 \u06a9\u06cc \u06af\u0626\u06cc \u0631\u0642\u0645 \u0627\u0648\u0631 \u0627\u0635\u0644 \u0631\u0642\u0645 \u0646\u0638\u0631 \u0622\u0626\u06d2 \u06af\u06cc\u06d4<\/p>\n<\/li>\n<\/ol>\n<p>\u06cc\u06c1 \u0641\u0631\u0642 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u06cc \u0633\u0627\u0644\u0645\u06cc\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06c1\u0645 \u06c1\u06d2\u06d4 \u0688\u0627\u0624\u0646 \u0627\u0633\u0679\u0631\u06cc\u0645 \u0633\u0633\u0679\u0645\u0632 (\u0688\u06cc\u0634 \u0628\u0648\u0631\u0688\u0632\u060c \u0627\u06cc\u0646\u0627\u0644\u06cc\u0679\u06a9\u0633\u060c \u0633\u067e\u0648\u0631\u0679 \u0679\u0648\u0644\u0632) \u06a9\u0648 \u062f\u0631\u0633\u062a \u0627\u0633\u0679\u06cc\u0679\u0633 \u0648\u06cc\u0644\u06cc\u0648\u0632 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <code>partially_refunded<\/code> \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc\u0627\u06ba \u0627\u0628 \u0628\u06be\u06cc \u0641\u0639\u0627\u0644 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u06cc \u0646\u0645\u0627\u0626\u0646\u062f\u06af\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-how-conditional-steps-work\">\u0645\u0634\u0631\u0648\u0637 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u06a9\u06cc\u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/h3>\n<p>&quot;GitHub \u0631\u0633\u0627\u0626\u06cc \u06a9\u0648 \u0645\u0646\u0633\u0648\u062e \u06a9\u0631\u06cc\u06ba&#8221; \u0645\u0631\u062d\u0644\u06c1 \u0635\u0631\u0641 \u0627\u0633 \u0635\u0648\u0631\u062a \u0645\u06cc\u06ba \u0686\u0644\u06d2 \u06af\u0627 \u062c\u0628 \u062a\u06cc\u0646\u0648\u06ba \u0634\u0631\u0627\u0626\u0637 \u067e\u0648\u0631\u06cc \u06c1\u0648\u062c\u0627\u0626\u06cc\u06ba\u06d4 \u06cc\u0639\u0646\u06cc\u060c \u0627\u06af\u0631 \u06cc\u06c1 \u0645\u06a9\u0645\u0644 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 GitHub \u0635\u0627\u0631\u0641 \u0646\u0627\u0645 \u06c1\u06d2 \u0627\u0648\u0631 \u0631\u0633\u0627\u0626\u06cc \u067e\u06c1\u0644\u06d2 \u062f\u06cc \u06af\u0626\u06cc \u062a\u06be\u06cc\u06d4<\/p>\n<pre><code class=\"language-typescript\">if (isFullRefund && user.githubUsername && purchase.githubAccessGranted) {\n  const revokeResult = await step.run(\"revoke-github-access\", async () => {\n    return removeCollaborator(user.githubUsername!);\n  });\n  accessRevoked = revokeResult.success;\n}\n<\/code><\/pre>\n<p>\u0627\u06af\u0631 \u0627\u0646 \u0634\u0631\u0627\u0626\u0637 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u063a\u0644\u0637 \u06c1\u06d2\u060c \u062a\u0648 \u0648\u06c1 \u0645\u0631\u062d\u0644\u06c1 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0686\u06be\u0648\u0691 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 Ingest \u0635\u0641\u0627\u0626\u06cc \u0633\u06d2 \u06cc\u06c1 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2. \u06cc\u06c1 \u062e\u0635\u0648\u0635\u06cc\u062a \u0645\u0631\u062d\u0644\u06c1 3 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062c\u0627\u0631\u06cc \u0631\u06c1\u062a\u06cc \u06c1\u06d2 (\u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u06cc\u06ba)\u06d4 <code>accessRevoked<\/code> \u0627\u0628 \u0628\u06be\u06cc \u0633\u06cc\u0679 \u0627\u067e <code>false<\/code>.<\/p>\n<h2 id=\"heading-how-to-recover-abandoned-checkouts\">\u062a\u0631\u06a9 \u0634\u062f\u06c1 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc\u0648\u06ba \u06a9\u06cc \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u06af\u0627\u06c1\u06a9 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u0634\u0631\u0648\u0639 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0644\u06cc\u06a9\u0646 \u0627\u0633\u06d2 \u0645\u06a9\u0645\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0628\u0627\u0644\u0622\u062e\u0631 Stripe \u0633\u06cc\u0634\u0646 \u06a9\u06cc \u0645\u06cc\u0639\u0627\u062f \u062e\u062a\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u06cc (\u0628\u0637\u0648\u0631 \u0688\u06cc\u0641\u0627\u0644\u0679\u060c 24 \u06af\u06be\u0646\u0679\u06d2 \u06a9\u06d2 \u0628\u0639\u062f)\u06d4 \u0622\u067e \u0627\u0633 \u0627\u06cc\u0648\u0646\u0679 \u06a9\u0648 \u0633\u0646 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0628\u0627\u0632\u06cc\u0627\u0628\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0627\u06c1\u0645 \u0628\u0635\u06cc\u0631\u062a \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u0627\u0628\u06be\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u0628\u06be\u06cc\u062c\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2\u06d4 \u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u06af\u0627\u06c1\u06a9 \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0648\u0627\u067e\u0633 \u0622\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u06af\u06be\u0646\u0679\u06c1 \u06a9\u0627 \u0648\u0642\u062a \u062f\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/lib\/jobs\/functions\/stripe.ts\nexport const handleCheckoutExpired = inngest.createFunction(\n  {\n    id: \"checkout-expired\",\n    triggers: [{ event: \"stripe\/checkout.session.expired\" }],\n  },\n  async ({ event, step }) => {\n    const { customerEmail, sessionId } = event.data as {\n      customerEmail: string | null;\n      sessionId: string;\n    };\n\n    if (!customerEmail) {\n      return { success: false, reason: \"no_email\" };\n    }\n\n    \/\/ Wait 1 hour before sending recovery email\n    await step.sleep(\"wait-before-recovery-email\", \"1h\");\n\n    \/\/ Send abandoned cart email\n    await step.run(\"send-abandoned-cart-email\", async () => {\n      const baseUrl =\n        process.env.BETTER_AUTH_URL ?? \"https:\/\/your-app.com\";\n      const checkoutUrl = `${baseUrl}\/pricing`;\n\n      await sendEmail({\n        to: customerEmail,\n        subject: `Your ${brand.name} checkout is waiting`,\n        template: createElement(AbandonedCartEmail, {\n          customerEmail,\n          checkoutUrl,\n        }),\n      });\n    });\n\n    \/\/ Track the recovery attempt\n    await step.run(\"track-abandoned-cart\", async () => {\n      try {\n        await trackServerEvent(\"anonymous\", \"abandoned_cart_email_sent\", {\n          customer_email: customerEmail,\n          session_id: sessionId,\n        });\n      } catch (error) {\n        console.error(`Failed to track to PostHog:`, error);\n      }\n    });\n\n    return { success: true, customerEmail };\n  }\n);\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>step.sleep(\"wait-before-recovery-email\", \"1h\")<\/code> \u062c\u0648\u0644 \u06a9\u0633\u06cc \u06a9\u0645\u067e\u06cc\u0648\u0679\u0646\u06af \u0648\u0633\u0627\u0626\u0644 \u06a9\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u0627\u06cc\u06a9 \u06af\u06be\u0646\u0679\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0641\u0639\u0627\u0644\u06cc\u062a \u06a9\u0648 \u0645\u0639\u0637\u0644 \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0627\u062e\u06cc\u0631 \u06a9\u06d2 \u0628\u0639\u062f \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0627 \u0634\u06cc\u0688\u0648\u0644 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u06cc \u06a9\u0631\u0648\u0646 \u0646\u0648\u06a9\u0631\u06cc\u0627\u06ba \u0646\u06c1\u06cc\u06ba\u060c \u06a9\u0648\u0626\u06cc \u0631\u06cc\u0688\u06cc\u0633 \u0642\u0637\u0627\u0631 \u0646\u06c1\u06cc\u06ba\u060c \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba\u06d4 <code>setTimeout<\/code> \u062c\u0628 \u0633\u0631\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u0648\u06c1 \u06a9\u06be\u0648 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u062a\u0642\u0631\u06cc\u0628 \u06a9\u06d2 \u0627\u0648\u067e\u0631\u06cc \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u06af\u0627\u0631\u0688 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0686\u06cc\u06a9 \u0622\u0624\u0679 \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u06af\u0627\u06c1\u06a9 \u06a9\u0627 \u06a9\u0648\u0626\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 (\u06af\u0627\u06c1\u06a9 \u0646\u06d2 \u0627\u067e\u0646\u0627 \u0627\u06cc \u0645\u06cc\u0644 \u062f\u0627\u062e\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0635\u0641\u062d\u06c1 \u0628\u0646\u062f \u06a9\u0631 \u062f\u06cc\u0627 \u06c1\u06d2)\u060c \u0641\u0646\u06a9\u0634\u0646 \u062c\u0644\u062f \u0648\u0627\u067e\u0633 \u0622\u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u067e\u062a\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u062a\u0648 \u06c1\u0645 \u0622\u067e \u06a9\u0648 \u0628\u0627\u0632\u06cc\u0627\u0628\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u0628\u06be\u06cc\u062c \u0633\u06a9\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<p>\u0622\u067e \u062a\u06cc\u0646 \u062f\u0646 \u0628\u0639\u062f \u062f\u0648\u0633\u0631\u06cc \u0646\u06cc\u0646\u062f \u0627\u0648\u0631 \u0641\u0627\u0644\u0648 \u0627\u067e \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0633 \u0637\u0631\u0632 \u067e\u0631 \u062a\u0648\u0633\u06cc\u0639 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0622\u067e \u06cc\u06c1 \u0628\u06be\u06cc \u0686\u06cc\u06a9 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u06a9\u0633\u06cc \u0635\u0627\u0631\u0641 \u0646\u06d2 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u0645\u06a9\u0645\u0644 \u06a9\u0631 \u0644\u06cc \u06c1\u06d2 (\u0627\u067e\u0646\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u0631 \u06a9\u06d2)\u06d4 <code>step.run()<\/code>) \u0627\u06af\u0631 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u0627\u06cc \u0645\u06cc\u0644 \u06c1\u06d2 \u062a\u0648 \u0627\u0633\u06d2 \u0686\u06be\u0648\u0691 \u062f\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-why-one-hour-is-the-right-delay\">1 \u06af\u06be\u0646\u0679\u06d2 \u06a9\u06cc \u062a\u0627\u062e\u06cc\u0631 \u06a9\u06cc\u0648\u06ba \u062f\u0631\u0633\u062a \u06c1\u06d2\u06d4<\/h3>\n<p>\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06cc \u0645\u06cc\u0639\u0627\u062f \u062e\u062a\u0645 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0641\u0648\u0631\u0627\u064b \u0628\u0639\u062f \u0631\u06cc\u06a9\u0648\u0631\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u0646\u0627 \u062c\u0627\u0631\u062d\u0627\u0646\u06c1 \u0645\u062d\u0633\u0648\u0633 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0635\u0627\u0631\u0641\u06cc\u0646 \u0627\u0628 \u0628\u06be\u06cc \u0627\u062e\u062a\u06cc\u0627\u0631\u0627\u062a \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u0648\u06ba\u060c \u062a\u0646\u062e\u0648\u0627\u06c1 \u06a9\u06d2 \u062f\u0646 \u06a9\u0627 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u0648\u06ba\u060c \u06cc\u0627 \u0645\u062d\u0636 \u0645\u0634\u063a\u0648\u0644 \u06c1\u0648\u06ba\u06d4 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06c1\u062a\u06cc \u06c1\u06d2\u060c &quot;\u06c1\u0645\u06cc\u06ba \u067e\u062a\u06c1 \u0686\u0644\u0627 \u06a9\u06c1 \u0622\u067e \u0686\u0644\u06d2 \u06af\u0626\u06d2\u060c&#8221; \u062c\u0648 \u0646\u06af\u0631\u0627\u0646\u06cc \u06a9\u06cc \u0637\u0631\u062d \u0645\u062d\u0633\u0648\u0633 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>24 \u06af\u06be\u0646\u0679\u06d2 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u0646\u0627 \u0628\u06c1\u062a \u0637\u0648\u06cc\u0644 \u06c1\u06d2\u06d4 \u06af\u0627\u06c1\u06a9 \u0622\u06af\u06d2 \u0628\u0691\u06be \u06af\u06cc\u0627\u06d4 \u0648\u06c1 \u06cc\u0627 \u062a\u0648 \u0622\u067e \u06a9\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0679 \u06a9\u0648 \u0628\u06be\u0648\u0644 \u06af\u0626\u06d2 \u06c1\u06cc\u06ba \u06cc\u0627 \u06a9\u0648\u0626\u06cc \u0645\u062a\u0628\u0627\u062f\u0644 \u062a\u0644\u0627\u0634 \u06a9\u0631 \u0686\u06a9\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u062c\u0627\u0646\u0686 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u06c1\u0645\u06cc\u06ba \u062c\u0648 \u0628\u06c1\u062a\u0631\u06cc\u0646 \u0648\u0642\u062a \u0645\u0644\u0627 \u06c1\u06d2 \u0648\u06c1 1 \u06af\u06be\u0646\u0679\u06c1 \u06c1\u06d2\u06d4 \u06af\u0627\u06c1\u06a9 \u06a9\u0627 \u0627\u0631\u0627\u062f\u06c1 \u0627\u0628\u06be\u06cc \u0628\u06be\u06cc \u062a\u0627\u0632\u06c1 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u06cc \u0645\u06cc\u0644 \u062f\u0628\u0627\u0624 \u0688\u0627\u0644\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0645\u062f\u062f\u06af\u0627\u0631 \u0645\u062d\u0633\u0648\u0633 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0622\u067e \u06a9\u0627 \u0645\u0627\u0626\u0644\u06cc\u062c \u0645\u062e\u062a\u0644\u0641 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0627\u062e\u06cc\u0631 \u0642\u0627\u0628\u0644 \u062a\u0631\u062a\u06cc\u0628 \u06c1\u06cc\u06ba\u06d4 \u062a\u0628\u062f\u06cc\u0644\u06cc <code>\"1h\"<\/code> \u06a9\u0648 <code>\"30m\"<\/code> \u06cc\u0627 <code>\"3h\"<\/code> \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u0642\u0633\u06cc\u0645.<\/p>\n<h3 id=\"heading-why-this-is-better-than-a-cron-job\">\u06cc\u06c1 \u06a9\u0631\u0648\u0646 \u062c\u0627\u0628 \u0633\u06d2 \u0628\u06c1\u062a\u0631 \u06a9\u06cc\u0648\u06ba \u06c1\u06d2\u06d4<\/h3>\n<p>\u0627\u06cc\u06a9 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0639\u0645\u0644 \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c \u062a\u0631\u06a9 \u0634\u062f\u06c1 \u06a9\u0627\u0631\u0679 \u06a9\u06cc \u0628\u0627\u0632\u06cc\u0627\u0628\u06cc \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633 \u0637\u0631\u062d \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2: \u0627\u06cc\u06a9 \u06a9\u0631\u0648\u0646 \u062c\u0627\u0628 \u06c1\u0631 \u06af\u06be\u0646\u0679\u06d2 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u060c \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0645\u06cc\u0639\u0627\u062f \u062e\u062a\u0645 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0633\u06cc\u0634\u0646\u0632 \u062c\u0648 \u0627\u0628\u06be\u06cc \u062a\u06a9 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0626\u06d2 \u06c1\u06cc\u06ba\u060c \u06c1\u0631 \u0633\u06cc\u0634\u0646 \u06a9\u0648 \u0627\u06cc\u06a9 \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u06d2 \u0628\u0637\u0648\u0631 \u0646\u0634\u0627\u0646 \u0632\u062f \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u0646\u0642\u0637\u06c1 \u0646\u0638\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0626\u06cc \u0645\u0633\u0627\u0626\u0644 \u06c1\u06cc\u06ba. \u062a\u0645 \u06c1\u0648 <code>recovered_at<\/code> \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0627\u06cc \u0645\u06cc\u0644\u0632 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u0633\u06d2 \u0628\u0686\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0644\u0645 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0622\u067e \u06a9\u0648 \u0627\u06cc\u0633\u06d2 \u0645\u0639\u0627\u0645\u0644\u0627\u062a \u0633\u06d2 \u0646\u0645\u0679\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u06a9\u0631\u0648\u0646 \u062c\u0627\u0628\u0632 \u0645\u0688 \u0628\u06cc\u0686 \u06a9\u0631\u06cc\u0634 \u06c1\u0648 \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0622\u067e \u06a9\u0648 \u06a9\u0631\u0648\u0646 \u0648\u0642\u0641\u0648\u06ba \u06a9\u0648 \u0627\u062d\u062a\u06cc\u0627\u0637 \u0633\u06d2 \u0679\u06cc\u0648\u0646 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06c1 <code>step.sleep()<\/code> \u0646\u0642\u0637\u06c1 \u0646\u0638\u0631 \u0627\u0646 \u0633\u0628 \u06a9\u0648 \u062e\u062a\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u0645\u06cc\u0639\u0627\u062f \u062e\u062a\u0645 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0633\u06cc\u0634\u0646 \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0679\u0627\u0626\u0645\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u067e\u0646\u06cc \u0641\u0646\u06a9\u0634\u0646 \u0645\u062b\u0627\u0644 \u0645\u0644\u062a\u06cc \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u06cc \u0628\u06cc\u0686 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u0646\u06c1\u06cc\u06ba\u060c \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u06d2 \u062c\u06be\u0646\u0688\u06d2 \u0646\u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0646\u0642\u0644 \u06a9\u0627 \u06a9\u0648\u0626\u06cc \u062e\u0637\u0631\u06c1 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-how-to-send-transactional-emails-with-react-email\">\u0631\u06cc \u0627\u06cc\u06a9\u0679 \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0644\u06cc\u0646 \u062f\u06cc\u0646 \u06a9\u06cc \u0627\u06cc \u0645\u06cc\u0644\u0632 \u06a9\u06cc\u0633\u06d2 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4<\/h2>\n<p>\u0686\u06cc\u06a9 \u0622\u0624\u0679 \u0641\u0644\u0648 \u0645\u06cc\u06ba \u062a\u0645\u0627\u0645 \u0627\u06cc \u0645\u06cc\u0644\u0632 React \u0627\u062c\u0632\u0627\u0621 \u06c1\u06cc\u06ba \u062c\u0648 HTML \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u06cc\u0634 \u06a9\u06cc\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0631\u06cc \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0628\u06be\u06cc\u062c\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u067e\u0631\u0648\u067e\u0633\u060c \u0627\u062c\u0632\u0627\u0621 \u06a9\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644\u060c \u0627\u0648\u0631 \u062a\u0631\u0642\u06cc \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0628\u0631\u0627\u0624\u0632\u0631 \u0645\u06cc\u06ba \u0627\u06cc \u0645\u06cc\u0644\u0632 \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06cc\u0646\u06d2 \u06a9\u06cc \u0635\u0644\u0627\u062d\u06cc\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0679\u0627\u0626\u067e \u0633\u06cc\u0641 \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679\u0633 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-how-to-set-up-the-email-client\">\u0627\u067e\u0646\u06d2 \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u0644\u0627\u0626\u0646\u0679 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u06ba\u06d4<\/h3>\n<p>\u0627\u06cc \u0645\u06cc\u0644 \u06a9\u0644\u0627\u0626\u0646\u0679\u0633 \u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 \u0633\u0679\u0631\u0646\u06af \u0645\u06cc\u06ba \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u06be\u06cc\u062c\u06cc\u06ba \u0644\u067e\u06cc\u0679\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>sendEmail<\/code> \u0641\u0646\u06a9\u0634\u0646:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/lib\/email\/index.ts\nimport { render } from \"@react-email\/components\";\nimport type { ReactElement } from \"react\";\nimport { Resend } from \"resend\";\n\nimport { brand } from \"@\/lib\/brand\";\n\nlet resendClient: Resend | null = null;\n\nfunction getResend(): Resend {\n  if (!resendClient) {\n    const apiKey = process.env.RESEND_API_KEY;\n    if (!apiKey) {\n      throw new Error(\"RESEND_API_KEY is not set\");\n    }\n    resendClient = new Resend(apiKey);\n  }\n  return resendClient;\n}\n\ninterface SendEmailOptions {\n  to: string | string[];\n  subject: string;\n  template: ReactElement;\n  from?: string;\n  replyTo?: string;\n}\n\nexport async function sendEmail({\n  to,\n  subject,\n  template,\n  from = process.env.EMAIL_FROM ?? brand.emails.from,\n  replyTo,\n}: SendEmailOptions) {\n  const resend = getResend();\n  const html = await render(template);\n\n  return resend.emails.send({\n    from,\n    to,\n    subject,\n    html,\n    replyTo,\n  });\n}\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>render()<\/code> \u0641\u0646\u06a9\u0634\u0646 <code>@react-email\/components<\/code> React \u0639\u0646\u0627\u0635\u0631 \u06a9\u0648 HTML \u0633\u0679\u0631\u0646\u06af\u0632 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u06cc\u06c1 HTML \u0648\u06c1\u06cc \u06c1\u06d2 \u062c\u0648 \u0622\u067e \u06a9\u06d2 \u06af\u0627\u06c1\u06a9 \u06a9\u06d2 \u0627\u0646 \u0628\u0627\u06a9\u0633 \u0645\u06cc\u06ba \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u06be\u06cc\u062c\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06c1 <code>from<\/code> \u067e\u062a\u06c1 \u0622\u067e \u06a9\u06d2 \u0628\u0631\u0627\u0646\u0688 \u06a9\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0641\u0627\u0644\u0679 \u06c1\u0648\u06af\u0627\u06d4 \u0627\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0631\u06cc \u0688\u0627\u0626\u0631\u06cc\u06a9\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0635\u062f\u06cc\u0642 \u0634\u062f\u06c1 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u0688\u06cc\u0648\u0644\u067e\u0645\u0646\u0679 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646\u060c \u0631\u06cc \u0633\u06cc\u0646\u0688 \u06a9\u0627 \u0641\u0631\u06cc \u0679\u0627\u0626\u0631 \u0622\u067e \u06a9\u0648 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0627\u067e\u0646\u06d2 \u0627\u06cc \u0645\u06cc\u0644 \u0627\u06cc\u0688\u0631\u06cc\u0633 \u067e\u0631 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-how-to-build-a-purchase-confirmation-template\">\u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642\u06cc \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0645\u06a9\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u06cc\u06c1\u0627\u06ba \u0627\u0635\u0644 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-tsx\">\/\/ src\/lib\/email\/emails\/purchase-confirmation.tsx\nimport {\n  Body,\n  Container,\n  Head,\n  Heading,\n  Hr,\n  Html,\n  Link,\n  Preview,\n  Section,\n  Text,\n} from \"@react-email\/components\";\n\nimport { brand } from \"@\/lib\/brand\";\n\ninterface PurchaseConfirmationEmailProps {\n  amount: number;\n  currency: string;\n  customerEmail: string;\n}\n\nconst colors = {\n  primary: \"#d97757\",\n  background: \"#faf9f5\",\n  foreground: \"#30302e\",\n  muted: \"#6b6860\",\n  border: \"#e5e4df\",\n  card: \"#ffffff\",\n  success: \"#16a34a\",\n  successLight: \"#f0fdf4\",\n};\n\nexport default function PurchaseConfirmationEmail({\n  amount,\n  currency,\n  customerEmail,\n}: PurchaseConfirmationEmailProps) {\n  const formattedAmount = new Intl.NumberFormat(\"en-US\", {\n    style: \"currency\",\n    currency: currency.toUpperCase(),\n  }).format(amount \/ 100);\n\n  return (\n    \n      <\/code>\n      <preview>Your {brand.name} purchase is confirmed!<\/preview>\n      \n        <container style=\"{container}\">\n          <section style=\"{header}\">\n            <text style=\"{logoText}\">{brand.name}<\/text>\n          <\/section>\n\n          <hr style=\"{divider}\"\/>\n\n          <section style=\"{successBadge}\">\n            <text style=\"{successText}\">Payment Successful<\/text>\n          <\/section>\n\n          <heading style=\"{h1}\">Thank you for your purchase!<\/heading>\n\n          <text style=\"{text}\">\n            Your payment has been processed successfully. We are now setting\n            up your GitHub repository access. You will receive another email\n            shortly with your access link.\n          <\/text>\n\n          <section style=\"{detailsBox}\">\n            <text style=\"{detailsTitle}\">Order Details<\/text>\n\n            <section style=\"{detailRow}\">\n              <text style=\"{detailLabel}\">Product<\/text>\n              <text style=\"{detailValue}\">{brand.name}<\/text>\n            <\/section>\n\n            <section style=\"{detailRow}\">\n              <text style=\"{detailLabel}\">Amount<\/text>\n              <text style=\"{detailValue}\">{formattedAmount}<\/text>\n            <\/section>\n\n            <section style=\"{detailRow}\">\n              <text style=\"{detailLabel}\">Email<\/text>\n              <text style=\"{detailValue}\">{customerEmail}<\/text>\n            <\/section>\n          <\/section>\n\n          <text style=\"{text}\">\n            This is a one-time purchase. No recurring charges will be made.\n          <\/text>\n\n          <hr style=\"{divider}\"\/>\n\n          <text style=\"{footer}\">\n            Questions about your purchase? Reply to this email or reach\n            out at{\" \"}\n            <link href=\"{`mailto:${brand.emails.support}`}\" style=\"{link}\"\/>\n              {brand.emails.support}\n            \n          <\/text>\n        <\/container>\n      \n    \n  );\n}\n\nPurchaseConfirmationEmail.PreviewProps = {\n  amount: 9900,\n  currency: \"usd\",\n  customerEmail: \"customer@example.com\",\n} satisfies PurchaseConfirmationEmailProps;\n<\/pre>\n<p>\u0627\u0633 \u0633\u0627\u0646\u0686\u06d2 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0686\u0646\u062f \u0628\u0627\u062a\u06cc\u06ba \u0642\u0627\u0628\u0644 \u062a\u0648\u062c\u06c1 \u06c1\u06cc\u06ba:<\/p>\n<ul>\n<li>\n<p><strong>\u06a9\u0631\u0646\u0633\u06cc \u06a9\u06cc \u0641\u0627\u0631\u0645\u06cc\u0679\u0646\u06af \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679 \u0645\u06cc\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/strong> \u06a9\u06c1 <code>amount<\/code> \u067e\u0631\u067e\u0633 \u0633\u06cc\u0646\u0679 \u0645\u06cc\u06ba \u06c1\u06cc\u06ba (\u0648\u06c1\u06cc \u0641\u0627\u0631\u0645\u06cc\u0679 \u062c\u0648 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u0645\u062d\u0641\u0648\u0638 \u06c1\u06d2 \u0627\u0648\u0631 \u067e\u0679\u06cc \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0648\u0627\u067e\u0633 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2)\u06d4 \u06a9\u06c1 <code>Intl.NumberFormat<\/code> \u06a9\u0627\u0644 \u0627\u0633\u06d2 &quot;$99.00&#8221; \u062c\u06cc\u0633\u06cc \u0627\u0646\u0633\u0627\u0646\u06cc \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u0633\u0679\u0631\u0646\u06af \u0645\u06cc\u06ba \u0628\u062f\u0644 \u062f\u06cc\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u06a9\u0631\u0646\u0633\u06cc \u06a9\u06cc \u0641\u0627\u0631\u0645\u06cc\u0679\u0646\u06af \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0627\u06cc\u06a9 \u062c\u06af\u06c1 \u067e\u0631 \u0631\u06a9\u06be\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u06a9\u06c1<\/strong> <code>PreviewProps<\/code> <strong>\u0645\u0642\u0635\u062f \u062a\u0631\u0642\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u06c1\u06d2\u06d4<\/strong> \u0631\u06cc \u0627\u06cc\u06a9\u0679 \u0627\u06cc \u0645\u06cc\u0644 \u0628\u0631\u0627\u0624\u0632\u0631 \u0645\u06cc\u06ba \u067e\u06cc\u0634 \u0646\u0638\u0627\u0631\u06c1 \u067e\u06cc\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0646 \u067e\u0631\u0648\u067e\u0633 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u06c1 <code>satisfies<\/code> \u06a9\u0644\u06cc\u062f\u06cc \u0644\u0641\u0638 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u067e\u06cc\u0634 \u0646\u0638\u0627\u0631\u06c1 \u067e\u0631\u0648\u067e \u0627\u062c\u0632\u0627\u0621 \u06a9\u06d2 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 \u0633\u06d2 \u0645\u06cc\u0644 \u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u062a\u0645\u0627\u0645 \u0637\u0631\u0632\u06cc\u06ba \u0627\u0646 \u0644\u0627\u0626\u0646 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06c1\u06cc\u06ba\u06d4<\/strong> \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u0644\u0627\u0626\u0646\u0679 \u06a9\u06cc \u067e\u0679\u06cc <code\/> \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0633\u06cc \u0627\u06cc\u0633 \u0627\u06cc\u0633 \u06a9\u0648 \u0679\u06cc\u06af \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0646\u0638\u0631 \u0627\u0646\u062f\u0627\u0632 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 Gmail\u060c Outlook\u060c Apple Mail\u060c \u0627\u0648\u0631 \u062f\u06cc\u06af\u0631 \u062a\u0645\u0627\u0645 \u06a9\u0644\u0627\u0626\u0646\u0679\u0633 \u0645\u06cc\u06ba \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u0648 \u0633\u0679\u0627\u0626\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0627\u0646 \u0644\u0627\u0626\u0646 \u0637\u0631\u0632\u06cc\u06ba \u0648\u0627\u062d\u062f \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0637\u0631\u06cc\u0642\u06c1 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-how-to-build-a-repo-access-template\">\u0631\u06cc\u067e\u0648 \u0627\u06cc\u06a9\u0633\u06cc\u0633 \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/h3>\n<p>\u0622\u067e \u06a9\u06d2 GitHub \u062f\u0639\u0648\u062a \u0646\u0627\u0645\u06d2 \u06a9\u06d2 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0622\u067e \u06a9\u0648 \u0631\u06cc\u067e\u0648\u0632\u0679\u0631\u06cc \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u06a9\u0627 \u0627\u06cc \u0645\u06cc\u0644 \u0645\u0648\u0635\u0648\u0644 \u06c1\u0648\u06af\u0627\u06d4<\/p>\n<pre><code class=\"language-tsx\">\/\/ src\/lib\/email\/emails\/repo-access-granted.tsx\nimport {\n  Body,\n  Button,\n  Container,\n  Head,\n  Heading,\n  Hr,\n  Html,\n  Link,\n  Preview,\n  Section,\n  Text,\n} from \"@react-email\/components\";\n\nimport { brand } from \"@\/lib\/brand\";\n\ninterface RepoAccessGrantedEmailProps {\n  repoUrl: string;\n}\n\nexport default function RepoAccessGrantedEmail({\n  repoUrl,\n}: RepoAccessGrantedEmailProps) {\n  return (\n    \n      <\/code>\n      <preview>Your {brand.name} repository access is ready!<\/preview>\n      \n        <container style=\"{container}\">\n          <section style=\"{header}\">\n            <text style=\"{logoText}\">{brand.name}<\/text>\n          <\/section>\n\n          <hr style=\"{divider}\"\/>\n\n          <heading style=\"{h1}\">You are in!<\/heading>\n\n          <text style=\"{text}\">\n            Your GitHub repository access has been granted. You now have\n            full access to the {brand.name} codebase.\n          <\/text>\n\n          <section style=\"{buttonContainer}\">\n            <button style=\"{button}\" href=\"{repoUrl}\">\n              Open Repository\n            <\/button>\n          <\/section>\n\n          <section style=\"{infoBox}\">\n            <text style=\"{infoTitle}\">Quick Start<\/text>\n            <text style=\"{infoText}\">\n              <strong>1.<\/strong> Clone the repository to your machine\n            <\/text>\n            <text style=\"{infoText}\">\n              <strong>2.<\/strong> Run{\" \"}\n              <code style=\"{codeStyle}\">bun install<\/code> to install\n              dependencies\n            <\/text>\n            <text style=\"{infoText}\">\n              <strong>3.<\/strong> Follow the README for environment setup\n            <\/text>\n            <text style=\"{infoText}\">\n              <strong>4.<\/strong> Run{\" \"}\n              <code style=\"{codeStyle}\">bun dev<\/code> to start building\n            <\/text>\n          <\/section>\n\n          <hr style=\"{divider}\"\/>\n\n          <text style=\"{footer}\">\n            Need help? Reply to this email or reach out at{\" \"}\n            <link href=\"{`mailto:${brand.emails.support}`}\" style=\"{link}\"\/>\n              {brand.emails.support}\n            \n          <\/text>\n        <\/container>\n      \n    \n  );\n}\n<\/pre>\n<p>\u0627\u0633 \u0633\u0627\u0646\u0686\u06d2 \u0645\u06cc\u06ba <code><button\/><\/code> \u0627\u06cc\u06a9 \u062c\u0632\u0648 \u062c\u0648 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a GitHub \u0630\u062e\u06cc\u0631\u06c1 \u0633\u06d2 \u062c\u0691\u062a\u0627 \u06c1\u06d2\u06d4 \u0641\u0648\u0631\u06cc \u0622\u063a\u0627\u0632 \u06a9\u0627 \u0633\u06cc\u06a9\u0634\u0646 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u06af\u0644\u06d2 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062a\u0627\u06a9\u06c1 \u0648\u06c1 \u06cc\u06c1 \u0646\u06c1\u06cc\u06ba \u0633\u0648\u0686\u062a\u06d2 \u06a9\u06c1 \u0631\u0633\u0627\u0626\u06cc \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u0648\u06c1 \u06a9\u06cc\u0627 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-how-to-build-an-abandoned-cart-template\">\u0627\u06cc\u06a9 \u062a\u0631\u06a9 \u0634\u062f\u06c1 \u06a9\u0627\u0631\u0679 \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u0626\u06cc\u06ba<\/h3>\n<p>\u062a\u0631\u06a9 \u0634\u062f\u06c1 \u06a9\u0627\u0631\u0679 \u0627\u06cc \u0645\u06cc\u0644\u0632 \u06af\u0627\u06c1\u06a9\u0648\u06ba \u06a9\u0648 \u0622\u067e \u06a9\u06d2 \u0642\u06cc\u0645\u062a\u0648\u06ba \u06a9\u06d2 \u0635\u0641\u062d\u06c1 \u067e\u0631 \u0648\u0627\u067e\u0633 \u0628\u06be\u06cc\u062c\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-tsx\">\/\/ src\/lib\/email\/emails\/abandoned-cart.tsx\nimport {\n  Body,\n  Button,\n  Container,\n  Head,\n  Heading,\n  Hr,\n  Html,\n  Preview,\n  Section,\n  Text,\n} from \"@react-email\/components\";\n\nimport { brand } from \"@\/lib\/brand\";\n\ninterface AbandonedCartEmailProps {\n  customerEmail: string;\n  checkoutUrl: string;\n}\n\nexport default function AbandonedCartEmail({\n  customerEmail,\n  checkoutUrl,\n}: AbandonedCartEmailProps) {\n  return (\n    \n      <\/code>\n      <preview>Your {brand.name} checkout is waiting for you<\/preview>\n      \n        <container style=\"{container}\">\n          <section style=\"{header}\">\n            <text style=\"{logoText}\">{brand.name}<\/text>\n          <\/section>\n\n          <hr style=\"{divider}\"\/>\n\n          <heading style=\"{h1}\">You left something behind<\/heading>\n\n          <text style=\"{text}\">\n            We noticed you started a checkout but did not complete your\n            purchase. No worries. Your cart is still waiting for you.\n          <\/text>\n\n          <text style=\"{text}\">\n            {brand.name} gives you everything you need to ship your\n            startup this weekend: authentication, payments, email,\n            background jobs, and more. All wired together and ready\n            to go.\n          <\/text>\n\n          <section style=\"{buttonContainer}\">\n            <button style=\"{button}\" href=\"{checkoutUrl}\">\n              Complete Your Purchase\n            <\/button>\n          <\/section>\n\n          <text style=\"{textSmall}\">\n            If you ran into any issues during checkout or have questions\n            about {brand.name}, just reply to this email. I read every\n            message personally.\n          <\/text>\n\n          <hr style=\"{divider}\"\/>\n\n          <text style=\"{footer}\">\n            This email was sent to {customerEmail} because you started\n            a checkout on {brand.name}. If this was not you, you can\n            safely ignore this email.\n          <\/text>\n        <\/container>\n      \n    \n  );\n}\n<\/pre>\n<p>\u0644\u06c1\u062c\u06c1 \u06cc\u06c1\u0627\u06ba \u0627\u06c1\u0645 \u06c1\u06d2\u06d4 &quot;\u0622\u067e \u0646\u06d2 \u06a9\u0686\u06be \u067e\u06cc\u0686\u06be\u06d2 \u0686\u06be\u0648\u0691 \u062f\u06cc\u0627&#8221; \u0627\u06cc\u06a9 \u062f\u0648\u0633\u062a\u0627\u0646\u06c1\u060c \u063a\u06cc\u0631 \u0632\u0628\u0631\u062f\u0633\u062a\u06cc \u0628\u06cc\u0627\u0646 \u06c1\u06d2\u06d4 \u0627\u06cc \u0645\u06cc\u0644 \u0645\u062e\u062a\u0635\u0631 \u0637\u0648\u0631 \u067e\u0631 \u0622\u067e \u06a9\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0679 \u06a9\u06cc \u0642\u062f\u0631 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0633 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f\u060c \u0648\u0627\u0636\u062d \u06a9\u0627\u0644 \u0679\u0648 \u0627\u06cc\u06a9\u0634\u0646 \u0634\u0627\u0645\u0644 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u06a9\u0648 \u0641\u0648\u0679\u0631 \u0645\u06cc\u06ba \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06cc\u0648\u06ba \u0645\u0648\u0635\u0648\u0644 \u06c1\u0648\u0626\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-how-templates-integrate-with-durable-steps\">\u0679\u06cc\u0645\u067e\u0644\u06cc\u0679\u0633 \u0645\u0633\u062a\u0642\u0644 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u06cc\u0633\u06d2 \u0636\u0645 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/h3>\n<p>\u062a\u0645\u0627\u0645 \u0627\u06cc \u0645\u06cc\u0644 \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679\u0633 \u06a9\u0648 \u0628\u0630\u0631\u06cc\u0639\u06c1 \u0628\u0644\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2: <code>createElement<\/code> \u0645\u06cc\u06ba <code>step.run()<\/code> \u0628\u0644\u0627\u06a9:<\/p>\n<pre><code class=\"language-typescript\">await step.run(\"send-purchase-confirmation\", async () => {\n  await sendEmail({\n    to: user.email,\n    subject: `Your ${brand.name} purchase is confirmed!`,\n    template: createElement(PurchaseConfirmationEmail, {\n      amount: purchase.amount,\n      currency: purchase.currency,\n      customerEmail: user.email,\n    }),\n  });\n});\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>createElement<\/code> \u06a9\u0627\u0644 \u062f\u06cc\u06d2 \u06af\u0626\u06d2 \u067e\u0631\u067e\u0633 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679 \u06a9\u06d2 \u062c\u0632\u0648 \u0633\u06d2 \u0627\u06cc\u06a9 React \u0639\u0646\u0635\u0631 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06d2\u06d4 \u06a9\u06c1 <code>sendEmail<\/code> \u0641\u0646\u06a9\u0634\u0646 \u0631\u06cc \u0627\u06cc\u06a9\u0679 \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 HTML \u06a9\u0648 \u0631\u06cc\u0646\u0688\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>render()<\/code> \u0631\u06cc \u0679\u0631\u0627\u0646\u0633\u0645\u06cc\u0634\u0646 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4<\/p>\n<p>\u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0627\u0646\u062f\u0631 \u06c1\u06d2\u06d4 <code>step.run()<\/code>\u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06cc \u062a\u0631\u0633\u06cc\u0644 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u067e\u0631 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0679\u0631\u0627\u0646\u0633\u0645\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u062e\u0644\u0644 \u067e\u0691\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0645\u0631\u062d\u0644\u06c1 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u067e\u0686\u06be\u0644\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u062e\u0648\u062f \u06c1\u06cc \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0627\u06cc \u0645\u06cc\u0644\u0632 \u0645\u0648\u0635\u0648\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u06ba \u06af\u06cc\u06d4<\/p>\n<h2 id=\"heading-how-to-test-the-complete-flow-locally\">\u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u067e\u0648\u0631\u06d2 \u0628\u06c1\u0627\u0624 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u067e\u0648\u0631\u06d2 \u0644\u0627\u0626\u0641 \u0633\u0627\u0626\u06cc\u06a9\u0644 \u06a9\u0648 \u062c\u0627\u0646\u0686\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0622\u067e \u06a9\u0648 \u0628\u06cc\u06a9 \u0648\u0642\u062a \u062a\u06cc\u0646 \u0686\u06cc\u0632\u0648\u06ba \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2: \u0622\u067e \u06a9\u06cc \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646\u060c \u0627\u0633\u0679\u0631\u0627\u0626\u067e CLI\u060c \u062c\u0648 \u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u0648 \u0628\u06be\u06cc\u062c\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 Ingest \u0688\u0648\u06cc\u0644\u067e\u0645\u0646\u0679 \u0633\u0631\u0648\u0631\u060c \u062c\u0648 \u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u0679\u0627\u0633\u06a9 \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-step-1-start-the-stripe-cli\">\u0645\u0631\u062d\u0644\u06c1 1: \u067e\u0679\u06cc CLI \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0627\u0633\u0679\u0631\u0627\u0626\u067e CLI \u0627\u0646\u0633\u0679\u0627\u0644 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0644\u0627\u06af \u0627\u0646 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\"># macOS\nbrew install stripe\/stripe-cli\/stripe\n\n# Authenticate\nstripe login\n<\/code><\/pre>\n<p>\u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u0648 \u0645\u0642\u0627\u0645\u06cc \u0633\u0631\u0648\u0631 \u067e\u0631 \u0641\u0627\u0631\u0648\u0631\u0688 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-bash\">stripe listen --forward-to localhost:3000\/api\/payments\/webhook\n<\/code><\/pre>\n<p>CLI \u0627\u0633 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0648\u06cc\u0628 \u06c1\u06a9 \u067e\u0631 \u062f\u0633\u062a\u062e\u0637 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0631\u0627\u0632 \u06a9\u0648 \u067e\u0631\u0646\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>whsec_<\/code>. \u06cc\u06c1 \u0622\u067e \u06a9\u0627 \u06c1\u06d2\u06d4 <code>.env<\/code> \u067e\u0633\u0646\u062f <code>STRIPE_WEBHOOK_SECRET<\/code>.<\/p>\n<h3 id=\"heading-step-2-start-the-inngest-dev-server\">\u0645\u0631\u062d\u0644\u06c1 2: Ingest Dev \u0633\u0631\u0648\u0631 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0627\u0646\u062c\u0633\u0679 \u0688\u0648\u06cc\u0644\u067e\u0645\u0646\u0679 \u0633\u0631\u0648\u0631 \u06c1\u0631 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u0639\u0645\u0644\u060c \u06c1\u0631 \u0642\u062f\u0645\u060c \u0627\u0648\u0631 \u06c1\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u0645\u06cc\u06ba \u0631\u06cc\u0626\u0644 \u0679\u0627\u0626\u0645 \u0645\u0631\u0626\u06cc\u062a \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-bash\">npx inngest-cli@latest dev -u http:\/\/localhost:3000\/api\/inngest\n<\/code><\/pre>\n<p>\u06a9\u06be\u0644\u0627 <code>http:\/\/localhost:8288<\/code> \u0622\u067e \u06a9\u06d2 \u0628\u0631\u0627\u0624\u0632\u0631 \u0645\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0627\u0646\u062c\u0633\u0679 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0622\u067e \u0642\u062f\u0645 \u0628\u06c1 \u0642\u062f\u0645 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-step-3-start-your-application\">\u0645\u0631\u062d\u0644\u06c1 3: \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<pre><code class=\"language-bash\">bun run dev\n<\/code><\/pre>\n<p>\u0622\u067e \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0648 \u0627\u0628 \u0627\u0633 \u067e\u0631 \u0686\u0644\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2: <code>http:\/\/localhost:3000<\/code>.<\/p>\n<h3 id=\"heading-step-4-test-the-purchase-flow\">\u0645\u0631\u062d\u0644\u06c1 4: \u0627\u067e\u0646\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<ol>\n<li>\n<p>\u0642\u06cc\u0645\u062a\u0648\u06ba \u06a9\u06d2 \u0635\u0641\u062d\u06c1 \u067e\u0631 \u062c\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u0679\u0646 \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u067e\u0679\u06cc \u06a9\u0627 \u0679\u06cc\u0633\u0679 \u06a9\u0627\u0631\u0688 \u0646\u0645\u0628\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>4242 4242 4242 4242<\/code> \u0645\u0633\u062a\u0642\u0628\u0644 \u06a9\u06cc \u0645\u06cc\u0639\u0627\u062f \u062e\u062a\u0645 \u06c1\u0648\u0646\u06d2 \u06a9\u06cc \u062a\u0627\u0631\u06cc\u062e \u0627\u0648\u0631 CVC \u0634\u0627\u0645\u0644 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u067e\u0646\u06cc \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u0645\u06a9\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u067e\u0679\u06cc \u0622\u067e \u06a9\u0648 \u06a9\u0627\u0645\u06cc\u0627\u0628\u06cc \u06a9\u06d2 URL \u067e\u0631 \u0628\u06be\u06cc\u062c\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0622\u067e \u06a9\u0627 \u0641\u0631\u0646\u0679 \u0627\u06cc\u0646\u0688 \u06c1\u06d2 <code>\/api\/purchases\/claim<\/code> \u0633\u06cc\u0634\u0646 ID \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u06c1\u06d4<\/p>\n<\/li>\n<li>\n<p>Ingest \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u062f\u06cc\u06a9\u06be\u06cc\u06ba\u06d4 \u062a\u0645 \u06c1\u0648 <code>purchase-completed<\/code> \u0641\u0646\u06a9\u0634\u0646 \u0679\u0631\u06af\u0631 \u0627\u0648\u0631 \u06c1\u0631 \u0642\u062f\u0645 \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u0633\u06d2 \u0639\u0645\u0644 \u0645\u06cc\u06ba \u0644\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ol>\n<p>Ingest \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2:<\/p>\n<ul>\n<li>\n<p><strong>\u0645\u0631\u062d\u0644\u06c1 1:<\/strong> \u0635\u0627\u0631\u0641 \u0627\u0648\u0631 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06d2 \u0688\u06cc\u0679\u0627 \u06a9\u06d2 \u0633\u0627\u062a\u06be &quot;\u0644\u064f\u06a9 \u0627\u067e \u06cc\u0648\u0632\u0631 \u0627\u0648\u0631 \u067e\u0631\u0686\u06cc\u0632&#8221; \u0645\u06a9\u0645\u0644 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0645\u0631\u062d\u0644\u06c1 2:<\/strong> &quot;Track-purchase-to-posthog&#8221; \u0645\u06a9\u0645\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 (\u06cc\u0627 \u0627\u06af\u0631 PostHog \u06a9\u0648 \u06a9\u0646\u0641\u06cc\u06af\u0631 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u0627\u06cc\u06a9 \u0648\u0627\u0631\u0646\u0646\u06af \u0644\u0627\u06af \u06a9\u0631\u062a\u0627 \u06c1\u06d2)\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0645\u0631\u062d\u0644\u06c1 3:<\/strong> &quot;\u0628\u06be\u06cc\u062c\u06cc\u06ba-\u062e\u0631\u06cc\u062f\u0627\u0631\u06cc-\u062a\u0635\u062f\u06cc\u0642&#8221; \u0645\u06a9\u0645\u0644 \u06c1\u0648 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0627\u067e\u0646\u0627 \u0627\u06cc \u0645\u06cc\u0644 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0645\u0631\u062d\u0644\u06c1 4:<\/strong> &quot;\u0627\u06cc\u0688\u0645\u0646\u0633\u0679\u0631\u06cc\u0679\u0631 \u06a9\u06cc \u0627\u0637\u0644\u0627\u0639 \u0628\u06be\u06cc\u062c\u06cc\u06ba&#8221; \u0645\u06a9\u0645\u0644 \u06c1\u06d2 (\u0627\u06af\u0631 <code>ADMIN_EMAIL<\/code> \u0633\u06cc\u0679)\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0645\u0631\u062d\u0644\u06c1 5 \u0633\u06d2 9:<\/strong> \u0686\u0644\u0627\u0626\u06cc\u06ba \u0627\u06af\u0631 \u0635\u0627\u0631\u0641 \u06a9\u0627 GitHub \u0635\u0627\u0631\u0641 \u0646\u0627\u0645 \u0627\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0648\u0627\u0628\u0633\u062a\u06c1 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-step-5-test-a-refund\">\u0645\u0631\u062d\u0644\u06c1 5: \u0627\u067e\u0646\u06cc \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0627\u0633\u0679\u0631\u0627\u0626\u067e CLI \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0631\u06cc\u0641\u0646\u0688\u0632 \u06a9\u0648 \u0645\u062a\u062d\u0631\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">stripe trigger charge.refunded\n<\/code><\/pre>\n<p>\u0645\u062a\u0628\u0627\u062f\u0644 \u0637\u0648\u0631 \u067e\u0631\u060c \u0627\u067e\u0646\u06d2 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u067e\u0631 \u062c\u0627\u0626\u06cc\u06ba\u060c \u062c\u0627\u0646\u0686 \u06a9\u06cc \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u062a\u0644\u0627\u0634 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0648\u0631 \u062f\u0633\u062a\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u062c\u0627\u0631\u06cc \u06a9\u0631\u06cc\u06ba\u06d4 \u067e\u0679\u06cc CLI \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>charge.refunded<\/code> \u0645\u0642\u0627\u0645\u06cc \u0633\u0631\u0648\u0631 \u067e\u0631 \u0648\u06cc\u0628 \u06c1\u06a9\u06d4<\/p>\n<p>Ingest \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2: <code>refund-processed<\/code> \u0627\u06cc\u06a9 \u0641\u0646\u06a9\u0634\u0646 \u0679\u0631\u06af\u0631 \u062c\u0633 \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u0645\u0631\u0627\u062d\u0644 \u06a9\u06d2 \u0633\u06cc\u0679 \u06c1\u06cc\u06ba\u060c \u062c\u06cc\u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631\u060c \u0645\u0634\u0631\u0648\u0637 \u0631\u0633\u0627\u0626\u06cc \u06a9\u06cc \u0645\u0646\u0633\u0648\u062e\u06cc\u060c \u0627\u0633\u0679\u06cc\u0679\u0633 \u0627\u067e \u0688\u06cc\u0679\u060c \u0627\u06cc\u0646\u0627\u0644\u06cc\u0679\u06a9\u0633 \u0679\u0631\u06cc\u06a9\u0646\u06af\u060c \u0627\u06cc \u0645\u06cc\u0644 \u0627\u0637\u0644\u0627\u0639 \u0648\u063a\u06cc\u0631\u06c1\u06d4<\/p>\n<h3 id=\"heading-step-6-test-abandoned-cart-recovery\">\u0645\u0631\u062d\u0644\u06c1 6: \u0686\u06be\u0648\u0691\u06cc \u06c1\u0648\u0626\u06cc \u0679\u0648\u06a9\u0631\u06cc \u06a9\u06cc \u0628\u0627\u0632\u06cc\u0627\u0628\u06cc \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06cc \u0645\u06cc\u0639\u0627\u062f \u062e\u062a\u0645 \u06c1\u0648\u0646\u06d2 \u06a9\u0648 \u0645\u062a\u062d\u0631\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">stripe trigger checkout.session.expired\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>checkout-expired<\/code> \u06cc\u06c1 \u062e\u0635\u0648\u0635\u06cc\u062a Ingest \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 1 \u06af\u06be\u0646\u0679\u06d2 \u06a9\u06cc \u0646\u06cc\u0646\u062f \u06a9\u06d2 \u0645\u0631\u0627\u062d\u0644 \u062f\u06a9\u06be\u0627\u0626\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0688\u06cc\u0648\u0644\u067e\u0645\u0646\u0679 \u0633\u0631\u0648\u0631 \u067e\u0631\u060c \u0622\u067e \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0645\u06cc\u06ba &quot;\u0627\u0633\u06a9\u06cc\u067e&#8221; \u0628\u0679\u0646 \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u06a9\u06d2 \u0633\u0644\u06cc\u067e \u0645\u0648\u0688 \u06a9\u0648 \u062a\u06cc\u0632\u06cc \u0633\u06d2 \u0622\u06af\u06d2 \u0628\u0691\u06be\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u06af\u06be\u0646\u0679\u06c1 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u062a\u0627\u062e\u06cc\u0631\u06cc \u0627\u06cc \u0645\u06cc\u0644\u0632 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-how-to-simulate-step-failures\">\u0645\u0631\u062d\u0644\u06c1 \u0648\u0627\u0631 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06cc \u0646\u0642\u0644 \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0631\u0648\u06cc\u06d2 \u06a9\u0648 \u062c\u0627\u0646\u0686\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0639\u0627\u0631\u0636\u06cc \u0637\u0648\u0631 \u067e\u0631 \u062f\u0631\u062c \u0630\u06cc\u0644 \u0645\u0631\u0627\u062d\u0644 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0633\u06cc \u0627\u06cc\u06a9 \u0645\u06cc\u06ba \u063a\u0644\u0637\u06cc \u067e\u06cc\u062f\u0627 \u06a9\u0631\u06cc\u06ba:<\/p>\n<pre><code class=\"language-typescript\">const collaboratorResult = await step.run(\n  \"add-github-collaborator\",\n  async () => {\n    throw new Error(\"Simulated GitHub API failure\");\n  }\n);\n<\/code><\/pre>\n<p>Ingest \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2:<\/p>\n<ul>\n<li>\n<p>\u0645\u0631\u062d\u0644\u06c1 1 \u0633\u06d2 4 \u062a\u06a9 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648 \u06af\u0626\u06d2 \u0627\u0648\u0631 \u0646\u062a\u0627\u0626\u062c \u06a9\u06cc\u0634 \u06c1\u0648 \u06af\u0626\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0645\u0631\u062d\u0644\u06c1 5 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u06cc\u06a9\u0633\u067e\u0648\u0646\u06cc\u0634\u0646\u0644 \u0628\u06cc\u06a9 \u0622\u0641 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0641\u06cc\u0632 6-9 \u0627\u0628\u06be\u06cc \u0628\u0627\u0642\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u06a9\u0633\u06cc \u0628\u06be\u06cc \u062e\u0631\u0627\u0628\u06cc \u06a9\u0648 \u06c1\u0679\u0627 \u062f\u06cc\u06ba \u0627\u0648\u0631 \u0627\u06af\u0644\u06cc \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u067e\u0631 \u0645\u0631\u062d\u0644\u06c1 5 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 \u0645\u0631\u062d\u0644\u06c1 6 \u0633\u06d2 9 \u062a\u06a9 \u0639\u0645\u0644 \u0645\u06cc\u06ba \u0644\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u060c \u0644\u06cc\u06a9\u0646 \u0645\u0631\u062d\u0644\u06c1 1 \u0633\u06d2 4 \u062a\u06a9 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0639\u0645\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679\u0646\u06af \u0631\u0648\u06cc\u06c1 \u06c1\u06d2 \u062c\u0648 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0639\u0645\u0644\u062f\u0631\u0622\u0645\u062f \u06a9\u0648 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-conclusion\">\u0646\u062a\u06cc\u062c\u06c1<\/h2>\n<p>\u0645\u06a9\u0645\u0644 SaaS \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u06a9\u06cc \u062a\u0639\u0645\u06cc\u0631 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0686\u06cc\u06a9 \u0622\u0624\u0679 \u06a9\u0648 \u0645\u0631\u0628\u0648\u0637 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0628\u0627\u0644\u0627\u062a\u0631 \u06c1\u06d2\u06d4 &quot;\u062e\u0631\u06cc\u062f\u06cc\u06ba&#8221; \u0628\u0679\u0646 \u0633\u06d2 \u0644\u06d2 \u06a9\u0631 &quot;\u062e\u0648\u0634 \u0622\u0645\u062f\u06cc\u062f&#8221; \u0627\u06cc \u0645\u06cc\u0644 \u062a\u06a9 \u06a9\u0627 \u067e\u0648\u0631\u0627 \u0644\u0627\u0626\u0641 \u0633\u0627\u0626\u06cc\u06a9\u0644\u060c \u0628\u0634\u0645\u0648\u0644 \u06a9\u0686\u06be \u063a\u0644\u0637 \u06c1\u0648\u0646\u06d2 \u067e\u0631 \u06a9\u06cc\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0645\u06cc\u06ba \u06c1\u0645 \u0646\u06d2 \u062c\u0648 \u0628\u0646\u0627\u06cc\u0627 \u06c1\u06d2 \u0648\u06c1 \u06cc\u06c1 \u06c1\u06d2:<\/p>\n<ul>\n<li>\n<p>\u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <strong>\u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0633\u06a9\u06cc\u0645\u0627<\/strong> \u0645\u06a9\u0645\u0644\u060c \u062c\u0632\u0648\u06cc \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc\u060c \u0627\u0648\u0631 \u0645\u06a9\u0645\u0644 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u0633\u0645\u06cc\u062a \u062a\u0645\u0627\u0645 \u062d\u0627\u0644\u062a\u0648\u06ba \u0645\u06cc\u06ba \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc\u0648\u06ba \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <strong>\u067e\u0679\u06cc \u06a9\u06cc \u0645\u0635\u0646\u0648\u0639\u0627\u062a \u0627\u0648\u0631 \u0642\u06cc\u0645\u062a \u06a9\u06d2 \u0628\u06cc\u062c \u0633\u06a9\u0631\u067e\u0679<\/strong> \u067e\u0631\u0648\u06af\u0631\u0627\u0645 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u06a9\u06cc\u0679\u0644\u0627\u06af \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <strong>\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0627 \u0628\u06c1\u0627\u0624<\/strong> \u0633\u06cc\u0634\u0646 \u06a9\u06cc \u062a\u062e\u0644\u06cc\u0642\u060c \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642\u060c \u0627\u0648\u0631 \u063a\u06cc\u0631\u0645\u0639\u0645\u0648\u0644\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u0628\u0644\u0646\u06af \u0634\u0627\u0645\u0644 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <strong>\u067e\u062a\u0644\u0627 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631<\/strong> \u062f\u0633\u062a\u062e\u0637\u0648\u06ba \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u0648 \u067e\u0633 \u0645\u0646\u0638\u0631 \u06a9\u06d2 \u06a9\u0627\u0645\u0648\u06ba \u062a\u06a9 \u0644\u06d2 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <strong>9 \u0633\u0637\u062d \u06a9\u06d2 \u0627\u0633\u062a\u062d\u06a9\u0627\u0645 \u06a9\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062a\u0642\u0631\u06cc\u0628<\/strong> \u06cc\u06c1\u0627\u06ba \u06c1\u0631 \u0642\u062f\u0645 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u067e\u0691\u062a\u0627\u0644 \u0627\u0648\u0631 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <strong>\u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u067e\u0631\u0648\u0633\u06cc\u0633\u0631<\/strong> \u06c1\u0645 \u0645\u06a9\u0645\u0644 \u0627\u0648\u0631 \u062c\u0632\u0648\u06cc \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0631\u0642 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0635\u0631\u0641 \u0645\u0646\u0627\u0633\u0628 \u06c1\u0648\u0646\u06d2 \u067e\u0631 \u0631\u0633\u0627\u0626\u06cc \u0645\u0646\u0633\u0648\u062e \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0646\u06c1\u06cc\u06ba <strong>\u062a\u0631\u06a9 \u0634\u062f\u06c1 \u06a9\u0627\u0631\u0679 \u0631\u06cc\u06a9\u0648\u0631\u06cc \u0641\u0644\u0648<\/strong> \u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0627\u067e\u0646\u0627 \u062f\u0648\u0633\u062a\u0627\u0646\u06c1 \u0631\u06cc\u06a9\u0648\u0631\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u06cc\u06a9 \u06af\u06be\u0646\u0679\u06c1 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u062a\u06cc\u0646 \u0679\u0631\u0627\u0646\u0632\u06cc\u06a9\u0634\u0646\u0644 \u0627\u06cc \u0645\u06cc\u0644 \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679\u0633<\/strong> \u0631\u06cc \u0627\u06cc\u06a9\u0679 \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0628\u0646\u0627\u06cc\u0627 \u06af\u06cc\u0627: \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc\u0648\u06ba \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u06cc\u06ba\u060c \u0645\u062e\u0632\u0646 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u06cc\u06ba\u060c \u06a9\u0627\u0631\u0679 \u06a9\u0648 \u062a\u0631\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <strong>\u0645\u0642\u0627\u0645\u06cc \u0679\u06cc\u0633\u0679 \u0633\u06cc\u0679 \u0627\u067e<\/strong> \u06cc\u06c1 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0633\u06cc \u0627\u06cc\u0644 \u0622\u0626\u06cc\u060c \u0627\u0646\u062c\u06cc\u0633\u0679 \u0688\u0648\u06cc\u0644\u067e\u0645\u0646\u0679 \u0633\u0631\u0648\u0631\u060c \u0627\u0648\u0631 \u0642\u062f\u0645 \u0628\u06c1 \u0642\u062f\u0645 \u0645\u0634\u0627\u06c1\u062f\u06d2 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0633\u0628 \u0633\u06d2 \u0627\u06c1\u0645 \u0646\u0645\u0648\u0646\u06c1 \u0627\u0633\u062a\u0642\u0628\u0627\u0644\u06cc\u06c1 \u0627\u0648\u0631 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0639\u0644\u06cc\u062d\u062f\u06af\u06cc \u06c1\u06d2\u06d4 API \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679\u0633 \u0627\u0648\u0631 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631\u0632 \u067e\u062a\u0644\u06d2 \u06c1\u0648\u0646\u06d2 \u0686\u0627\u06c1\u0626\u06cc\u06ba: \u062a\u0648\u062b\u06cc\u0642\u060c \u0631\u06cc\u06a9\u0627\u0631\u0688\u0646\u06af\u060c \u0642\u0637\u0627\u0631 \u0628\u0646\u062f\u06cc\u060c \u0627\u0648\u0631 \u0648\u0627\u067e\u0633\u06cc\u06d4 \u062a\u0645\u0627\u0645 \u067e\u06cc\u0686\u06cc\u062f\u06c1 \u0645\u0644\u0679\u06cc \u0633\u0679\u06cc\u067e \u0622\u067e\u0631\u06cc\u0634\u0646\u0632 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u0641\u0646\u06a9\u0634\u0646\u0632 \u0645\u06cc\u06ba \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u06c1\u0627\u06ba \u063a\u0644\u0637\u06cc\u0648\u06ba \u06a9\u0648 \u0627\u0644\u06af \u062a\u06be\u0644\u06af \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0645\u0631\u062d\u0644\u06c1 \u0648\u0627\u0631 \u0633\u0637\u062d \u067e\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0648 \u0648\u0633\u0639\u062a \u062f\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4 \u062c\u0628 \u0622\u067e \u0627\u067e\u0646\u06d2 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0645\u0631\u062d\u0644\u06c1 \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u06a9\u0648 \u0648\u06c1\u06cc \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u0645\u0644\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0628\u0631\u062a\u0627\u0624 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0648\u06cc\u0628 \u06c1\u06a9 \u06a9\u06d2 \u0646\u0626\u06d2 \u0627\u06cc\u0648\u0646\u0679\u0633 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0646\u06c1\u06cc\u06ba \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u06a9\u06cc \u0637\u0631\u0641 \u0644\u06d2 \u062c\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<p>\u0622\u067e \u06a9\u06cc \u0636\u0631\u0648\u0631\u06cc\u0627\u062a \u0645\u062e\u062a\u0644\u0641 \u06c1\u0648 \u0633\u06a9\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0622\u067e \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u06a9\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0633\u0628\u0633\u06a9\u0631\u067e\u0634\u0646\u0632 \u0628\u06cc\u0686 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u06cc\u0627 GitHub \u0631\u0633\u0627\u0626\u06cc \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 API \u06a9\u06cc\u0632 \u06a9\u06cc \u0641\u0631\u0627\u06c1\u0645\u06cc \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0645\u062e\u0635\u0648\u0635 \u0645\u0631\u0627\u062d\u0644 \u0628\u062f\u0644 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0644\u06cc\u06a9\u0646 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u0648\u06c1\u06cc \u0631\u06c1\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0622\u067e \u0627\u0646 \u062a\u0645\u0627\u0645 \u0646\u0645\u0648\u0646\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0634\u0631\u0648\u0639 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 \u06a9\u0648\u0688 \u0628\u06cc\u0633 \u0633\u06d2 \u062c\u0691\u06d2 \u06c1\u0648\u0626\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u06cc\u0688\u0646 \u0627\u0633\u0679\u06cc\u06a9 \u0645\u06cc\u06ba \u0627\u0633 \u0645\u0636\u0645\u0648\u0646 \u0645\u06cc\u06ba \u0628\u06cc\u0627\u0646 \u06a9\u0631\u062f\u06c1 \u0645\u06a9\u0645\u0644 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u060c \u062a\u0635\u062f\u06cc\u0642\u060c \u0627\u06cc \u0645\u06cc\u0644\u060c \u062a\u062c\u0632\u06cc\u0627\u062a\u060c \u067e\u0633 \u0645\u0646\u0638\u0631 \u06a9\u06d2 \u06a9\u0627\u0645\u0648\u06ba \u0627\u0648\u0631 \u0645\u0632\u06cc\u062f \u06a9\u06d2 \u0644\u06cc\u06d2 30+ \u0627\u0636\u0627\u0641\u06cc \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0679\u06cc\u0633\u0679 \u067e\u06cc\u0679\u0631\u0646 \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><em>Magnus R\u00f8dseth AI \u067e\u0631 \u0645\u0628\u0646\u06cc \u0627\u06cc\u067e\u0644\u06cc \u06a9\u06cc\u0634\u0646\u0632 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631<\/em> <em>\u0627\u06cc\u0688\u0646 \u0627\u0633\u0679\u06cc\u06a9<\/em><em>30+ \u06a9\u0644\u0627\u0688 \u0679\u06cc\u06a9\u0646\u0627\u0644\u0648\u062c\u06cc\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 \u0627\u0633\u0679\u0627\u0631\u0679\u0631 \u06a9\u0679 \u062c\u0648 AI \u0633\u06d2 \u0686\u0644\u0646\u06d2 \u0648\u0627\u0644\u06d2 SaaS \u06a9\u06cc \u062a\u0631\u0642\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0648 \u0627\u0646\u06a9\u0648\u0688 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/em><\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u067e\u0679\u06cc \u0648\u0627\u0644\u06d2 \u0633\u0628\u0642 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0635\u0641\u062d\u06c1 \u067e\u0631 \u062e\u062a\u0645 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062c\u0628 \u06a9\u0648\u0626\u06cc \u0635\u0627\u0631\u0641 &quot;\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc&#8221; \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0628\u0644\u0646\u06af \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u0627 \u062c\u0634\u0646 \u0645\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u06cc\u06a9\u0646 \u06cc\u06c1 \u0627\u0635\u0644 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0646\u0638\u0627\u0645 \u06a9\u0627 \u0635\u0631\u0641 \u067e\u06c1\u0644\u0627 10% \u06c1\u06d2\u06d4 \u06af\u0627\u06c1\u06a9 \u06a9\u06cc \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u06a9\u06cc\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u061f [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":23747,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[1],"tags":[],"class_list":["post-23746","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/posts\/23746","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/comments?post=23746"}],"version-history":[{"count":1,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/posts\/23746\/revisions"}],"predecessor-version":[{"id":23748,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/posts\/23746\/revisions\/23748"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/media\/23747"}],"wp:attachment":[{"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/media?parent=23746"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/categories?post=23746"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/tags?post=23746"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}