Marketplace PSD2

1 Introduction

If you are interested in cooperation with PayU as marketplace please contact us.

1.1 Submerchant registration form

When marketplace company registration process is completed there is a special submerchant registration form available at:

https://secure.payu.com/boarding/#/form?lang=en&nsf=false&partnerId=MARKETPLACE_ID&marketplaceExtCustomerId=EXT_CUSTOMER_ID

MARKETPLACE_ID is unique marketplace identifier given by PayU.

EXT_CUSTOMER_ID is unique submerchant identifier given by marketplace.

Every submerchant must be verified by PayU. If submerchant is not verified then order creation for this submerchant is not allowed and error is returned.

1.2 Testing Marketplace

Functionality of marketplace can be tested on sandbox environment. Test account is available for anyone testing this service, beacuse of that marketplace or submerchants balances can change without your contribution.

Sandbox account

                    
                    Point of Sale Id (pos_id):          341009
                    Second key (MD5):                   289c28ec590ba6940746266c5d64932f
                    OAuth Protocol (client_id):         341009
                    OAuth Protocol (client_secret):     ff9994baa59b73c7ca56a5480e608f02
                    
                

List of ext_customer_id

                    
                    //submerchants ext_customer_id
                    submerchant_A
                    submerchant_B
                    submerchant_C
                    submerchant_unverified -- this submerchant is not verified - you can't make some requests such as payout etc.
                    
                

Note!If you want to perform payout from a test account, you should set value of shopId parameter to 0pKb1aqC

2 Marketplace API

Integration is consistent with REST API 2.1. There are some API extensions available only for marketplace companies.

Authentication methods are described in: Signing API calls parameters.

2.1 Submerchant status

Submerchant status can be retrieved with the following request:
                    curl -v -X GET https://secure.payu.com/api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/status?currencyCode=PLN \
                    -H "Content-Type: application/json" \
                    -H "Authorization: Bearer <AUTH_TOKEN>"
                
EXT_CUSTOMER_ID is submerchant identifier.

Request parameters are:

Parameter Required Comment
currencyCode yes Currency code according to ISO-4217.

Sample response:
                    {
                        "customerVerificationStatus": "Verified",
                        "name": "Example Company",
                        "taxId": "123123123",
                        "regon": "123123123"
                    }
                
Response fields are:
Field Comment
customerVerificationStatus Submerchant status. Available values:
  • Verified submerchant is verified by PayU and orders for this submerchant are allowed
  • NotVerified submerchant is not verified by PayU or does not exist
name Name of the company
taxId Company NIP. For companies registered abroad the field contains: Tax ID or VAT UE.
regon Regon number of the company

2.2 Order creation

Marketplace order creation is consistent with standard integration method via REST API: Creating new order. Below marketplace specific changes are described.

shoppingCarts section

Complex shoppingCarts element defines distribution to particular submerchants.

    ...
    "shoppingCarts": [
        {
            "extCustomerId": "ext-customer-1",
            "amount": 1800,
            "fee": 20,
            "shippingMethods": [
                {
                    "country": "EN",
                    "price": 1500,
                    "name": "Shipping Method 1"
                }
            ],
            "products": [
                {
                    "name": "product-x",
                    "unitPrice": 100,
                    "quantity": 3
                }
            ]
        },
        {
            "extCustomerId": "ext-customer-2",
            "amount": 2700,
            "fee": 27,
            "shippingMethods": [
                {
                    "country": "EN",
                    "price": 2000,
                    "name": "Shipping Method 2"
                }
            ],
            "products": [
                {
                    "name": "product-y",
                    "unitPrice": 700,
                    "quantity": 1
                }
            ]
        }
    ]
    ...
                
