PayPal In-Store

PXP Financial are partnering with PayPal and support PayPal's In-Store QR-Code based payment solution.

There are two available flows for PayPal’s in-store QR code payments:

  1. Consumer-presented, in which the customers PayPal app displays a barcode to be scanned by the
    POS.
  2. Merchant-presented, in which the merchant POS displays a QR code to be scanned by the customer using the PayPal app.

The following method IDs are covered in this section:

IDNameCredit/Debit StateFlow
427PayPal User Initiated POS DepositDepositedByProvider (29)Consumer Presented
426PayPal Merchant Initiated POS DepositDepositedByProvider (29)Merchant Presented

Consumer Presented vs. Merchant Presented Flow

Consumer-presented QR code use case

  1. User shops in a retail store and brings items to the POS for checkout.
  2. When prompted, the user indicates they want to pay with PayPal. The user opens the PayPal app on the mobile and displays a QR code.
  3. The POS scans the QR code and passes the value to the PXP System using payment method ID 427 PayPal User Initiated POS Deposit
  4. PXP system parses the QR code value and calls PayPal’s API, which returns a reference ID and indicates that the
    consumer needs to approve the transaction on their phone.
  5. Once the user confirms the purchase, the payment is completed.
  6. Depending on the user’s individual settings, they may receive a notification (push, SMS, email)
    from PayPal indicating that the account was charged.
  7. The user collects the POS receipt and exits the store with the purchased goods.
11791179

Consumer Experience - Consumer presented QR code

Sequence Diagram:

10121012

Consumer presented QR code Sequence Diagram

Merchant-presented flow

In the merchant-presented flow, the transaction starts by the POS generating and displaying a QR code,
which is scanned by the PayPal app. After that, the user experience is identical to that of the
consumer-presented flow.

11611161

Consumer Experience - Merchant presented QR code

Sequence Diagram:

10121012

Merchant presented QR code Sequence Diagram

Merchant and Site Onboarding

Merchant Account Onboarding

PXP has a partner integration with PayPal to offer PayPal In-Store to the merchants. PXP acts as the API caller for the merchant. The merchant needs to have a PayPal business account (with a confirmed/validated email address) and will receive the money directly via PayPal on his Paypal account.

Before a merchant can start processing PayPal In-Store transactions via PXP, merchants need to grant permission to PXP to process PayPal Transactions for them using a predefined onboarding process. This will be done together with the merchant during the test setup for PayPal In-Store. The PXP support team will guide the merchant through this exercise.

Merchant Business Onboarding for Marketing

After adding a merchant via the referral process (see above), PXP is obliged to onboard each merchant with the valid logo URI and the Merchant Business Name for marketing purposes with PayPal.

This information is needed from the merchant:

  • id: The publicly visible label of this location. Max Length: 64
  • business name: The business name of the party, this will be used as default merchant name
    for branding. Max Length: 300
  • logo url: (optional) The url of the logo of the merchant. It is also possible that PayPal hosts the logo.
    If this information is not passed to Paypal, only the Merchant’s Business Name will be
    shown on the buyers PayPal App screen during transaction approval.
    PayPal recommends:
    • Smallest size: 100x100 px saved at 1x, 2x, and 3x (high res)
    • Logo centered with a 15 px margin all around, so that the logo will
    sit in the whitespace at approximately 70px.
    • The file should be of type .png
    Format: URI
  • country_code: The two-character ISO 3166-1 code that identifies the country or region.
    Note from Paypal: The country code for Great Britain is GB and not UK as used in the top-level domain names for that country. Use the C2 country code for China worldwide for comparable uncontrolled price (CUP) method, bank card, and cross-border transactions.

Onboarding Locations

In order for PayPal to accept in-store payments, PXP must onboard each merchant’s store
locations with PayPal.

