Skip to content

Conversation

@angelbanderasudg
Copy link
Contributor

@angelbanderasudg angelbanderasudg commented Oct 22, 2025

Summary

What — What changes are introduced in this PR?

This pull request adds support for OXXO payments to the Stripe payment provider module. The main changes include the addition of a new OxxoProviderService, updates to type definitions to support OXXO-specific options, and integration of the new service into the provider's exports and registration.

Why — Why are these changes relevant or necessary?
I was testing the MedusaJs server, I live in México and here oxxo as a Payment method is very used.

How — How have these changes been implemented?

  • Introduced OxxoProviderService in stripe-oxxo.ts, which extends StripeBase and configures Stripe payment intents for OXXO, including expiration settings.
  • Updated StripeOptions and PaymentIntentOptions types to include oxxoExpiresDays and OXXO-specific payment method options for intent configuration.
  • Added OXXO to the PaymentProviderKeys enum for provider identification.

Testing — How have these changes been tested, or how can the reviewer test the feature?

You need to launch the medusa server, add Stripe OXXO as Payment Provider in your Store Region (OXXO only works in México and with mxn currency) and set payment_method_data type to oxxo.

Also you need to allow oxxo payment as payment method in stripe and configure your stripe webhook to your medusa server


Examples

Provide examples or code snippets that demonstrate how this feature works, or how it can be used in practice.
This helps with documentation and ensures maintainers can quickly understand and verify the change.

// Example usage using nextjs starter

const confirmParams: any = {
      return_url: returnUrl,
    }

    if (isOxxo(providerId)) {
      confirmParams.payment_method_data = {
        type: "oxxo",
        billing_details: {
          name:
            cart.billing_address?.first_name +
            " " +
            cart.billing_address?.last_name,
          address: {
            city: cart.billing_address?.city ?? undefined,
            country: cart.billing_address?.country_code ?? undefined,
            line1: cart.billing_address?.address_1 ?? undefined,
            line2: cart.billing_address?.address_2 ?? undefined,
            postal_code: cart.billing_address?.postal_code ?? undefined,
            state: cart.billing_address?.province ?? undefined,
          },
          email: cart.email,
          phone: cart.billing_address?.phone ?? undefined,
        },
      }

      await stripe
        .confirmPayment({
          clientSecret,
          confirmParams,
          redirect: "if_required",
        })
        .then(({ error, paymentIntent }) => {
          console.log({ error, paymentIntent })
          const validateIntent = async (paymentIntent: any) => {
            const link =
              paymentIntent.next_action?.oxxo_display_details
                ?.hosted_voucher_url
            if (link) {
              setSubmitting(false)
              setMessage(
                "Se ha generado un cupón de pago de OXXO. Por favor, revisa la nueva pestaña abierta."
              )
              await onPaymentCompleted() // Here I call the function because I have custom logic for creating a pending order
            }
          }

          if (error) {
            const pi = error.payment_intent

            if (
              (pi && pi.status === "requires_capture") ||
              (pi && pi.status === "succeeded")
            ) {
              onPaymentCompleted()
            }

            if (pi && pi.status === "requires_action") {
              validateIntent(pi)
              return
            }

            setErrorMessage(error.message || null)
            setSubmitting(false)
            return
          }

          if (
            (paymentIntent && paymentIntent.status === "requires_capture") ||
            (paymentIntent && paymentIntent.status === "succeeded")
          ) {
            return onPaymentCompleted()
          }

          if (paymentIntent && paymentIntent.status === "requires_action") {
            validateIntent(paymentIntent) // This is the action that you normally get
          }
        })
    }
}


// Configuration on the server  (medusa-config.ts)
modules: [
    {
      resolve: "@medusajs/medusa/payment",
      options: {
        providers: [
          {
            resolve: "@medusa/payment-stripe",
            id: "stripe",
            options: {
              apiKey: process.env.STRIPE_API_KEY,
              webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
              capture: true,
              oxxoExpiresDays: 7, // default to 3
            },
          },
        ],
      },
    },
  ],

// And not necessary buy you can extend even more creating a pending-orders module (for showing the vouchers created that costumer need to pay in the frontend, because if not the order only creates after the user have payed the voucher, for testing is 3 minutes), this is an example model:

import { model } from "@medusajs/framework/utils";

export const PendingOrder = model.define("pending_order", {
  id: model.id().primaryKey(),
  cart_id: model.text().unique(),
  user_id: model.text(),
  total: model.number(),
  payment_type: model.text(),
  voucher_url: model.text().nullable(),
  payment_session_id: model.text(), // this are the ones that works to identify the payment
  payment_collection_id: model.text(), // this are the ones that works to identify the payment
});
export default PendingOrder;

Checklist

Please ensure the following before requesting a review:

  • I have added a changeset for this PR
    • Every non-breaking change should be marked as a patch
    • To add a changeset, run yarn changeset and follow the prompts
  • The changes are covered by relevant tests
  • I have verified the code works as intended locally
  • [x ] I have linked the related issue(s) if applicable

