Skip to main content

Stripe

Payment plugin for Stripe, based on Payment Intents and Setup Intents (SCA-compliant, supports saved payment methods).

Installation​

Included in the all preset — registerAllPlugins() registers the plugin together with its webhook route.

To register it individually:

import { pluginRegistry } from '@unchainedshop/core';
import { StripePlugin } from '@unchainedshop/plugins/payment/stripe';

pluginRegistry.register(StripePlugin);

Register before startPlatform(). At startup, the plugin enables the webhook route POST /payment/stripe/webhook (path configurable via STRIPE_WEBHOOK_PATH); the Express/Fastify connector mounts it on the Unchained HTTP server. If STRIPE_SECRET is missing, initialization logs a warning and skips this plugin's adapter and route. A missing STRIPE_ENDPOINT_SECRET produces a warning; webhook verification requires it.

The stripe npm package is an optional peer dependency:

npm install stripe

Environment Variables​

VariableDefaultDescription
STRIPE_SECRET-Stripe secret key (required; the adapter and route are skipped without it)
STRIPE_ENDPOINT_SECRET-Webhook signing secret for signature verification (required for webhooks)
STRIPE_WEBHOOK_PATH/payment/stripe/webhookWebhook endpoint path
STRIPE_WEBHOOK_ENVIRONMENT-Environment tag stored in intent metadata; webhooks for other environments are skipped (multi-environment setups)
EMAIL_WEBSITE_NAMEUnchainedFallback description on payment/setup intents

Create Provider​

mutation CreateStripeProvider {
createPaymentProvider(
paymentProvider: {
type: GENERIC
adapterKey: "shop.unchained.payment.stripe"
}
) {
_id
}
}

Provider configuration (via updatePaymentProvider):

KeyDescription
descriptorPrefixCustom prefix for statement descriptors (optional)

Configure Stripe Dashboard​

  1. Go to Developers > Webhooks
  2. Add endpoint: https://your-domain.com/payment/stripe/webhook
  3. Select events payment_intent.succeeded and setup_intent.succeeded
  4. Copy the signing secret to STRIPE_ENDPOINT_SECRET

Payment Flow​

Follows the standard checkout flow. Stripe specifics:

  1. signPaymentProviderForCheckout(orderPaymentId: "...") creates a payment intent and returns its client secret.
  2. Confirm the payment client-side with Stripe.js (stripe.confirmPayment({ clientSecret, ... })).
  3. On payment_intent.succeeded, the webhook checks out the cart server-side.
  4. Fallback — checkout with the payment intent id:
mutation {
checkoutCart(paymentContext: { paymentIntentId: "pi_..." }) {
_id
status
}
}

The plugin validates that amount, currency, and orderPaymentId metadata of the payment intent match the order payment.

Saved Payment Methods​

  1. Create a setup intent:
mutation {
signPaymentProviderForCredentialRegistration(
paymentProviderId: "stripe-provider-id"
)
}
  1. Confirm it client-side with stripe.confirmSetup({ clientSecret, ... }).

  2. On setup_intent.succeeded, the webhook registers the credentials — or register manually:

mutation {
registerPaymentCredentials(
paymentProviderId: "stripe-provider-id"
transactionContext: { setupIntentId: "seti_..." }
) {
_id
}
}
  1. Checkout with the saved payment method:
mutation {
checkoutCart(
paymentContext: {
paymentCredentials: {
token: "pm_stripe_payment_method_id"
meta: {
customer: "cus_stripe_customer_id"
payment_method_types: ["card"]
}
}
}
) {
_id
status
}
}

The plugin creates and reuses Stripe customers automatically, deduplicated by metadata["userId"].

Testing​

Forward webhooks to your local server with the Stripe CLI:

stripe listen --forward-to http://localhost:4010/payment/stripe/webhook

Test card numbers: see Stripe testing docs.

Adapter Details​

PropertyValue
Keyshop.unchained.payment.stripe
TypeGENERIC
Version2.0.0
Sourcepayment/stripe/