Authorize a payment and capture funds later
DocsCurrentLast updated: September 6th 2023, @ 12:43:42 pm
While the default solution for Checkout integration is one-step payment, you can also implement a two-step payment solution.
A two-step payment solution authorizes a card, then settles the purchase later. Choose a two-step payment option to complete a task before finalizing the transaction, such as verifying that you have the item in stock.
How it works
- The payer checks out and provides a card for payment.
- You authorize the payment.
- A hold is placed on the payer's card until you are ready to capture payment.
- You finalize the transaction and capture the payment.
- The payer's card is charged.
Know before you code
This client- and server-side feature modifies an existing checkout integration and uses the following:
- PayPal JavaScript SDK
- Orders REST API
- Payments REST API
Use Postman to explore and test PayPal APIs.
Note: Authorization and capture can incur merchant fees in some markets. For more information, see your PayPal User Agreement.
1. Separate authorize and capture in the approval intent
The default approval intent of the JavaScript SDK is to both authorize the transaction and capture payment immediately. To split authorize and capture into separate actions, add &intent=authorize
to the JavaScript SDK script tag, as shown in the following example:
<script
src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&intent=authorize">
</script>
2. Authorize payment
The onApprove
function in the default integration captures the payment immediately. Replace the existing onApprove
function with the following code. This code authorizes the payment but doesn't capture it.
onApprove: function(data) {
// Authorize the transaction
return fetch('/my-server/authorize-paypal-order', {
method: 'post',
body: JSON.stringify({
orderID: data.orderID
})
})
.then(response => response.json())
.then((authorizePayload) => {
// Get the authorization id from your payload
const authorizationID = authorizePayload.authorizationID;
// Optional message given to purchaser
alert(`
You have authorized this transaction.
Order ID: ${data.orderID}
Authorization ID: ${authorizationID}
`);
// Later you can use your server to validate and capture the transaction
});
})
}
Step result
A successful authorization results in:
- A
Pending
transaction in your business account. - A hold on the money that is valid for 29 days. After a successful authorization, capture the payment within the 3-day honor period. Payment capture is subject to risk and money availability.
You can use your server-side code to capture the order ID and authorization ID passed in the fetch
method in the onApprove
function.
3. Capture order and authorization IDs
Each server implementation is different. Make sure you have logic in your server-side code to receive the order ID and authorization ID that you pass from the client-side JavaScript fetch
function.
4. Save transaction information
Copy the following code and modify it to save the details to your server-side database:
Sample request
API endpoint used: Show order details
curl -v -X GET https://api-m.sandbox.paypal.com/v2/checkout/orders/48S239579N169645 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <Access-Token>"
Modify the code
After you copy the code in the sample request, modify the following:
Access-Token
- Your access token.- Order ID - In the URI for the API call, replace the sample ID with your order ID. In this example, the sample order ID is
48S239579N169645
.
Step result
A successful request results in the following:
- A return status code of HTTP
200 OK
. - A JSON response body containing order details that you can save to your server-side database.
After you capture the order details, you can complete any business tasks, such as verifying you have the item in stock, before you capture the payment.
Sample response
{
"id": "48S239579N1696452",
"intent": "AUTHORIZE",
"purchase_units": [{
"reference_id": "default",
"amount": {
"currency_code": "USD",
"value": "30.00"
},
"payee": {
"email_address": "test-facilitator@email.com",
"merchant_id": "JK9AB28SRU4XL"
},
"shipping": {
"name": {
"full_name": "Test Buyer"
},
"address": {
"address_line_1": "1 Main St",
"admin_area_2": "San Jose",
"admin_area_1": "CA",
"postal_code": "95131",
"country_code": "US"
}
},
"payments": {
"authorizations": [{
"status": "CREATED",
"id": "66P728836U784324A",
"amount": {
"currency_code": "USD",
"value": "30.00"
},
"seller_protection": {
"status": "ELIGIBLE",
"dispute_categories": ["ITEM_NOT_RECEIVED", "UNAUTHORIZED_TRANSACTION"]
},
"expiration_time": "2020-01-01T15:57:51Z",
"links": [{
"href": "https://api-m.sandbox.paypal.com/v2/payments/authorizations/66P728836U784324A",
"rel": "self",
"method": "GET"
}, {
"href": "https://api-m.sandbox.paypal.com/v2/payments/authorizations/66P728836U784324A/capture",
"rel": "capture",
"method": "POST"
}, {
"href": "https://api-m.sandbox.paypal.com/v2/payments/authorizations/66P728836U784324A/void",
"rel": "void",
"method": "POST"
}, {
"href": "https://api-m.sandbox.paypal.com/v2/payments/authorizations/66P728836U784324A/reauthorize",
"rel": "reauthorize",
"method": "POST"
}, {
"href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/48S239579N1696452",
"rel": "up",
"method": "GET"
}],
"create_time": "2020-02-03T15:57:51Z",
"update_time": "2020-02-03T15:57:51Z"
}]
}
}],
"payer": {
"name": {
"given_name": "Test",
"surname": "Buyer"
},
"email_address": "test-buyer@email.com",
"payer_id": "8Y7QBG68GYPHQ",
"address": {
"country_code": "US"
}
},
"create_time": "2020-02-03T15:57:17Z",
"update_time": "2020-02-03T15:57:51Z",
"links": [{
"href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/48S239579N1696452",
"rel": "self",
"method": "GET"
}],
"status": "COMPLETED"
}
5. Reauthorize payment
If you haven’t captured the payment within 3 days of authorization, you can reauthorize the payment to make sure the money is still available.
You can issue multiple reauthorizations within the 29-day authorization period after the honor period expires. A reauthorization generates a new authorization ID and restarts the 3-day honor period. Use the new authorization ID on subsequent captures.
If you reauthorize on the 27th day of the authorization period, you get only 2 days of the honor period.
To reauthorize a payment, copy the following code and modify it.
Sample request
API endpoint used: Reauthorize authorized payment
curl -v -X POST https://api-m.sandbox.paypal.com/v2/payments/authorizations/66P728836U784324A/reauthorize \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <Access-Token>" \
-H "PayPal-Request-Id: 123e4567-e89b-12d3-a456-426655440040" \
Modify the code
After you copy the code in the sample request, modify the following:
Access-Token
- Your access token.- Authorization ID - In the URI of the API call, replace the sample ID with your authorization ID. In this example, the authorization ID is
66P728836U784324A
. PayPal-RequestId
- Replace the sample ID with a unique ID that you generate. The PayPal request ID helps prevent duplicate authorizations if the API call is interrupted. For more information, see API idempotency.
Step result
A successful request results in the following:
- A return status code of HTTP
201 Created
. - A JSON response body containing a new authorization ID that you can use to capture the payment.
Sample response
{
"id": "8AA831015G517922L",
"status": "CREATED",
"links": [{
"rel": "self",
"method": "GET",
"href": "https://api-m.paypal.com/v2/payments/authorizations/8AA831015G517922L"
}, {
"rel": "capture",
"method": "POST",
"href": "https://api-m.paypal.com/v2/payments/authorizations/8AA831015G517922L/capture"
}, {
"rel": "void",
"method": "POST",
"href": "https://api-m.paypal.com/v2/payments/authorizations/8AA831015G517922L/void"
}, {
"rel": "reauthorize",
"method": "POST",
"href": "https://api-m.paypal.com/v2/payments/authorizations/8AA831015G517922L/reauthorize"
}]
}
6. Capture payment
To capture the payment, copy the following code and modify it.
Sample request
API endpoint used: Capture authorized payment
curl -v -X POST https://api-m.sandbox.paypal.com/v2/payments/authorizations/66P728836U784324A/capture \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <Access-Token>" \
-H "PayPal-Request-Id: 123e4567-e89b-12d3-a456-426655440010" \
Modify the code
After you copy the code in the sample request, modify the following:
Access-Token
- Your access token.- Authorization ID - In the URI for the API call, replace the sample ID with your authorization ID. The authorization ID is either the original authorization ID or the ID from reauthorizing the transaction.
PayPal-RequestId
- Replace the sample ID with a unique ID you generate. The PayPal request ID helps prevent duplicate authorizations if the API call is interrupted. For more information, see API idempotency.
Step result
A successful request results in the following:
- A return status code of HTTP
201 Created
. - A JSON response body containing details for the captured payment. Use the that is ID returned if you need to refund the transaction in the future.
- The transaction in your business account changes from
Pending
toCompleted
.
Sample response
{
"id": "5KA38057EC136584R",
"status": "COMPLETED",
"links": [{
"href": "https://api-m.sandbox.paypal.com/v2/payments/captures/5KA38057EC136584R",
"rel": "self",
"method": "GET"
}, {
"href": "https://api-m.sandbox.paypal.com/v2/payments/captures/5KA38057EC136584R/refund",
"rel": "refund",
"method": "POST"
}, {
"href": "https://api-m.sandbox.paypal.com/v2/payments/authorizations/66P728836U784324A",
"rel": "up",
"method": "GET"
}]
}
Next steps
Test in the PayPal sandbox, then go live in PayPal's live environment.
See also
- Authorization and honor periods — Learn more about the authorization and honor period that govern two-step payment solutions
- Payments REST API — Learn about other payment tasks you can complete, including how to void authorized transactions and refund a captured payment.