Capture payments later

Authorizing and capturing funds enables you to build a payment interface that places funds, from a funding source, on hold (authorization) until a service is rendered or order shipped, at which time the payment is processed (capture).

To complete an authorization, and later capture, complete these steps:

1. Set up the authorization information object.
2. Initialize the authorization and redirect the user.
3. Complete the payment and get the authorization ID.
4. At a later time, capture authorization.

Tip: An authorized payment places funds on hold for a later payment while an order indicates that the buyer has consented to the purchase but does not place the funds on hold.

Set up the authorization information object

The authorization object defines the method of payment, transaction details, where to redirect the user after he or she accepts the payment on PayPal, and so on. To start the authorization, create this object:

// Build PayPal payment request.
var payReq = JSON.stringify({
  intent: 'authorize',
  payer: {
    payment_method: 'paypal'
  },
  redirect_urls: {
    return_url: 'http://localhost:3000/process',
    cancel_url: 'http://localhost:3000/cancel'
  },
  transactions: [{
    amount: {
      total: '5.54',
      currency: 'USD'
    },
    description: 'This is the payment transaction description.',
  }]
});
use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\PaymentExecution;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;

// Create new payer and method
$payer = new Payer();
$payer->setPaymentMethod("paypal");

// Set redirect urls
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl("http://localhost:3000/process")
  ->setCancelUrl("http://localhost:3000/cancel");

// Set payment amount
$amount = new Amount();
$amount->setCurrency("USD")
  ->setTotal(4.54);

// Set transaction object
$transaction = new Transaction();
$transaction->setAmount($amount)
  ->setDescription("Payment description");

// Create the full payment object
$payment = new Payment();
$payment->setIntent("authorize")
  ->setPayer($payer)
  ->setRedirectUrls($redirectUrls)
  ->setTransactions(array($transaction));
from paypalrestsdk import Payment
from paypalrestsdk import Authorization

# Create payment object
payment = Payment({
  "intent": "authorize",

  # Set payment method
  "payer": {
    "payment_method": "paypal"
  },

  # Set redirect urls
  "redirect_urls": {
    "return_url": "http://localhost:3000/process",
    "cancel_url": "http://localhost:3000/cancel"
  },

  # Set transaction object
  "transactions": [{
    "amount": {
      "total": "4.54",
      "currency": "USD"
    },
    "description": "payment description"
  }]
})
# Create payment object
payment = Payment.new({
  :intent =>  "authorize",

  # Set payment type
  :payer =>  {
    :payment_method =>  "paypal"
  },

  # Set redirect urls
  :redirect_urls => {
    :return_url => "http://localhost/payment/execute",
    :cancel_url => "http://localhost:3000/"
  },

  # Set transaction object
  :transactions =>  [{

    # Items
    :item_list => {
      :items => [{
        :name => "item",
        :sku => "item",
        :price => "10",
        :currency => "USD",
        :quantity => 1
      }]
    },

    # Amount - must match item list breakdown price
    :amount =>  {
      :total =>  "10",
      :currency =>  "USD"
    },
    :description =>  "payment description."
  }]
})
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.paypal.api.payments.Amount;
import com.paypal.api.payments.Authorization;
import com.paypal.api.payments.Capture;
import com.paypal.api.payments.Details;
import com.paypal.api.payments.Links;
import com.paypal.api.payments.Payer;
import com.paypal.api.payments.Payment;
import com.paypal.api.payments.PaymentExecution;
import com.paypal.api.payments.RedirectUrls;
import com.paypal.api.payments.Transaction;
import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.PayPalRESTException;

// Add payer details
Payer payer = new Payer();
payer.setPaymentMethod("paypal");

// Redirect URLs
RedirectUrls redirectUrls = new RedirectUrls();
redirectUrls.setCancelUrl("http://localhost:3000/cancel");
redirectUrls.setReturnUrl("http://localhost:3000/process");

// Set payment details
Details details = new Details();
details.setShipping("0.50");
details.setSubtotal("4");
details.setTax("0.04");

// Payment amount
Amount amount = new Amount();
amount.setCurrency("USD");
// Total must be equal to sum of shipping, tax and subtotal.
amount.setTotal("4.54");
amount.setDetails(details);

// Transaction information
Transaction transaction = new Transaction();
transaction.setAmount(amount);
transaction.setDescription("This is the payment transaction description.");

// Add transaction to a list
ListTransaction transactions = new ArrayListTransaction();
transactions.add(transaction);

// Add payment details
Payment payment = new Payment();
payment.setIntent("authorize");
payment.setPayer(payer);
payment.setTransactions(transactions);
payment.setRedirectUrls(redirectUrls);
var payer = new Payer() { payment_method = "paypal" };