Additional Context

#13804


Note

Adds OXXO payment support to the Stripe provider with configurable expiration days and updates intent option handling and typings.

  • Payment Providers:
    • New OxxoProviderService (services/stripe-oxxo.ts): configures payment_intent for OXXO with expires_after_days (defaults to 3, configurable via options.oxxoExpiresDays).
    • Registered in src/index.ts and exported from services/index.ts.
  • Types:
    • StripeOptions adds oxxoExpiresDays.
    • PaymentIntentOptions adds payment_method_options.oxxo.expires_after_days.
    • PaymentProviderKeys adds OXXO.
  • Core:
    • core/stripe-base.ts: normalizePaymentIntentParameters now falls back to this.paymentIntentOptions.payment_method_options when not provided in extra.
  • Changeset:
    • Patch release for @medusajs/payment-stripe.

Written by Cursor Bugbot for commit 4d7fe06. This will update automatically on new commits. Configure here.

@angelbanderasudg angelbanderasudg requested a review from a team as a code owner October 22, 2025 05:41
@changeset-bot
Copy link

changeset-bot bot commented Oct 22, 2025

🦋 Changeset detected

Latest commit: 4d7fe06

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 74 packages
Name Type
@medusajs/payment-stripe Patch
@medusajs/medusa Patch
@medusajs/test-utils Patch
@medusajs/medusa-oas-cli Patch
integration-tests-http Patch
@medusajs/analytics Patch
@medusajs/api-key Patch
@medusajs/auth Patch
@medusajs/caching Patch
@medusajs/cart Patch
@medusajs/currency Patch
@medusajs/customer Patch
@medusajs/file Patch
@medusajs/fulfillment Patch
@medusajs/index Patch
@medusajs/inventory Patch
@medusajs/link-modules Patch
@medusajs/locking Patch
@medusajs/notification Patch
@medusajs/order Patch
@medusajs/payment Patch
@medusajs/pricing Patch
@medusajs/product Patch
@medusajs/promotion Patch
@medusajs/region Patch
@medusajs/sales-channel Patch
@medusajs/settings Patch
@medusajs/stock-location Patch
@medusajs/store Patch
@medusajs/tax Patch
@medusajs/user Patch
@medusajs/workflow-engine-inmemory Patch
@medusajs/workflow-engine-redis Patch
@medusajs/draft-order Patch
@medusajs/oas-github-ci Patch
@medusajs/cache-inmemory Patch
@medusajs/cache-redis Patch
@medusajs/event-bus-local Patch
@medusajs/event-bus-redis Patch
@medusajs/analytics-local Patch
@medusajs/analytics-posthog Patch
@medusajs/auth-emailpass Patch
@medusajs/auth-github Patch
@medusajs/auth-google Patch
@medusajs/caching-redis Patch
@medusajs/file-local Patch
@medusajs/file-s3 Patch
@medusajs/fulfillment-manual Patch
@medusajs/locking-postgres Patch
@medusajs/locking-redis Patch
@medusajs/notification-local Patch
@medusajs/notification-sendgrid Patch
@medusajs/core-flows Patch
@medusajs/framework Patch
@medusajs/js-sdk Patch
@medusajs/modules-sdk Patch
@medusajs/orchestration Patch
@medusajs/types Patch
@medusajs/utils Patch
@medusajs/workflows-sdk Patch
@medusajs/cli Patch
@medusajs/deps Patch
@medusajs/telemetry Patch
@medusajs/admin-bundler Patch
@medusajs/admin-sdk Patch
@medusajs/admin-shared Patch
@medusajs/admin-vite-plugin Patch
@medusajs/dashboard Patch
@medusajs/icons Patch
@medusajs/toolbox Patch
@medusajs/ui-preset Patch
create-medusa-app Patch
medusa-dev-cli Patch
@medusajs/ui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Oct 22, 2025

@angelbanderasudg is attempting to deploy a commit to the medusajs Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

@willbouch willbouch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -131,7 +132,7 @@ abstract class StripeBase extends AbstractPaymentProvider<StripeOptions> {
res.shared_payment_token = extra?.shared_payment_token as
| string
| undefined

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

woops ;)

@willbouch willbouch changed the title Add OXXO payment provider support with configurable expiration feat(payment-stripe): OXXO payment provider support with configurable expiration Nov 4, 2025
@willbouch
Copy link
Contributor

Hey @angelbanderasudg and thanks for the contribution. Sorry for the late review. This looks good to me. Can you maybe just resolve the conflicts?

CC @shahednasser idk but we might want to document this

@angelbanderasudg
Copy link
Contributor Author

@willbouch sorry for the inactivity, conflicts resolved :)

@kodiakhq kodiakhq bot merged commit 3a1ed74 into medusajs:develop Nov 18, 2025
27 of 38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants