Integrate Pay upon Invoice
DocsLast updated: July 8th 2024, @ 6:50:56 am
Pay upon Invoice is a payment method in Europe.
Countries | Payment type | Currencies | Minimum amount | Maximum amount | Refunds |
---|---|---|---|---|---|
Germany (DE ) | Deferred payment | EUR | 5 EUR | 2,500 EUR | Within 180 days |
Know before you code
- Make sure you're subscribed to the following webhook events:
- The
PAYMENT.CAPTURE.COMPLETED
webhook event indicates a successful order capture. In the case of Pay Upon Invoice, this means that the order status changed fromPENDING_APPROVAL
toAPPROVED
. - The
PAYMENT.CAPTURE.DENIED
andCHECKOUT.PAYMENT-APPROVAL.REVERSED
webhook events indicate a failed order capture.
- The
- Make sure your preference for receiving payments in your PayPal business or merchant account is set to accept and convert to the currency in your account. In your profile, select Account Settings > Payment preferences > Block payments and click Update to mark this preference.
- You can use only
intent=CAPTURE
in Create order to process payments using Pay upon Invoice. - Request that buyers provide their birth date to process payments using Pay upon Invoice.
- You are legally obligated to display the messages to the buyer as described in the Error codes and corresponding error messages to be displayed to the buyer section.
Use Postman to explore and test PayPal APIs.
Step 1: Offer Pay upon Invoice on your checkout page
Create the user interface to offer Pay upon Invoice and collect the buyer's information.
On your Pay upon Invoice checkout page you'll need to do the following:
Required. Integrate with the FraudNet JavaScript library to allow Ratepay to complete their buyer credit and risk checks.
Required. Present the following legal text to the buyer in English or German in one of the following ways:
A. Integrate with the PUI Legal Component:
1<script src="https://www.paypal.com/sdk/js?client-id=test&components=legal"></script>2 <div id="paypal-legal-container"></div>3 <script>4 paypal5 .Legal({6 fundingSource: paypal.Legal.FUNDING.PAY_UPON_INVOICE,7 })8 .render("#paypal-legal-container");9 </script>
B. Copy and paste the below text directly.- English
- German
By clicking on the button, you agree to the terms of payment and performance of a risk check from the payment partner, Ratepay. You also agree to PayPal’s privacy statement. If your request to purchase upon invoice is accepted, the purchase price claim will be assigned to Ratepay, and you may only pay Ratepay, not the merchant.Note: The legal text needs to be integrated in close proximity to the choice of the Pay Upon Invoice payment method in a way that it cannot be overlooked by the customer even at cursory glance at average attention.
Use the API calls and webhooks described in the remainder of this topic to:
- Create the order with Pay upon Invoice as the payment source.
- Listen to webhooks to get the result of the order capture and fulfill the order.
Step 2: Onboard your sellers
Onboard your sellers before payment so they can accept Pay upon Invoice as a payment method. You can also build onboarding into your software.
Follow the steps in this guide to onboard your sellers for Pay upon Invoice.
Partner Referrals API for Pay upon Invoice has a sample request and response specific to Pay upon Invoice.
Partner configuration
You must configure your account to enable Pay upon Invoice. Work with your account manager to configure the features you need.
Partner Referrals API for Pay upon Invoice
Call the Partner Referrals API to generate a sign-up link that redirects your sellers to sign up with PayPal. Passing your seller's information during the API call will pre-fill the PayPal sign-up flow with your seller's information.
Note: To accept Pay upon Invoice payments, you must pass
PAYMENT_METHODS
as the value for theproducts
parameter andPAY_UPON_INVOICE
as the value for the capabilities parameter. This is only supported with the v2 version of the Partner Referrals API.
Request sample
curl -v -X POST https://api-m.sandbox.paypal.com/v2/customer/partner-referrals \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <Access-Token>" \
-H "PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a" \
-H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \
-H "PayPal-Partner-Attribution-Id: BN-CODE" \
-d '{
"business_entity": {
"business_type": {
"type": "PRIVATE_CORPORATION"
},
"addresses": [
{
"address_line_1": "Parkstr. 26",
"admin_area_1": "Berlin",
"postal_code": "13086",
"country_code": "DE",
"type": "WORK"
}
]
},
"tracking_id": "testenterprices123122",
"partner_config_override": {
"partner_logo_url": "https://www.paypalobjects.com/webstatic/mktg/logo/pp_cc_mark_111x69.jpg",
"return_url": "https://testenterprises.com/merchantonboarded",
"return_url_description": "the url to return the merchant after the PayPal onboarding process.",
"action_renewal_url": "https://testenterprises.com/renew-exprired-url",
"show_add_credit_card": true
},
"operations": [
{
"operation": "API_INTEGRATION",
"api_integration_preference": {
"rest_api_integration": {
"integration_method": "PAYPAL",
"integration_type": "THIRD_PARTY",
"third_party_details": {
"features": [
"PAYMENT",
"REFUND",
"PARTNER_FEE"
]
}
}
}
}
],
"products": [
"PAYMENT_METHODS"
],
"capabilities": [
"PAY_UPON_INVOICE"
],
"legal_consents": [
{
"type": "SHARE_DATA_CONSENT",
"granted": true
}
]
}'
Modify the code
After you copy the code in the sample request, modify the following:
- Change
Access-Token
to your access token. - Change
PAYPAL-AUTH-ASSERTION
to your PayPal-Auth-Assertion token. - Change
BN-CODE
to your PayPal Attribution ID to receive revenue attribution. To find your BN code, see Code and Credential Reference. - It is possible to onboard a seller for the products
PPCP
andPay Upon Invoice
simultaneously. To offer this, your account must be configured for both products. In the above sample changeproducts
to["PPCP", "PAYMENT_METHODS"]
andcapabilities
to["PAY_UPON_INVOICE"]
. - Prevent duplicate transactions by passing the
PayPal-Request-Id
parameter in the header of your/v2/checkout/orders
requests. - Optional: Pass a tracking ID in the tracking_id field. You can use this ID to track the status of your seller as they complete onboarding.
Response sample
{
"links": [
{
"href": "https://api-m.sandbox.paypal.com/v2/customer/partner-referrals/ZjcyODU4ZWYtYTA1OC00ODIwLTk2M2EtOTZkZWQ4NmQwYzI3RU12cE5xa0xMRmk1NWxFSVJIT1JlTFdSbElCbFU1Q3lhdGhESzVQcU9iRT0=",
"rel": "self",
"method": "GET",
"description": "The read referral data shared by the partner."
},
{
"href": "https://api-m.sandbox.paypal.com/bizsignup/partner/entry?referralToken=ZjcyODU4ZWYtYTA1OC00ODIwLTk2M2EtOTZkZWQ4NmQwYzI3RU12cE5xa0xMRmk1NWxFSVJIT1JlTFdSbElCbFU1Q3lhdGhESzVQcU9iRT0=",
"rel": "action_url",
"method": "GET",
"description": "The target web redirect URL for the next action."
}]
}
A successful call returns a 201 created status. The following HATEOAS links are also returned:
- A self link. You can make a GET request to this link to retrieve the referral data and to reinitialize the action_url.
- An action_url link. You can place this link in a button or link tag to redirect your sellers to sign up with PayPal. The action_url expires after its first use. You can reinitialize it by making a GET request to the self link or by making another Partner Referrals API call.
Note: If you call
GET /v2/customer/partner-referrals/{partner_referral_id},
the response returns only user data you have passed in about the seller and not any data the seller might have provided on PayPal.com.
URL Onboarding
Use URL onboarding only if you have already onboarded with URL onboarding or if you have a specific use case for URL onboarding. With URL onboarding, sellers are required to complete all sign-up fields. Sellers must also have a PayPal business account. Casual sellers are not supported.
Example URL for Pay upon Invoice
https://www.sandbox.paypal.com/bizsignup/partner/entry?&partnerClientId=<var><partner_client_id></var>&partnerId=<var><partner_payer_id></var>&partnerLogoUrl=<var><partner_logo_url></var>&returnToPartnerUrl=<var><return_url_for_done_page_button></var>&product=payment_methods&capabilities=PAY_UPON_INVOICE&integrationType=FO&features=PAYMENT,REFUND&country.x=DE
Example URL for enabling PPCP and Pay upon Invoice
https://www.sandbox.paypal.com/bizsignup/partner/entry?&partnerClientId=<var><partner_client_id></var>&partnerId=<var><partner_payer_id></var>&partnerLogoUrl=<var><partner_logo_url></var>&returnToPartnerUrl=<var><return_url_for_done_page_button></var>&product=ppcp&secondaryProducts=payment_methods&capabilities=PAY_UPON_INVOICE&integrationType=FO&features=PAYMENT,REFUND&country.x=DE
Note: the query parameter
productIntentId
is not supported for Pay upon Invoice.
Track Seller Onboarding Status
You can track seller status by makings a show seller status call.
Sample response for Pay Upon Invoice
{
"merchant_id": "CG5RZJV4NR5P4",
"tracking_id": "1537989077589",
"products": [
{
"name": "PAYMENT_METHODS",
"vetting_status": "SUBSCRIBED",
"capabilities": [
"PAY_UPON_INVOICE",
"VAT_TAX",
"PAY_WITH_PAYPAL"
]
},
],
"payments_receivable": true,
"primary_email_confirmed": true,
"products.vetting status": "SUBSCRIBED",
"capabilities[name==PAY_UPON_INVOICE].status": "ACTIVE",
"capabilities[name==PAY_UPON_INVOICE].limits": {
"type": "GENERAL"
},
"oauth_integrations": [{
"integration_type": "OAUTH_THIRD_PARTY",
"integration_method": "PAYPAL",
"oauth_third_party": [
{
"partner_client_id": "Af1bGDNgFBtbJvzEkG25zt4SoNQQ3ustiLm84GWXxe8nq_HE_0wCQ9SH8M1ScmSBURBIzPiCjr5gu-Dq",
"merchant_client_id": "AQ7u3fJkUH4cdCEBidsh5U_F1RQCGjglJQdNEEsXCzvQsGsS5MmC8Dk7_ug_IlkUASJezaGqQxQQfVhQ",
"scopes": ["https://uri.paypal.com/services/payments/realtimepayment", "https://uri.paypal.com/services/payments/refund", "https://uri.paypal.com/services/payments/payment/authcapture"]
}
]
}]
}
Note: Seller Status API call will return
limits
:GENERAL
for the capabilityPAY_UPON_INVOICE
. This means that although the seller can conduct invoice payments, they are limited to a threshold to 2500€. They can visit their PayPal Business Account to lift all limits.
Step 3: Create an order with Pay upon Invoice as the payment source
Use the buyer information you captured from your user interface to create an order with Pay upon Invoice as the payment source.
Sample request
API endpoint used: Create order
curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <Access-Token>" \
-H "PAYPAL-CLIENT-METADATA-ID: d4e0d7b9-4f75-43f9-9437-d8a57c901585" \
-H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \
-H "PayPal-Partner-Attribution-Id: BN-CODE" \
-d '{
"intent": "CAPTURE",
"processing_instruction": "ORDER_COMPLETE_ON_PAYMENT_APPROVAL",
"purchase_units": [
{
"amount": {
"currency_code": "EUR",
"value": "100.00",
"breakdown": {
"item_total": {
"currency_code": "EUR",
"value": "81.00"
},
"tax_total": {
"currency_code": "EUR",
"value": "19.00"
}
}
},
"shipping": {
"name": {
"full_name": "John Doe"
},
"address": {
"address_line_1": "Taunusanlage 12",
"admin_area_2": "FRANKFURT AM MAIN",
"postal_code": "60325",
"country_code": "DE"
}
},
"items": [
{
"name": "Air Jordan Shoe",
"category": "PHYSICAL_GOODS",
"unit_amount": {
"currency_code": "EUR",
"value": "81.00"
},
"tax": {
"currency_code": "EUR",
"value": "19.00"
},
"tax_rate": "19.00",
"quantity": "1"
}
],
"invoice_id": "MERCHANT_INVOICE_ID",
"custom_id": "MERCHANT_CUSTOM_ID"
}
],
"payment_source": {
"pay_upon_invoice": {
"name": {
"given_name": "John",
"surname": "Doe"
},
"email": "buyer@example.com",
"birth_date": "1990-01-01",
"phone": {
"national_number": "6912345678",
"country_code": "49"
},
"billing_address": {
"address_line_1": "Schönhauser Allee 84",
"admin_area_2": "Berlin",
"postal_code": "10439",
"country_code": "DE"
},
"experience_context": {
"locale": "en-DE",
"brand_name": "EXAMPLE INC",
"logo_url": "https://example.com/logoUrl.svg",
"customer_service_instructions": [
"Customer service phone is +49 6912345678."
]
}
}
}
}'
Modify the code
After you copy the code in the sample request, modify the following:
Access-Token
- Your access token.PAYPAL-AUTH-ASSERTION
: Your PayPal-Auth-Assertion token.BN-CODE
: Your PayPal Attribution ID to receive revenue attribution. To find your BN code, see Code and Credential Reference.intent
- This parameter must be set toCAPTURE
as it is in this sample code.purchase_units: amount
- Pass the amount of the order and the currency code.purchase_units: items
- Pass the name, category, unit amount, tax amount and tax rate of various items in the order. Please note: only items from the categoryPHYSICAL_GOODS
are permissible for Pay Upon Invoice. If items that do not belong in this category are wrongfully tagged as such, the transaction can be reversed.purchase_units: shipping
- Pass the optional shipping name and address.payment_source
- Specify the following:pay_upon_invoice
as thepayment_source
and include thecountry_code
.- Account holder's name on
name
field. - Account holder's email on
email
field. - Account holder's date of birth on
birth_date
field. - Account holder's phone number on
phone
field. - Account holder's billing address on
billing_address
field. experience_context
- Specify preferred language, brand name, logo, and customer service instructions to be presented on Ratepay'spayment instruction
email sent to the buyer. Currently, you can only useGerman
as the preferred language (locale
=de-DE
).
processing_instruction
- Set this value toORDER_COMPLETE_ON_PAYMENT_APPROVAL
as it is in this sample code.invoice_id
- Pass the optional invoice number that identifies the order in your system. This order ID shows up in thepayment instruction
email that Ratepay sends to the buyer. We recommend that you pass this value to help Ratepay communicate with the buyer. If your request doesn't pass a value forinvoice_id
, Ratepay'spayment instruction
email shows theid
value of the PayPal checkout order resource. For this reason, theinvoice_id
value can't be modified after Step 3.- Optional: Change or add other parameters in the Create order request body to create an order that reflects the actual order details.
Step result
A successful request results in the following:
- A return status code of HTTP
201 Created
. - A JSON response body that contains the order ID. You'll use the order ID in the next step.
This indicates that Ratepay performed the buyer risk assessment successfully and approved the payment.
When the status returns PENDING_APPROVAL
, display a message to the buyer that indicates that checkout is complete. The order was confirmed, and the payer action has been completed, but the order approval process from PayPal is pending. No action is needed from the payee or payer. In Step 4, listen to the webhooks to get the result of the order capture, so you can notify the buyer offline of a successful or failed transaction.
Sample response
{
"id": "5O190127TN364715T",
"status": "PENDING_APPROVAL",
"payment_source": {
"pay_upon_invoice": {
"birth_date": "1990-01-01",
"name": {
"given_name": "John",
"surname": "Doe"
},
"email": "buyer@example.com",
"phone": {
"national_number": "6912345678",
"country_code": "49"
},
"billing_address": {
"address_line_1": "Schönhauser Allee 84",
"admin_area_2": "Berlin",
"postal_code": "10439",
"country_code": "DE"
}
}
},
"links": [
{
"href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
"rel": "self",
"method": "GET"
}
]
}
Step 4: Listen to webhooks to get the result of order capture
Listen to the following webhooks to get the result of order capture
- The
PAYMENT.CAPTURE.COMPLETED
webhook event indicates a successful order capture. - The
PAYMENT.CAPTURE.DENIED
andCHECKOUT.PAYMENT-APPROVAL.REVERSED
webhook events indicate a failed order capture.
Getting the result might be delayed by a few moments.
Sample PAYMENT.CAPTURE.COMPLETED webhook
{
"id": "WH-6WA12701B00483532-15737896PW730511B",
"event_version": "1.0",
"create_time": "2021-03-19T08:07:57.563Z",
"resource_type": "capture",
"resource_version": "2.0",
"event_type": "PAYMENT.CAPTURE.COMPLETED",
"summary": "Payment completed for EUR 1.0 EUR",
"resource": {
"id": "84745544P6340640G",
"status": "COMPLETED",
"amount": {
"value": "100.00",
"currency_code": "EUR"
},
"seller_receivable_breakdown": {
"paypal_fee": {
"value": "3.00",
"currency_code": "EUR"
},
"gross_amount": {
"value": "100.00",
"currency_code": "EUR"
},
"net_amount": {
"value": "97.00",
"currency_code": "EUR"
}
},
"custom_id": "MERCHANT_CUSTOM_ID",
"invoice_id": "MERCHANT_INVOICE_ID",
"seller_protection": {
"status": "NOT_ELIGIBLE"
},
"supplementary_data": {
"related_ids": {
"order_id": "5O190127TN364715T"
}
},
"update_time": "2021-03-19T08:07:40Z",
"create_time": "2021-03-19T08:06:45Z",
"final_capture": true,
"links": [
{
"method": "GET",
"rel": "self",
"href": "https://api-m.sandbox.paypal.com/v2/payments/captures/826413372K501814R"
},
{
"method": "POST",
"rel": "refund",
"href": "https://api-m.sandbox.paypal.com/v2/payments/captures/826413372K501814R/refund"
},
{
"method": "GET",
"rel": "up",
"href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T"
}
]
},
"links": [
{
"href": "https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-6WA12701B00483532-15737896PW730511B",
"rel": "self",
"method": "GET"
},
{
"href": "https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-6WA12701B00483532-15737896PW730511B/resend",
"rel": "resend",
"method": "POST"
}
]
}
The order ID from Step 3 should match resource.supplementary_data.related_ids.order_id
parameter in the webhook payload.
Sample PAYMENT.CAPTURE.DENIED webhook
{
"id": "WH-11M70257FM3776948-8B478027S4286991F",
"event_version": "1.0",
"create_time": "2021-03-19T08:17:29.782Z",
"resource_type": "capture",
"resource_version": "2.0",
"event_type": "PAYMENT.CAPTURE.DENIED",
"summary": "Payment denied for EUR 100.0 EUR",
"resource": {
"id": "826413372K501814R",
"status": "DECLINED",
"amount": {
"value": "100.00",
"currency_code": "EUR"
},
"seller_receivable_breakdown": {
"gross_amount": {
"value": "100.00",
"currency_code": "EUR"
},
"net_amount": {
"value": "100.00",
"currency_code": "EUR"
}
},
"custom_id": "MERCHANT_CUSTOM_ID",
"invoice_id": "MERCHANT_INVOICE_ID",
"seller_protection": {
"status": "NOT_ELIGIBLE"
},
"supplementary_data": {
"related_ids": {
"order_id": "5O190127TN364715T"
}
},
"update_time": "2021-03-19T08:17:12Z",
"create_time": "2021-03-19T08:16:01Z",
"final_capture": true,
"links": [
{
"method": "GET",
"rel": "self",
"href": "https://api-m.sandbox.paypal.com/v2/payments/captures/826413372K501814R"
},
{
"method": "POST",
"rel": "refund",
"href": "https://api-m.sandbox.paypal.com/v2/payments/captures/826413372K501814R/refund"
},
{
"method": "GET",
"rel": "up",
"href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T"
}
]
},
"links": [
{
"href": "https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-11M70257FM3776948-8B478027S4286991F",
"rel": "self",
"method": "GET"
},
{
"href": "https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-11M70257FM3776948-8B478027S4286991F/resend",
"rel": "resend",
"method": "POST"
}
]
}
The order ID from Step 3 should match resource.supplementary_data.related_ids.order_id
parameter in the webhook payload.
{
"id": "WH-COC11055RA711503B-4YM959094A144403T",
"create_time": "2021-03-19T08:17:29.782Z",
"event_type": "CHECKOUT.PAYMENT-APPROVAL.REVERSED",
"summary": "A payment has been reversed after approval.",
"resource": {
"order_id": "5O190127TN364715T",
"purchase_units": [
{
"custom_id": "MERCHANT_CUSTOM_ID",
"invoice_id": "MERCHANT_INVOICE_ID"
}
],
"payment_source": {
"pay_upon_invoice": {
"birth_date": "1990-01-01",
"name": {
"given_name": "John",
"surname": "Doe"
},
"email": "buyer@example.com",
"phone": {
"national_number": "6912345678",
"country_code": "49"
},
"billing_address": {
"address_line_1": "Schönhauser Allee 84",
"admin_area_2": "Berlin",
"postal_code": "10439",
"country_code": "DE"
}
}
}
},
"event_version": "1.0"
}
The order ID from Step 3 should match resource.order_id
parameter in the webhook payload.
Alternatively, you can get the order capture result from the Show order details endpoint.
Important: Exercise caution when polling for order capture result using Show order details endpoint. PayPal enforces rate limits on API requests.
Sample request
curl -v -X GET https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <Access-Token>" \
-H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \
-H "PayPal-Partner-Attribution-Id: BN-CODE"
Sample response
{
"id": "5O190127TN364715T",
"intent": "CAPTURE",
"status": "COMPLETED",
"processing_instruction": "ORDER_COMPLETE_ON_PAYMENT_APPROVAL",
"payment_source": {
"pay_upon_invoice": {
"birth_date": "1990-01-01",
"name": {
"given_name": "John",
"surname": "Doe"
},
"email": "buyer@example.com",
"phone": {
"national_number": "6912345678",
"country_code": "49"
},
"billing_address": {
"address_line_1": "Schönhauser Allee 84",
"admin_area_2": "Berlin",
"postal_code": "10439",
"country_code": "DE"
},
"payment_reference": "b8a1525dlYzu6Mn62umI",
"deposit_bank_details": {
"bic": "DEUTDEFFXXX",
"bank_name": "Deutsche Bank",
"iban": "DE89370400440532013000",
"account_holder_name": "Paypal - Ratepay GmbH - Test Bank Account"
}
}
},
"purchase_units": [
{
"invoice_id": "MERCHANT_INVOICE_ID",
"custom_id": "MERCHANT_CUSTOM_ID",
"amount": {
"currency_code": "EUR",
"value": "100.00",
"breakdown": {
"item_total": {
"currency_code": "EUR",
"value": "81.00"
},
"tax_total": {
"currency_code": "EUR",
"value": "19.00"
}
}
},
"shipping": {
"name": {
"full_name": "John Doe"
},
"address": {
"address_line_1": "Taunusanlage 12",
"admin_area_2": "FRANKFURT AM MAIN",
"postal_code": "60325",
"country_code": "DE"
}
},
"items": [
{
"name": "Air Jordan Shoe",
"category": "PHYSICAL_GOODS",
"unit_amount": {
"currency_code": "EUR",
"value": "100.00"
},
"tax": {
"currency_code": "EUR",
"value": "19.00"
},
"tax_rate": "19.00",
"quantity": "1"
}
],
"payments": {
"captures": [
{
"id": "826413372K501814R",
"status": "COMPLETED",
"amount": {
"currency_code": "EUR",
"value": "100.00"
},
"final_capture": true,
"seller_protection": {
"status": "NOT_ELIGIBLE"
},
"seller_receivable_breakdown": {
"gross_amount": {
"currency_code": "EUR",
"value": "100.00"
},
"paypal_fee": {
"currency_code": "EUR",
"value": "3.00"
},
"net_amount": {
"currency_code": "EUR",
"value": "97.00"
}
},
"invoice_id": "MERCHANT_INVOICE_ID",
"custom_id": "MERCHANT_CUSTOM_ID",
"links": [
{
"href": "https://api-m.paypal.com/v2/payments/captures/3C679366HH908993F",
"rel": "self",
"method": "GET"
},
{
"href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
"rel": "up",
"method": "GET"
},
{
"href": "https://api-m.paypal.com/v2/payments/captures/3C679366HH908993F/refund",
"rel": "refund",
"method": "POST"
}
],
"create_time": "2021-03-19T08:16:01Z",
"update_time": "2021-03-19T08:17:12Z"
}
]
}
}
],
"links": [
{
"href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
"rel": "self",
"method": "GET"
}
]
}
Step result
A successful request returns the HTTP 200 OK
status code with a JSON response body that returns a COMPLETED
status.
A successfully captured order has the following:
- The order status as
COMPLETED
, which means the order was captured successfully. - A capture with
COMPLETED
status is present in the response parameterpurchase_units[0].payments.captures[0]
. Theup
HATEOAS link indicates the order associated with this capture.
Step 5: Notify buyer of success
Notify the buyer of the successful transaction offline and send the instructions to pay the invoice. Obtain these instructions on a per transaction basis from the Show order details endpoint. The payment reference is present in payment_source.pay_upon_invoice.payment_reference
response parameter. Buyer needs to enter this value in the reason for transfer (dt. Verwendungszweck) during bank transfer. The deposit bank information is present in the payment_source.pay_upon_invoice.deposit_bank_details
response parameter.
Sample request
curl -v -X GET https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <Access-Token>" \
-H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \
-H "PayPal-Partner-Attribution-Id: BN-CODE"
Sample response
{
"id": "5O190127TN364715T",
"intent": "CAPTURE",
"status": "COMPLETED",
"processing_instruction": "ORDER_COMPLETE_ON_PAYMENT_APPROVAL",
"payment_source": {
"pay_upon_invoice": {
"birth_date": "1990-01-01",
"name": {
"given_name": "John",
"surname": "Doe"
},
"email": "buyer@example.com",
"phone": {
"national_number": "6912345678",
"country_code": "49"
},
"billing_address": {
"address_line_1": "Schönhauser Allee 84",
"admin_area_2": "Berlin",
"postal_code": "10439",
"country_code": "DE"
},
"payment_reference": "b8a1525dlYzu6Mn62umI",
"deposit_bank_details": {
"bic": "DEUTDEFFXXX",
"bank_name": "Deutsche Bank",
"iban": "DE89370400440532013000",
"account_holder_name": "Paypal - Ratepay GmbH - Test Bank Account"
}
}
},
"purchase_units": [
{
"invoice_id": "MERCHANT_INVOICE_ID",
"custom_id": "MERCHANT_CUSTOM_ID",
"amount": {
"currency_code": "EUR",
"value": "100.00",
"breakdown": {
"item_total": {
"currency_code": "EUR",
"value": "81.00"
},
"tax_total": {
"currency_code": "EUR",
"value": "19.00"
}
}
},
"shipping": {
"name": {
"full_name": "John Doe"
},
"address": {
"address_line_1": "Taunusanlage 12",
"admin_area_2": "FRANKFURT AM MAIN",
"postal_code": "60325",
"country_code": "DE"
}
},
"items": [
{
"name": "Air Jordan Shoe",
"category": "PHYSICAL_GOODS",
"unit_amount": {
"currency_code": "EUR",
"value": "100.00"
},
"tax": {
"currency_code": "EUR",
"value": "19.00"
},
"tax_rate": "19.00",
"quantity": "1"
}
],
"payments": {
"captures": [
{
"id": "826413372K501814R",
"status": "COMPLETED",
"amount": {
"currency_code": "EUR",
"value": "100.00"
},
"final_capture": true,
"seller_protection": {
"status": "NOT_ELIGIBLE"
},
"seller_receivable_breakdown": {
"gross_amount": {
"currency_code": "EUR",
"value": "100.00"
},
"paypal_fee": {
"currency_code": "EUR",
"value": "3.00"
},
"net_amount": {
"currency_code": "EUR",
"value": "97.00"
}
},
"invoice_id": "MERCHANT_INVOICE_ID",
"custom_id": "MERCHANT_CUSTOM_ID",
"links": [
{
"href": "https://api-m.paypal.com/v2/payments/captures/3C679366HH908993F",
"rel": "self",
"method": "GET"
},
{
"href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
"rel": "up",
"method": "GET"
},
{
"href": "https://api-m.paypal.com/v2/payments/captures/3C679366HH908993F/refund",
"rel": "refund",
"method": "POST"
}
],
"create_time": "2021-03-19T08:16:01Z",
"update_time": "2021-03-19T08:17:12Z"
}
]
}
}
],
"links": [
{
"href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
"rel": "self",
"method": "GET"
}
]
}
Step result
A successful request returns the HTTP 200 OK
status code with a JSON response body that returns a COMPLETED
status.
A successfully captured order has the following:
- The order status is
COMPLETED
, which means the order was captured successfully. - A capture with
COMPLETED
status is present in the response parameterpurchase_units[0].payments.captures[0]
. Theup
HATEOAS link indicates the order associated with this capture. - The payment reference is present in
payment_source.pay_upon_invoice.payment_reference
response parameter. Buyer needs to enter this value in the reason (dt. Verwendungszweck) during the bank transfer. - The deposit bank information is present in the
payment_source.pay_upon_invoice.deposit_bank_details
response parameter.
Send an invoice to the buyer including the payment instructions as received on a per transaction basis pointing out that payment must be made to Ratepay.
Display the appropriate error message to the buyer
Step 1 when unsuccessful returns the HTTP 422 UNPROCESSABLE_ENTITY
status code with a JSON response body that contains an error code in the issue
parameter.
Sample request
API endpoint used: Create order
curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <Access-Token>" \
-H "PAYPAL-CLIENT-METADATA-ID: d4e0d7b9-4f75-43f9-9437-d8a57c901585" \
-H "PayPal-Auth-Assertion: PAYPAL-AUTH-ASSERTION" \
-H "PayPal-Partner-Attribution-Id: BN-CODE" \
-d '{
"intent": "CAPTURE",
"processing_instruction": "ORDER_COMPLETE_ON_PAYMENT_APPROVAL",
"purchase_units": [
{
"amount": {
"currency_code": "EUR",
"value": "100.00",
"breakdown": {
"item_total": {
"currency_code": "EUR",
"value": "81.00"
},
"tax_total": {
"currency_code": "EUR",
"value": "19.00"
}
}
},
"shipping": {
"name": {
"full_name": "John Doe"
},
"address": {
"address_line_1": "Taunusanlage 12",
"admin_area_2": "FRANKFURT AM MAIN",
"postal_code": "60325",
"country_code": "DE"
}
},
"items": [
{
"name": "Air Jordan Shoe",
"category": "PHYSICAL_GOODS",
"unit_amount": {
"currency_code": "EUR",
"value": "81.00"
},
"tax": {
"currency_code": "EUR",
"value": "19.00"
},
"tax_rate": "19.00",
"quantity": "1"
}
],
"invoice_id": "MERCHANT_INVOICE_ID",
"custom_id": "MERCHANT_CUSTOM_ID"
}
],
"payment_source": {
"pay_upon_invoice": {
"name": {
"given_name": "John",
"surname": "Doe"
},
"email": "payment_source_info_cannot_be_verified@example.com",
"birth_date": "1990-01-01",
"phone": {
"national_number": "6912345678",
"country_code": "49"
},
"billing_address": {
"address_line_1": "Schönhauser Allee 84",
"admin_area_2": "Berlin",
"postal_code": "10439",
"country_code": "DE"
},
"experience_context": {
"locale": "en-DE",
"brand_name": "EXAMPLE INC",
"logo_url": "https://example.com/logoUrl.svg",
"customer_service_instructions": [
"Customer service phone is +49 6912345678."
]
}
}
}
}'
Step result
An unsuccessful request results in the following:
- A return status code of HTTP
422 Unprocessable Entity
. - A JSON response body that contains an error code in the
issue
parameter and the error description in thedescription
parameter.
Sample response
{
"name": "UNPROCESSABLE_ENTITY",
"details": [
{
"issue": "PAYMENT_SOURCE_INFO_CANNOT_BE_VERIFIED",
"description": "The combination of the payment_source name, billing address, shipping name and shipping address could not be verified. Please correct this information and try again by creating a new order."
}
],
"message": "The requested action could not be performed, semantically incorrect, or failed business validation.",
"debug_id": "82c4e721e5c58",
"links": [
{
"href": "https://developer.paypal.com/api/orders/v2/#error-PAYMENT_SOURCE_INFO_CANNOT_BE_VERIFIED",
"rel": "information_link",
"method": "GET"
}
]
}
Duplicate orders
When a duplicate order is detected, the Orders API declines the order and returns the following error code and description:
Error code: PUI_DUPLICATE_ORDER
Error description: A Pay Upon Invoice (Rechnungskauf) order with the same payload has already been successfully processed in the last few seconds. To process a new order, please try again in a few seconds.
Error codes and corresponding error messages to be displayed to the buyer
RatePay mandates that you display the error messages to the buyer as described in the below table for the following error codes.
Error code | Error message (English) | Error message (German) |
---|---|---|
PAYMENT_SOURCE_INFO_CANNOT_BE_VERIFIED | The combination of your name and address could not be validated. Please correct your data and try again. You can find further information in the Ratepay Data Privacy Statement or you can contact Ratepay using this contact form. | Die Kombination aus Ihrem Namen und Ihrer Anschrift konnte nicht validiert werden. Bitte korrigieren Sie Ihre Daten und versuchen Sie es erneut. Weitere Informationen finden Sie in den Ratepay Datenschutzbestimmungen oder nutzen Sie das Ratepay Kontaktformular. |
PAYMENT_SOURCE_DECLINED_BY_PROCESSOR | It is not possible to use the selected payment method. This decision is based on automated data processing. You can find further information in the Ratepay Data Privacy Statement or you can contact Ratepay using this contact form. | Die gewählte Zahlungsart kann nicht genutzt werden. Diese Entscheidung basiert auf einem automatisierten Datenverarbeitungsverfahren. Weitere Informationen finden Sie in den Ratepay Datenschutzbestimmungen oder nutzen Sie das Ratepay Kontaktformular. |
Test your integration
Use these buyer email addresses to simulate the failure scenarios in the PayPal sandbox environment.
Error code | Buyer email |
---|---|
PAYMENT_SOURCE_INFO_CANNOT_BE_VERIFIED | payment_source_info_cannot_be_verified@example.com |
PAYMENT_SOURCE_DECLINED_BY_PROCESSOR | payment_source_declined_by_processor@example.com |
PAYMENT_SOURCE_CANNOT_BE_USED | payment_source_cannot_be_used@example.com |
BILLING_ADDRESS_INVALID | billing_address_invalid@example.com |
SHIPPING_ADDRESS_INVALID | shipping_address_invalid@example.com |
Any buyer email not listed in the table will simulate a successful scenario on PayPal sandbox environment.