# How to Use Stripe for Paid Memberships in GPT-Image2: Complete Integration Guide

> Integrate Stripe for paid memberships in GPT-Image2. Learn how to manage recurring payments and grant monthly credits with this complete guide.

- Repository: [苍何/awesome-gpt-image-2](https://github.com/freestylefly/awesome-gpt-image-2)
- Tags: how-to-guide
- Published: 2026-08-26

---

**GPT-Image2 implements a three-layer Stripe architecture—client initialization, checkout session creation, and webhook event processing—to handle recurring membership payments and automatically grant monthly credits upon successful transactions.**

The freestylefly/awesome-gpt-image-2 repository provides a production-ready integration for selling paid memberships through Stripe. The system handles subscription lifecycle management, from initial checkout to recurring invoice payments, while maintaining payment order state in Supabase and synchronizing user credit allowances.

## Configuring the Stripe Client and Helpers

Before processing payments, the application initializes the Stripe SDK through utility functions in [`api/_lib/billing.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/billing.js). The `isStripeConfigured()` function validates that `STRIPE_SECRET_KEY` exists in environment variables, while `getStripeClient()` creates a singleton Stripe instance pinned to a specific API version.

```javascript
// api/_lib/billing.js
export function isStripeConfigured() {
  return Boolean(process.env.STRIPE_SECRET_KEY);
}

export function getStripeClient() {
  if (!isStripeConfigured()) return null;
  if (!stripeClient) {
    stripeClient = new Stripe(process.env.STRIPE_SECRET_KEY, {
      apiVersion: STRIPE_API_VERSION
    });
  }
  return stripeClient;
}

```

The `checkoutLineItem()` helper transforms internal product objects into Stripe-compatible line items. For membership products, it injects recurring interval metadata; for credit packs, it treats them as one-time payments.

```javascript
// api/_lib/billing.js (lines 66-86)
export function checkoutLineItem(product) {
  const priceData = {
    currency: product.currency,
    unit_amount: product.amountCents,
    product_data: {
      name: product.name.en,
      description: product.description.en,
      metadata: { productType: product.type, productId: product.id }
    }
  };
  if (product.type === 'membership') {
    priceData.recurring = { interval: product.interval };
  }
  return { quantity: 1, price_data: priceData };
}

```

## Creating Stripe Checkout Sessions for Memberships

The [`api/billing/checkout.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/billing/checkout.js) endpoint orchestrates the purchase flow. It validates the request method, resolves the selected product, creates or retrieves a Stripe Customer for the authenticated user, persists a preliminary payment order in Supabase, and constructs the checkout session payload.

Key implementation steps in the checkout handler:

1. **Validate prerequisites** – Ensure `POST` method and that both Supabase and Stripe are configured
2. **Resolve product** – Fetch membership or credit pack details via `getBillingProduct()`
3. **Customer management** – Create or retrieve Stripe Customer ID using `getOrCreateStripeCustomer()`
4. **Order persistence** – Store pending order in Supabase via `createPaymentOrder()`
5. **Session construction** – Build payload with mode, line items, and return URLs

```javascript
// api/billing/checkout.js (lines 60-104)
const sessionPayload = {
  mode: productType === 'membership' ? 'subscription' : 'payment',
  customer: customerId,
  client_reference_id: auth.user.id,
  line_items: [checkoutLineItem(product)],
  success_url: `${appUrl}/?billing=success&session_id={CHECKOUT_SESSION_ID}`,
  cancel_url: `${appUrl}/?billing=cancelled`,
  allow_promotion_codes: true,
  metadata
};

if (productType === 'membership') {
  sessionPayload.subscription_data = { metadata };
} else {
  sessionPayload.payment_intent_data = { metadata };
}

const session = await stripe.checkout.sessions.create(sessionPayload);

```

The endpoint returns `session.url` to redirect users to Stripe's hosted checkout page.

## Processing Webhook Events for Membership Fulfillment

Stripe posts event notifications to [`api/billing/webhook.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/billing/webhook.js), which verifies signatures using `STRIPE_WEBHOOK_SECRET` before routing events to specific handlers. The endpoint handles three critical event types for paid memberships:

- `checkout.session.completed` – Initial subscription activation
- `invoice.payment_succeeded` – Recurring credit grants
- `customer.subscription.updated/deleted` – Status synchronization

### Handling Initial Checkout Completion

When `checkout.session.completed` fires, the `handleCheckoutCompleted` function retrieves the subscription object from Stripe, upserts membership records into the `user_memberships` table, grants initial credits via `grantMembershipCredits()`, and marks the payment order as completed.

```javascript
// api/billing/webhook.js (lines 21-73)
if (productType === 'membership') {
  const subscription = await stripe.subscriptions.retrieve(subscriptionId);
  await upsertMembershipFromSubscription(client, subscription, { /* user context */ });
  await grantMembershipCredits(client, { /* credit details */ });
  await client.from('payment_orders')
    .update({ status: 'completed', stripeSubscriptionId })
    .eq('id', order.id);
}

```

### Processing Recurring Invoice Payments

For monthly credit allowances, the `invoice.payment_succeeded` event triggers `handleInvoicePaid` (lines 76-88), which calls `grantMembershipCredits()` with metadata linking the credit grant to the specific Stripe invoice and subscription.

## Managing Customer Subscriptions and Billing

Beyond initial purchase, the integration supports ongoing subscription management through dedicated endpoints:

- **[`api/billing/portal.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/billing/portal.js)** – Creates Stripe Customer Portal sessions allowing users to update payment methods or cancel subscriptions
- **[`api/billing/plans.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/billing/plans.js)** – Exposes the active catalog of membership tiers and credit packs from Supabase

Both endpoints import the shared billing library ([`api/_lib/billing.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/billing.js)) to ensure consistent Stripe client configuration and error handling.