The below information has to be provided for each location:

  • name: The publicly visible label of this location. Max Length: 128
  • internalName: A merchant-assigned internal name of this location. This will be used as part of the soft descriptor by Networks (Visa, Mastercard etc.) to present in the bank statement. Max Length: 64
  • mobility: The mobile setting for this location. Enum: mobile, fixed, Recommended value: “fixed”
  • phoneNumber (optional): The phone number for this location. Max Length: 40
  • address: address line 1, addres line 2 (optional), city, state, country, postalCode
  • latitude: The latitude of this location. Max Length: 200
    Location data will be utilized for enhanced Risk assessment capabilities and proximity alerts for marketing purposes by Paypal.
  • longitude: The longitude of this location. Max Length: 200
  • tabType: The type of tab supported at this location. Enum: standard, none; Recommended value: "none"
  • availability: Whether this location is currently open for business. Enum: open, closed
    This value does not affect the payment authorization. Recommended value: “open”.
  • gratuityType: The type of gratuity that is accepted by this location. Enum: standard, none; Recommended value: “none”

Example:
"name": "Jewelry Loc 1",
"internalName": "Jewelery San Jose",
"mobility": "fixed",
"phoneNumber": "408-967-9174",
"address": {
"line1": "2212 N First Street",
"city": "San Jose",
"state": "CA",
"postalCode": "95131",
"country": "US"
},
"latitude": 49.265,
"longitude": -125.569,
"tabType": "none",
"availability": "closed",
"gratuityType": "STANDARD"

Backend2Backend Integration - Consumer Presented Flow

Payment Method ID covered in this section:

IDName
427PayPal User Initiated POS Deposit

Preconditions:

  • Customer is at the counter in the store and wants to pay with PayPal
  • Merchant wants to use the Consumer Presented Flow

Step 1: Merchant POS to scan the QR code from the consumers PayPal App

Merchant should ask the customer to open his Paypal App on his mobile and create a QR code.
Then the merchant has to scan this QR code.

📘

QR Code Refresh and Time-to-Live

The PayPal QR codes are dynamic, one-time-use tokens with a limited time-to-live (TTL).
For the consumer-presented QRC flow, the PayPal app display each QR code for 1 minute
before the screen refreshes automatically and generates a new code.
Once a QR code is scanned and submitted to Paypal (via PXP gateway), the transaction must be
completed within 50 seconds or else PayPal will time out the transaction.

288288

Consumer presents the QR code in the PayPal App

Step 2: Payment Initiation

After the merchant POS has scanned the QR code presented by the consumer, the merchant has to call the PXP API with the below mentioned additional information.

❗️

Only accept PayPal QR Code

The merchant should only initiate the payment with PXP if the QR code is a "PayPal-code".
The QR code format will start with “79” for PayPal. If the QR code does not start with "79", then it must not be sent to PXP. (e.g. “89” would be for Venmo).

The following parameters have to be provided in initiatePaymentRequest.specificPaymentData:

key (value type, account type, required)value
CustomerQRcode
(string, required)
The code of the scanned QR code which was presented by the Customer in his PayPal App.

Example: 791020281849
PaymentDescription
(string)
Must be set to Merchant’s name.
Used as transaction invoice soft_descriptor in the capture request to PayPal. PayPal uses the value of this field for constructing the merchant’s description in the customer’s credit card statement

This field is used for
branding in the Paypal receipt.
Also used to construct the merchant’s description in the
customer’s credit card statement:
Ex: “PAYPAL *<soft_descriptor> ” where Store
Id is the name of the store as it was defined when onboarding the merchant location with PayPal (in the setup process)

Example initiatePaymentRequest for a successful payment

