Skip to main content

Payment Providers

Payment providers handle payment processing, authorization, capture, refunds, and webhook events. Medusa’s payment provider interface supports complex payment flows including 3D Secure, async payment methods, and account holder management.

Available Payment Providers

Medusa includes the following payment providers:

Stripe Provider

The Stripe provider (@medusajs/medusa/payment-stripe) supports multiple payment methods:
  • stripe - Default Stripe payment (cards)
  • stripe-bancontact - Bancontact payments
  • stripe-blik - BLIK payments (Poland)
  • stripe-giropay - Giropay payments (Germany)
  • stripe-ideal - iDEAL payments (Netherlands)
  • stripe-przelewy24 - Przelewy24 payments (Poland)
  • stripe-promptpay - PromptPay payments (Thailand)
  • stripe-oxxo - OXXO payments (Mexico)

Installation

The Stripe payment provider is included in the core Medusa package:
npm install @medusajs/medusa

Configuration

Configure the Stripe provider in your medusa-config.ts:
import { defineConfig } from "@medusajs/framework/utils"

export default defineConfig({
modules: [
{
  resolve: "@medusajs/medusa/payment",
  options: {
    providers: [
      {
        resolve: "@medusajs/medusa/payment-stripe",
        id: "stripe",
        options: {
          apiKey: process.env.STRIPE_API_KEY,
          webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
        },
      },
    ],
  },
},
],
})

Environment Variables

Set the following environment variables in your .env file:
STRIPE_API_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
Get your API keys from the Stripe Dashboard. Create a webhook endpoint to get your webhook secret.

Payment Provider Interface

All payment providers implement the AbstractPaymentProvider interface with the following methods:

Core Payment Methods

initiatePayment(input: InitiatePaymentInput): Promise<InitiatePaymentOutput>

Creates a new payment session with the provider.
const result = await paymentProvider.initiatePayment({
  amount: 1000,
  currency_code: "usd",
  data: {
    session_id: "sess_123",
    metadata: {
      order_id: "order_123",
    },
  },
  context: {
    account_holder: customerAccountHolder,
    idempotency_key: "key_123",
  },
})
// Result: { id: "pi_123", status: "pending", data: {...} }

authorizePayment(input: AuthorizePaymentInput): Promise<AuthorizePaymentOutput>

Authorizes a payment (holds funds without capturing).

capturePayment(input: CapturePaymentInput): Promise<CapturePaymentOutput>

Captures an authorized payment.
const result = await paymentProvider.capturePayment({
  data: { id: "pi_123" },
  context: { idempotency_key: "key_123" },
})

cancelPayment(input: CancelPaymentInput): Promise<CancelPaymentOutput>

Cancels a payment before it’s captured.

refundPayment(input: RefundPaymentInput): Promise<RefundPaymentOutput>

Refunds a captured payment.
const result = await paymentProvider.refundPayment({
  amount: 1000,
  data: { id: "pi_123", currency: "usd" },
  context: { idempotency_key: "key_123" },
})

Account Holder Methods

Manage customer accounts in the payment provider (e.g., Stripe customers).

createAccountHolder(input: CreateAccountHolderInput): Promise<CreateAccountHolderOutput>

updateAccountHolder(input: UpdateAccountHolderInput): Promise<UpdateAccountHolderOutput>

deleteAccountHolder(input: DeleteAccountHolderInput): Promise<DeleteAccountHolderOutput>

Payment Method Methods

listPaymentMethods(input: ListPaymentMethodsInput): Promise<ListPaymentMethodsOutput>

List saved payment methods for an account holder.

savePaymentMethod(input: SavePaymentMethodInput): Promise<SavePaymentMethodOutput>

Save a payment method for future use.

Webhook Handling

getWebhookActionAndData(payload: ProviderWebhookPayload): Promise<WebhookActionResult>

Processes webhook events from the payment provider. Supported Stripe webhook events:
  • payment_intent.created
  • payment_intent.processing
  • payment_intent.succeeded
  • payment_intent.canceled
  • payment_intent.payment_failed
  • payment_intent.requires_action
  • payment_intent.amount_capturable_updated

Using the Payment Module

Access payment providers through the Payment Module:
import { Modules } from "@medusajs/framework/utils"

const paymentModule = container.resolve(Modules.PAYMENT)

// Create a payment collection
const paymentCollection = await paymentModule.createPaymentCollections({
  region_id: "reg_123",
  currency_code: "usd",
  amount: 1000,
})

// Create a payment session
const paymentSession = await paymentModule.createPaymentSession(
  paymentCollection.id,
  {
    provider_id: "stripe",
    data: {
      // Provider-specific data
    },
    context: {
      customer: customerData,
    },
  }
)

Payment Workflows

Use payment workflows from @medusajs/core-flows:
import { createPaymentCollectionWorkflow } from "@medusajs/core-flows"

const { result } = await createPaymentCollectionWorkflow(container).run({
  input: {
    region_id: "reg_123",
    currency_code: "usd",
    amount: 1000,
  },
})

Creating Custom Payment Providers

Create a custom payment provider by extending AbstractPaymentProvider:
packages/modules/providers/payment-custom/src/services/custom-payment.ts
import { AbstractPaymentProvider } from "@medusajs/framework/utils"
import {
  InitiatePaymentInput,
  InitiatePaymentOutput,
  PaymentSessionStatus,
} from "@medusajs/framework/types"

export class CustomPaymentProvider extends AbstractPaymentProvider {
  static identifier = "custom-payment"

  constructor(container, options) {
    super(...arguments)
    this.options_ = options
  }

  async initiatePayment(
    input: InitiatePaymentInput
  ): Promise<InitiatePaymentOutput> {
    // Create payment with your payment gateway
    const payment = await this.createPayment(input)

    return {
      id: payment.id,
      status: PaymentSessionStatus.PENDING,
      data: payment,
    }
  }

  async authorizePayment(input) {
    // Authorize payment
  }

  async capturePayment(input) {
    // Capture payment
  }

  async cancelPayment(input) {
    // Cancel payment
  }

  async refundPayment(input) {
    // Refund payment
  }

  async getPaymentStatus(input) {
    // Get payment status
  }

  async retrievePayment(input) {
    // Retrieve payment
  }

  async updatePayment(input) {
    // Update payment
  }

  async deletePayment(input) {
    // Delete payment
  }

  // Account holder methods
  async createAccountHolder(input) {}
  async updateAccountHolder(input) {}
  async deleteAccountHolder(input) {}

  // Payment method methods
  async listPaymentMethods(input) {}
  async savePaymentMethod(input) {}

  // Webhook handling
  async getWebhookActionAndData(payload) {
    // Process webhooks
  }
}
Register your custom provider:
packages/modules/providers/payment-custom/src/index.ts
import { ModuleProvider, Modules } from "@medusajs/framework/utils"
import { CustomPaymentProvider } from "./services/custom-payment"

export default ModuleProvider(Modules.PAYMENT, {
  services: [CustomPaymentProvider],
})

Reference

  • Source: packages/modules/providers/payment-stripe/
  • Base class: packages/core/utils/src/payment/abstract-payment-provider.ts
  • Types: packages/core/types/src/payment/provider.ts

Next Steps

Fulfillment Providers

Configure shipping and fulfillment

Notification Providers

Set up payment confirmation emails

Build docs developers (and LLMs) love