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.
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 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.
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.
- 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, 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.