Setup payment method and create subscriptions

A step-by-step guide for setting up payment methods and creating subscriptions using the OpenPay SDK and OpenPay.js

This is to be used when you want to collect payment method first and then create a subscription later time. If you want to accept payments and directly create subscription in one simple form please see this guide:

Create subscriptions via checkout

This is for when you want to accept payments and directly create subscriptions in one simple form.

Step 1: Create a secure checkout tokenCopied!

First, you need to create a Checkout Session using the checkout.create_checkout_session method via the OpenPay SDK in the backend.

You can configure the session according to your specific requirements, such as defining the mode of the checkout session. In this case, since we only want to save the payment method (and will create subscriptions later), we'll use SETUP mode.

For detailed API references, please refer to the API documentation.

Here’s an example of how to generate a secure checkout session:

# Setup Mode
checkout = op_client.checkout.create_checkout_session(
    CreateCheckoutSessionRequest(
      customer_id=customer_id,   # (Optional) To create session specific customer
      line_items=[],             # No line items for setup mode
      mode=CheckoutMode.SETUP,   # Setup mode for saving payment info
    )
)
secure_token = checkout.secure_token  # Token to be passed to the frontend
// JavaScript Example
const checkoutSession = await apiClient.checkoutApi.createCheckoutSession({
  createCheckoutSessionRequest: {
    mode: CheckoutMode.Setup,
    lineItems: [],
    currency: CurrencyEnum.Usd, 
  }
})

const secureToken = checkoutSession.secureToken;

Once the secure_token is generated, you can pass it to the frontend to securely collect payment details. This token will be used in the <ElementsForm /> component in your React application to handle the payment setup.

Step 2: Implement the payment formCopied!

On the frontend, use the <ElementsForm /> component to display a secure form where customers can enter their payment details. While the form operates similarly to a subscription form, in SETUP mode it only saves the payment method for future use.

React implementation example:

<ElementsForm
  checkoutSecureToken={`checkout-secure-token-uuid`}  // Token from Step 1
  onChange={() => setError(undefined)}                
  onLoad={onLoad}                                     // Called when the form is loaded
  onValidationError={(message) => setError(message)}  // Handles form validation errors
  onSetupPaymentMethodSuccess={(paymentMethodId) => { // Callback for successful setup
    // Handle setup success  
  }}
  onCheckoutSuccess={(invoiceUrls, subscriptionIds, customerId) => {
    // Handle checkout success (only in 'SUBSCRIPTION' or 'PAYMENT' modes)
  }}
  onCheckoutError={onCheckoutError}                   // Handles checkout errors
>
  {({ submit }) => (
    <>
       <StyledWrapper>
            <div className="flex gap-2 items-center justify-between">
              <Input placeholder="Given name" openPayId={FieldName.FIRST_NAME} />
              <Input placeholder="Family name" openPayId={FieldName.LAST_NAME} />
            </div>
            <Divider />
            <Input placeholder="Email" type="email" openPayId={FieldName.EMAIL} />
            <Divider />
            <div className="flex gap-2 items-center justify-between">
              <Input placeholder="Country" openPayId={FieldName.COUNTRY} />
              <Input placeholder="ZIP" openPayId={FieldName.ZIP_CODE} />
            </div>
        </StyledWrapper>

        <StyledWrapper>
          <CardElement />
        </StyledWrapper>

        {error && <small className="font-bold text-xs mt-2 text-red-500">{error}</small>}

        <button
          onClick={submit}
          className="px-4 py-2 mt-2 w-full font-bold rounded-lg bg-emerald-500 text-white hover:bg-emerald-400 active:bg-emerald-600"
        >
          Setup payment
        </button>
    </>
  )}
</ElementsForm>

Key callbacks and props:

  • checkoutSecureToken: The secure token generated from the backend to link the session.

  • onSetupPaymentMethodSuccess: Callback that provides the paymentMethodId after successfully setting up the payment method. [Applicable for Checkout session mode SETUP]

  • onCheckoutError: Handles any errors encountered during the setup process.

For detailed props and callbacks, please refer to the main guide:

Guide (React)

Integrating payment elements

Note (For using staging environment for testing purpose) - please provide baseUrl prop with our staging environment. baseUrl is default to our production environment.

Example:

<ElementsForm
  baseUrl={isStagingEnv ?   "https://cde.openpaystaging.com/": undefined}
>
   ...
</ElementsForm>

Step 3: Authorize payment method (optional)Copied!

After the customer successfully saves their payment method, the onSetupPaymentMethodSuccess callback is triggered. This callback provides a paymentMethodId, which can be sent to the backend for authorization.

To authorize the saved payment method, use the payment_methods.authorize_payment_method method via the OpenPay SDK.

For detailed API references, see Authorize Payment Method.

Authorizing Payment Method Example:
# Authorize the payment method
request = AuthorizePaymentMethodRequest(
   payment_method_id=payment_method_id,
   authorize_amount_atom=randint(5_00, 55_00),  # Random authorization amount
   currency=CurrencyEnum.USD
)

pm_external = client.payment_methods.authorize_payment_method(request)
// JavaScript Example
const request = {
  paymentMethodId: paymentMethodId,
  authorizeAmountAtom: 5_00, // Amount in cents (e.g., $5.00)
  currency: CurrencyEnum.Usd,
};

const authorized = await apiClient.paymentMethodsApi.authorizePaymentMethod({
  authorizePaymentMethodRequest: request,
});

Step 4: Create a subscriptionCopied!

Once the payment method is successfully saved, you can use the paymentMethodId to create a subscription for the customer.

To create a subscription, use the subscriptions.create_subscriptions method via the OpenPay SDK.

For detailed API references, see Create Subscription.

Creating a subscription example:

# Create a subscription request
create_request = CreateSubscriptionRequest(
  customer_id=customer.id,
  payment_method_id=pm_id,
  selected_product_price_quantity=[
    SelectedPriceQuantity(price_id=price.id, quantity=initial_quantity)
  ],
  total_amount_atom=initial_quantity * price.unit_amount_atom,
  coupon_id=coupon_id,  # Optional
  is_preview=True       # Option to preview subscription details
)

# Create the subscription
sub_create_res = client.subscriptions.create_subscriptions(create_request)
// JavaScript Example
const selectedPriceQuantity = [
  {
    priceId: price.id,
    quantity: initialQuantity,
  },
];

const request = {
  customerId: customer_id,
  couponId: coupon_id,  // Optional
  selectedProductPriceQuantity: selectedPriceQuantity,
  totalAmountAtom: initialQuantity * price.unitAmountAtom,
};

const subscriptionResponse = await apiClient.subscriptionsApi.createSubscriptions({
  createSubscriptionRequest: request,
});