var guid = Convert.ToString((new Random()).Next(100000));
var redirUrls = new RedirectUrls()
{
  cancel_url = "http://localhost:3000/cancel",
  return_url = "http://localhost:3000/process"
};

var itemList = new ItemList()

{
  items = new List()
  {
    new Item()
    {
      name = "Item Name",
      currency = "USD",
      price = "15",
      quantity = "5",
      sku = "sku"
    }
  }
};

var details = new Details()
{
  tax = "15",
  shipping = "10",
  subtotal = "75"
};

var amount = new Amount()
{
  currency = "USD",
  total = "100.00", // Total must be equal to sum of shipping, tax and subtotal.
  details = details
};

var transactionList = new List();

transactionList.Add(new Transaction()
{
  description = "Transaction description.",
  invoice_number = Common.GetRandomInvoiceNumber(),
  amount = amount,
  item_list = itemList
});

var payment = new Payment()
{
  intent = "authorize",
  payer = payer,
  transactions = transactionList,
  redirect_urls = redirUrls
};

Set the intent to authorize to request an authorization for any payment type, including a credit card or PayPal payment. The intent is what defines a payment as an authorization, direct payment, or an order.

Initialize the authorization and redirect the user

With the authorization object set, you can create the approval process on PayPal. Issue a call to create the authorization, passing in the authorization information object that was set in the previous step.

paypal.payment.create(payReq, function (error, payment) {
  var links = {};

  if (error){
    console.error(JSON.stringify(error));
  } else {
    // Capture HATEOAS links.
    payment.links.forEach(function (linkObj) {
      links[linkObj.rel] = {
        href: linkObj.href,
        method: linkObj.method
      };
    });

    // When approval_url is present, redirect user.
    if (links.hasOwnProperty('approval_url')) {
      // REDIRECT USER TO links['approval_url'].href
    } else {
      console.error('no redirect URI present');
    }
  }
});
// Create payment with valid API context
try {
  $payment->create($apiContext);

  // Get paypal redirect URL and redirect user
  $approvalUrl = $payment->getApprovalLink();

  // REDIRECT USER TO $approvalUrl
} catch (PayPal\Exception\PayPalConnectionException $ex) {
  echo $ex->getCode();
  echo $ex->getData();
  die($ex);
} catch (Exception $ex) {
  die($ex);
}
# Create payment
if payment.create():
  # Extract redirect url
  for link in payment.links:
    if link.method == "REDIRECT":
      # Capture redirect url
      redirect_url = str(link.href)

      # REDIRECT USER to redirect_url
else:
  print("Error while creating payment:")
  print(payment.error)
# Create payment
if payment.create
  # Capture redirect url
  redirect_url = payment.links.find{|v| v.rel == "approval_url" }.href

  # REDIRECT USER TO redirect_url
else
  logger.error payment.error.inspect
end
// Create authorization payment
try {
  Payment createdPayment = payment.create(apiContext);

  Iterator links = createdPayment.getLinks().iterator();
  while (links.hasNext()) {
    Links link = links.next();
    if (link.getRel().equalsIgnoreCase("approval_url")) {
      // REDIRECT USER TO link.getHref()
    }
  }
} catch (PayPalRESTException e) {
  System.err.println(e.getDetails());
}
var createdPayment = payment.Create(apiContext);

var links = createdPayment.links.GetEnumerator();
while (links.MoveNext())
{
  var link = links.Current;
  if (link.rel.ToLower().Trim().Equals("approval_url"))
  {
    // REDIRECT USER TO link.href
  }
}

Once you send the request to create an authorization, PayPal will respond with a JSON response that includes a links object. Within the links object is the approval_url, which is the location that you need to redirect the user so that they can verify (or cancel) the authorization.

Complete the payment and get the authorization ID

After the user confirms authorization information, he or she is redirected to the URL that you specified in the payment information object in the initial step. The query string also contains the PayerID and paymentId parameters. These parameters are confirmation objects used to complete the authorization in order to get the authorization ID.

var paymentId = req.query.paymentId;
var payerId = { payer_id: req.query.PayerID };
var authid;

paypal.payment.execute(paymentId, payerId, function (error, payment) {
  if (error) {
    console.error(JSON.stringify(error));
  } else {
    if (payment.state === 'approved'
    && payment.transactions
    && payment.transactions[0].related_resources
    && payment.transactions[0].related_resources[0].authorization) {
      // Capture authorization.
      authid = payment.transactions[0].related_resources[0].authorization.id;
    } else {
      console.log('payment not successful');
    }
  }
});
// Get payment object by passing paymentId
$paymentId = $_GET['paymentId'];
$payment = Payment::get($paymentId, $apiContext);

