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 checkoutThis 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 thepaymentMethodId
after successfully setting up the payment method. [Applicable for Checkout session modeSETUP
] -
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,
});