Field Required Comment
shoppingCarts.extCustomerId yes Submerchant identifier.
shoppingCarts.amount yes Total amount for given submerchant.
shoppingCarts.fee no Marketplace fee. Value should be in range <0, amount>
shoppingCarts.products yes List of products.
shoppingCarts.products.name yes Product name.
shoppingCarts.products.unitPrice yes Product unit price.
shoppingCarts.products.quantity yes Quantity.
shoppingCarts.shippingMethods no Shipping method.
shoppingCarts.shippingMethods.name yes, only if field shippingMethods is filled Shipping method name.
shoppingCarts.shippingMethods.price yes, only if field shippingMethods is filled Shipping price.
shoppingCarts.shippingMethods.country yes, only if field shippingMethods is filled Shipping country code according to ISO-3166.

Sum of amount field values in each element of shoppingCarts should be equal to value of totalAmount field in order.

If you received the following response to your order please check extCustomerId parameter.

                {
                    "iFrameAllowed": false,
                    "status": {
                        "statusCode": "DATA_NOT_FOUND",
                        "code": "9999",
                        "codeLiteral": "CUSTOMER_NOT_FOUND"
                    }
                }
                
            

buyer/extCustomerId field

buyer section was extended with extCustomerId field which is a buyer identifer defined by marketplace:
                    ...
                    "buyer": {
                        "extCustomerId": "buyer-id-1234",
                        "email": "buyer-id-1234@email.com",
                        ...
                    }
                    ...
                
Field Required Comment
buyer.extCustomerId yes Buyer identifier. There is no need to create or verify buyer earlier - it will be automatically created when is used first time.

Sample marketplace OrderCreateRequest

                    curl -v -X POST https://secure.payu.com/api/v2_1/orders \
                    -H "Content-Type: application/json" \
                    -H "Authorization: Bearer <AUTH_TOKEN>" \
                    -d '{
                            "merchantPosId":"341009",
                            "customerIp": "127.0.0.1",
                            "continueUrl": "http://your.eshop.com/continue",
                            "notifyUrl": "https://your.eshop.com/notify",
                            "currencyCode": "PLN",
                            "totalAmount": 5000,
                            "extOrderId": "marketplace-order-xyz-123",
                            "description": "order XYZ-123",
                            "additionalDescription": "additional description",
                            "buyer": {
                                "email": "john.doe@email.com",
                                "phone": "(012)1234567",
                                "firstName": "John",
                                "lastName": "Doe",
                                "language": "pl",
                                "extCustomerId": "john-doe-12345"
                            },
                            "shoppingCarts": [
                                {
                                    "extCustomerId": "marketplace-submerchant-1",
                                    "amount": 200,
                                    "fee": 20,
                                    "products": [
                                        {
                                            "name": "product A",
                                            "quantity": 2,
                                            "unitPrice": 100
                                        }
                                    ]
                                },
                                {
                                    "extCustomerId": "marketplace-submerchant-2",
                                    "amount": 1300,
                                    "products": [
                                        {
                                            "name": "product B",
                                            "quantity": 2,
                                            "unitPrice": 200
                                        },
                                        {
                                            "name": "product C",
                                            "quantity": 3,
                                            "unitPrice": 300
                                        }
                                    ]
                                },
                                {
                                    "extCustomerId": "marketplace-submerchant-3",
                                    "amount": 3500,
                                    "fee":350,
                                    "products": [
                                        {
                                            "name": "product D",
                                            "quantity": 1,
                                            "unitPrice": 3500
                                        }
                                    ]
                                }
                            ]
                        }'
                
When order transaction is authorized successfully then order funds are assigned as follows:
  • marketplace-submerchant-1: +1.80 PLN
  • marketplace-submerchant-2: +13.00 PLN
  • marketplace-submerchant-3: +31.50 PLN
  • marketplace: +3.70 PLN