<?xml version="1.0" encoding="UTF-8"?>
<initiatePaymentRequest xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <merchantID>B2BTestMerchant</merchantID>
    <shopID>IrisMockShop</shopID>
    <merchantTransactionID>{{$guid}}</merchantTransactionID>
    <paymentMethodID>63</paymentMethodID>
    <amount currencyCode="USD">16.5</amount>
    <userID>{{$guid}}</userID>
    <userData>
        <username>johndoe</username>
        <firstname>John</firstname>
        <lastname>Doe</lastname>
    </userData>
    <userIP>127.0.0.1</userIP>
    <userSessionID>6013e9af-89b6-4fc3-8f47-0d78264038b2</userSessionID>
    <creationTypeID>12</creationTypeID>
    <specificPaymentData>
        <data xsi:type="keyStringValuePair">
            <key>PaymentDescription</key>
            <value>QRCode deposit</value>
        </data>
        <data xsi:type="keyIntValuePair">
            <key>PaymentProviderID</key>
            <value>56</value>
        </data>
        <data xsi:type="keyStringValuePair">
            <key>CustomerQRcode</key>
            <value>791020281849</value>
                </data>
    </specificPaymentData>
</initiatePaymentRequest>

Step 3: PayPal asks Customer to confirm

After the merchant has sent the initiatePaymentRequest to PXP, PXP sends a capture request to PayPal.
If that is successful, PayPal then asks the customer to approve the payment in the PayPal App.
If that is not successful, PXP will respond with an error state, see possible states in Step4 below.

📘

QuickPay

In the consumer presented flow, PayPal has "QuickPay" enabled by default, which means that the Customer approval in Step 3 is not applicable and auto-approved.

566566

Customer Approval in PayPal App

Step 4: PXP to send Payment Initiation Response

After the customer has approved the payment, PXP system will query the PayPal System for the success status (or failure status) and return the synchronous response to the initiatePaymentRequest.

Example initiatePaymentResponse for a successful payment

<initiatePaymentResponse xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <payment xsi:type="paymentWithPaymentAccount">
        <merchantID>B2BTestMerchant</merchantID>
        <shopID>IrisMockShop</shopID>
        <paymentMethod>
            <key>427</key>
            <value>PayPal User Initiated POS Deposit</value>
        </paymentMethod>
        <merchantTransactionID>5285b3f2-c8ea-4864-a109-bffd45a63e9a</merchantTransactionID>
        <paymentID>a0c4cf91-f0e5-4c36-b6f6-4520f1cae4e1</paymentID>
        <userID>c137af64-72b7-49a1-8ef8-05236cd0397f</userID>
        <paymentProvider>
            <key>56</key>
            <value>PayPal</value>
        </paymentProvider>
        <amount currencyCode="USD">16.5</amount>
        <creationType>
            <key>12</key>
            <value>POS</value>
        </creationType>
        <userIP>127.0.0.1</userIP>
        <state>
            <id>c6e6e7be-4279-42ad-bfd0-b4cb3743327a</id>
            <definition>
                <key>29</key>
                <value>DepositedByProvider</value>
            </definition>
            <createdOn>2021-09-22T09:29:45.2955844Z</createdOn>
            <paymentStateDetails xsi:nil="true"></paymentStateDetails>
        </state>
        <isExecuted>true</isExecuted>
        <baseAmount currencyCode="EUR">12.4</baseAmount>
        <paymentDetails>
            <detail xsi:type="keyStringValuePair">
                <key>ProviderTransactionID</key>
                <value>3ba7d6da-35d0-42ff-a5bf-31064a5b6592</value>
            </detail>
            <detail xsi:type="keyStringValuePair">
                <key>ProviderExternalID</key>
                <value>38063311</value>
            </detail>
        </paymentDetails>
        <paymentAccount>
            <paymentAccountID>6bab8749-7d7c-4282-b2ec-1b1b77c26f71</paymentAccountID>
        </paymentAccount>
    </payment>
</initiatePaymentResponse>

Possible payment states in initiatePaymentResponse:

