Delay disbursement

DocsCurrent


Use this integration to hold funds from a buyer before disbursing it to your seller. Holding funds gives you time to conduct additional vetting. If you want to capture funds immediately, use Immediate capture.

Delayed disbursement supports:

  • Authorization: Set intent to authorize in the create order call to authorize a payment and place funds on hold after the customer makes a payment.
  • Capture: Set intent to capture create order call to capture payment immediately after the customer makes a payment.

Note: Funds are automatically disbursed to the seller after 28 days, and PayPal deducts fees from the seller’s funds.

Know before you code

Required

To use this integration you must:

Run in Postman

Note: This server-side integration uses the Orders REST API for this server-side integration.

1. Generate PayPal-Auth-Assertion header

You’ll need to Pass the PayPal-Auth-Assertion header with the standard Content-Type, Authorization, and PayPal-Request-ID headers. The value of the PayPal-Auth-Assertion header can be generated as follows:

1const clientId = "CLIENT-ID";
2const sellerPayerId = "SELLER=PAYER=ID"
3const jwt = getAuthAssertionValue(clientId, sellerPayerId);
4console.log(jwt);
5function getAuthAssertionValue(clientId, sellerPayerId) {
6 const header = {
7 "alg": "none"
8 };
9 const encodedHeader = base64url(header);
10 const payload = {
11 "iss": clientId,
12 "payer_id": sellerPayerId
13 };
14 const encodedPayload = base64url(payload);
15 return `${encodedHeader}.${encodedPayload}.`;
16}
17function base64url(json) {
18 return btoa(JSON.stringify(json)).replace(/=+$/, '').replace(/+/g, '-').replace(///g, '_');
19}

Note: This example contains two period (.) characters, which are required.

Modify the code

  • Use the client ID with the client ID of the platform or marketplace from your PayPal Developer dashboard.
  • The sellerPayerId is the payer ID of the reciving seller's PayPal account. You can also use `email` instead of payer_id and supply the email address of the seller's PayPal account.

Example functions to generate the PayPal-Auth-Assertion header:

Node.js

1const clientID = "CLIENT-ID";
2const merchantIDOrEmail = "identity_seller@paypal.com";
3const auth1 = Buffer.from('{"alg":"none"}').toString("base64");
4const auth2 = Buffer.from(`{"iss":${clientID},"payer_id":${merchantIDOrEmail}}`).toString("base64");
5const authAssertionHeader = `${auth1}.${auth2}.`;

Java

1import org.apache.commons.codec.binary.Base64;
2public class Base64Encode {
3public static void main(String[] args)
4{
5 String header = "{"alg":"none"}";
6 String payload = "{"email":"identity_seller@paypal.com","iss":"CLIENT-ID"}";
7 //iss is the client id of the actor and email is the email id of the subject
8 byte[] encodedBytes = Base64.encodeBase64(header.getBytes());
9 System.out.println("Header encoded " + new String(encodedBytes));
10 byte[] encodedBytesPayload = Base64.encodeBase64(payload.getBytes());
11 System.out.println("Payload encoded " + new String(encodedBytesPayload));
12 System.out.println("Paypal-Auth-Assertion=" + new String(encodedBytes) + "." + new String(encodedBytesPayload) + ".");
13 }
14}

2. Create order

You must first create an order and capture funds. To create an order, copy the following code and modify as follows:

  • Replace BN-CODE with your PayPal attribution ID.
  • Replace PAYPAL-AUTH-ASSERTION with your PayPal auth assertion generated from Step 1.
  • Use the purchase_units/payee object to specify the end receiver of the funds.
  • Use the purchase_units/payment_instruction/disbursement_mode field to specify when funds should be disbursed to the payee upon calling capture order. In this integration, set this field to DELAYED.
  • Use the purchase_units/payment_instruction/platform_fees array to specify fees for the order. You must onboard your seller with the PARTNER_FEE feature to use this array.

Sample request - cURL

1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders
2-H 'Content-Type: application/json'
3-H 'Authorization: Bearer ACCESS-TOKEN'
4-H 'PayPal-Partner-Attribution-Id: BN-CODE'
5-H 'PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION'
6-d '{
7 "intent": "CAPTURE",
8 "purchase_units": [{
9 "amount": {
10 "currency_code": "USD",
11 "value": "100.00"
12 },
13 "payee": {
14 "email_address": "seller@example.com"
15 },
16 "payment_instruction": {
17 "disbursement_mode": "DELAYED",
18 "platform_fees": [{
19 "amount": {
20 "currency_code": "USD",
21 "value": "25.00"
22 }
23 }]
24 }
25 }]
26 }'

Sample request - Node

1var express = require('express');
2var request = require('request');
3express().post('/my-server/create-order', function(req, res) {
4 request.post('https://api-m.sandbox.paypal.com/v2/checkout/orders', {
5 headers: {
6 "Content-Type": "application/json",
7 "Authorization": "Bearer ACCESS-TOKEN",
8 "PayPal-Partner-Attribution-Id": "BN-CODE",
9 "PayPal-Auth-Assertion": "PAYPAL-AUTH-ASSERTION"
10 },
11 body: {
12 "intent": "CAPTURE",
13 "purchase_units": [{
14 "amount": {
15 "currency_code": "USD",
16 "value": "100.00"
17 },
18 "payee": {
19 "email_address": "seller@example.com"
20 },
21 "payment_instruction": {
22 "disbursement_mode": "DELAYED",
23 "platform_fees": [{
24 "amount": {
25 "currency_code": "USD",
26 "value": "25.00"
27 }
28 }]
29 }
30 }],
31 },
32 json: true
33 }, function(err, response, body) {
34 if (err) {
35 console.error(err);
36 return res.sendStatus(500);
37 }
38 res.json({
39 id: body.id
40 });
41 });
42});