Sample marketplace OrderCreateRequest with chosen payment method

                    curl -v -X POST https://secure.payu.com/api/v2_1/orders \
                    -H "Content-Type: application/json" \
                    -H "Authorization: Bearer <AUTH_TOKEN>" \
                    -d '{
                            "merchantPosId":"341009",
                            "customerIp": "127.0.0.1",
                            "continueUrl": "http://your.eshop.com/continue",
                            "notifyUrl": "https://your.eshop.com/notify",
                            "currencyCode": "PLN",
                            "totalAmount": 5000,
                            "extOrderId": "marketplace-order-xyz-123",
                            "description": "order XYZ-123",
                            "additionalDescription": "additional description",
                            "buyer": {
                                "email": "john.doe@email.com",
                                "phone": "(012)1234567",
                                "firstName": "John",
                                "lastName": "Doe",
                                "language": "pl",
                                "extCustomerId": "john-doe-12345"
                            },
                            "shoppingCarts": [
                                {
                                    "extCustomerId": "marketplace-submerchant-1",
                                    "amount": 200,
                                    "fee": 20,
                                    "products": [
                                        {
                                            "name": "product A",
                                            "quantity": 2,
                                            "unitPrice": 100
                                        }
                                    ]
                                },
                                {
                                    "extCustomerId": "marketplace-submerchant-2",
                                    "amount": 1300,
                                    "products": [
                                        {
                                            "name": "product B",
                                            "quantity": 2,
                                            "unitPrice": 200
                                        },
                                        {
                                            "name": "product C",
                                            "quantity": 3,
                                            "unitPrice": 300
                                        }
                                    ]
                                },
                                {
                                    "extCustomerId": "marketplace-submerchant-3",
                                    "amount": 3500,
                                    "fee":350,
                                    "products": [
                                        {
                                            "name": "product D",
                                            "quantity": 1,
                                            "unitPrice": 3500
                                        }
                                    ]
                                }
                            ],
                            "payMethods": {
                                "payMethod":{
                                    "type":"PBL",
                                    "value":"m",
                                    "amount":5000
                                }
                            }
                        }'
                

payMethods section fields description

Field Required Comment
payMethod.type Yes Payment method type.
payMethod.value Yes Payment type.
payMethod.amount Yes Total price of order. Should be equal to totalAmount field, as well as sum of all amount fields in shoppingCarts section.

Additional error codes for order creation

StatusCode Code CodeLiteral Description
DATA_NOT_FOUND CUSTOMER_NOT_FOUND 9999 Submerchant doesn't exist.

2.3 Refund

Marketplace refund processing is consistent with standard integration method via REST API: Refunds. Below marketplace specific changes are described.

There is a possibility to create partial or full refund for selected submerchant or for all submerchants from order:
curl -X POST https://secure.payu.com/api/v2_1/orders/<ORDER_ID>/refunds \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer <AUTH_TOKEN>" \
    -d '{
        "refund": {
            "description": "Refund",
            "amount": 1000
            "extCustomerId": "ext-customer-1",
            "extRefundId": "ext-refund-id-1"
        }
    }'
                
ORDER_ID is order identifier, which refund is created for.
Field Required Comment
refund.extRefundId yes External refund identifier.
refund.amount yes Refund amount. If amount is equal to totalAmount value from order then full refund for all submerchants from order is created.
refund.extCustomerId yes, if amount field value is not equal to totalAmount value in order Submerchant identifier.
Sample response:
                    {
                        "status": {
                            "statusCode":"SUCCESS",
                            "statusDesc": "Refund queued for processing"
                        },
                        "orderId":"47FD97QSPL140325GUEST000P01",
                        "refund":{
                            "dispositions": {
                                "instrumentAmount": "1000",
                                "walletAmount": "0",
                                "couponAmount": "0"
                            },
                            "refundId": "R84FWMHX6K150901abjtwtchP01",
                            "extRefundId": "ext-refund-id-1"
                        }
                    }
                

Additional error codes for refund creation

StatusCode Code CodeLiteral Description
BUSINESS_ERROR AMOUNT_EXCEEDED 9109 Refund amount exceeds amount for given submerchant in order.
BUSINESS_ERROR AMBIGUOUS_REFUND_SOURCE 9110 Refund can't be realized from more than one source.
BUSINESS_ERROR AMOUNT_MISSING 9114 Amount is missing.
BUSINESS_ERROR AMOUNT_INVALID 9115 extCustomerId is empty and refund amount is not equal to totalAmount in order.
BUSINESS_ERROR EXT_REFUND_ID_MISSING 9116 extRefundId is missing.
BUSINESS_ERROR NO_SHOPPING_CARTS_IN_ORDER 9118 Missing shopping carts in order.
DATA_NOT_FOUND MARKETPLACE_TRANSACTION_NOT_FOUND 9119 Order with given identifier doesn't exist.
DATA_NOT_FOUND CUSTOMER_NOT_FOUND 9999 Submerchant doesn't exist.