## Summary

- **Initialization**: The Stripe client initializes lazily in [`api/_lib/billing.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/billing.js) using environment variables `STRIPE_SECRET_KEY` and `STRIPE_API_VERSION`
- **Checkout Flow**: [`api/billing/checkout.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/billing/checkout.js) creates subscription-mode sessions for memberships, storing pending orders in Supabase before redirecting to Stripe
- **Webhook Security**: [`api/billing/webhook.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/billing/webhook.js) verifies Stripe signatures, then grants credits and updates membership status upon `checkout.session.completed` and `invoice.payment_succeeded` events
- **Recurring Credits**: Memberships automatically grant monthly credits through the `invoice.payment_succeeded` handler, ensuring users receive allowances without manual intervention
- **Self-Service**: The billing portal endpoint allows customers to manage subscriptions independently through Stripe's hosted interface

## Frequently Asked Questions

### How does GPT-Image2 handle Stripe webhook security?

The webhook handler in [`api/billing/webhook.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/billing/webhook.js) constructs the event using `stripe.webhooks.constructEvent()` with the `STRIPE_WEBHOOK_SECRET` environment variable. This cryptographically verifies that payloads originate from Stripe, rejecting unauthorized requests with a 400 status before any business logic executes.

### What happens when a membership invoice payment succeeds?

The system listens for `invoice.payment_succeeded` events and triggers `grantMembershipCredits()` via the handler at lines 76-88 of [`api/billing/webhook.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/billing/webhook.js). This credits the user's account with their monthly allowance and records the transaction source as `stripe_membership_invoice` for audit trails.

### Can users manage their subscriptions after purchase?

Yes. The [`api/billing/portal.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/billing/portal.js) endpoint creates Stripe Customer Portal sessions. Existing subscribers can update payment methods, view invoices, or cancel subscriptions through Stripe's hosted interface, with changes synchronized back to Supabase via subsequent webhook events.

### What environment variables are required to enable Stripe payments?

The integration requires `STRIPE_SECRET_KEY` for API authentication and `STRIPE_WEBHOOK_SECRET` for webhook verification. Optionally, `APP_URL` configures the return URLs for checkout completion and cancellation redirects. These variables enable the `isStripeConfigured()` checks in [`api/_lib/billing.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/billing.js).