3. Capture order

After your buyer approves the order, call capture order to capture the buyer’s funds.

Copy the following code and modify as follows:

  • Replace ACCESS-TOKEN with your access token.
  • Replace BN-CODE with your PayPal partner attribution ID.
  • Replace PAYPAL-AUTH-ASSERTION with your PayPal auth assertion generated from Step 1.

Sample request - cURL

1curl -v -k -X POST https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T/capture
2-H 'Content-Type: application/json'
3-H 'Authorization: Bearer ACCESS-TOKEN'
4-H 'PayPal-Partner-Attribution-Id: BN-CODE'
5-H 'PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION'
6-d '{}'

Sample request - Node

1var express = require('express');
2var request = require('request');
3express().post('/my-server/handle-approve/:id', function(req, res) {
4 var OrderID = req.params.id;
5 request.post('https://api-m.sandbox.paypal.com/v2/checkout/orders/' + OrderID + '/capture', {
6 headers: {
7 "Content-Type": "application/json",
8 "Authorization": "Bearer ACCESS-TOKEN",
9 "PayPal-Partner-Attribution-Id": "BN-CODE",
10 "PayPal-Auth-Assertion": "PAYPAL-AUTH-ASSERTION"
11 }
12 }, function(err, response, body) {
13 if (err) {
14 console.error(err);
15 return res.sendStatus(500);
16 }
17 res.json({
18 status: 'success'
19 });
20 });
21});

Note: Note: Orders cannot be captured until the status of the order is set to APPROVED. The order status is set to APPROVED when the buyer successfully completes the checkout flow.

4. Show order details

To see your order details, pass the order ID as a path parameter in a show order details call.

Copy the following code and modify as follows:

  • Replace ACCESS-TOKEN with your access token.
  • Replace BN-CODE with your PayPal partner attribution ID.
  • Replace PAYPAL-AUTH-ASSERTION with your PayPal auth assertion generated from Step 1.

Sample request - cURL

1curl -v -X GET https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T
2-H "Content-Type: application/json"
3-H 'Authorization: Bearer ACCESS-TOKEN'
4-H 'PayPal-Partner-Attribution-Id: BN-CODE'
5-H 'PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION'

Sample request - Node

1var http = require("https");
2var options = {
3 "method": "GET",
4 "hostname": "api-m.sandbox.paypal.com",
5 "port": null,
6 "path": "/v2/checkout/orders/5O190127TN364715T",
7 "headers": {
8 "Content-Type": "application/json",
9 "Authorization": "Bearer ACCESS-TOKEN",
10 "PayPal-Partner-Attribution-Id": "BN-CODE",
11 "PayPal-Auth-Assertion": "PAYPAL-AUTH-ASSERTION"
12 }
13};
14var req = http.request(options, function(res) {
15 var chunks = [];
16 res.on("data", function(chunk) {
17 chunks.push(chunk);
18 });
19 res.on("end", function() {
20 var body = Buffer.concat(chunks);
21 console.log(body.toString());
22 });
23});
24req.end();

A successful request returns the HTTP 200 OK status code and a JSON response body that shows order details.

1{
2 "id": "5O190127TN364715T",
3 "status": "CREATED",
4 "intent": "CAPTURE",
5 "purchase_units": [
6 {
7 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
8 "amount": {
9 "currency_code": "USD",
10 "value": "100.00"
11 }
12 }
13 ],
14 "create_time": "2018-04-01T21:18:49Z",
15 "links": [
16 {
17 "href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
18 "rel": "self",
19 "method": "GET"
20 },
21 {
22 "href": "https://www.paypal.com/checkoutnow?token=5O190127TN364715T",
23 "rel": "approve",
24 "method": "GET"
25 },
26 {
27 "href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T/capture",
28 "rel": "capture",
29 "method": "POST"
30 }
31 ]
32}

5. Disburse funds

Once funds are captured, call /v1/payments/referenced-payouts-items to disburse funds to your seller. To make this call you must pass a reference_id. Retrieve the reference_id by making a show order details call and note down the urchase_units/payments/captures/id field.

Copy the following code and modify as follows:

Sample request - cURL

1curl -v https://api-m.sandbox.paypal.com/v1/payments/referenced-payouts-items
2-X POST
3-H "Content-Type: application/json"
4-H "Authorization: Bearer ACCESS-TOKEN"
5-H "PayPal-Partner-Attribution-Id: BN-CODE"
6-d '{
7 "reference_id": "29N36144XH0198422",
8 "reference_type": "TRANSACTION_ID"
9}'

Sample request - Node

1var http = require("https");
2var options = {
3 "method": "GET",
4 "hostname": "api-m.sandbox.paypal.com",
5 "port": null,
6 "path": "/v2/checkout/orders/5O190127TN364715T",
7 "headers": {
8 "content-type": "application/json",
9 "Authorization": "Bearer ACCESS-TOKEN",
10 }
11};
12var req = http.request(options,
13function (res) {
14 var chunks = [];
15 res.on("data ", function (chunk) {
16 chunks.push(chunk);
17 });
18 res.on("end ", function () {
19 var body = Buffer.concat(chunks);
20 console.log(body.toString());
21 })
22;});
23req.end();

A successful request returns the HTTP 200 OK status code and a JSON response body that shows order details.

Next steps

Recommended
Integration Checklist

Go through the integration checklist before you go live.