2.4 Payout

Marketplace payout processing is consistent with standard integration method via REST API: Payouts. Below marketplace specific changes are described.

In order to create payout the following request should be sent:
                    curl -X POST https://secure.payu.com/api/v2_1/payouts \
                    -H "Content-Type: application/json" \
                    -H "Authorization: Bearer <AUTH_TOKEN>" \
                    -d '{
                        "shopId":"shop-id",
                        "payout": {
                            "amount": "1000",
                            "currencyCode": "PLN",
                            "description": "Some payout",
                            "extPayoutId": "my_payout_id_123"
                        },
                        "account": {
                            "extCustomerId": "ext-customer-id-1"
                        }
                    }'
                
In order to make a payout for the marketplace sandbox account use the parameter extCustomerId: MARKETPLACE_K2_FEE
Field Required Comment
shopId Yes Public shop Id obtained from the PayU panel.
payout.amount No If this field is empty then full payout will be performed.
payout.extPayoutId Yes External payout identifier.
account.extCustomerId Yes Submerchant identifier.
Sample response:
                {
                    "payout": {
                        "payoutId": "b3e4fc98c6894239864a9d6941f0fe76",
                        "extPayoutId": "PAYOUT23423423423",
                        "extCustomerId": "12345678",
                        "status": "PENDING"
                    },
                    "status": {
                        "statusCode": "SUCCESS"
                    }
                }
                

Additional error codes for payout creation

StatusCode Code CodeLiteral Description
BUSINESS_ERROR MISSING_EXTERNAL_CUSTOMER_ID 8362 extCustomerId is missing.
BUSINESS_ERROR MISSING_EXTERNAL_PAYOUT_ID 8363 extPayoutId is missing.
ERROR_VALUE_INVALID MARKETPLACE_CUSTOMER_NOT_VERIFIED 9132 Submerchant is not verified by PayU.
ERROR_VALUE_INVALID PROVIDING_BANK_ACCOUNT_IS_FORBIDDEN 9133 Bank account is forbidden for marketplace payout.
DATA_NOT_FOUND CUSTOMER_NOT_FOUND 9999 Submerchant doesn't exist.

2.5 Operation history

Submerchant operation history can be retrieved with the following request:
                    
                    curl -X GET \
                    'https://secure.payu.com/api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/operations?eventDateFrom=<EVENT_DATE_FROM>&eventDateTo=<EVENT_DATE_TO>' \
                    -H 'Authorization: Bearer <AUTH_TOKEN>' \
                    -H 'Content-Type: application/json' \
                    -H 'cache-control: no-cache'
                    
                
EXT_CUSTOMER_ID is submerchant identifier.
Request parameters are:
Parameter Required Comment
eventDateFrom yes Start of the search range for "eventDate".

Format: 2019-01-30T20%3A59%3A00%2B02%3A00

Date must be url encoded.
eventDateTo yes End of the search range for "eventDate".

Format: 2019-04-30T20%3A59%3A00%2B02%3A00

Date must be url encoded.
creationDateFrom no Start of the search range for "creationDate".

Format: 2019-04-30T20%3A59%3A00%2B02%3A00

Date must be url encoded.
creationDateTo no End of the search range for "creationDate".

Format: 2019-04-30T20%3A59%3A00%2B02%3A00

Date must be url encoded.
type no Operation type. Possible values:
  • PAYMENT_SENT
  • PAYMENT_RECEIVED
  • PAYOUT
  • REFUND_SENT
  • REFUND_RECEIVED
  • RETURN
  • ADMIN_TRANSFER_SENT
  • ADMIN_TRANSFER_RECEIVED
  • TRANSFER_SENT
  • TRANSFER_RECEIVED