// Execute payment with payer id
$execution = new PaymentExecution();
$execution->setPayerId($_GET['PayerID']);

try {
  // Execute payment
  $result = $payment->execute($execution, $apiContext);

  // Extract authorization id
  $authid = $payment->transactions[0]->related_resources[0]->authorization->id;
} catch (PayPal\Exception\PayPalConnectionException $ex) {
  echo $ex->getCode();
  echo $ex->getData();
  die($ex);
} catch (Exception $ex) {
  die($ex);
}
# Payment id obtained when creating the payment (following redirect)
payment = Payment.find("PAY-28103131SP722473WKFD7VGQ")

# Execute payment using payer_id obtained when creating the payment (following redirect)
if payment.execute({"payer_id": "DUFRQ8GWYMJXC"}):
  print("Payment execute successfully")
  authid = payment.transactions[0].related_resources[0].authorization.id
else:
  print(payment.error)
# Get payment id from query string following redirect
payment = Payment.find(ENV["PAYMENT_ID"])

# Execute payment using payer_id obtained from query string following redirect
if payment.execute( :payer_id => ENV["PAYER_ID"] )
  logger.info "authorization executed successfully"

  # Capture auth id
  auth_id = payment.transactions[0].related_resources[0].authorization.id;
else
  logger.error payment.error.inspect
end
Payment payment = new Payment();
payment.setId(paymentId);

PaymentExecution paymentExecution = new PaymentExecution();
paymentExecution.setPayerId(payerId);
try {
  Payment createdAuthPayment = payment.execute(apiContext, paymentExecution);
  Authorization authorization = createdAuthPayment.getTransactions().get(0).getRelatedResources().get(0).getAuthorization();
} catch (PayPalRESTException e) {
  System.err.println(e.getDetails());
}
var guid = Request.Params["guid"];

// Using the information from the redirect, setup the payment to execute.
var paymentId = Session[guid] as string;
var paymentExecution = new PaymentExecution() { payer_id = payerId };
var payment = new Payment() { id = paymentId };

// Execute authorization.
var executedPayment = payment.Execute(apiContext, paymentExecution);

// Capture authorization object
var authorization = executedPayment.transactions[0].related_resources[0].authorization;

To complete the authorization, extract the paymentId and PayerID from the query string parameters. Once obtained, make a call to the respective SDK execute method to complete the authorization. In the success response object that is returned, extract the authorization ID.

Capture authorization

To capture an authorization, set the details about the amount that you would like to capture, and whether it should be the final capture being made. Using these settings, you can make multiple captures from the same authorization. Once set, make the request to capture the authorization, passing in the authorization ID that was captured in the last step.

// Set capture details.
var capture_details = {
  amount: {
    currency: 'USD',
    total: '4.54'
  },
  is_final_capture: false
};

// Capture authorization.
paypal.authorization.capture(authid, capture_details, function (error, capture) {
  if (error) {
    console.error(JSON.stringify(error));
  } else {
    console.log(JSON.stringify(capture));
  }
});
try {
  // Set capture details
  $amt = new Amount();
  $amt->setCurrency("USD")
    ->setTotal(4.54);

  // Capture authorization
  $capture = new Capture();
  $capture->setAmount($amt);
  $getCapture = $authorization->capture($capture, $apiContext);
} catch (PayPal\Exception\PayPalConnectionException $ex) {
  echo $ex->getCode();
  echo $ex->getData();
  die($ex);
} catch (Exception $ex) {
  die($ex);
}
// Get authorization
authorization = Authorization.find(authid)

// Set capture details
capture = authorization.capture({
  "amount": {
    "currency": "USD",
    "total": "4.54"
  },
  "is_final_capture": True
})

// Capture authorization
if capture.success():
  print("Capture[%s] successfully" % (capture.id))
else:
  print(capture.error)
authorization = Authorization.find(auth_id)
capture = authorization.capture({
  :amount => {
    :currency => "USD",
    :total => "10"
  },
  :is_final_capture => true
})

if capture.success?
  logger.info "Capture[#{capture.id}]"
else
  logger.error capture.error.inspect
end
// Set capture amount
Amount amount = new Amount();
amount.setCurrency("USD");
amount.setTotal("4.54");

Capture capture = new Capture();
capture.setAmount(amount);

// Set as final capture amount
capture.setIsFinalCapture(true);

// Capture payment
Capture responseCapture = authorization.capture(apiContext, capture);

System.out.println("Capture id = " + responseCapture.getId() + " and status = " + responseCapture.getState());
var capture = new Capture()
{
  amount = new Amount()
  {
    currency = "USD",
    total = "4.54"
  },
  is_final_capture = true
};

var responseCapture = authorization.Capture(apiContext, capture);

Additional information