PayPal

Server-Side Implementation

Important

Your integration may be impacted by upcoming certificate changes. Visit our best practices guide to learn more.

GraphQL

Click here to view the server-side implementation using GraphQL.

Creating transactionsAnchorIcon

Once the customer has successfully authenticated with PayPal, include the paymentMethodNonce() parameter in the Transaction: Sale call on your server.

Updating PayPal Payment Resource After Buyer ApprovalAnchorIcon

In certain edge cases, merchants may need to update some transaction parameters, such as the total amount, after the buyer has approved the payment in the PayPal checkout window. In such cases, it is essential to include updated line items in the server-side call to ensure the final amount reflects the correct total.

These updates can include modifications to line items, currency, custom fields, or any other supported parameter.
To complete an update, use the PayPalPaymentResource.update() method on the server side after tokenization of the payment resource and before calling Customer.create() to vault the payment method.

Note
The paymentMethodNonce is a required parameter. The update() call returns a new nonce, which must be used with Customer.create() to ensure the updated payment resource is properly vaulted. In addition to the required parameter, merchants can include any optional fields in the update call based on what needs to be modified. The sample code snippet below includes the full list of supported parameters. You can update only the fields relevant to your specific use case.
  1. Java
PayPalPaymentResourceRequest request = new PayPalPaymentResourceRequest().
            amount(new BigDecimal("55.00")).
            amountBreakdown().
                discount(new BigDecimal("15.00")).
                handling(new BigDecimal("0.00")).
                insurance(new BigDecimal("5.00")).
                itemTotal(new BigDecimal("45.00")).
                shipping(new BigDecimal("10.00")).
                shippingDiscount(new BigDecimal("0.00")).
                taxTotal(new BigDecimal("10.00")).
                done().
            currencyIsoCode("USD").
            customField("0437").
            description("This is a test").
            addLineItem(lineItem).
            orderId("order-123456789").
            payeeEmail("bt_buyer_us@paypal.com").
            paymentMethodNonce(nonce).
            shipping().
                firstName("John").
                lastName("Doe").
                streetAddress("123 Division Street").
                extendedAddress("Apt. #1").
                locality("Chicago").
                region("IL").
                postalCode("60618").
                countryName("United States").
                countryCodeAlpha2("US").
                countryCodeAlpha3("USA").
                countryCodeNumeric("484").
                internationalPhone().
                    countryCode("1").
                    nationalNumber("4081111111").
                    done().
                done().
            shippingOption().
                amount(new BigDecimal("10.00")).
                id("option1").
                label("fast").
                selected(true).
                type("SHIPPING").
                done();

        Result<PaymentMethodNonce> result = gateway.paypalPaymentResource().update(request);
        assertTrue(result.isSuccess());

        PaymentMethodNonce newNonce = result.getTarget();
        assertNotNull(newNonce);
        assertNotNull(newNonce.getNonce());


Using device dataAnchorIcon

If the PayPal transaction was initiated from a Vault record and is not a recurring transaction, collect device data from the client and include the collected client device data via the top-level deviceData parameter. Doing so will help reduce decline rates.

Below includes an example call with relevant PayPal parameters and device data:

  1. Java
TransactionRequest request = new TransactionRequest()
  .amount(request.queryParams("amount"))
  .paymentMethodNonce(request.queryParams("paymentMethodNonce"))
  .deviceData(request.queryParams("device_data"))
  .orderId("Mapped to PayPal Invoice Number")
  .options()
    .submitForSettlement(true)
    .paypal()
      .customField("PayPal custom field")
      .description("Description for PayPal email receipt")
      .done()
    .storeInVaultOnSuccess(true)
    .done();

Result<Transaction> saleResult = gateway.transaction().sale(request);

if (result.isSuccess()) {
  Transaction transaction = result.getTarget();
  System.out.println("Success ID: " + transaction.getId());
} else {
  System.out.println("Message: " + result.getMessage());
}

See the recurring transactions section below for more information on recurring transactions.

If you want to create a new payment method in the Vault upon a successful transaction , use the options-storeInVaultOnSuccess() option. If a customerId is not included, a new customer will be created. If you want to include a PayPal Billing Agreement with the vaulted payment method, use the Checkout with Vault flow .

Currency supportAnchorIcon

The customer will be charged in the currency associated with the merchantAccountId passed in the Transaction: Sale call. We support all currencies that PayPal REST APIs support .

For details on accepting foreign currencies with PayPal, see our PayPal account setup guide .

Shipping addressesAnchorIcon

If you've collected a shipping address, you will need to pass that along with the Transaction: Sale call. The following fields are required when passing a shipping address for PayPal transactions:

For details on how to add a shipping address when creating a transaction, see the transaction reference full example . PayPal validates the shipping address, so it must follow the PayPal address conventions .

When creating a transaction using a PayPal account stored in the Vault, see the example of using stored addresses as well as the billingAddressId() and shippingAddressId() parameters.

Seller ProtectionAnchorIcon

By passing a shipping address, you may also be eligible for PayPal Seller Protection . You can check the status of Seller Protection as follows:

  1. Java
Transaction transaction = gateway.transaction().find("the_transaction_id");

transaction.getPayPalDetails().getSellerProtectionStatus();
// "ELIGIBLE"

SettlementAnchorIcon

Unlike most payment types that settle in batches, we capture PayPal funds immediately when you submit each transaction for settlement .

Capturing greater than authorization amountAnchorIcon

You can't settle more than the authorized amount unless your industry and processor support settlement adjustment (settling a certain percentage over the authorized amount); contact us for details. If your capture amount exceeds the allowable limit you will receive the respective settlement response code .

Capturing multiple partial amounts against the same authorizationAnchorIcon

If you send physical goods to customers in multiple shipments, you can capture the total authorized amount across multiple partial settlements using Transaction: Submit For Partial Settlement .

Recurring transactionsAnchorIcon

Recurring payments are merchant-initiated payments based on a schedule or other service usage criteria and fall into several categories based on billing frequency and amount. transactionSource() parameter with a value of recurring if the customer is not present when you create a PayPal transaction from their Vault record. Typical examples are a recurring subscription or an automatic top-up charge.

Note

You won't need to do this if you're using our recurring billing system – our logic creates subscription transactions with this parameter automatically. If you've built your own recurring logic, though, be sure your transaction sale calls include the recurring parameter.

  1. Java
TransactionRequest transactionRequest = new TransactionRequest()
  .amount(new BigDecimal("1000.00"))
  .paymentMethodToken("the_token")
  .transactionSource("recurring")
  .options()
    .submitForSettlement(true);

Result<Transaction> result = gateway.transaction().sale(transactionRequest);

See also


Next Page: Testing and Go Live