You can enter multiple values. Subsequent entries should be separated by a comma.
currencyCode no Currency code according to ISO-4217.
You can enter multiple values. Subsequent entries should be separated by a comma.
sortBy no Sorting field. Additional sign + or - before field name defines sorting order. Default is ascending. Parameters that can be used to sort the operation history are as follows:
  • eventDate
  • creationDate
  • type
  • currencyCode
e.g. sortBy=-eventDate will sort results by eventDate descending.
limit no Number of records per page.
offset no Page number (indexing from 0).
Sample response:
                    {
                        "operations": [
                            {
                                "type": "PAYMENT_RECEIVED",
                                "amount": "1500",
                                "currencyCode": "PLN",
                                "description": "operation description",
                                "status": "COMPLETED",
                                "creationDate": "2016-04-20T11:05:54+02:00",
                                "eventDate": "2016-04-20T12:05:54+02:00",
                                "details": {
                                    "orderId": "CWDBL3KD6G170110GUEST000P01",
                                    "extOrderId": "105877825874b0c0b47a0",
                                    "counterparties": [
                                        {
                                            "extCustomerId": "35463545",
                                            "name": "Alice",
                                            "email": "alice@email.com",
                                            "products": [
                                                {
                                                    "name": "product-x",
                                                    "unitPrice": "1500",
                                                    "quantity": "1"
                                                }
                                            ]
                                        }
                                    ],
                                    "funds": []
                                }
                            }
                        ],
                        "pageResponse": {
                            "records": "1",
                            "size": "1",
                            "pageCount": "1"
                        }
                    }
                
Common response fields are:
Field Description
operations List of operations.
operations.type Operation type. Possible values:
  • PAYMENT_SENT
  • PAYMENT_RECEIVED
  • PAYOUT
  • REFUND_SENT
  • REFUND_RECEIVED
  • RETURN
  • ADMIN_TRANSFER_SENT
  • ADMIN_TRANSFER_RECEIVED
  • TRANSFER_SENT
  • TRANSFER_RECEIVED
operations.amount Amount (of order, refund, payout).
operations.currencyCode Currency code according to ISO-4217.
operations.description Operation description.
operations.status Operation status.
operations.creationDate Operation request moment. Format: 2019-11-30T20:33:44+02:00
operations.eventDate Operation ending moment. Format: 2019-11-30T22:33:44+02:00
pageResponse.records Total number of records found.
pageResponse.size Number of returned operations.
pageResponse.pageCount Page count.

Additional response fields for PAYMENT_RECEIVED operation:

Field Description
operations.details.orderId Order identifier.
operations.details.extOrderId External order identifier.
operations.details.counterparties Order elements.
operations.details.counterparties.extCustomerId Buyer identifier.
operations.details.counterparties.name Buyer name.
operations.details.counterparties.email Buyer email.
operations.details.counterparties.products List of products in order.
operations.details.counterparties.products.name Product name.
operations.details.counterparties.products.unitPrice Unit price of product.
operations.details.counterparties.products.quantity Quantity.

Additional response fields for REFUND_SENT operation:

Field Description
operations.details.orderId Order identifier.
operations.details.extOrderId External order identifier.
operations.details.refundId Refund identifier.
operations.details.extRefundId External refund identifier.
operations.details.counterparties Order elements.
operations.details.counterparties.extCustomerId Buyer identifier.
operations.details.counterparties.name Buyer name.
operations.details.counterparties.email Buyer email.

Additional response fields for PAYOUT operation:

Field Description
operations.details.payoutId Payout identifier.
operations.details.extPayoutId External payout identifier.

Additional response fields for RETURN operation:

Field Description
operations.details.payoutId Payout identifier.
operations.details.extPayoutId External payout identifier.

2.6 Submerchant balance

Submerchant balance can be retrieved with the following request:
                    curl -v -X GET https://secure.payu.com/api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/balances?currencyCode=PLN \
                    -H "Content-Type: application/json" \
                    -H "Authorization: Bearer <AUTH_TOKEN>"
                
