Skip to main content

Hold then Capture

Learn how to separately authorize an amount then capture the funds later.

Overview

In your payments integration, you can setup to hold or reserve the authorized amount of your customer and capture the funds later. One common use case for this type of integration is hotel bookings. Hotels often authorize the payment in full before a guest arrives or during checkins, then capture the money when the guest checks out.

An authorized payment ensures an amount was authorized by your customer. You need to capture the authorized amount before the authorization expires. If the authorization expires before you capture the authorized amount, the amount will be released back to the customer.

Before implementing, please see the following limitations for authorizing and capturing separately.

  • Hold then capture is only supported in card payment method.
  • The authorization of the amount expires in 7 days. This means you must capture the authorized amount before the authorization expires and the funds are returned back to your customer.

Hold a payment and authorize an amount later

To specify that your integration should separate authorize and capture, specify the payment_method_options.card.capture_type payload attribute to manual when creating a Payment Intent. This attribute configures a Payment Intent to authorize the amount but not capture it.

info

If you don't know yet how to integrate payments, please refer to this guide

create_payment_intent.js
// Protect your PayRex Secret API key at all costs. One common approach
// to store it in an environment variable.
// Add your PayRex test secret API key.
const payrexSecretApiKey = '';

const payrex = require('payrex-node')(payrexSecretApiKey);

// Create a PaymentIntent with amount and currency
const paymentIntent = await payrex.paymentIntents.create({
// Amount is in cents. The sample below is 100.00.
amount: 10000,
currency: 'PHP',
payment_method_options: {
card: {
capture_type: 'manual'
}
},
payment_methods: ['card'],
});

const output = {
clientSecret: paymentIntent.clientSecret,
}

console.log(JSON.stringify(output));

With the code above, the Payment Intent created sets the payment methods that supports hold then capture to separate authorization and capture. For example, if you set the allowed payment methods with card, and gcash, only card payments will separate the authorization and capture while gcash payments will combine both authorization and capture since gcash does not support hold then capture.

After creating the payment intent, present the payment form and let your customer pay using card payment method. Paying using card is a required step before you can capture an amount.

Capture the authorized amount

After your customer authorized an amount, the Payment Intent status transitions to awaiting_capture.

Capturing the authorized amount can be triggered either via webhook. If you want to capture an amount once your customer authorizes it, you can subscribe to the payment_intent via payment_intent.amount_capturable webhook event and capture the authorized amount. You can refer to this guide to know more about webhooks.

To capture the authorized amount, you must call the capture payment intent endpoint. This API call captures the authorized amount and transitions the Payment Intent status to succeeded. You can refer to the amount_capturable attribute to know how much you can capture from the authorized amount.

info

You can capture either partial or the full authorized amount once. This means once you captured the Payment Intent, you cannot capture further amount from the same Payment Intent.

capture_payment_intent.js
// Protect your PayRex Secret API key at all costs. One common approach
// to store it in an environment variable.
// Add your PayRex test secret API key.
const payrexSecretApiKey = '';

const payrex = require('payrex-node')(payrexSecretApiKey);

// Capture a PaymentIntent with amount
const paymentIntent = await payrex.paymentIntents.capture(
// existing payment intent you want to capture.
'pi_1234',
{
// Amount is in cents. The sample below is 100.00.
amount: 10000,
}
)

Once the Payment Intent is captured, the payment intent transitions to the succeeded status and a payment resource is created. You can refer to the amount_received regarding the captured amount of the Payment Intent.