Payment StateDescriptionWhat to do
DepositedByProviderID = 29
Success state
Print receipt
RefusedByProviderError state, Refused by Provider
AbortedByProviderError state
AbortedByCustomerError state
InitiateRequestProviderCommunicationErrorOccurredPXP Capture request to PayPal failed due to a communication errorPayment not successful, ask Customer to try again or choose other payment method
QueryPaymentStateCommunicationErrorOccuredPXP request to query for the payment state in the PayPal system failed due to a communication errorPayment not successful, ask Customer to try again or choose other payment method
QueryPaymentStateErrorReportedByProviderPXP request to query for the payment state in the PayPal system failed due to an unknown error at PayPal sidePayment not successful, ask customer to choose other payment method

Timeout
If the initiatePayment request failed due to a time out, merchant should use
https://developer.kalixa.com/reference/getpayments
to get the status of the payment and see if the payment was successful
if not, merchant can trigger the scanning of the qr code again.

Step 5: Notifications

The standard notification mechanism is used for notifying the merchant in the background (asynchronously) about payment state changes. For more information see PaymentStateChangedNotification.

In case the payment initiation with PayPal has failed due to communication errors (see step 4), PXP will automatically cancel the payment with PayPal and notify the merchant about the Cancellation.

Example handlePaymentStateChangedNotification:

<?xml version="1.0" encoding="utf-8"?>
<handlePaymentStateChangedNotificationRequest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.cqrpayments.com/PaymentProcessing">
    <payment xsi:type="paymentWithPaymentAccount">
        <merchantID>B2BTestMerchant</merchantID>
        <shopID>IrisMockShop</shopID>
        <paymentMethod>
            <key>63</key>
            <value>PayPalDeposit</value>
        </paymentMethod>
        <merchantTransactionID>6f651a86-9005-414c-9096-ca7fc4dd2dad</merchantTransactionID>
        <paymentID>826c7106-5238-4d5a-85dd-119fe7bab66b</paymentID>
        <userID>zc1544de-7443-45f6-976e-d253c2</userID>
        <paymentProvider>
            <key>56</key>
            <value>PayPal</value>
        </paymentProvider>
        <amount currencyCode="USD">1.0000</amount>
        <creationType>
            <key>12</key>
            <value>POS</value>
        </creationType>
        <userIP>127.0.0.1</userIP>
        <state>
            <id>400eaecb-89ef-489b-9683-4fa8a9b922b0</id>
            <definition>
                <key>113</key>
                <value>Cancelled</value>
            </definition>
            <createdOn>2021-09-22T05:45:59.807</createdOn>
            <paymentStateDetails xsi:nil="true" />
        </state>
        <isExecuted>true</isExecuted>
        <baseAmount currencyCode="EUR">0.6600</baseAmount>
        <paymentDetails>
            <detail xsi:type="keyStringValuePair">
                <key>ProviderExternalID</key>
                <value>38062121</value>
            </detail>
            <detail xsi:type="keyIntValuePair">
                <key>MerchantSettlementCurrencyID</key>
                <value>2</value>
            </detail>
            <detail xsi:type="keyStringValuePair">
                <key>ProviderTransactionID</key>
                <value>d768f80e-a136-4e15-8382-ebe04f548eb5</value>
            </detail>
        </paymentDetails>
        <paymentAccount>
            <paymentAccountID>53db5a8e-a0e1-4a13-8251-af94959b3873</paymentAccountID>
        </paymentAccount>
    </payment>
</handlePaymentStateChangedNotificationRequest>

State Diagram for the Consumer Presented Flow

The following diagram shows the state flow of a 427 PayPal User Initiated POS Deposit in the PXP System:

13191319

Backend2Backend Integration - Merchant Presented Flow

Payment Method ID covered in this section:

IDName
246PayPal Merchant Initiated POS Deposit

Preconditions:

  • Customer is at the counter in the store and wants to pay with PayPal
  • Merchant wants to use the Merchant Presented Flow

Step 1: Call PXP to retrieve the QR code

📘

QR Code Validity

If a QR code was already generated but not yet scanned by the merchant POS, it will remain valid for up to 15 minutes.

The following parameters have to be provided in initiatePaymentRequest.specificPaymentData:

keyvalue
PaymentDescription
(string)
Must be set to Merchant’s name.
Used as transaction invoice soft_descriptor in the capture request to PayPal. PayPal uses the value of this field for constructing the merchant’s description in the customer’s credit card statement

This field is used for
branding in the Paypal receipt.
Also used to construct the merchant’s description in the
customer’s credit card statement:
Ex: “PAYPAL *<soft_descriptor> ” where Store
Id is the name of the store as it was defined when onboarding the merchant location with PayPal (in the setup process)

Example initiatePaymentRequest to receive the QR code

<?xml version="1.0" encoding="UTF-8"?>
<initiatePaymentRequest xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <merchantID>B2BTestMerchant</merchantID>
    <shopID>IrisMockShop</shopID>
    <merchantTransactionID>{{$guid}}</merchantTransactionID>
    <paymentMethodID>426</paymentMethodID>
    <amount currencyCode="USD">16.5</amount>
    <userID>{{$guid}}</userID>
    <userData>
        <username>johndoe</username>
        <firstname>John</firstname>
        <lastname>Doe</lastname>
    </userData>
    <userIP>127.0.0.1</userIP>
    <userSessionID>6013e9af-89b6-4fc3-8f47-0d78264038b2</userSessionID>
    <creationTypeID>12</creationTypeID>
    <specificPaymentData>
        <data xsi:type="keyStringValuePair">
            <key>PaymentDescription</key>
            <value>QRCode deposit</value>
        </data>
        <data xsi:type="keyIntValuePair">
            <key>PaymentProviderID</key>
            <value>56</value>
        </data>
    </specificPaymentData>
</initiatePaymentRequest>

Example initiatePaymentResponse (success case) to receive the QR code

<initiatePaymentResponse xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <payment xsi:type="paymentWithPaymentAccount">
        <merchantID>B2BTestMerchant</merchantID>
        <shopID>IrisMockShop</shopID>
        <paymentMethod>
            <key>426</key>
            <value>PayPal Merchant Initiated POS Deposit</value>
        </paymentMethod>
        <merchantTransactionID>emma_testing_00001</merchantTransactionID>
        <paymentID>6756c158-ee1e-40f1-b613-18dc817cb244</paymentID>
        <userID>82937a69-ff7e-4ec3-8985-56f221659e87</userID>
        <paymentProvider>
            <key>56</key>
            <value>PayPal</value>
        </paymentProvider>
        <amount currencyCode="USD">16.5</amount>
        <creationType>
            <key>12</key>
            <value>POS</value>
        </creationType>
        <userIP>127.0.0.1</userIP>
        <state>
            <id>80ea0fb3-ae1b-42a2-8b4c-9b0c7df74e65</id>
            <definition>
                <key>612</key>
                <value>PendingOnConfirmation</value>
            </definition>
            <createdOn>2021-12-08T07:26:47.1896733Z</createdOn>
            <paymentStateDetails xsi:nil="true"></paymentStateDetails>
        </state>
        <isExecuted>true</isExecuted>
        <baseAmount currencyCode="EUR">10.96</baseAmount>
        <paymentDetails>
            <detail xsi:type="keyStringValuePair">
                <key>QRCodeData</key>
                <value>https://www.paypal.com/qrcodes/integrated?payer_id=UMU2UCQWS123Q&amp;merchant_ref_id=39241301&amp;time_stamp=1638954227</value>
            </detail>
            <detail xsi:type="keyStringValuePair">
                <key>ProviderTransactionID</key>
                <value>8ba39a08-165b-46df-9ad6-b52cf86598ad</value>
            </detail>
            <detail xsi:type="keyStringValuePair">
                <key>ProviderExternalID</key>
                <value>39240296</value>
            </detail>
        </paymentDetails>
        <paymentAccount>
            <paymentAccountID>3ddb4e8f-e70b-42f7-ad22-962aec9830a0</paymentAccountID>
        </paymentAccount>
    </payment>
</initiatePaymentResponse>

important Parameters in the response

KeyDetailsExample
paymentDetails.QRCodeDataContains the data to generate the QR code on the POShttps://www.paypal.com/qrcodes/integrated?payer_id=UMU2UCQWS123Q&merchant_ref_id=39241301&time_stamp=1638954227
state.definition612 PendingOnConfirmation
paymentIDThe ID of the payment, to be stored and used for follow-up transactions like refunds.6756c158-ee1e-40f1-b613-18dc817cb244

Timeout
If the initiatePayment request failed due to a time out, retry mechanism not possible using
https://developer.kalixa.com/reference/getpayments
to get the status of the payment and to get QR code, this is not yet offered by PXP

Instead, merchant should start the request again.

Step 2: Present the QR code to the customer

The POS has to present the QR code.

Step 3: Customer to scan the QR code with PayPal App

Cashier to ask the customer to scan the QR code with his Paypal App.

❗️

PayPal App has to be used

The customer has to use the PayPal App (and not Venmo for example, which is also powered by PayPal), otherwise the payment would fail at a later stage.
PXP Financial only supports PayPal In-store at the time being.

Doing this will trigger the following actions which are handled between PayPal and PXP systems:

  • PayPal notifies the PXP of the scan
  • PXP triggers the payment creation with PayPal
  • PayPal asks the customer for confirmation in the App

Step 4: Customer to approve the payment in the PaypPal App

The customer now has to approve the payment by confirming the PayPal prompt in the Paypal app.

📘

Time Limit: 50 seconds

If the customer does not approve the payment in his App within 50 seconds, the session will time out (error: buyer confirmation not received).
In that case, the flow would need to be started over because the consumer would get an error when they try to advance and so they’d be taken back to the scan screen.

The customer approval triggers the completion of the payment in the PayPal system.

Step 5: Merchant send execute request

Now the merchant POS system has to send an executePaymentAction request containing the following data:

keyvalue
paymentIDThe paymentID as received in the initiatePaymentResponse
actionIDwith value 39 QueryPaymentStateAtProvider

Example executePaymentRequest:

<?xml version="1.0" encoding="utf-8"?>
<executePaymentActionRequest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.cqrpayments.com/PaymentProcessing">
  <merchantID>B2BTestMerchant</merchantID>
  <shopID>IrisMockShop</shopID>
  <paymentID>6756c158-ee1e-40f1-b613-18dc817cb244</paymentID>
  <actionID>39</actionID>
</executePaymentActionRequest>

Based on this request, PXP system will start pulling information about the success of the transaction from Paypal and respond to the executePaymentRequest.

Example executePaymentResponse:

<executePaymentActionResponse xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <statusCode>0</statusCode>
    <actionResults>
        <result xsi:type="keyStringValuePair">
            <key>lastStateDefinition</key>
            <value>29</value>
        </result>
        <result xsi:type="keyStringValuePair">
            <key>QRCodeData</key>
            <value>https://www.paypal.com/qrcodes/integrated?payer_id=UMU2UCQWS123Q&amp;merchant_ref_id=39241422&amp;time_stamp=1638959848</value>                                                                                                                                                                                                                                                                          
        <result xsi:type="keyStringValuePair">
            <key>ProviderTransactionID</key>
            <value>563c593f-820e-4553-918c-4b89a2dd0a52</value>
        </result>
    </actionResults>
</executePaymentActionResponse>
parametervalueWhat it means
statusCode0 if executeAction request was successful

anything else than 0 if action was not executed successfully by PXP
lastStateDefinition29 = DepositedByProvidersuccess case
continue
lastStateDefinition RefusedByProvider
AbortedByProvider
AbortedByCustomer
InitiateRequestProviderCommunicationErrorOccurred
QueryPaymentStateErrorReportedByProvider
InitiateErrorReportedByProvider
error cases,
do not continue

Step6: Merchant POS to display the success message and print receipt

