Authorize a payment and capture funds later
While the default for the checkout integration is a one-step payment solution, PayPal also supports two-step payments. A two-step payment solutions enables you to first authorize a card, then settle the purchase later. Authorizing a payment guarantees the funds from the card issuer, and places a hold on the customer’s card for the funds. Settling a purchase is also known as capturing the payment.
You might choose a two-step payment option when you need to complete a task before finalizing the transaction, like verifying you have the item in stock.
Know before you code
- This procedure modifies an existing checkout integration.
-
Complete the steps in Get started to get the following sandbox account information from the Developer Dashboard:
- Your sandbox client ID
- Your sandbox account login information
- Your access token
-
This client-side and server-side integration uses the following:
1. Approval intent
The default approval intent of the PayPal JavaScript SDK is to both authorize the transaction and capture funds immediately. To split authorize and capture into separate actions, add &intent=authorize
to the PayPal JavaScript SDK script tag as seen in the following example.
<script
src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&intent=authorize">
</script>
2. Update order information
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, actions) {
// Authorize the transaction
actions.order.authorize().then(function(authorization) {
// Get the authorization id
var authorizationID = authorization.purchase_units[0].payments.authorizations[0].id
alert('You have authorized this transaction. Order ID: ' + data.orderID + ', Authorization ID: ' + authorizationID); // Optional message given to purchaser
// Call your server to validate and capture the transaction
return fetch('/paypal-transaction-complete', {
method: 'post',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
orderID: data.orderID,
authorizationID: authorizationID
})
});
});
}
Step result
A successful authorization results in:
- A transaction in the merchant's account in the
Pending
status. - A hold on the funds, valid for 29 days. After a successful authorization, we recommend you capture the funds within the three-day honor period. Funds capture is subject to risk and availability of funds.
You can now create code on the server side to capture the order ID and authorization ID passed in the fetch
method in the onApprove
function.
3. Capture order and auth IDs
Each server implementation is different. Make sure you have logic in your server-side code to receive the order ID and authorization ID you pass from the client-side JavaScript fetch
function.
4. Save transaction info
To save the details to your server-side database, copy the following code and modify it.
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.
Step result
A successful request results in the following:
- A return status code of HTTP
200 OK
. - A JSON response body that contains order details that you can save to your server-side database.
Once you've captured the order details, you can complete any business tasks, like 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 three days of authorization, you can reauthorize the payment to make sure the funds are still available.
While an authorization places a hold on the funds and is valid for 29 days, we recommend that you capture the funds within the three-day honor period. Success of the capture is subject to risk and availability of funds.
Within the 29-day authorization period, you can issue multiple re-authorizations after the honor period expires. A re-authorization generates a new authorization ID and restarts the honor period. Any subsequent capture should be performed on the new authorization ID. If you do a re-authorization on the 27th day of the authorization, you get only two days of 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.
PayPal-RequestId
- Replace the sample ID with a unique ID you generate. This ID helps prevent duplicate authorizations in the event that the API call is disrupted. See also: API idempotency.
Step result
A successful request results in the following:
- A return status code of HTTP
201 Created
. - A JSON response body that contains a new authorization ID 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. This 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. This ID helps prevent duplicate captures in the event that the API call is disrupted. See also: API idempotency.
Step result
A successful request results in the following:
- A return status code of HTTP
201 Created
. - A JSON response body that contains details for the captured payment. Use the ID returned if you need to refund the transaction in the future.
- The transaction in the merchant's 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
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 if you decide not to capture the payment and how to refund a captured payment