EXT_CUSTOMER_ID is submerchant identifier.

Request parameters are:

Parameter Required Comment
currencyCode yes Currency code according to ISO-4217.

Sample response:
                    {
                        "balance": {
                            "availableAmount": "5494",
                            "totalAmount": "5500"
                        },
                        "status": {
                            "statusCode": "SUCCESS"
                        }
                    }
                

Response fields are:

Field Comment
balance.availableAmount Available funds.
balance.totalAmount Total submerchant funds (including blocked funds).
status.statusCode Response status.

2.7 Transfering funds between balances

In marketplace exists possibility to transfer funds between submerchant and marketplace balances.

To enable this functionality, configuration on the PayU side and Compliance consent is required. To enable it please contact us.

Transfer from submerchant to marketplace balance

Acces token client_credentials for given marketplace is required for this requests.
                    
                    curl -X POST https://secure.snd.payu.com/api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/feeDebitTransfer \
                     -H 'Authorization: Bearer 4b29a650-82b7-4c1b-8b6f-2786edd6d2bd' \
                     -H 'Content-Type: application/json' \
                     -H 'Postman-Token: dc779a1e-07d4-4998-bbb6-bb7e0bbbf45b' \
                     -H 'cache-control: no-cache' \
                     -d '{
                         "amount": 25, 
                         "currencyCode": "PLN",
                         "description": "Get fee for order XX2ORD2",
                         "extTransferId": "debit-9dbc62be-dfc8-401f-a9f4-79e5013cb734"
                     }'
                    
                
EXT_CUSTOMER_ID is submerchant identifier.

Request parameters:

Parameter Comment
amount Transfer amount.
currencyCode Currency code according to ISO-4217.
description Description of the operation.
extTransferId Unique transfer identifier for given marketplace.

Sample response for transfer between balances

                    
                    {
                        "extCustomerId": "<extCustomerId>",
                        "extTransferId": "debit-9dbc62be-dfc8-401f-a9f4-79e5013cb734",
                        "status": {
                            "statusCode": "SUCCESS"
                        }
                    }
                    
                

Response parameters:

Parameter Comment
extCustomerId Unique submerchant identifier.
extTransferId Unique transfer identifier for given marketpalce.
status.statusCode Response status.

Transfer from marketplace to submerchant balance

                    
                    curl -X POST https://secure.snd.payu.com/api/v2_1/customers/ext/<EXT_CUSTOMER_ID>/feeCreditTransfer \
                     -H 'Authorization: Bearer 4b29a650-82b7-4c1b-8b6f-2786edd6d2bd' \
                     -H 'Content-Type: application/json' \
                     -H 'Postman-Token: 9f9a1496-1864-4856-9b50-699fc1e0ef1f' \
                     -H 'cache-control: no-cache' \
                     -d '{
                         "amount": 25, 
                         "currencyCode": "PLN",
                         "description": "Return fee for order XXX1ORD",
                         "extTransferId": "credit-63a3e837-ba7e-45a0-b1b5-267e2c237cd6"
                     }'
                    
                
EXT_CUSTOMER_ID is submerchant identifier.

Request parameters:

Parameter Comment
amount Transfer amount.
currencyCode Currency code according to ISO-4217.
description Description of the operation.
extTransferId Unique transfer identifier for given marketplace.

Sample response for transfer between balances

                    
                    {
                        "extCustomerId": "<extCustomerId>",
                        "extTransferId": "debit-9dbc62be-dfc8-401f-a9f4-79e5013cb734",
                        "status": {
                            "statusCode": "SUCCESS"
                        }
                    }
                    
                

Response parameters:

Parameter Comment
extCustomerId Unique submerchant identifier.
extTransferId Unique transfer identifier for given marketpalce.
status.statusCode Response status.

Potential error codes for transfering funds between balances

HttpStatus StatusCode CodeLiteral
400 BUSINESS_ERROR MARKETPLACE_TRANSFER_EXISTS
400 BUSINESS_ERROR MARKETPLACE_NO_BALANCE