If the executePaymentAction request was successful, the merchant POS should to display the success message to the cashier and print receipt.
The customer will also see a success message in the app displayed by PayPal.

309309

State Diagram for the Merchant Presented Flow

The following diagram shows the state flow of a 426 PayPal Merchant Initiated POS Deposit PayPal Merchant Initiated POS Deposit (426) in the PXP System:

16371637

Receipts

PayPal recommends including the following on each payment receipt:

  • Tender Type: PayPal
  • Currency
  • PayPal’s Transaction ID (ProviderTransactionID field from the PXP responses), example how such a Paypal Transaction ID would look like: "7JD25560JU073942S"
  • Timestamp
  • Store name and address

Automatic Cancellation of PayPal In-Store Deposit in case of communication error

If a PayPal In-Store Deposit Payment is not successful and results in one of those states (when PXP initiates the Deposit with PayPal), then the PXP system will automatically cancel refund to revert the request.

This applies to the following states of a PayPal In-Store Deposit payment:

  • InitiateRequestProviderCommunicationErrorOccurred
  • QueryPaymentStateCommunicationErrorOccured
  • QueryPaymentStateErrorReportedByProvider

The transaction will be in Cancelled state in case the refund cancellation was successful.
In case the Cancellation failed, the payment will be in one of those states:

  • CancelCommunicationErrorOccurred
  • FailedToCancel

In this case, the PXP System will re-try the cancellation automatically.

Merchants can receive state change notification for the Cancellation outcome via the standard notification mechanism, see PaymentStateChangedNotification.

Cancel a PayPal In-Store Payment manually

📘

Automatic Cancellation

The manual cancel option needs not be integrated by the merchant, because PXP system automatically cancels payments, see previous chapter.

Merchant can manually cancel a PayPal In-Store payment if it is in one of the following states, by using the executePaymentAction with actionID = 1 (Cancel):

  • InitiateRequestProviderCommunicationErrorOccurred
  • QueryPaymentStateCommunicationErrorOccured
  • QueryPaymentStateErrorReportedByProvider
  • CancelCommunicationErrorOccurred
  • FailedToCancel

The transaction will be in Cancelled state in case the refund cancellation was successful.
In case the Cancellation failed, the payment will be in one of those states:

  • CancelCommunicationErrorOccurred
  • FailedToCancel

Refund a PayPal In-Store Payment

When a customer returns some of his purchased items or goods in the store and has paid for it successfully with PayPal In-Store payment method before, the merchant can initiate the regarding refund In-Store with PayPal as well.

To initiate a refund for a PayPal In-Store payment, an initiatePaymentFromReference request using paymentMethodID = 400 ("PayPal Refund") has to be sent with the PaymentID of the original related PayPal In-Store payment (which must have been successfully completed DepositedByProvider).

The paymentID of the original PayPal In-Store payment must be used as originalPaymentID in the initiatePaymentFromReferenceRequest for creating the refund.

The merchant can decide to refund the full or a partial amount - but it must sum up to a maximum of the total captured amount of the PayPal payment.

📘

Default Refund Window 180 days

A Paypal In-Store Capture payment can be refunded for 180 days. To change/extend this time window the merchant's PayPal Account Manager needs to be contacted.

Example initiatePaymentFromReferenceRequest:

<?xml version="1.0" encoding="utf-8"?>
<initiatePaymentFromReferenceRequest 
  xmlns="http://www.cqrpayments.com/PaymentProcessing" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <merchantID>B2BTestMerchant</merchantID>
    <shopID>ProviderTesting</shopID>
    <originalPaymentID>63948678-f523-4e32-8853-7590897124f3</originalPaymentID>
    <merchantTransactionID>providertest_refundkiet7</merchantTransactionID>
    <paymentMethodID>400</paymentMethodID>
    <amount currencyCode="USD">2.5</amount>
    <specificPaymentData>               
        <data xsi:type="keyStringValuePair">
            <key>PaymentDescription</key>
            <value>Your reason for refund</value>
        </data>
    </specificPaymentData>
    <creationTypeID>12</creationTypeID>
