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.
If you don't know yet how to integrate payments, please refer to this guide
- Node
- PHP
- Python
- Ruby
// 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));
<?php
require_once '../vendor/autoload.php';
// 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.
$payrexSecretApiKey = '';
$payrex = new \Payrex\PayrexClient($payrexSecretApiKey);
// Create a PaymentIntent with amount and currency
$paymentIntent = $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'
],
]);
$output = [
'clientSecret' => $paymentIntent->client_secret,
];
echo json_encode($output);
from payrex import Client as PayrexClient
# 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.
payrex_secret_api_key = ''
payrex = PayrexClient(payrex_secret_api_key)
# Create a PaymentIntent with amount and currency
payment_intent = payrex.payment_intents.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',
'gcash'
]
}
)
output = {
'client_secret': payment_intent.client_secret
}
print(output)
require "payrex-ruby"
# 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.
payrex_secret_api_key = ""
payrex = Payrex::Client.new(payrex_secret_api_key)
# Create a PaymentIntent with amount and currency
payment_intent = payrex.payment_intents.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"
]
)
output = {
clientSecret: payment_intent.client_secret
}
puts output.to_json
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.
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.
- Node
- PHP
- Python
- Ruby
// 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,
}
)
<?php
require_once '../vendor/autoload.php';
// 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.
$payrexSecretApiKey = '';
$payrex = new \Payrex\PayrexClient($payrexSecretApiKey);
// Capture a PaymentIntent with amount
$paymentIntent = $payrex->paymentIntents->capture([
// existing payment intent you want to capture.
'id' => 'pi_1234',
// Amount is in cents. The sample below is 100.00.
'amount' => 10000,
]);
from payrex import Client as PayrexClient
# 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.
payrex_secret_api_key = ''
payrex = PayrexClient(payrex_secret_api_key)
# Capture a PaymentIntent with amount
payment_intent = payrex.payment_intents.capture(
# existing payment intent you want to capture.
'pi_1234',
{
# Amount is in cents. The sample below is 100.00.
'amount': 10000
}
)
require "payrex-ruby"
# 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.
payrex_secret_api_key = ""
payrex = Payrex::Client.new(payrex_secret_api_key)
# Capture a PaymentIntent with amount
payment_intent = payrex.payment_intents.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.