Skip to main content

Hold then Capture

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

Overview

In your payments integration, you can set up to hold or reserve your customer's authorized amount 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 check-ins, then capture the money when the guest checks out.

An authorized payment ensures that your customer authorized the amount. 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 expires in 7 days. This means you must capture the authorized amount before the authorization expires and return the funds 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.

Integrating payments

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 support hold and 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 required before you can capture an amount.

Capture the authorized amount

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

Capturing the authorized amount can be triggered either via webhook. Suppose you want to capture an amount once your customer authorizes it. In that case, 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.

You must call the capture payment intent endpoint to capture the authorized amount. 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.

Capturing amount

You can capture either partial or the full authorized amount once. This means once you capture the Payment Intent, you cannot capture further amounts 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, it transitions to the succeeded status, and a payment resource is created. You can refer to the amount_received for the captured amount of the Payment Intent.