</initiatePaymentFromReferenceRequest>

The PayPal payment for which the initiatePaymentFromReference request was sent will remain in state ExecutedByProvider (142). A new payment which is linked to the original PayPal payment will be created.

IDNameSuccessful State
400PayPal RefundRefunded (125)

Example initiatePaymentFromReferenceResponse:

<initiatePaymentFromReferenceResponse xmlns="http://www.cqrpayments.com/PaymentProcessing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <payment xsi:type="paymentWithPaymentAccount">
        <merchantID>B2BTestMerchant</merchantID>
        <shopID>ProviderTesting</shopID>
        <paymentMethod>
            <key>400</key>
            <value>PayPal Refund</value>
        </paymentMethod>
        <merchantTransactionID>providertest_refundkiet7</merchantTransactionID>
        <paymentID>e532840a-55c8-4663-99be-16b9b2966396</paymentID>
        <userID>b4195619-0537-45bd-90ea-96cd3d9e8452</userID>
        <paymentProvider>
            <key>56</key>
            <value>PayPal</value>
        </paymentProvider>
        <amount currencyCode="USD">2.5</amount>
        <creationType>
            <key>12</key>
            <value>POS</value>
        </creationType>
        <userIP>127.0.0.1</userIP>
        <state>
            <id>0b027443-e8aa-4c98-a4d9-1bb97af36141</id>
            <definition>
                <key>125</key>
                <value>Refunded</value>
            </definition>
            <createdOn>2021-12-21T08:15:34.3113386Z</createdOn>
            <paymentStateDetails>
                <detail xsi:type="keyStringValuePair">
                    <key>ProviderResponseCode</key>
                    <value>0</value>
                </detail>
            </paymentStateDetails>
        </state>
        <isExecuted>true</isExecuted>
        <baseAmount currencyCode="EUR">1.88</baseAmount>
        <paymentDetails>
            <detail xsi:type="keyIntValuePair">
                <key>OriginalPaymentID</key>
                <value>39401058</value>
            </detail>
            <detail xsi:type="keyStringValuePair">
                <key>ProviderTransactionID</key>
                <value>063238933H511101R</value>
            </detail>
            <detail xsi:type="keyStringValuePair">
                <key>ProviderExternalID</key>
                <value>39418166</value>
            </detail>
        </paymentDetails>
        <paymentAccount>
            <paymentAccountID>6ce25a90-d525-4f8e-80c3-996920511bc2</paymentAccountID>
        </paymentAccount>
    </payment>
</initiatePaymentFromReferenceResponse>

Payment State Flow for all PayPal Partial Refund payments:

891891

Automatic cancellation of refund in case of a request communication error

In case the refund request from PXP to PayPal results in an error state (RefundCommunicationErrorOccurred or InitiateRefundErrorReportedByProvider), PXP will try to cancel the refund request automatically to revert the transaction.

The refund transaction will be in Cancelled state in case the refund cancellation was successful.

Error states would be:

  • CancelCommunicationErrorOccurred
  • FailedToCancel
    In this case, the PXP System will re-try the cancellation automatically.

Merchants can receive state change notification for the Cancellation outcome via the standard notification mechanism, see PaymentStateChangedNotification.

POS Best Practices provided by PayPal

  1. The POS should clearly label a tender type button as “PayPal" in an obvious manner so that
    the process is intuitive to kick off the transaction process with little to no cashier training. When a
    customer indicates he or she wants to Pay with PayPal, the next steps should be
    obvious to the cashier.

  2. The POS should display the transaction status clearly to the cashier. E.g., “Waiting for Customer
    Confirmation”, “Processing”, “Customer Cancelled,” etc.

  3. In the unlikely event that PXP returns unexpected content in an API response, the POS should recover gracefully.