Last active
November 7, 2025 10:14
-
-
Save acomagu/fc473bcd1a7ddce002a210fe10b89e2e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import * as restate from "@restatedev/restate-sdk"; | |
| import { serde } from "@restatedev/restate-sdk-zod"; | |
| import { Stripe } from 'stripe'; | |
| const stripe = new Stripe('STRIPE_KEY'); | |
| const apiHandler = restate.service({ | |
| name: "APIHandler", | |
| handlers: { | |
| async onStripeEvent(ctx, event: Stripe.Event) { | |
| if (event.type === 'checkout.session.completed') { | |
| const purchaseId = event.data.object.client_reference_id; | |
| if (!purchaseId) return; | |
| ctx.workflowSendClient(purchaseWorkflow, purchaseId).onPaymentSucceeded(); | |
| } else if (event.type === 'checkout.session.expired') { | |
| const purchaseId = event.data.object.client_reference_id; | |
| if (!purchaseId) return; | |
| ctx.workflowSendClient(purchaseWorkflow, purchaseId).onPaymentExpired(); | |
| } | |
| }, | |
| async createCheckoutSession(ctx) { | |
| const purchaseId = ctx.rand.uuidv4(); | |
| const stripeCheckoutSession = await ctx.run('Checkout Session 作成', () => { | |
| return stripe.checkout.sessions.create({ | |
| line_items: [{ | |
| quantity: 1, | |
| price_data: { | |
| currency: 'JPY', | |
| unit_amount: 100, | |
| product_data: { | |
| name: '商品', | |
| }, | |
| }, | |
| }], | |
| success_url: 'http://example.com', | |
| mode: 'payment', | |
| client_reference_id: purchaseId, | |
| }); | |
| }); | |
| ctx.workflowClient(purchaseWorkflow, purchaseId).run(); | |
| return stripeCheckoutSession.url; | |
| }, | |
| }, | |
| }); | |
| const purchaseWorkflow = restate.workflow({ | |
| name: 'Purchase', | |
| handlers: { | |
| async run(ctx) { | |
| console.log('商品確保'); | |
| const paymentSucceeded = await ctx.promise<boolean>('paymentSucceeded'); | |
| if (!paymentSucceeded) { | |
| console.log('商品解放'); | |
| return; | |
| } | |
| console.log('商品購入完了'); | |
| await ctx.run(() => { | |
| console.log('メール送信'); | |
| }); | |
| }, | |
| async onPaymentSucceeded(ctx: restate.WorkflowSharedContext) { | |
| await ctx.promise<boolean>('paymentSucceeded').resolve(true); | |
| }, | |
| async onPaymentExpired(ctx: restate.WorkflowSharedContext) { | |
| await ctx.promise<boolean>('paymentSucceeded').resolve(false); | |
| }, | |
| }, | |
| }); | |
| restate.serve({ | |
| services: [apiHandler, purchaseWorkflow], | |
| port: 9080, | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment