{"id":22889,"date":"2026-04-22T19:05:44","date_gmt":"2026-04-22T19:05:44","guid":{"rendered":"https:\/\/umang.pk\/2026\/04\/22\/%d8%a8%db%8c%da%a9-%da%af%d8%b1%d8%a7%d8%a4%d9%86%da%88-%d9%b9%d8%a7%d8%b3%da%a9-%da%a9%db%92-%d8%b7%d9%88%d8%b1-%d9%be%d8%b1-%d8%a7%d8%b3%d9%b9%d8%b1%d8%a7%d8%a6%d9%be-%d9%88%db%8c%d8%a8-%db%81%da%a9\/"},"modified":"2026-04-22T19:05:59","modified_gmt":"2026-04-22T19:05:59","slug":"%d8%a8%db%8c%da%a9-%da%af%d8%b1%d8%a7%d8%a4%d9%86%da%88-%d9%b9%d8%a7%d8%b3%da%a9-%da%a9%db%92-%d8%b7%d9%88%d8%b1-%d9%be%d8%b1-%d8%a7%d8%b3%d9%b9%d8%b1%d8%a7%d8%a6%d9%be-%d9%88%db%8c%d8%a8-%db%81%da%a9","status":"publish","type":"post","link":"https:\/\/umang.pk\/en_us\/2026\/04\/22\/%d8%a8%db%8c%da%a9-%da%af%d8%b1%d8%a7%d8%a4%d9%86%da%88-%d9%b9%d8%a7%d8%b3%da%a9-%da%a9%db%92-%d8%b7%d9%88%d8%b1-%d9%be%d8%b1-%d8%a7%d8%b3%d9%b9%d8%b1%d8%a7%d8%a6%d9%be-%d9%88%db%8c%d8%a8-%db%81%da%a9\/","title":{"rendered":"\u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u0679\u0627\u0633\u06a9 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u06a9\u0648 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06a9\u06cc\u0633\u06d2 \u067e\u0631\u0648\u0633\u06cc\u0633 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4"},"content":{"rendered":"\n<div id=\"\">\n<p>\u0622\u067e \u0646\u06d2 \u067e\u0679\u06cc \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc \u06c1\u06d2\u06d4 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u0635\u0627\u0631\u0641\u06cc\u0646 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0644\u06cc\u06a9\u0646 \u06a9\u06cc\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 <em>~ \u0628\u0639\u062f<\/em> \u0627\u062f\u0627<\/p>\n<p>\u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0648\u06c1 \u062c\u06af\u06c1 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0627\u0646\u0636\u0645\u0627\u0645 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0631\u06a9 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0631\u0633\u0627\u0626\u06cc \u062f\u06cc\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a \u0633\u0631\u0648\u0631 \u06a9\u0631\u06cc\u0634 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 \u0645\u06cc\u06ba \u0646\u06d2 \u062a\u0635\u062f\u06cc\u0642\u06cc \u067e\u06cc\u063a\u0627\u0645 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u06cc \u062a\u0648 \u0645\u06cc\u0631\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0633\u0631\u0648\u0633 \u0628\u0646\u062f \u062a\u06be\u06cc\u06d4 \u0644\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u0627 \u0648\u0642\u062a \u062e\u062a\u0645 \u06c1\u0648 \u06af\u06cc\u0627\u06d4<\/p>\n<p>\u0627\u0633\u0679\u0631\u0627\u0626\u067e \u067e\u0648\u0631\u06d2 \u0648\u06cc\u0628 \u06c1\u06a9 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0622\u0632\u0645\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0646\u06d2 \u06a9\u0631\u06cc\u0634 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0627\u06cc\u06a9 \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c \u062f\u06cc\u0627 \u06c1\u06d2\u06d4 \u0627\u0628 \u0635\u0627\u0631\u0641 \u06a9\u0648 \u062f\u0648 \u0627\u06cc \u0645\u06cc\u0644\u0632 \u0645\u0648\u0635\u0648\u0644 \u06c1\u0648\u0626\u06cc \u06c1\u06cc\u06ba \u0644\u06cc\u06a9\u0646 \u0627\u0646 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u062d\u0627\u0635\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u0631 \u0633\u06a9\u062a\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0645\u0636\u0645\u0648\u0646 \u0622\u067e \u06a9\u0648 \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0627\u0633 \u0645\u0633\u0626\u0644\u06d2 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u062d\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4 \u0622\u067e \u0627\u06cc\u06a9 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u0627 \u0637\u0631\u06cc\u0642\u06c1 \u0633\u06cc\u06a9\u06be\u06cc\u06ba \u06af\u06d2 \u062c\u0648 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u06a9\u06cc \u0645\u0646\u0637\u0642 \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 \u0622\u0632\u0645\u0627\u0626\u06d2 \u06af\u0626\u06d2 \u0645\u0631\u0627\u062d\u0644 \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06a9\u0631\u06a9\u06d2 \u0646\u0627\u06a9\u0627\u0645\u06cc \u0633\u06d2 \u0628\u0686 \u062c\u0627\u0626\u06d2\u06d4 \u06cc\u06c1 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0645\u0644\u0679\u06cc \u0633\u0679\u06cc\u067e \u0648\u06cc\u0628 \u06c1\u06a9 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0646\u06c1 \u06a9\u06c1 \u0635\u0631\u0641 \u067e\u0679\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2\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>\u06a9\u06cc\u0648\u06ba \u067e\u0679\u06cc \u0648\u0627\u0644\u06d2 \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u062e\u0627\u0645\u0648\u0634\u06cc \u0633\u06d2 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u06cc\u0633\u06d2 \u0633\u0627\u062f\u06c1 \u0627\u0646 \u0644\u0627\u0626\u0646 \u06c1\u06cc\u0646\u0688\u0644\u0631\u0632 \u062d\u0642\u06cc\u0642\u06cc \u0632\u0646\u062f\u06af\u06cc \u06a9\u06d2 \u062d\u0627\u0644\u0627\u062a \u0645\u06cc\u06ba \u06a9\u0627\u0645 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06d2<\/p>\n<\/li>\n<li>\n<p>\u067e\u06cc\u0679\u0631\u0646: \u0648\u06cc\u0628 \u06c1\u06a9 \u0648\u0635\u0648\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648\u062b\u06cc\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0642\u0637\u0627\u0631\u06cc\u06ba (\u0645\u0632\u06cc\u062f \u0646\u06c1\u06cc\u06ba)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u0646\u0641\u0631\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0634\u0646\u0627\u062e\u062a \u0634\u062f\u06c1 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u062e\u0631\u06cc\u062f\u0627\u0631\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>\u0627\u0633\u06cc \u067e\u06cc\u0679\u0631\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u0627\u0648\u0631 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06cc \u0686\u06be\u0648\u0679 \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>\u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u067e\u0646\u06d2 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<h2 id=\"heading-prerequisites\">\u0634\u0631\u0627\u0626\u0637<\/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>Node.js \u0627\u0648\u0631 TypeScript<\/p>\n<\/li>\n<li>\n<p>\u0645\u0642\u0627\u0645\u06cc \u067e\u0679\u06cc \u0627\u0646\u0636\u0645\u0627\u0645 (\u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u0633\u06cc\u0634\u0646\u060c \u0648\u06cc\u0628 \u06c1\u06a9\u0633)<\/p>\n<\/li>\n<li>\n<p>\u0627\u06cc\u0633 \u06a9\u06cc\u0648 \u0627\u06cc\u0644 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 (\u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0628\u0648\u0646\u062f\u0627 \u0628\u0627\u0646\u062f\u06cc ORM \u06a9\u06d2 \u0633\u0627\u062a\u06be PostgreSQL \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba)<\/p>\n<\/li>\n<li>\n<p>npm \u06cc\u0627 Node.js \u067e\u06cc\u06a9\u06cc\u062c \u0645\u06cc\u0646\u06cc\u062c\u0631<\/p>\n<\/li>\n<\/ul>\n<p>Ingest \u06cc\u0627 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0639\u0645\u0644\u062f\u0631\u0622\u0645\u062f \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 \u0645\u0636\u0645\u0648\u0646 \u0634\u0631\u0648\u0639 \u0633\u06d2 \u062f\u0648\u0646\u0648\u06ba \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-what-you-need-to-install\">\u0622\u067e \u06a9\u0648 \u0627\u0646\u0633\u0679\u0627\u0644\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06cc\u0627 \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\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\">npm install inngest stripe drizzle-orm @react-email\/components resend\n<\/code><\/pre>\n<p>\u0645\u0642\u0627\u0645\u06cc \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0622\u067e \u06a9\u0648 \u0627\u0633\u0679\u0631\u0627\u0626\u067e CLI \u06a9\u06cc \u0628\u06be\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u06d4 \u06c1\u0648\u0645\u0628\u0631\u06cc\u0648 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0645\u06cc\u06a9 \u0627\u0648 \u0627\u06cc\u0633 \u067e\u0631 \u0627\u0646\u0633\u0679\u0627\u0644 \u06a9\u0631\u06cc\u06ba (<code>brew install stripe\/stripe-cli\/stripe<\/code>) \u06cc\u0627 \u062f\u0648\u0633\u0631\u06d2 \u067e\u0644\u06cc\u0679 \u0641\u0627\u0631\u0645\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a \u0645\u06cc\u06ba \u062f\u06cc \u06af\u0626\u06cc \u06c1\u062f\u0627\u06cc\u0627\u062a \u067e\u0631 \u0639\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-table-of-contents\">\u0627\u0646\u0688\u06cc\u06a9\u0633<\/h2>\n<h2 id=\"heading-why-stripe-webhooks-fail-silently\">\u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u062e\u0627\u0645\u0648\u0634\u06cc \u0633\u06d2 \u06a9\u06cc\u0648\u06ba \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/h2>\n<p>\u062e\u0648\u0634\u06cc \u06a9\u0627 \u0631\u0627\u0633\u062a\u06c1 \u0622\u0633\u0627\u0646 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062c\u0628 \u06af\u0627\u06c1\u06a9 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u067e\u0679\u06cc <code>checkout.session.completed<\/code> \u0627\u06cc\u06a9 \u0648\u0627\u0642\u0639\u06c1 \u0633\u0631\u0648\u0631 \u06a9\u0648 \u067e\u06c1\u0646\u0686\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0627\u0633 \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u06c1\u0645\u06cc\u0634\u06c1 \u062a\u0631\u0642\u06cc \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0645\u062e\u062a\u0644\u0641 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u06a9\u0648 \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u06a9\u0626\u06cc \u06a9\u0627\u0645 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u067e\u0646\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u062a\u0644\u0627\u0634 \u06a9\u0631\u06cc\u06ba\u060c \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc\u0648\u06ba \u06a9\u0648 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0631\u06cc\u06ba\u060c \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u06cc \u0645\u06cc\u0644\u0632 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u060c \u0645\u0646\u062a\u0638\u0645\u06cc\u0646 \u06a9\u0648 \u0645\u0637\u0644\u0639 \u06a9\u0631\u06cc\u06ba\u060c \u0645\u0635\u0646\u0648\u0639\u0627\u062a \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u06cc\u06ba (GitHub invites \u06cc\u0627 API \u06a9\u06cc\u0632 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2)\u060c \u0627\u0648\u0631 \u0641\u0627\u0644\u0648 \u0627\u067e \u0627\u06cc \u0645\u06cc\u0644\u0632 \u06a9\u0627 \u0634\u06cc\u0688\u0648\u0644 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 \u06cc\u06c1 5-6 \u06a9\u0627\u0645 \u06c1\u06cc\u06ba \u062c\u0646 \u0645\u06cc\u06ba 3-4 \u0628\u06cc\u0631\u0648\u0646\u06cc \u062e\u062f\u0645\u0627\u062a \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0637\u0631\u06cc\u0642\u06d2 \u062c\u0648 \u0622\u062e\u0631 \u06a9\u0627\u0631 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0645\u06cc\u06ba \u062e\u062a\u0645 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u0648\u06c1 \u06c1\u06cc\u06ba:<\/p>\n<h4 id=\"heading-1-your-server-crashes-mid-processing\">1. \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0633\u0631\u0648\u0631 \u06a9\u0631\u06cc\u0634 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/h4>\n<p>\u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0644\u06a9\u06be\u0646\u0627 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u0631\u06c1\u0627\u060c \u0644\u06cc\u06a9\u0646 \u0627\u06cc \u0645\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u0628\u06be\u06cc\u062c\u06cc \u06af\u0626\u06cc\u06d4 \u062c\u0628 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0648\u06cc\u0628 \u06c1\u06a9 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0622\u0632\u0645\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0627\u0628 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u06cc\u0627 \u062a\u0648 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0627\u0646\u062f\u0631\u0627\u062c \u06c1\u06d2 \u06cc\u0627 \u067e\u06be\u0631 \u0627\u06cc\u06a9 \u0627\u0646\u0648\u06a9\u06be\u06cc \u0631\u06a9\u0627\u0648\u0679 \u06a9\u06cc \u063a\u0644\u0637\u06cc \u06c1\u06d2 \u062c\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0648 \u0631\u0648\u06a9\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-2-an-external-service-is-temporarily-down\">2. \u062c\u0628 \u0627\u06cc\u06a9 \u0628\u06cc\u0631\u0648\u0646\u06cc \u0633\u0631\u0648\u0633 \u0639\u0627\u0631\u0636\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0628\u0646\u062f \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/h4>\n<p>\u0645\u06cc\u0631\u0627 \u0627\u06cc \u0645\u06cc\u0644 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0646\u0646\u062f\u06c1 500 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 GitHub API \u06a9\u0627\u0644 \u06a9\u06cc \u0634\u0631\u062d \u0645\u062d\u062f\u0648\u062f \u06c1\u06d2\u06d4 \u062a\u062c\u0632\u06cc\u06c1 \u0633\u0631\u0648\u0633 \u06a9\u0627 \u0648\u0642\u062a \u062e\u062a\u0645 \u06c1\u0648 \u06af\u06cc\u0627\u06d4<\/p>\n<p>\u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0641\u0627\u0626\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u067e\u0648\u0631\u06cc \u0686\u06cc\u0632 \u06a9\u06cc \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0627\u06c1\u0645\u060c \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u06c1\u06cc \u06a9\u0627\u0645\u06cc\u0627\u0628 \u0627\u0642\u062f\u0627\u0645\u0627\u062a (\u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0644\u06a9\u06be\u0646\u0627\u060c \u067e\u06c1\u0644\u0627 \u0627\u06cc \u0645\u06cc\u0644) \u062f\u0648\u0628\u0627\u0631\u06c1 \u0639\u0645\u0644 \u0645\u06cc\u06ba \u0644\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<h4 id=\"heading-3-the-handler-times-out\">3. \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0679\u0627\u0626\u0645 \u0622\u0624\u0679<\/h4>\n<p>\u0627\u0633\u0679\u0631\u0627\u0626\u067e \u06a9\u0648 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b 20 \u0633\u06cc\u06a9\u0646\u0688 \u0645\u06cc\u06ba 2xx \u062c\u0648\u0627\u0628 \u06a9\u06cc \u062a\u0648\u0642\u0639 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0628\u06c1\u062a \u0632\u06cc\u0627\u062f\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0627\u0633\u06d2 \u0646\u0627\u06a9\u0627\u0645 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0646\u0634\u0627\u0646 \u0632\u062f \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0648\u0642\u062a \u062e\u062a\u0645 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u062c\u0632\u0648\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u06a9\u0645\u0644 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-4-partial-completion-with-no-rollback\">4. \u0631\u0648\u0644 \u0628\u06cc\u06a9 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u062c\u0632\u0648\u06cc \u062a\u06a9\u0645\u06cc\u0644<\/h4>\n<p>\u06cc\u06c1 \u0628\u062f\u062a\u0631\u06cc\u0646 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u0627 \u0645\u0648\u0688 \u06c1\u06d2\u06d4 \u0645\u0631\u062d\u0644\u06c1 1-3 \u06a9\u0627\u0645\u06cc\u0627\u0628\u06d4 \u0645\u0631\u062d\u0644\u06c1 4 \u0646\u0627\u06a9\u0627\u0645\u06d4 \u067e\u0679\u06cc \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0622\u0632\u0645\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0642\u062f\u0627\u0645\u0627\u062a 1-3 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0639\u0645\u0644 \u0645\u06cc\u06ba \u0644\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u062f\u0648 \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u06cc \u0645\u06cc\u0644\u0632 \u0645\u0648\u0635\u0648\u0644 \u06c1\u0648\u06ba \u06af\u06cc\u06d4 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u0645\u0648\u062c\u0648\u062f \u06c1\u06cc\u06ba\u06d4 \u062a\u0627\u06c1\u0645\u060c \u0645\u0631\u062d\u0644\u06c1 4 \u0627\u0628 \u0628\u06be\u06cc \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0645\u0633\u0626\u0644\u06c1 (\u0631\u06cc\u0679 \u0645\u062d\u062f\u0648\u062f \u06a9\u0631\u0646\u0627\u060c \u0633\u0631\u0648\u0633 \u06a9\u06cc \u0628\u0646\u062f\u0634) \u06a9\u0648 \u062d\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-5-race-conditions-on-retry\">5. \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u067e\u0631 \u0631\u06cc\u0633 \u06a9\u06d2 \u062d\u0627\u0644\u0627\u062a<\/h4>\n<p>\u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0622\u067e \u06a9\u06cc \u0637\u0631\u0641 \u0633\u06d2 \u063a\u0644\u0637\u06cc \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u06cc\u0648\u0646\u0679 \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0628\u0627\u0631 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u06cc \u062e\u0631\u0627\u0628\u06cc\u0627\u06ba\u060c \u0644\u0648\u0688 \u0628\u06cc\u0644\u0646\u0633 \u06a9\u0627 \u0679\u0627\u0626\u0645 \u0622\u0624\u0679\u060c \u0627\u0648\u0631 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u06a9\u06cc \u0627\u067e\u0646\u06cc \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u06cc \u0645\u0646\u0637\u0642 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u06c1\u06cc\u0646\u0688\u0644\u0631\u0632 \u06a9\u0648 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0688\u06cc\u0644\u06cc\u0648\u0631\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 \u0631\u06c1\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u0627\u06af\u0631 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u062a\u0645\u0627\u0645 \u0645\u0631\u0627\u062d\u0644 \u0645\u06cc\u06ba \u0642\u0627\u0628\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u062a\u0648\u060c \u0646\u0642\u0644 \u062c\u0632\u0648\u06cc \u062a\u06a9\u0645\u06cc\u0644 \u06a9\u06d2 \u0645\u0633\u0626\u0644\u06d2 \u06a9\u0648 \u0645\u0632\u06cc\u062f \u067e\u06cc\u0686\u06cc\u062f\u06c1 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633\u0679\u0631\u0627\u0626\u067e \u06a9\u0627 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0637\u0631\u0632 \u0639\u0645\u0644 \u0627\u0686\u06be\u06cc \u0637\u0631\u062d \u0633\u06d2 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9\u0633\u067e\u0648\u0646\u06cc\u0646\u0634\u0644 \u0628\u06cc\u06a9 \u0622\u0641 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06a9\u0626\u06cc \u062f\u0646\u0648\u06ba \u0645\u06cc\u06ba \u062f\u0631\u062c\u0646\u0648\u06ba \u0628\u0627\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0644\u06cc\u06a9\u0646 \u067e\u0679\u06cc <em>\u0645\u06a9\u0645\u0644 \u0648\u06cc\u0628 \u06c1\u06a9 \u06a9\u06cc \u062a\u0631\u0633\u06cc\u0644<\/em>.<\/p>\n<p>\u06c1\u0645 \u0646\u06c1\u06cc\u06ba \u062c\u0627\u0646\u062a\u06d2 \u06a9\u06c1 \u0622\u06cc\u0627 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0646\u06d2 1-3 \u06a9\u06d2 \u0645\u0631\u0627\u062d\u0644 \u0645\u06a9\u0645\u0644 \u06a9\u0631 \u0644\u06cc\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0635\u0631\u0641 \u0645\u0631\u062d\u0644\u06c1 4 \u067e\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0641\u0631\u0642 \u06a9\u0631\u0646\u0627 \u0622\u067e \u06a9\u06cc \u0630\u0645\u06c1 \u062f\u0627\u0631\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0628\u0646\u06cc\u0627\u062f\u06cc \u0645\u0633\u0626\u0644\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0627\u06cc\u06a9 \u06c1\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0645\u06cc\u06ba \u0628\u06c1\u062a \u0632\u06cc\u0627\u062f\u06c1 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u0628\u06cc\u0631\u0648\u0646\u06cc \u06a9\u0627\u0644 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u0627 \u0627\u06cc\u06a9 \u0645\u0645\u06a9\u0646\u06c1 \u0646\u0642\u0637\u06c1 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0646 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u06a9\u0648\u0626\u06cc \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u0627\u0633 \u0628\u0627\u062a \u06a9\u0627 \u0633\u0631\u0627\u063a \u0646\u06c1\u06cc\u06ba \u0644\u06af\u0627 \u0633\u06a9\u062a\u06d2 \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648 \u0686\u06a9\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-the-naive-approach-and-why-it-breaks\">\u0628\u0648\u0644\u06cc \u0627\u067e\u0631\u0648\u0686 (\u0627\u0648\u0631 \u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2)<\/h2>\n<p>\u0627\u06cc\u06a9 \u0639\u0627\u0645 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0627\u0633 \u0637\u0631\u062d \u0646\u0638\u0631 \u0622\u062a\u0627 \u06c1\u06d2: \u0645\u06cc\u06ba \u0646\u06d2 \u06a9\u0648\u0688 \u0628\u06cc\u0633\u0632\u060c \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644\u0632\u060c \u0627\u0648\u0631 \u0627\u0633\u0679\u06cc\u06a9 \u0627\u0648\u0648\u0631 \u0641\u0644\u0648 \u062c\u0648\u0627\u0628\u0627\u062a \u0645\u06cc\u06ba \u0627\u0633 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u06d2 \u0633\u06cc\u0646\u06a9\u0691\u0648\u06ba \u062a\u063a\u06cc\u0631\u0627\u062a \u062f\u06cc\u06a9\u06be\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">app.post(\"\/api\/payments\/webhook\", async (req, res) => {\n  const event = stripe.webhooks.constructEvent(\n    req.body,\n    req.headers[\"stripe-signature\"],\n    process.env.STRIPE_WEBHOOK_SECRET\n  );\n\n  if (event.type === \"checkout.session.completed\") {\n    const session = event.data.object;\n\n    \/\/ Step 1: Look up the user\n    const user = await db.users.findOne({ id: session.metadata.userId });\n\n    \/\/ Step 2: Record the purchase\n    await db.purchases.insert({\n      userId: user.id,\n      stripeSessionId: session.id,\n      amount: session.amount_total,\n      status: \"completed\",\n    });\n\n    \/\/ Step 3: Send confirmation email\n    await sendEmail({\n      to: user.email,\n      subject: \"Purchase confirmed!\",\n      template: \"purchase-confirmation\",\n    });\n\n    \/\/ Step 4: Grant product access (GitHub repo invitation)\n    await addCollaborator(user.githubUsername);\n\n    \/\/ Step 5: Send access email\n    await sendEmail({\n      to: user.email,\n      subject: \"Your repository access is ready!\",\n      template: \"repo-access\",\n    });\n\n    \/\/ Step 6: Track analytics\n    await analytics.track(user.id, \"purchase_completed\", {\n      amount: session.amount_total,\n    });\n  }\n\n  res.json({ received: true });\n});\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0635\u0627\u0641 \u0646\u0638\u0631 \u0622\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0648\u067e\u0631 \u0633\u06d2 \u0646\u06cc\u0686\u06d2 \u062a\u06a9 \u067e\u0691\u06be\u06cc\u06ba\u06d4 \u062a\u0645\u0627\u0645 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644\u0632 \u06cc\u06c1 \u0633\u06a9\u06be\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0628 \u062f\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0627\u06af\u0631 \u0645\u0631\u062d\u0644\u06c1 4 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u06a9\u06cc\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0634\u0627\u06cc\u062f GitHub \u06a9\u0627 API \u0631\u0641\u062a\u0627\u0631 \u0645\u062d\u062f\u0648\u062f \u06c1\u06d2 \u0627\u0648\u0631 <code>addCollaborator<\/code> \u062c\u0628 \u0645\u06cc\u06ba \u0627\u0633\u06d2 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u0648\u06ba \u062a\u0648 \u0645\u062c\u06be\u06d2 \u0627\u06cc\u06a9 \u063a\u0644\u0637\u06cc \u06c1\u0648\u062a\u06cc \u06c1\u06d2: \u06c1\u06cc\u0646\u0688\u0644\u0631 500 \u06a9\u0648 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u067e\u0631 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u06cc\u06c1 \u06c1\u06d2:<\/p>\n<ul>\n<li>\n<p>\u0635\u0627\u0631\u0641 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2 (\u0645\u0631\u062d\u0644\u06c1 1 \u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 \u0633\u0648\u0627\u0644 \u062a\u06be\u0627\u060c \u0644\u06c1\u0630\u0627 \u06a9\u0648\u0626\u06cc \u0645\u0633\u0626\u0644\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0627 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u0628\u0646\u0627\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 (\u0645\u0631\u062d\u0644\u06c1 2 \u06a9\u0627\u0645\u06cc\u0627\u0628)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06cc\u06a9 \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 (\u0645\u0631\u062d\u0644\u06c1 3 \u06a9\u0627\u0645\u06cc\u0627\u0628)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u067e\u0686\u06be\u0644\u06cc GitHub \u0631\u0633\u0627\u0626\u06cc \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a\u0648\u06ba \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba: <strong>~ \u0646\u06c1\u06cc\u06ba<\/strong> \u0645\u0646\u0638\u0648\u0631 \u0634\u062f\u06c1 (\u0645\u0631\u062d\u0644\u06c1 4 \u0646\u0627\u06a9\u0627\u0645)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0622\u067e \u06a9\u06cc \u0631\u0633\u0627\u0626\u06cc \u06a9\u0627 \u0627\u06cc \u0645\u06cc\u0644 \u06cc\u06c1 \u06c1\u06d2: <strong>~ \u0646\u06c1\u06cc\u06ba<\/strong> \u0628\u06be\u06cc\u062c\u0627 \u06af\u06cc\u0627 (\u0645\u0631\u062d\u0644\u06c1 5 \u067e\u0631 \u0639\u0645\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0627)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u062a\u062c\u0632\u06cc\u06c1 \u06c1\u06d2\u06d4 <strong>~ \u0646\u06c1\u06cc\u06ba<\/strong> \u0679\u0631\u06cc\u06a9 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 (\u0645\u0631\u062d\u0644\u06c1 6 \u0646\u0627\u0641\u0630 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0627)\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0648\u06cc\u0628 \u06c1\u06a9 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0622\u0632\u0645\u0627\u0626\u06d2 \u06af\u0627\u06d4 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0627\u0648\u067e\u0631 \u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<ul>\n<li>\n<p>\u0645\u0631\u062d\u0644\u06c1 1: \u0635\u0627\u0631\u0641 \u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u0631\u06cc\u06ba\u06d4 \u0679\u06be\u06cc\u06a9 \u06c1\u06d2<\/p>\n<\/li>\n<li>\n<p>\u0645\u0631\u062d\u0644\u06c1 2: \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0627 \u062f\u0648\u0633\u0631\u0627 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u062f\u0627\u062e\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u0627\u0646\u0648\u06a9\u06be\u06cc \u0631\u06a9\u0627\u0648\u0679\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 <code>stripeSessionId<\/code>\u0645\u06cc\u06ba \u06cc\u06c1 \u067e\u06be\u06cc\u0646\u06a9 \u0631\u06c1\u0627 \u06c1\u0648\u06ba\u06d4 \u0627\u06af\u0631 \u0646\u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0627\u0628 \u0627\u06cc\u06a9 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0645\u0631\u062d\u0644\u06c1 3: \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4 \u06af\u0627\u06c1\u06a9 \u062f\u0648\u0633\u0631\u0627 \u06a9\u0644\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 &quot;\u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u06cc\u06ba!&#8221; \u0622\u067e \u06a9\u0648 \u067e\u06cc\u063a\u0627\u0645 \u0645\u0648\u0635\u0648\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc \u0645\u06cc\u0644<\/p>\n<\/li>\n<li>\n<p>\u0645\u0631\u062d\u0644\u06c1 4: GitHub \u062a\u06a9 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0631\u0633\u0627\u0626\u06cc \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u0633 \u0628\u0627\u0631 \u06cc\u06c1 \u06a9\u0627\u0645 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u06cc\u0627 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0645\u0631\u062d\u0644\u06c1 5-6: \u0645\u0631\u062d\u0644\u06c1 4 \u067e\u0631 \u0645\u0646\u062d\u0635\u0631 \u06c1\u06d2\u060c \u06cc\u06c1 \u0686\u0644 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u06cc\u0627 \u0646\u06c1\u06cc\u06ba \u0686\u0644 \u0633\u06a9\u062a\u0627\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0622\u067e \u0627\u0633\u06d2 \u0622\u0626\u06cc\u0688\u06cc\u0645\u067e\u0648\u0679\u06cc\u0646\u0633\u06cc \u0686\u06cc\u06a9 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u067e\u06cc\u0686 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 &quot;\u0627\u06af\u0631 \u0622\u067e \u06a9\u06cc \u062e\u0631\u06cc\u062f\u06cc \u06c1\u0648\u0626\u06cc \u0686\u06cc\u0632 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2 \u062a\u0648 \u0645\u0631\u062d\u0644\u06c1 2 \u06a9\u0648 \u0686\u06be\u0648\u0691 \u062f\u06cc\u06ba\u06d4&#8221; \u0644\u06cc\u06a9\u0646 \u0627\u0628 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u06c1\u0631 \u0642\u062f\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0634\u0631\u0648\u0637 \u0645\u0646\u0637\u0642 \u0633\u06d2 \u0628\u06be\u0631\u0627 \u06c1\u0648\u0627 \u06c1\u06d2\u06d4 \u0627\u0648\u0631 \u0645\u06cc\u0631\u06d2 \u067e\u0627\u0633 \u0627\u0628 \u0628\u06be\u06cc \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u0627 \u0645\u0633\u0626\u0644\u06c1 \u06c1\u06d2\u06d4 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0686\u06cc\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u06a9\u0648\u0626\u06cc \u0637\u0631\u06cc\u0642\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 &quot;\u06a9\u06cc\u0627 \u0645\u06cc\u06ba \u0646\u06d2 \u06cc\u06c1 \u0627\u06cc \u0645\u06cc\u0644 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0628\u06be\u06cc\u062c \u062f\u06cc\u0627 \u06c1\u06d2\u061f&#8221; \u0627\u067e\u0646\u0627 \u0679\u0631\u06cc\u06a9\u0646\u06af \u0633\u0633\u0679\u0645 \u0628\u0646\u0627\u0626\u06d2 \u0628\u063a\u06cc\u0631\u06d4<\/p>\n<p>\u06cc\u06c1 \u0646\u0642\u0637\u06c1 \u0646\u0638\u0631 \u067e\u06cc\u0645\u0627\u0646\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06c1\u0631 \u0646\u0626\u06d2 \u0642\u062f\u0645 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0627\u0648\u0631 \u0646\u0627\u06a9\u0627\u0645\u06cc \u0645\u0648\u0688\u060c \u0627\u06cc\u06a9 \u0627\u0648\u0631 \u0622\u0626\u06cc\u0688\u06cc\u0645\u067e\u0648\u0679\u06cc\u0646\u0633\u06cc \u0686\u06cc\u06a9\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0627\u0648\u0631 \u0627\u06cc\u062c \u06a9\u06cc\u0633 \u0634\u0627\u0645\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-the-pattern-webhook-to-event-to-durable-function\">\u067e\u06cc\u0679\u0631\u0646\u0632: \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u0633\u06d2 \u0644\u06d2 \u06a9\u0631 \u0648\u0627\u0642\u0639\u0627\u062a \u062a\u06a9 \u0645\u0633\u062a\u0642\u0644 \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u062a\u06a9<\/h2>\n<p>\u062d\u0644 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u062e\u062f\u0634\u0627\u062a \u06a9\u0648 \u0627\u0644\u06af \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4 \u0627\u06cc\u06a9 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u06a9\u0648 \u0628\u0627\u0644\u06a9\u0644 \u0627\u06cc\u06a9 \u06a9\u0627\u0645 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2: \u0622\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u06d2 \u0644\u0626\u06d2 \u0627\u0646 \u06a9\u06cc \u0642\u0637\u0627\u0631 \u0644\u06af\u0627\u0626\u06cc\u06ba\u06d4 \u0627\u0648\u0631 \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>\u062a\u0645\u0627\u0645 \u0627\u0635\u0644 \u06a9\u0627\u0645 (\u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0631\u0627\u0626\u0679\u060c \u0627\u06cc \u0645\u06cc\u0644\u0632\u060c API \u06a9\u0627\u0644\u0632\u060c \u0627\u06cc\u0646\u0627\u0644\u06cc\u0679\u06a9\u0633) \u06a9\u0648 \u0627\u06cc\u06a9 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u0641\u0646\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u06c1\u0631 \u0642\u062f\u0645 \u06a9\u0627 \u0627\u0646\u0641\u0631\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u0639\u0627\u0626\u0646\u06c1\u060c \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u0627\u0648\u0631 \u0679\u0631\u06cc\u06a9 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0628\u06c1\u0627\u0624 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-text\">Stripe webhook\n    |\n    v\nWebhook endpoint (validate signature, extract event, enqueue)\n    |\n    v\nBackground job system (receives event)\n    |\n    v\nDurable function\n    |-- Step 1: Look up user and purchase (checkpointed)\n    |-- Step 2: Track analytics (checkpointed)\n    |-- Step 3: Send confirmation email (checkpointed)\n    |-- Step 4: Send admin notification (checkpointed)\n    |-- Step 5: Grant GitHub access (checkpointed)\n    |-- Step 6: Track GitHub access (checkpointed)\n    |-- Step 7: Update purchase record (checkpointed)\n    |-- Step 8: Send repo access email (checkpointed)\n    |-- Step 9: Schedule follow-up sequence (checkpointed)\n<\/code><\/pre>\n<p>\u06c1\u0631 \u0642\u062f\u0645 \u06a9\u0627 \u0627\u062d\u0627\u0637\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 <code>step.run()<\/code> \u06cc\u06c1 \u0627\u06cc\u06a9 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0686\u0648\u06a9\u06cc \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:<\/p>\n<ul>\n<li>\n<p>\u0627\u0633 \u0637\u0631\u062d \u06a9\u06d2 \u0627\u0642\u062f\u0627\u0645\u0627\u062a 1 \u0633\u06d2 4 \u067e\u0631 \u0639\u0645\u0644 \u06a9\u0631\u06cc\u06ba: <strong>~ \u0646\u06c1\u06cc\u06ba<\/strong> \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4 \u0646\u062a\u0627\u0626\u062c \u0645\u062d\u0641\u0648\u0638 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0645\u0631\u062d\u0644\u06c1 5 \u0627\u067e\u0646\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u0627\u0624\u0646\u0679\u0631 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06af\u0631 \u0645\u0631\u062d\u0644\u06c1 5 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062a\u0648\u060c 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<\/li>\n<\/ul>\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 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u0628\u06be\u06cc \u0641\u0639\u0627\u0644\u06cc\u062a \u0645\u06cc\u06ba \u067e\u06cc\u0634 \u0631\u0641\u062a \u0628\u0631\u0642\u0631\u0627\u0631 \u06c1\u06d2\u06d4 \u0641\u0646\u06a9\u0634\u0646 \u0644\u06cc\u0648\u0644 \u06a9\u06cc \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634\u0648\u06ba \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0645\u0631\u062d\u0644\u06c1 \u0648\u0627\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634\u06cc\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u06a9\u0648\u0626\u06cc \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0627\u06cc \u0645\u06cc\u0644\u0632 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u06a9\u0648\u0626\u06cc \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0631\u0627\u0626\u0679 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u06cc \u062c\u0632\u0648\u06cc \u062a\u06a9\u0645\u06cc\u0644 \u0646\u06c1\u06cc\u06ba\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 \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 \u06a9\u0627 \u067e\u0644\u06cc\u0679 \u0641\u0627\u0631\u0645 \u062c\u0648 \u0628\u0627\u06a9\u0633 \u0633\u06d2 \u0628\u0627\u06c1\u0631 \u0627\u0633\u0679\u06cc\u062c \u0644\u06cc\u0648\u0644 \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679\u0646\u06af \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 \u06a9\u0648\u0626\u06cc Redis\u060c \u06a9\u0648\u0626\u06cc \u06a9\u0627\u0631\u06a9\u0646 \u0639\u0645\u0644 \u0646\u06c1\u06cc\u06ba\u060c \u06a9\u0648\u0626\u06cc \u062d\u0633\u0628 \u0636\u0631\u0648\u0631\u062a \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0627 \u06a9\u0648\u0688 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u062f\u0648\u0633\u0631\u06d2 \u0679\u0648\u0644\u0632 \u0628\u06be\u06cc \u0627\u0633\u06cc \u0637\u0631\u062d \u06a9\u06d2 \u0646\u062a\u0627\u0626\u062c \u062d\u0627\u0635\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba (\u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0639\u0627\u0631\u0636\u06cc)\u060c \u0644\u06cc\u06a9\u0646 Ingest \u06a9\u06d2 \u0688\u0648\u06cc\u0644\u067e\u0631 \u06a9\u06d2 TypeScript \u06a9\u06d2 \u062a\u062c\u0631\u0628\u06d2 \u0646\u06d2 \u0645\u062c\u06be\u06d2 \u0627\u067e\u0646\u06cc \u0637\u0631\u0641 \u0645\u062a\u0648\u062c\u06c1 \u06a9\u06cc\u0627\u06d4 \u0639\u0627\u0645 \u063a\u06cc\u0631 \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u0627\u0641\u0639\u0627\u0644 \u0644\u06a9\u06be\u06cc\u06ba\u06d4 \u06a9\u06c1 <code>step.run()<\/code> \u0686\u0627\u062f\u0631 \u0648\u0627\u062d\u062f \u0627\u0636\u0627\u0641\u06c1 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-how-to-set-up-the-webhook-endpoint\">\u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u06cc\u0633\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/h2>\n<p>\u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679\u0633 \u06a9\u0645 \u0633\u06d2 \u06a9\u0645 \u06c1\u0648\u0646\u06d2 \u0686\u0627\u06c1\u0626\u06cc\u06ba\u06d4 \u06cc\u06c1 \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u06cc\u0648\u0646\u0679 \u06a9\u0627 \u0688\u06cc\u0679\u0627 \u0646\u06a9\u0627\u0644\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0633\u06d2 \u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u0679\u0627\u0633\u06a9 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u0628\u06be\u06cc\u062c\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 200 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0645\u06cc\u0631\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u06a9\u0648\u0688 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u0648\u06cc\u0628 \u06c1\u06a9 \u06a9\u0627 \u0627\u0635\u0644 \u0646\u0642\u0637\u06c1 \u06cc\u06c1 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-typescript\">import { constructWebhookEvent } from \"@\/lib\/payments\";\nimport { inngest } from \"@\/lib\/jobs\";\n\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;\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;\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>\u0646\u0648\u0679\u0633 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u06cc\u06c1 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u06a9\u06cc\u0627 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <strong>~ \u0646\u06c1\u06cc\u06ba<\/strong> \u06a9\u06cc\u0627 \u06a9\u0631\u06cc\u06ba: \u0635\u0627\u0631\u0641\u06cc\u0646 \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u060c \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u067e\u0631 \u0646\u06c1 \u0644\u06a9\u06be\u06cc\u06ba\u060c \u0627\u06cc \u0645\u06cc\u0644\u0632 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u060c \u06cc\u0627 \u0628\u06cc\u0631\u0648\u0646\u06cc APIs \u06a9\u0648 \u06a9\u0627\u0644 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4 \u067e\u0679\u06cc \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u0645\u062a\u0639\u0644\u0642\u06c1 \u0641\u06cc\u0644\u0688\u0632 \u06a9\u0648 \u0646\u06a9\u0627\u0644\u062a\u06cc \u06c1\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\u062a\u06cc \u06c1\u06d2\u06d4 \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>\u06a9\u06c1 <code>constructWebhookEvent<\/code> \u0641\u0646\u06a9\u0634\u0646 \u067e\u0679\u06cc \u06a9\u06d2 \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0648 \u0644\u067e\u06cc\u0679\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">import Stripe from \"stripe\";\n\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 = new Stripe(process.env.STRIPE_SECRET_KEY);\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: <strong>\u062e\u0627\u0645 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u062c\u0633\u0645<\/strong> (\u0633\u0679\u0631\u0646\u06af \u06cc\u0627 \u0628\u0641\u0631 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631) \u067e\u0679\u06cc \u0645\u06cc\u06ba \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0641\u0631\u06cc\u0645 \u0648\u0631\u06a9 \u062e\u0627\u0645 \u0633\u0679\u0631\u0646\u06af \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \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 \u06cc\u06c1 &quot;\u0648\u06cc\u0628 \u06c1\u06a9 \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642 \u0645\u06cc\u06ba \u0646\u0627\u06a9\u0627\u0645\u06cc&#8221; \u06a9\u06cc \u062e\u0631\u0627\u0628\u06cc \u06a9\u06cc \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0645\u06a9\u0646\u06c1 \u0648\u062c\u06c1 \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\">import { Inngest } from \"inngest\";\n\nexport const inngest = new Inngest({\n  id: \"my-app\",\n});\n<\/code><\/pre>\n<p>\u062e\u0627\u0635 \u0637\u0648\u0631 \u067e\u0631 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u062f\u0648\u0633\u0631\u06d2 \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679\u0633 \u0627\u06cc\u0648\u0646\u0679\u0633 \u0628\u06be\u06cc\u062c\u062a\u06d2 \u06c1\u06cc\u06ba (&quot;\u0628\u0644\u0646\u06af&#8221; \u06a9\u0627 \u0631\u0627\u0633\u062a\u06c1 \u062c\u0633\u06d2 \u0641\u0631\u0646\u0679 \u0627\u06cc\u0646\u0688 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u06af\u0627\u06c1\u06a9 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u0633\u06d2 \u0648\u0627\u067e\u0633 \u0622\u062a\u0627 \u06c1\u06d2)\u06d4 \u0644\u06cc\u06a9\u0646 \u0627\u0635\u0648\u0644 \u0648\u06c1\u06cc \u06c1\u06cc\u06ba\u06d4 \u062a\u0648\u062b\u06cc\u0642\u060c \u0642\u0637\u0627\u0631\u060c \u0648\u0627\u067e\u0633\u06cc.<\/p>\n<pre><code class=\"language-typescript\">\/\/ After verifying payment status with Stripe\nawait inngest.send({\n  name: \"purchase\/completed\",\n  data: {\n    userId: session.user.id,\n    tier,\n    sessionId,\n  },\n});\n<\/code><\/pre>\n<h2 id=\"heading-how-to-build-a-durable-purchase-flow\">\u0627\u06cc\u06a9 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/h2>\n<p>\u06cc\u06c1 \u0645\u0636\u0645\u0648\u0646 \u06a9\u0627 \u0646\u0642\u0637\u06c1 \u06c1\u06d2\u06d4 \u06a9\u06c1 <code>handlePurchaseCompleted<\/code> \u06cc\u06c1 \u062e\u0635\u0648\u0635\u06cc\u062a \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0628\u0639\u062f 9 \u0627\u0646\u0641\u0631\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0686\u06cc\u06a9 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u0645\u0631\u0627\u062d\u0644 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0622\u067e \u06a9\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u062a\u0645\u0627\u0645 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0627\u0635\u0644 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u06a9\u0648\u0688 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0630\u06cc\u0644 \u06a9\u06cc \u0645\u062b\u0627\u0644 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u0627\u06cc\u06a9 \u0646\u062c\u06cc GitHub \u0630\u062e\u06cc\u0631\u06c1 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0648\u06c1\u06cc \u0686\u06cc\u0632 \u06c1\u06d2 \u062c\u0633\u06d2 \u06c1\u0645 \u0641\u0631\u0648\u062e\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u067e\u0631\u0648\u0688\u06a9\u0679 \u06a9\u06d2 \u0644\u06cc\u06d2 &quot;\u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u06d2&#8221; \u06a9\u06d2 \u0645\u0631\u0627\u062d\u0644 \u0645\u062e\u062a\u0644\u0641 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba: \u0635\u0627\u0631\u0641 \u06a9\u0648 \u067e\u0631\u0648 \u0645\u0645\u0628\u0631\u0634\u067e \u0645\u06cc\u06ba \u0627\u067e \u06af\u0631\u06cc\u0688 \u06a9\u0631\u0646\u0627\u060c API \u06a9\u0631\u06cc\u0688\u0679\u0633 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u0627\u060c \u06a9\u0648\u0631\u0633 \u06a9\u0648 \u063a\u06cc\u0631 \u0645\u0642\u0641\u0644 \u06a9\u0631\u0646\u0627\u060c \u0633\u0628\u0633\u06a9\u0631\u067e\u0634\u0646 \u06a9\u0648 \u0686\u0627\u0644\u0648 \u06a9\u0631\u0646\u0627 \u0648\u063a\u06cc\u0631\u06c1\u06d4 \u0627\u06cc\u06a9 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0642\u062f\u0645 \u06a9\u0627 \u0646\u0645\u0648\u0646\u06c1 \u0627\u06cc\u06a9 \u062c\u06cc\u0633\u0627 \u06c1\u06cc \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0642\u0637\u0639 \u0646\u0638\u0631 \u0627\u0633 \u06a9\u06d2 \u06a9\u06c1 \u0622\u067e \u062c\u0648 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0645\u0631\u062d\u0644\u06c1 5 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 (\u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631\u060c \u0627\u06af\u0631 \u0622\u067e \u06a9\u0627 \u0627\u06cc \u0645\u06cc\u0644 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0646\u0646\u062f\u06c1 \u0628\u0646\u062f \u06c1\u06d2)\u060c Ingest \u0635\u0631\u0641 \u0645\u0631\u062d\u0644\u06c1 5 \u06a9\u06cc \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u06d2 \u06af\u0627\u06d4 \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 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0648\u06c1 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u0631 \u0686\u06a9\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0645\u0631\u062d\u0644\u06c1 6 \u0633\u06d2 9 \u062a\u06a9\u060c \u0645\u0631\u062d\u0644\u06c1 5 \u06a9\u06d2 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648\u0646\u06d2 \u062a\u06a9 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">import { eq } from \"drizzle-orm\";\nimport { createElement } from \"react\";\n\nimport { inngest } from \"@\/lib\/jobs\/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;\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 completion in analytics\n    await step.run(\"track-purchase-to-posthog\", async () => {\n      await trackServerEvent(userId, \"purchase_completed_server\", {\n        tier,\n        amount_cents: purchase.amount,\n        currency: purchase.currency,\n        stripe_session_id: sessionId,\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 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 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      await sendEmail({\n        to: user.email,\n        subject: `Your repository access is ready!`,\n        template: createElement(RepoAccessGrantedEmail, {\n          repoUrl: \"https:\/\/github.com\/your-org\/your-repo\",\n        }),\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 \u0645\u06cc\u06ba \u06c1\u0631 \u0642\u062f\u0645 \u0633\u06d2 \u06af\u0632\u0631\u0648\u06ba \u06af\u0627 \u0627\u0648\u0631 \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u0648\u06ba \u06af\u0627 \u06a9\u06c1 \u0648\u06c1 \u0627\u0644\u06af \u0627\u0644\u06af \u0686\u0648\u06a9\u06cc\u0627\u06ba \u06a9\u06cc\u0648\u06ba \u06c1\u06cc\u06ba\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 ...\n    return { user: foundUser, purchase: foundPurchase };\n  }\n);\n<\/code><\/pre>\n<p>\u0627\u0633 \u0645\u0631\u062d\u0644\u06d2 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u0635\u0627\u0631\u0641 \u0627\u0648\u0631 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06d2 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \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\u060c \u062a\u0648 \u06cc\u06c1 \u0645\u0631\u062d\u0644\u06c1 \u062e\u0648\u062f \u06c1\u06cc \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0648\u0627\u067e\u0633\u06cc \u06a9\u06cc \u0642\u06cc\u0645\u062a (<code>user<\/code> \u0627\u0648\u0631 <code>purchase<\/code>) Ingest \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u06a9\u06cc\u0634 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0645\u0627\u0645 \u0628\u0639\u062f \u06a9\u06d2 \u0645\u0631\u0627\u062d\u0644 \u0645\u06cc\u06ba \u0622\u067e \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba: <code>user.email<\/code>, <code>user.githubUsername<\/code>\u0627\u0648\u0631 <code>purchase.amount<\/code> \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u06cc\u06c1 \u0645\u0631\u062d\u0644\u06c1 \u0645\u0633\u062a\u0642\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 (\u0635\u0627\u0631\u0641 \u0645\u0648\u062c\u0648\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2)\u060c \u0627\u06cc\u06a9 \u062e\u0631\u0627\u0628\u06cc \u0648\u0627\u0642\u0639 \u06c1\u0648 \u06af\u06cc \u062c\u0648 \u067e\u0648\u0631\u06cc \u0641\u0639\u0627\u0644\u06cc\u062a \u06a9\u0648 \u0631\u0648\u06a9 \u062f\u06d2 \u06af\u06cc\u06d4 \u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06c1\u06d2\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  await trackServerEvent(userId, \"purchase_completed_server\", {\n    tier,\n    amount_cents: purchase.amount,\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 (\u0631\u06cc\u0679 \u0645\u062d\u062f\u0648\u062f \u06a9\u0631\u0646\u0627\u060c \u0628\u0646\u062f\u0634\u060c \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u0679\u0627\u0626\u0645 \u0622\u0624\u0679)\u060c \u062a\u062c\u0632\u06cc\u0627\u062a \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u0646\u0627 \u0627\u06cc\u06a9 \u0627\u0644\u06af \u0645\u0631\u062d\u0644\u06c1 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 PostHog \u0628\u0646\u062f \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u0627\u067e\u0646\u06cc \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u06cc \u0645\u06cc\u0644\u0632 \u06a9\u0648 \u0645\u0633\u062f\u0648\u062f \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2\u06d4<\/p>\n<p>\u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u06a9\u0648\u0688 \u0645\u06cc\u06ba\u060c \u06cc\u06c1 \u0645\u0631\u062d\u0644\u06c1 \u06a9\u0627\u0644 \u06a9\u0648 \u0679\u0631\u06cc\u0633 \u06a9\u06cc\u0686 \u0645\u06cc\u06ba \u0644\u067e\u06cc\u0679\u062a\u0627 \u06c1\u06d2 \u062a\u0627\u06a9\u06c1 \u0679\u0631\u06cc\u0633 \u06a9\u06cc \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u0648 \u067e\u0648\u0631\u06d2 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u0679\u0648\u0679\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9\u0627 \u062c\u0627 \u0633\u06a9\u06d2\u06d4 \u062a\u062c\u0632\u06cc\u06d2 \u06a9\u06d2 \u0648\u0627\u0642\u0639\u0627\u062a \u063a\u06cc\u0631 \u0627\u06c1\u0645 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0648\u0627\u0642\u0639\u0627\u062a &quot;\u0627\u0686\u06be\u06d2 \u06c1\u06cc\u06ba&#8221;\u06d4<\/p>\n<h3 id=\"heading-step-3-send-purchase-confirmation-email\">\u0645\u0631\u062d\u0644\u06c1 3: \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4<\/h3>\n<pre><code class=\"language-typescript\">await step.run(\"send-purchase-confirmation\", async () => {\n  await sendEmail({\n    to: user.email,\n    subject: `Your 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>\u06cc\u06c1 \u0648\u06c1\u06cc \u06c1\u06d2 \u062c\u0648 \u06c1\u0645 \u0627\u067e\u0646\u06d2 \u06af\u0627\u06c1\u06a9\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba. \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0622\u0632\u0627\u062f \u06a9\u0627\u0645 \u06c1\u06d2\u060c \u06cc\u06c1 \u0627\u06cc\u0688\u0645\u0646 \u06a9\u06cc \u0627\u0637\u0644\u0627\u0639 (\u0645\u0631\u062d\u0644\u06c1 4) \u0633\u06d2 \u0627\u0644\u06af \u0645\u0631\u062d\u0644\u06c1 \u06c1\u06d2\u06d4 \u06cc\u06c1\u0627\u06ba \u062a\u06a9 \u06a9\u06c1 \u0627\u06af\u0631 \u0627\u06cc\u0688\u0645\u0646\u0633\u0679\u0631\u06cc\u0679\u0631 \u06a9\u0627 \u0627\u06cc \u0645\u06cc\u0644 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0628 \u0628\u06be\u06cc \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\u06af\u0627\u06d4<\/p>\n<p>\u06a9\u06c1 <code>sendEmail<\/code> \u0641\u0646\u06a9\u0634\u0646 \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0631\u06cc \u0679\u0631\u0627\u0646\u0633\u0645\u06cc\u0634\u0646 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u06be\u06cc\u062c\u0646\u0627 500 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u0633 \u0645\u0631\u062d\u0644\u06d2 \u067e\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u06cc \u062c\u0627\u0626\u06d2 \u06af\u06cc\u06d4 \u0645\u0631\u062d\u0644\u06c1 2 (\u062a\u062c\u0632\u06cc\u06c1) \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0645\u06a9\u0645\u0644 \u0627\u0648\u0631 \u0645\u0639\u0627\u0626\u0646\u06c1 \u06a9\u06cc\u0627 \u062c\u0627 \u0686\u06a9\u0627 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0627\u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0646\u06c1\u06cc\u06ba \u0686\u0644\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<h3 id=\"heading-step-4-send-admin-notification\">\u0645\u0631\u062d\u0644\u06c1 4: \u0627\u06cc\u0688\u0645\u0646\u0633\u0679\u0631\u06cc\u0679\u0631 \u06a9\u06cc \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4<\/h3>\n<pre><code class=\"language-typescript\">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 sale: ${user.email}`,\n    template: createElement(AdminPurchaseNotificationEmail, { \/* ... *\/ }),\n  });\n});\n<\/code><\/pre>\n<p>\u0627\u06cc\u0688\u0645\u0646\u0633\u0679\u0631\u06cc\u0679\u0631 \u06a9\u06cc \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u06af\u0627\u06c1\u06a9 \u06a9\u0648 \u062f\u0631\u067e\u06cc\u0634 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc\u0648\u06ba \u0633\u06d2 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0622\u0632\u0627\u062f \u06c1\u06cc\u06ba\u06d4 \u0627\u0646 \u06a9\u0648 \u0627\u0644\u06af \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06cc\u06a9 \u0645\u06cc\u06ba \u063a\u0644\u0637\u06cc\u0627\u06ba \u062f\u0648\u0633\u0631\u06d2 \u067e\u0631 \u0627\u062b\u0631 \u0627\u0646\u062f\u0627\u0632 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u06ba \u06af\u06cc\u06d4<\/p>\n<h3 id=\"heading-step-5-grant-github-access\">\u0645\u0631\u062d\u0644\u06c1 5: GitHub \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<pre><code class=\"language-typescript\">const 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\u06d4 \u0627\u0633 \u06a9\u0627 \u0648\u0642\u062a \u062e\u062a\u0645 \u06c1\u0648\u0633\u06a9\u062a\u0627 \u06c1\u06d2 \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 \u0642\u062f\u0645 \u06a9\u0648 \u0627\u067e\u0646\u0627 \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\u0632 (\u0645\u0631\u062d\u0644\u06c1 3) \u06cc\u0627 \u0645\u0646\u062a\u0638\u0645 \u0627\u0637\u0644\u0627\u0639\u0627\u062a (\u0645\u0631\u062d\u0644\u06c1 4) \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u0648 \u0645\u062a\u062d\u0631\u06a9 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u06cc\u06ba \u06af\u06cc\u06d4 \u0627\u0633 \u0642\u062f\u0645 \u06a9\u0648 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0686\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u06cc\u0627 \u062c\u0627 \u0686\u06a9\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0627\u0633 \u0642\u062f\u0645 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0628\u062a\u062f\u0627\u0626\u06cc \u0648\u0627\u067e\u0633\u06cc \u06a9\u0648 \u0646\u0648\u0679 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u067e\u0627\u0633 GitHub \u06a9\u0627 \u0635\u0627\u0631\u0641 \u0646\u0627\u0645 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u062a\u0648\u060c \u0641\u0646\u06a9\u0634\u0646 \u0645\u0631\u062d\u0644\u06c1 4 \u06a9\u06d2 \u0628\u0639\u062f \u062c\u0644\u062f \u0648\u0627\u067e\u0633 \u0622\u062c\u0627\u062a\u0627 \u06c1\u06d2\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-step-6-track-github-access\">\u0645\u0631\u062d\u0644\u06c1 6: GitHub \u0631\u0633\u0627\u0626\u06cc \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<pre><code class=\"language-typescript\">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<\/code><\/pre>\n<p>\u06cc\u06c1 \u06c1\u06d2 <code>collaboratorResult<\/code> \u0645\u0631\u062d\u0644\u06c1 5 \u0633\u06d2\u06d4 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 <code>step.run()<\/code> \u0648\u0627\u067e\u0633\u06cc \u06a9\u06cc \u0642\u06cc\u0645\u062a \u06a9\u0648 \u06a9\u06cc\u0634 \u06a9\u0631\u06cc\u06ba\u06d4 <code>collaboratorResult.status<\/code> \u0627\u06af\u0631 \u062e\u0635\u0648\u0635\u06cc\u062a \u0645\u06cc\u06ba \u062e\u0644\u0644 \u067e\u0691\u0627 \u062a\u06be\u0627 \u0627\u0648\u0631 \u0645\u0631\u0627\u062d\u0644 5 \u0627\u0648\u0631 6 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u060c \u062a\u0648 \u06cc\u06c1 \u0627\u0628 \u0628\u06be\u06cc \u06cc\u06c1\u0627\u06ba \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-step-7-update-purchase-record\">\u0645\u0631\u062d\u0644\u06c1 7: \u0627\u067e\u0646\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062a\u0627\u0631\u06cc\u062e \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<pre><code class=\"language-typescript\">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<\/code><\/pre>\n<p>\u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u06cc \u0627\u067e \u0688\u06cc\u0679\u0633 GitHub \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u06d2 \u0628\u0639\u062f \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u062a\u0645 \u0635\u0631\u0641 \u062f\u06a9\u06be\u0627\u0624 <code>githubAccessGranted: true<\/code> \u06cc\u06c1 \u062a\u0639\u0627\u0648\u0646 \u06a9\u0646\u0646\u062f\u06c1 \u06a9\u06cc \u062f\u0639\u0648\u062a \u06a9\u06d2 \u062d\u0642\u06cc\u0642\u062a \u0645\u06cc\u06ba \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0622\u067e \u0631\u0633\u0627\u0626\u06cc \u062f\u06cc\u0646\u06d2 \u0633\u06d2 \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 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u06d2 \u06af\u0627 \u06a9\u06c1 \u0631\u0633\u0627\u0626\u06cc \u062f\u06cc \u06af\u0626\u06cc \u06c1\u06d2 \u0627\u06af\u0631\u0686\u06c1 \u0631\u0633\u0627\u0626\u06cc \u0646\u06c1\u06cc\u06ba \u062f\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-step-8-send-repo-access-email\">\u0645\u0631\u062d\u0644\u06c1 8: \u0631\u06cc\u067e\u0648\u0632\u0679\u0631\u06cc \u062a\u06a9 \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  await sendEmail({\n    to: user.email,\n    subject: `Your repository access is ready!`,\n    template: createElement(RepoAccessGrantedEmail, {\n      repoUrl: \"https:\/\/github.com\/your-org\/your-repo\",\n    }),\n  });\n});\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0627\u06cc \u0645\u06cc\u0644 \u0635\u0631\u0641 \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 \u0628\u06be\u06cc\u062c\u06cc \u062c\u0627\u0626\u06d2 \u06af\u06cc (\u0645\u0631\u062d\u0644\u06c1 5) \u0627\u0648\u0631 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 (\u0645\u0631\u062d\u0644\u06c1 7)\u06d4 \u0622\u0631\u0688\u0631 \u0627\u06c1\u0645 \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 \u062a\u0648 \u0622\u067e \u0627\u067e\u0646\u06d2 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u06cc\u06c1 \u0646\u06c1\u06cc\u06ba \u0628\u062a\u0627\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06a9\u06c1 &quot;\u0631\u0633\u0627\u0626\u06cc \u062a\u06cc\u0627\u0631 \u06c1\u06d2&#8221;\u06d4<\/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 Ingest \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 \u200b\u200b\u062f\u0646 \u067e\u0631 \u062a\u0634\u062e\u06cc\u0635 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a)\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0648\u0627\u0642\u0639\u06c1 \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> \u0627\u06cc \u0645\u06cc\u0644\u0632 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2:<\/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    const { userId, purchaseId } = event.data;\n\n    await step.sleep(\"wait-7-days\", \"7d\");\n\n    await step.run(\"send-day-7-email\", async () => {\n      \/\/ Check eligibility (user exists, not unsubscribed, not refunded)\n      \/\/ Send onboarding tips email\n    });\n\n    await step.sleep(\"wait-14-days\", \"7d\");\n\n    await step.run(\"send-day-14-email\", async () => {\n      \/\/ Send feedback request email\n    });\n\n    await step.sleep(\"wait-30-days\", \"16d\");\n\n    await step.run(\"send-day-30-email\", async () => {\n      \/\/ Send testimonial request email\n    });\n  }\n);\n<\/code><\/pre>\n<p>\u062a\u0648\u062c\u06c1 \u0641\u0631\u0645\u0627\u0626\u06cc\u06ba <code>cancelOn<\/code> \u0627\u062e\u062a\u06cc\u0627\u0631\u0627\u062a\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06a9\u06cc \u06af\u0626\u06cc \u062a\u06be\u06cc\u060c \u062a\u0648 \u0622\u067e \u0628\u06be\u06cc\u062c \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba: <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\u0648 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-why-each-step-must-be-separate\">\u06c1\u0631 \u0642\u062f\u0645 \u06a9\u0648 \u0627\u0644\u06af \u0627\u0644\u06af \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06a9\u06cc\u0648\u06ba \u06c1\u06d2\u061f<\/h3>\n<p>\u0627\u0635\u0648\u0644 \u0633\u0627\u062f\u06c1 \u06c1\u06cc\u06ba\u06d4 <strong>\u0648\u06c1 \u0622\u067e\u0631\u06cc\u0634\u0646 \u062c\u0648 \u0628\u06cc\u0631\u0648\u0646\u06cc \u062e\u062f\u0645\u0627\u062a \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u06cc\u0627 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0646 \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u06c1\u0648\u0646\u06d2 \u0686\u0627\u06c1\u0626\u06cc\u06ba\u06d4<\/strong><\/p>\n<p>\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 \u0627\u06cc\u06a9 \u0642\u062f\u0645 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0622\u067e \u06a9\u0627 \u0627\u06cc \u0645\u06cc\u0644 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0646\u0646\u062f\u06c1 500 \u0648\u0627\u067e\u0633 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 GitHub API \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u0627 \u0627\u06cc\u06a9 \u0642\u062f\u0645 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0627\u0633 \u06a9\u06cc \u0631\u0641\u062a\u0627\u0631 \u0645\u062d\u062f\u0648\u062f \u06c1\u0648 \u0633\u06a9\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u062f\u0648 \u0622\u067e\u0631\u06cc\u0634\u0646\u0632 \u0627\u06cc\u06a9 \u06c1\u06cc \u0645\u0631\u062d\u0644\u06d2 \u0645\u06cc\u06ba \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u06af\u0631 \u0648\u06c1 \u06c1\u0645\u06cc\u0634\u06c1 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648 \u062c\u0627\u0626\u06cc\u06ba \u06cc\u0627 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06cc\u06ba (\u0627\u06cc\u06a9 \u0628\u06cc\u0631\u0648\u0646\u06cc \u06a9\u0627\u0644 \u06a9\u0627 \u0627\u0634\u062a\u0631\u0627\u06a9 \u06a9\u0631\u0646\u0627)\u06d4 \u062a\u0627\u06c1\u0645\u060c \u0627\u06af\u0631 \u0634\u06a9 \u06c1\u0648 \u062a\u0648 \u0627\u0644\u06af \u0627\u0644\u06af \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u067e\u0631 \u0622\u06af\u06d2 \u0628\u0691\u06be\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-with-the-same-pattern\">\u0627\u0633\u06cc \u067e\u06cc\u0679\u0631\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \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\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06a9\u0627 \u0628\u06c1\u0627\u0624 \u0627\u0633\u06cc \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0642\u062f\u0645\u06cc \u067e\u06cc\u0679\u0631\u0646 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0641\u0646\u06a9\u0634\u0646 \u062f\u0631\u062c \u0630\u06cc\u0644 \u0641\u0627\u0626\u0644 \u0645\u06cc\u06ba \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u06d4 <code>handlePurchaseCompleted<\/code>\u0644\u06c1\u0630\u0627\u060c \u0648\u06c1 \u0627\u06cc\u06a9 \u06c1\u06cc \u062f\u0631\u0622\u0645\u062f\u0627\u062a \u06a9\u0627 \u0627\u0634\u062a\u0631\u0627\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba (plus <code>removeCollaborator<\/code> \u0633\u06d2 <code>@\/lib\/github<\/code> \u0627\u0648\u0631 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u0633\u06d2 \u0645\u062a\u0639\u0644\u0642 \u0627\u06cc \u0645\u06cc\u0644 \u0679\u06cc\u0645\u067e\u0644\u06cc\u0679\u0633)\u06d4 \u06cc\u06c1\u0627\u06ba <code>handleRefund<\/code> \u0641\u0646\u06a9\u0634\u0646:<\/p>\n<pre><code class=\"language-typescript\">export const handleRefund = inngest.createFunction(\n  { id: \"refund-processed\", triggers: [{ event: \"stripe\/charge.refunded\" }] },\n  async ({ event, step }) => {\n    const {\n      chargeId,\n      paymentIntentId,\n      amountRefunded,\n      originalAmount,\n      currency,\n    } = event.data;\n\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      await trackServerEvent(user.id, \"refund_processed\", {\n        charge_id: chargeId,\n        amount_cents: amountRefunded,\n        original_amount_cents: originalAmount,\n        currency,\n        is_full_refund: isFullRefund,\n        github_access_revoked: accessRevoked,\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 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 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: ){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<p>\u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06a9\u06d2 \u0639\u0645\u0644 \u0645\u06cc\u06ba \u062a\u06cc\u0646 \u0686\u06cc\u0632\u06cc\u06ba \u0642\u0627\u0628\u0644 \u0630\u06a9\u0631 \u06c1\u06cc\u06ba:<\/p>\n<ol>\n<li>\n<p><strong>\u062c\u0632\u0648\u06cc \u0627\u0648\u0631 \u0645\u06a9\u0645\u0644 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc:<\/strong> \u06cc\u06c1 \u0641\u0646\u06a9\u0634\u0646 \u062f\u0648\u0646\u0648\u06ba \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0631\u0642 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>amountRefunded >= originalAmount<\/code>. \u062c\u0632\u0648\u06cc \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \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 \u0644\u06cc\u06a9\u0646 \u0627\u0646 \u06a9\u06cc \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u06cc: <code>partially_refunded<\/code>. \u0645\u06a9\u0645\u0644 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0622\u067e \u06a9\u06cc GitHub \u0631\u0633\u0627\u0626\u06cc \u0645\u0646\u0633\u0648\u062e \u06a9\u0631 \u062f\u06cc \u062c\u0627\u0626\u06d2 \u06af\u06cc \u0627\u0648\u0631 \u0627\u0633\u0679\u06cc\u0679\u0633 \u062f\u0631\u062c \u0630\u06cc\u0644 \u06c1\u0648 \u06af\u0627: <code>refunded<\/code>.  <\/p>\n<p>\u06cc\u06c1 \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<\/p>\n<\/li>\n<li>\n<p><strong>\u0645\u0634\u0631\u0648\u0637 \u0645\u0631\u062d\u0644\u06c1 \u067e\u0631 \u0639\u0645\u0644\u062f\u0631\u0622\u0645\u062f:<\/strong> &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 \u0634\u0631\u0627\u0626\u0637 \u067e\u0648\u0631\u06cc \u06c1\u0648\u06ba: \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u0645\u06a9\u0645\u0644 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06c1\u06d2\u060c \u0635\u0627\u0631\u0641 \u06a9\u06d2 \u067e\u0627\u0633 GitHub \u06a9\u0627 \u0635\u0627\u0631\u0641 \u0646\u0627\u0645 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0631\u0633\u0627\u0626\u06cc \u067e\u06c1\u0644\u06d2 \u062f\u06cc \u06af\u0626\u06cc \u062a\u06be\u06cc\u06d4 Ingest \u0627\u0646 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u06a9\u0648 \u0686\u06be\u0648\u0691 \u06a9\u0631 \u0635\u0627\u0641 \u0637\u0648\u0631 \u067e\u0631 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0646 \u067e\u0631 \u0639\u0645\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4  <\/p>\n<p>\u06cc\u06c1 \u0627\u06cc\u06a9 \u06cc\u06a9 \u0633\u0646\u06af\u06cc \u067e\u0631\u0648\u0633\u06cc\u0633\u0631 \u0645\u06cc\u06ba \u06af\u06c1\u0631\u0627\u0626\u06cc \u0633\u06d2 \u0627\u0646\u062f\u0631 \u0633\u06d2 \u062c\u0691\u06d2 if-else \u0628\u0644\u0627\u06a9\u0633 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0635\u0627\u0631\u0641\u06cc\u0646 \u0627\u0648\u0631 \u0645\u0646\u062a\u0638\u0645\u06cc\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0644\u06af \u0627\u0644\u06af \u06cc\u0627\u062f\u062f\u06c1\u0627\u0646\u06cc:<\/strong> \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u0645\u062e\u062a\u0644\u0641 \u0627\u06cc \u0645\u06cc\u0644\u0632 \u0645\u0648\u0635\u0648\u0644 \u06c1\u0648\u06ba \u06af\u06cc \u0627\u0633 \u067e\u0631 \u0645\u0646\u062d\u0635\u0631 \u06c1\u06d2 \u06a9\u06c1 \u0631\u0642\u0645 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u0645\u06a9\u0645\u0644 \u06c1\u06d2 \u06cc\u0627 \u062c\u0632\u0648\u06cc\u06d4 \u0645\u0646\u062a\u0638\u0645\u06cc\u0646 \u06a9\u0648 \u06c1\u0645\u06cc\u0634\u06c1 \u062a\u0641\u0635\u06cc\u0644\u06cc \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0645\u0648\u0635\u0648\u0644 \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u060c \u0628\u0634\u0645\u0648\u0644 \u0628\u0644\u0646\u06af ID\u060c \u0635\u0627\u0631\u0641 \u06a9\u0627 GitHub \u0635\u0627\u0631\u0641 \u0646\u0627\u0645\u060c \u0627\u0648\u0631 \u0622\u06cc\u0627 \u0631\u0633\u0627\u0626\u06cc \u0645\u0646\u0633\u0648\u062e \u06a9\u0631 \u062f\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ol>\n<p>\u06cc\u06c1 \u0627\u06cc\u06a9 \u0627\u0644\u06af \u0645\u0631\u062d\u0644\u06c1 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0627\u06cc\u0688\u0645\u0646\u0633\u0679\u0631\u06cc\u0679\u0631 \u06a9\u06cc \u0627\u0637\u0644\u0627\u0639 \u06a9\u06cc \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u06a9\u0633\u0679\u0645\u0631 \u06a9\u06cc \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u06a9\u0648 \u0628\u0644\u0627\u06a9 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u0622\u067e \u06a9\u06d2 \u06af\u0627\u06c1\u06a9 \u06a9\u06d2 \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u0648 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631\u062c\u06cc\u062d \u062d\u0627\u0635\u0644 \u06c1\u06d2\u06d4<\/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>\u0644\u0627\u0648\u0627\u0631\u062b \u06af\u0627\u0691\u06cc\u0648\u06ba \u06a9\u0648 \u06a9\u06c1\u0627\u06ba \u0633\u06d2 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4 <code>step.sleep()<\/code> \u0637\u0631\u06cc\u0642\u06c1 \u0686\u0645\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 \u0622\u067e \u06a9\u0627 \u0686\u06cc\u06a9 \u0622\u0624\u0679 \u0633\u06cc\u0634\u0646 \u062e\u062a\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u062a\u0648 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u0631\u06cc\u06a9\u0648\u0631\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u06d2 \u06af\u06cc\u06d4 \u0644\u06cc\u06a9\u0646 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06af\u0627\u06c1\u06a9\u0648\u06ba \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0648\u0627\u067e\u0633 \u0622\u0646\u06d2 \u06a9\u0627 \u0648\u0642\u062a \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u06af\u06be\u0646\u0679\u06c1 \u06cc\u0627 \u0627\u0633 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u062a\u0648\u0642\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">export 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;\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 checkoutUrl = `https:\/\/yoursite.com\/pricing`;\n\n      await sendEmail({\n        to: customerEmail,\n        subject: \"Your checkout is waiting\",\n        template: createElement(AbandonedCartEmail, {\n          customerEmail,\n          checkoutUrl,\n        }),\n      });\n    });\n\n    \/\/ Track the event\n    await step.run(\"track-abandoned-cart\", async () => {\n      await trackServerEvent(\"anonymous\", \"abandoned_cart_email_sent\", {\n        customer_email: customerEmail,\n        session_id: sessionId,\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> \u0644\u0627\u0626\u0646\u06cc\u06ba \u06a9\u0644\u06cc\u062f\u06cc \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \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 \u0641\u06cc\u0686\u0631 \u06a9\u0648 \u0627\u06cc\u06a9 \u06af\u06be\u0646\u0679\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0631\u0648\u06a9 \u062f\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0634\u06cc\u0688\u0648\u0644\u0646\u06af \u06c1\u06cc\u0646\u0688\u0644\u0632 \u06a9\u0648 \u062f\u0627\u062e\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 \u06af\u06be\u0646\u0679\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u0641\u0639\u0627\u0644\u06cc\u062a \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u06cc \u0627\u0648\u0631 \u0622\u067e \u06a9\u0627 \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c \u062f\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0639\u0645\u0644\u062f\u0631\u0622\u0645\u062f \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c \u0622\u067e \u06a9\u0648 \u0645\u06cc\u0639\u0627\u062f \u062e\u062a\u0645 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0633\u06cc\u0634\u0646\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0633\u06d2 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0631\u0648\u0646 \u062c\u0627\u0628 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u060c \u06cc\u0627 Redis \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0645\u0648\u062e\u0631 \u06a9\u0631\u062f\u06c1 \u0679\u0627\u0633\u06a9 \u0642\u0637\u0627\u0631 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\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 \u06a9\u06c1 <code>step.sleep()<\/code> \u0646\u0642\u0637\u06c1 \u0646\u0638\u0631 \u0622\u0633\u0627\u0646\u060c \u0632\u06cc\u0627\u062f\u06c1 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644\u060c \u0627\u0648\u0631 \u0632\u06cc\u0627\u062f\u06c1 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u06c1\u06d2\u06d4<\/p>\n<p>\u062a\u0642\u0631\u06cc\u0628 \u06a9\u06d2 \u0627\u0648\u067e\u0631 \u0627\u06cc\u06a9 \u06af\u0627\u0631\u0688 \u0628\u06be\u06cc \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u0633\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06af\u0627\u06c1\u06a9 \u06a9\u0627 \u0627\u06cc \u0645\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 (\u0627\u06af\u0631 \u0635\u0627\u0631\u0641 \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 \u0686\u06cc\u06a9 \u0622\u0624\u0679 \u0628\u0646\u062f \u06a9\u0631 \u062f\u06cc\u0627 \u06c1\u06d2)\u060c \u062a\u0648 \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 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0648\u0626\u06cc \u067e\u062a\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u062a\u0648 \u0631\u06cc\u06a9\u0648\u0631\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u0648 \u0634\u06cc\u0688\u0648\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0646\u0645\u0648\u0646\u06c1 \u0632\u06cc\u0627\u062f\u06c1 \u067e\u06cc\u0686\u06cc\u062f\u06c1 \u0628\u062d\u0627\u0644\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624 \u062a\u06a9 \u067e\u06be\u06cc\u0644\u0627 \u06c1\u0648\u0627 \u06c1\u06d2\u06d4 \u0622\u067e 1 \u0633\u06cc\u06a9\u0646\u0688 \u06a9\u0627 \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>step.sleep()<\/code> \u0627\u06af\u0631 \u06af\u0627\u06c1\u06a9 \u0646\u06d2 \u0627\u0628\u06be\u06cc \u062a\u06a9 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u0646\u06c1\u06cc\u06ba \u06a9\u06cc \u06c1\u06d2\u060c \u062a\u0648 \u062a\u06cc\u0646 \u062f\u0646 \u0628\u0639\u062f \u0641\u0627\u0644\u0648 \u0627\u067e \u0631\u06cc\u06a9\u0648\u0631\u06cc \u0627\u06cc \u0645\u06cc\u0644 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4 \u0622\u067e \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 (\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<p>\u06c1\u0631 \u0627\u0636\u0627\u0641\u06cc \u0642\u062f\u0645 \u0627\u06cc\u06a9 \u0627\u0636\u0627\u0641\u06cc \u0642\u062f\u0645 \u06c1\u06d2\u06d4 <code>step.run()<\/code> \u06cc\u0627 <code>step.sleep()<\/code> \u06a9\u0627\u0644 \u06cc\u06c1 \u0641\u0646\u06a9\u0634\u0646 \u0627\u06cc\u06a9 \u0627\u0633\u06a9\u0631\u067e\u0679 \u06a9\u06cc \u0637\u0631\u062d \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u06a9\u0627\u0631\u0648\u0628\u0627\u0631\u06cc \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0628\u06cc\u0627\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0628\u062c\u0627\u0626\u06d2 \u0627\u06cc\u06a9 \u067e\u06cc\u0686\u06cc\u062f\u06c1 \u06a9\u0631\u0648\u0646 \u062c\u0627\u0628 \u0627\u0648\u0631 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u06d2 \u062c\u06be\u0646\u0688\u0648\u06ba \u06a9\u06d2\u06d4<\/p>\n<h2 id=\"heading-how-to-test-webhook-handlers-locally\">\u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u067e\u0646\u06d2 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0645\u0642\u0627\u0645\u06cc \u062c\u0627\u0646\u0686 \u0633\u0679\u0631\u0627\u0626\u067e \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0633\u0628 \u0633\u06d2 \u0628\u0691\u06cc \u067e\u0631\u06cc\u0634\u0627\u0646\u06cc\u0648\u06ba \u0645\u06cc\u06ba \u0633\u06d2 \u0627\u06cc\u06a9 \u06c1\u06d2\u06d4 \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0645\u0642\u0627\u0645\u06cc \u06a9\u0645\u067e\u06cc\u0648\u0679\u0631 \u067e\u0631 \u0627\u06cc\u0648\u0646\u0679\u0633 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u060c \u0627\u0648\u0631 \u0622\u067e \u06a9\u0648 \u0627\u0646 \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06cc\u06a9 \u06af\u0631\u0627\u0624\u0646\u0688 \u0679\u0627\u0633\u06a9 \u0633\u0633\u0679\u0645 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u06d4 \u062a\u0631\u062a\u06cc\u0628\u0627\u062a \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u06c1\u06cc\u06ba:<\/p>\n<h3 id=\"heading-how-to-forward-stripe-events-locally\">\u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0628\u06be\u06cc\u062c\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 \u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0645\u0642\u0627\u0645\u06cc \u0633\u0631\u0648\u0631 \u067e\u0631 \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">stripe listen --forward-to localhost:3000\/api\/payments\/webhook\n<\/code><\/pre>\n<p>CLI \u0648\u06cc\u0628 \u06c1\u06a9 \u06a9\u06d2 \u062f\u0633\u062a\u062e\u0637\u06cc \u0631\u0627\u0632 \u06a9\u0648 \u067e\u0631\u0646\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 (\u0627\u0633 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2: <code>whsec_<\/code>)\u06d4 \u0627\u0633\u06d2 \u0627\u067e\u0646\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4 <code>STRIPE_WEBHOOK_SECRET<\/code> \u0645\u0642\u0627\u0645\u06cc \u062a\u0631\u0642\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u062a\u063a\u06cc\u0631\u0627\u062a\u06d4<\/p>\n<p>\u0622\u067e \u0679\u06cc\u0633\u0679 \u0627\u06cc\u0648\u0646\u0679\u0633 \u06a9\u0648 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0645\u062a\u062d\u0631\u06a9 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">stripe trigger checkout.session.completed\nstripe trigger charge.refunded\nstripe trigger checkout.session.expired\n<\/code><\/pre>\n<h3 id=\"heading-how-to-run-the-inngest-dev-server\">\u0627\u0646\u062c\u0633\u0679 \u0688\u06cc\u0648 \u0633\u0631\u0648\u0631 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/h3>\n<p>Ingest \u0627\u06cc\u06a9 \u0645\u0642\u0627\u0645\u06cc \u0688\u0648\u06cc\u0644\u067e\u0645\u0646\u0679 \u0633\u0631\u0648\u0631 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u062d\u0642\u06cc\u0642\u06cc \u0648\u0642\u062a \u0645\u06cc\u06ba \u06c1\u0631 \u0641\u0646\u06a9\u0634\u0646\u060c \u06c1\u0631 \u0642\u062f\u0645\u060c \u0627\u0648\u0631 \u06c1\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0648 \u0638\u0627\u06c1\u0631 \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\u06c1 <code>-u<\/code> \u062c\u06be\u0646\u0688\u0627 \u0627\u0646\u062c\u06cc\u0633\u0679 \u0688\u0648\u06cc\u0644\u067e\u0645\u0646\u0679 \u0633\u0631\u0648\u0631 \u06a9\u0648 \u0628\u062a\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u06a9\u06c1\u0627\u06ba \u0686\u0644 \u0631\u06c1\u06cc \u06c1\u06d2 \u062a\u0627\u06a9\u06c1 \u06cc\u06c1 \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u06a9\u0648 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u0631 \u0633\u06a9\u06d2\u06d4 \u06a9\u06be\u0644\u0627 <code>http:\/\/localhost:8288<\/code> \u0627\u067e\u0646\u06d2 \u0628\u0631\u0627\u0624\u0632\u0631 \u0645\u06cc\u06ba Ingest \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u062f\u06cc\u06a9\u06be\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-how-to-watch-step-execution\">\u0645\u0631\u062d\u0644\u06c1 \u0648\u0627\u0631 \u0639\u0645\u0644 \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u062f\u06cc\u06a9\u06be\u06cc\u06ba<\/h3>\n<p>\u0627\u0646\u062c\u0633\u0679 \u0688\u0648\u06cc\u0644\u067e\u0645\u0646\u0679 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0648\u06c1 \u062c\u06af\u06c1 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u06d2 \u0646\u0645\u0648\u0646\u06d2 \u0648\u0627\u0642\u0639\u06cc \u06a9\u0644\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062c\u0628 \u0622\u067e \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0627\u06cc\u0648\u0646\u0679 \u06a9\u0648 \u0645\u062a\u062d\u0631\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u0622\u067e \u062f\u06cc\u06a9\u06be\u06cc\u06ba \u06af\u06d2:<\/p>\n<ol>\n<li>\n<p>\u06cc\u06c1 \u0627\u06cc\u06a9 \u0648\u0627\u0642\u0639\u06c1 \u06c1\u06d2 \u062c\u0648 &#8216;\u0627\u06cc\u0648\u0646\u0679&#8217; \u0679\u06cc\u0628 \u0645\u06cc\u06ba \u0622\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06cc\u06c1 \u0641\u0646\u06a9\u0634\u0646 &quot;\u0631\u0646&#8221; \u0679\u06cc\u0628 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u0646 \u067e\u0679\u060c \u0622\u0624\u0679 \u067e\u0679\u060c \u0627\u0648\u0631 \u062f\u0648\u0631\u0627\u0646\u06cc\u06c1 \u0633\u0645\u06cc\u062a \u06c1\u0631 \u0645\u0631\u062d\u0644\u06c1 \u0627\u06cc\u06a9 \u0627\u06cc\u06a9 \u06a9\u0631\u06a9\u06d2 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u0645\u0631\u062d\u0644\u06c1 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648\u060c \u0627\u06cc\u06a9 \u063a\u0644\u0637\u06cc \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ol>\n<p>\u06cc\u06c1 \u0645\u0631\u0626\u06cc\u062a \u0627\u06cc\u0633\u06cc \u0686\u06cc\u0632 \u06c1\u06d2 \u062c\u0648 \u0622\u067e \u0627\u0646 \u0644\u0627\u0626\u0646 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062d\u0627\u0635\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u0631 \u0633\u06a9\u062a\u06d2\u06d4 \u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u06af\u0627\u06c1\u06a9 \u0631\u067e\u0648\u0631\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 &quot;\u0645\u06cc\u06ba \u0646\u06d2 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06cc\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0633 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u062d\u0627\u0635\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u0631 \u0633\u06a9\u062a\u0627&#8221;\u060c \u062a\u0648 \u0622\u067e \u0627\u067e\u0646\u06d2 Ingest \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0645\u06cc\u06ba \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u0627 \u0645\u0631\u062d\u0644\u06c1 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u0627 \u0627\u0648\u0631 \u06a9\u06cc\u0648\u06ba\u06d4 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0645\u06cc\u06ba \u0627\u0633 \u0642\u0633\u0645 \u06a9\u0627 \u0645\u0634\u0627\u06c1\u062f\u06c1 \u0628\u06c1\u062a \u0627\u06c1\u0645 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-how-to-simulate-failures\">\u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06cc \u062a\u0642\u0644\u06cc\u062f \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 \u0622\u067e \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0627\u06cc\u06a9 \u0642\u062f\u0645 \u06a9\u0648 \u0646\u0627\u06a9\u0627\u0645 \u0628\u0646\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631\u060c &quot;add-github-collaborator&#8221; \u0645\u0631\u062d\u0644\u06c1 \u0648\u0642\u0641\u06d2 \u0648\u0642\u0641\u06d2 \u0633\u06d2 \u0627\u06cc\u06a9 \u063a\u0644\u0637\u06cc \u067e\u06be\u06cc\u0646\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/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 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u06cc \u067e\u0627\u0644\u06cc\u0633\u06cc \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \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>\u0645\u0631\u062d\u0644\u06c1 6 \u0633\u06d2 9 \u062a\u06a9 \u0632\u06cc\u0631 \u0627\u0644\u062a\u0648\u0627\u0621 \u0631\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 \u0645\u0631\u062d\u0644\u06c1 5 \u06a9\u0627\u0645\u06cc\u0627\u0628 \u0646\u06c1\u06cc\u06ba \u06c1\u0648 \u062c\u0627\u062a\u0627\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 \u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f 6 \u0633\u06d2 9 \u062a\u06a9 \u06a9\u06d2 \u0645\u0631\u0627\u062d\u0644 \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\u060c \u0644\u06cc\u06a9\u0646 1 \u0633\u06d2 4 \u062a\u06a9 \u06a9\u06d2 \u0645\u0631\u0627\u062d\u0644 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0639\u0645\u0644 \u0645\u06cc\u06ba \u0646\u06c1\u06cc\u06ba \u0644\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u0635\u0644 \u0686\u0648\u06a9\u06cc \u0633\u0644\u0648\u06a9 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-conclusion\">\u0646\u062a\u06cc\u062c\u06c1<\/h2>\n<p>\u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u06a9\u0627 \u0646\u0645\u0648\u0646\u06c1 \u0627\u06cc\u06a9 \u0627\u0635\u0648\u0644 \u067e\u0631 \u0622\u062a\u0627 \u06c1\u06d2: <strong>\u0648\u0635\u0648\u0644 \u06a9\u0631\u0646\u06d2 \u0627\u0648\u0631 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u0648 \u0627\u0644\u06af \u06a9\u0631\u06cc\u06ba\u06d4<\/strong><\/p>\n<p>\u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679 \u067e\u0679\u06cc \u06a9\u06d2 \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u0627\u062e\u0644 \u06a9\u0631\u062f\u06c1 \u0648\u0627\u0642\u0639\u0627\u062a \u06a9\u0648 \u067e\u0633 \u0645\u0646\u0638\u0631 \u06a9\u06d2 \u0679\u0627\u0633\u06a9 \u0633\u0633\u0679\u0645 \u06a9\u0648 \u0628\u06be\u06cc\u062c\u062a\u0627 \u06c1\u06d2\u06d4 \u0628\u0633\u06d4 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u0627\u06cc\u06a9 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0641\u0646\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u06c1\u0631 \u0642\u062f\u0645 \u06a9\u0627 \u0645\u0639\u0627\u0626\u0646\u06c1 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0646\u0641\u0631\u0627\u062f\u06cc \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<p>\u06cc\u06c1 \u062c\u0648 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0648\u06c1 \u06cc\u06c1 \u06c1\u06d2:<\/p>\n<ul>\n<li>\n<p><strong>\u06a9\u0648\u0626\u06cc \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0627\u06cc \u0645\u06cc\u0644 \u0646\u06c1\u06cc\u06ba:<\/strong> \u0648\u06c1 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u062c\u0648 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u06a9\u0627\u0645\u06cc\u0627\u0628 \u06c1\u0648 \u0686\u06a9\u06d2 \u06c1\u06cc\u06ba \u062f\u0648\u0628\u0627\u0631\u06c1 \u0646\u06c1\u06cc\u06ba \u0686\u0644\u0627\u0626\u06d2 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u06a9\u0648\u0626\u06cc \u062c\u0632\u0648\u06cc \u062d\u0627\u0644\u062a \u0646\u06c1\u06cc\u06ba:<\/strong> \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 \u0645\u062d\u0641\u0648\u0638 \u0631\u06c1\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0645\u0631\u062d\u0644\u06c1 5 \u06a9\u0648 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0622\u0632\u0645\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0645\u06a9\u0645\u0644 \u0645\u0634\u0627\u06c1\u062f\u06c1:<\/strong> \u06c1\u0631 \u0641\u0646\u06a9\u0634\u0646 \u067e\u0631 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0622\u067e \u0628\u0627\u0644\u06a9\u0644 \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u0627 \u0645\u0631\u062d\u0644\u06c1 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u0627 \u0627\u0648\u0631 \u06a9\u06cc\u0648\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0628\u0644\u0679 \u0627\u0646 \u062a\u0627\u062e\u06cc\u0631 \u0633\u06d2 \u0639\u0645\u0644\u062f\u0631\u0622\u0645\u062f:<\/strong> <code>step.sleep()<\/code>    \u06a9\u0631\u0648\u0646 \u062c\u0627\u0628\u0632 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0631\u06cc\u06a9\u0648\u0631\u06cc \u0627\u06cc \u0645\u06cc\u0644\u0632 \u0627\u0648\u0631 \u0641\u0627\u0644\u0648 \u0627\u067e \u0633\u06cc\u06a9\u0648\u0646\u0633\u0632 \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0642\u0627\u0628\u0644 \u062a\u0631\u062a\u06cc\u0628 \u0648\u0631\u06a9 \u0641\u0644\u0648:<\/strong> \u0627\u06cc\u06a9 \u062e\u0635\u0648\u0635\u06cc\u062a \u06a9\u0633\u06cc \u0627\u06cc\u0648\u0646\u0679 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u062f\u0648\u0633\u0631\u06cc \u062e\u0635\u0648\u0635\u06cc\u062a \u06a9\u0648 \u0645\u062a\u062d\u0631\u06a9 \u06a9\u0631 \u0633\u06a9\u062a\u06cc \u06c1\u06d2\u060c \u0627\u06cc\u06a9 \u0633\u0644\u0633\u0644\u06c1 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u06cc\u0633\u06d2 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u06a9\u0631\u0646\u0627\u060c \u062c\u0633 \u0633\u06d2 30 \u062f\u0646 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u06cc\u06c1 \u067e\u06cc\u0679\u0631\u0646 \u0635\u0631\u0641 \u067e\u0679\u06cc\u0648\u06ba \u062a\u06a9 \u0645\u062d\u062f\u0648\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0639\u0645\u0644\u062f\u0631\u0622\u0645\u062f \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0645\u0644\u0679\u06cc \u0633\u0679\u06cc\u067e \u0648\u06cc\u0628 \u06c1\u064f\u06a9 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u0627 \u0641\u0627\u0626\u062f\u06c1 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u062c\u06cc\u0633\u06d2 \u06a9\u06c1 CI \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u0645\u062a\u062d\u0631\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 GitHub \u0648\u06cc\u0628 \u06c1\u064f\u06a9\u060c \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06cc \u062a\u0631\u0633\u06cc\u0644 \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0631\u06cc \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679 \u0648\u06cc\u0628 \u06c1\u064f\u06a9\u060c \u06cc\u0627 \u062e\u062f\u0645\u0627\u062a \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06cc\u0644\u0646\u0688\u0631 \u0648\u06cc\u0628 \u06c1\u064f\u06a9\u06d4<\/p>\n<p>\u0627\u0635\u0648\u0644 \u0648\u06c1\u06cc \u06c1\u06cc\u06ba\u06d4 \u062a\u0648\u062b\u06cc\u0642 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u0633\u06d2 \u0642\u0637\u0627\u0631 \u0645\u06cc\u06ba \u0644\u06af\u0627\u0626\u06cc\u06ba\u06d4 \u0645\u0633\u0644\u0633\u0644 \u0639\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u0645\u06cc\u06ba \u0646\u06d2 \u0627\u0633 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0648 \u0627\u06cc\u0688\u0646 \u0627\u0633\u0679\u06cc\u06a9 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0627 \u06c1\u06d2\u060c \u062c\u06c1\u0627\u06ba \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0627 \u0628\u06c1\u0627\u0624 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u0633\u06d2 \u0644\u06d2 \u06a9\u0631 GitHub \u0631\u06cc\u067e\u0648\u0632\u0679\u0631\u06cc \u06a9\u0648 \u0645\u0644\u0679\u06cc \u0648\u06cc\u06a9 \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u062f\u06cc\u0646\u06d2 \u062a\u06a9 \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0645\u0627\u0631\u06cc 9-\u0645\u0631\u062d\u0644\u06c1 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062e\u0635\u0648\u0635\u06cc\u062a \u0646\u06d2 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u06cc\u0627 \u06a9\u06c1 \u062a\u0645\u0627\u0645 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc\u0648\u06ba \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u06cc \u06af\u0626\u06cc\u060c \u0628\u063a\u06cc\u0631 \u0627\u06cc\u06a9 \u0642\u062f\u0645 \u0686\u06be\u0648\u0679 \u06af\u0626\u06d2 \u06cc\u0627 \u0627\u06cc \u0645\u06cc\u0644\u0632 \u06a9\u06cc \u0646\u0642\u0644 \u062a\u06cc\u0627\u0631 \u06a9\u06cc \u06af\u0626\u06cc\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0622\u067e Stripe \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 SaaS \u0628\u0646\u0627 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0627\u0633 \u0645\u0636\u0645\u0648\u0646 \u0645\u06cc\u06ba \u0648\u06cc\u0628 \u06c1\u06a9 \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u06d2 \u067e\u06cc\u0679\u0631\u0646 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u0648\u06ba \u06a9\u0648 \u067e\u062a\u0644\u0627 \u0631\u06a9\u06be\u06cc\u06ba \u0627\u0648\u0631 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u0648 \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u0645\u0631\u0627\u062d\u0644 \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u062c\u0628 \u06af\u0627\u06c1\u06a9 \u06a9\u06c1\u062a\u0627 \u06c1\u06d2\u060c &quot;\u0645\u06cc\u06ba \u0646\u06d2 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0631 \u062f\u06cc\u060c \u0644\u06cc\u06a9\u0646 \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0627&#8221;\u060c \u062a\u0648 \u0622\u067e \u0635\u0628\u062d 3 \u0628\u062c\u06d2 \u06a9\u06d2 \u0688\u06cc\u0628\u06af\u0646\u06af \u0633\u06cc\u0634\u0646 \u0633\u06d2 \u0628\u0627\u06c1\u0631 \u06c1\u0648 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0622\u067e \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062a\u0639\u0645\u06cc\u0631 \u0634\u062f\u06c1 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u06a9\u06d2 \u0628\u06c1\u0627\u0624\u060c \u0631\u06cc\u0641\u0646\u0688 \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af\u060c \u0627\u0648\u0631 \u0641\u0627\u0644\u0648 \u0627\u067e \u0627\u06cc \u0645\u06cc\u0644 \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u06a9\u0645\u0644 \u0627\u0633\u0679\u0631\u0627\u0626\u067e \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u0627\u0648\u0631 \u0627\u0646\u062c\u0633\u0679 \u0627\u0646\u0679\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0627\u06cc\u0688\u0646 \u0627\u0633\u0679\u06cc\u06a9 \u0645\u06cc\u06ba 30+ \u0627\u0636\u0627\u0641\u06cc \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0679\u06cc\u0633\u0679 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0633 \u0645\u0636\u0645\u0648\u0646 \u06a9\u06cc \u06c1\u0631 \u0686\u06cc\u0632 \u0634\u0627\u0645\u0644 \u06c1\u06d2\u06d4<\/p>\n<p><em>Magnus Rodseth 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>\u0622\u067e \u0646\u06d2 \u067e\u0679\u06cc \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc \u06c1\u06d2\u06d4 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u0635\u0627\u0631\u0641\u06cc\u0646 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0644\u06cc\u06a9\u0646 \u06a9\u06cc\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 ~ \u0628\u0639\u062f \u0627\u062f\u0627 \u0648\u06cc\u0628 \u06c1\u06a9 \u06c1\u06cc\u0646\u0688\u0644\u0631 \u0648\u06c1 \u062c\u06af\u06c1 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u06d2 \u0627\u0646\u0636\u0645\u0627\u0645 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0631\u06a9 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0631\u0633\u0627\u0626\u06cc \u062f\u06cc\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a \u0633\u0631\u0648\u0631 \u06a9\u0631\u06cc\u0634 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 \u0645\u06cc\u06ba \u0646\u06d2 \u062a\u0635\u062f\u06cc\u0642\u06cc \u067e\u06cc\u063a\u0627\u0645 [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":22890,"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-22889","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\/22889","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=22889"}],"version-history":[{"count":1,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/posts\/22889\/revisions"}],"predecessor-version":[{"id":22891,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/posts\/22889\/revisions\/22891"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/media\/22890"}],"wp:attachment":[{"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/media?parent=22889"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/categories?post=22889"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/tags?post=22889"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}