Card tokenization service is based on a transparent integration type which allows to accept card payments without redirecting users to a page hosted by the payment service provider. This integration type retains the security level and minimizes the PCI DSS compliance effort. It is also meant to give you more flexibility and increase conversion rates through better control over the payment process.
A payment flow is based on two steps - capturing card credentials in a secure way (front-end process) and then using them to create a payment transaction (back-end process). Card credentials are returned in the form of a token and a masked card number, therefore the Merchant never receives full card details.
Tokens received from PayU can be either single-use or multi-use. Multi-use tokens can be stored and used for future payments. Typically such functionality can be used by e.g. a merchant who has an extensive database of returning users – linking a user account with a multi-use token improves user experience, because the user no longer needs to enter card data each time.
Before integrating the service, please take a look at the requirements and recommendations prepared by our security experts. It will help you protect yourself against frauds.
SINGLE
type in your front-end and pass it to your back-endMULTI
type in your front-end and pass it to your back-endTransparent payment with a single-use token (first payment):
Transparent payment with a multi-use token (second and next payments):
The Secure Form is the preferred solution as it eliminates the need to handle the sensitive card data on your website - all the data are inputted in an iframe with PayU hosted form.
Note: when using Secure Form you should display text provided in the Information Requirements section.
Single-use form example.
<script type="text/javascript" src="https://secure.payu.com/javascript/sdk"></script>
<section class="container">
<div class="card-container">
<div class="payu-card-form" id="payu-card"></div>
</div>
<button id="tokenizeButton">Tokenize</button>
<div id="responseTokenize"></div>
</section>
var optionsForms = {
style: {
basic: {
fontSize: '18px'
}
},
lang: 'pl'
}
var renderError = function(element, errors) {
element.className = 'response-error';
var messages = [];
errors.forEach(function(error) {
messages.push(error.message);
});
element.innerText = messages.join(', ');
};
var renderSuccess = function(element, msg) {
element.className = 'response-success';
element.innerText = msg;
};
//initialize the SDK by providing your POS ID and create secureForms object
var payuSdkForms = PayU('393823');
var secureForms = payuSdkForms.secureForms();
//create the form by providing type and options
var card = secureForms.add('card', optionsForms);
//render the form in selected element
card.render('#payu-card');
var tokenizeButton = document.getElementById('tokenizeButton');
var responseElement = document.getElementById('responseTokenize');
tokenizeButton.addEventListener('click', function() {
responseElement.innerText = '';
try {
payuSdkForms.tokenize('SINGLE').then(function(result) { //example for SINGLE type token
result.status === 'SUCCESS'
? renderSuccess(responseElement, result.body.token) //pass the token to your back-end and charge it
: renderError(responseElement, result.error.messages); //check the business error type and messages and display appropriate information to the user
});
} catch(e) {
console.log(e); // technical errors
}
});
.container * {
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
color: #ffffff;
}
.container {
text-align: center;
width: 420px;
margin: 20px auto 10px;
display: block;
border-radius: 5px;
box-sizing: border-box;
}
.card-container {
width: 100%;
margin: 0 auto;
border-radius: 6px;
padding: 10px;
background: rgb(2,0,60);
text-align: left;
box-sizing: border-box;
}
.payu-card-form {
background-color: #ffffff;
padding: 5px;
border-radius: 4px;
}
button {
border: none;
background: #438F29;
padding: 8px 15px;
margin: 10px auto;
cursor: pointer;
}
.response-success {
color: #438F29;
}
.response-error {
color: #990000;
}
Example of individual fields as a separate forms.
<script type="text/javascript" src="https://secure.payu.com/javascript/sdk"></script>
<section class="container">
<div class="card-container">
<aside>Card Number</aside>
<div class="payu-card-form" id="payu-card-number"></div>
<div class="card-details clearfix">
<div class="expiration">
<aside>Valid Thru</aside>
<div class="payu-card-form" id="payu-card-date"></div>
</div>
<div class="cvv">
<aside>CVV</aside>
<div class="payu-card-form" id="payu-card-cvv"></div>
</div>
</div>
</div>
<button id="tokenizeButton">Tokenize</button>
<div id="responseTokenize"></div>
</section>
var optionsForms = {
cardIcon: true,
style: {
basic: {
fontSize: '24px'
}
},
placeholder: {
number: '',
date: 'MM/YY',
cvv: ''
},
lang: 'pl'
}
var renderError = function(element, errors) {
element.className = 'response-error';
var messages = [];
errors.forEach(function(error) {
messages.push(error.message);
});
element.innerText = messages.join(', ');
};
var renderSuccess = function(element, msg) {
element.className = 'response-success';
element.innerText = msg;
};
//initialize the SDK by providing your POS ID and create secureForms object
var payuSdkForms = PayU('393823');
var secureForms = payuSdkForms.secureForms();
//create the forms by providing type and options
var cardNumber = secureForms.add('number', optionsForms);
var cardDate = secureForms.add('date', optionsForms);
var cardCvv = secureForms.add('cvv', optionsForms);
//render the form in selected element
cardNumber.render('#payu-card-number');
cardDate.render('#payu-card-date');
cardCvv.render('#payu-card-cvv');
var tokenizeButton = document.getElementById('tokenizeButton');
var responseElement = document.getElementById('responseTokenize');
tokenizeButton.addEventListener('click', function() {
responseElement.innerText = '';
try {
////tokenize the card (communicate with PayU server)
payuSdkForms.tokenize('SINGLE').then(function(result) { // example for SINGLE type token
result.status === 'SUCCESS'
? renderSuccess(responseElement, result.body.token) //pass the token to your back-end and charge it
: renderError(responseElement, result.error.messages); //check the business error type and messages and display appropriate information to the user
});
} catch(e) {
console.log(e); // technical errors
}
});
.container * {
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
color: #ffffff;
}
.container {
text-align: center;
width: 420px;
margin: 20px auto 10px;
display: block;
border-radius: 5px;
box-sizing: border-box;
}
.card-container {
width: 100%;
margin: 0 auto;
border-radius: 6px;
padding: 10px;
background: rgb(2,0,60);
text-align: left;
box-sizing: border-box;
}
.card-container aside {
padding-bottom: 6px;
}
.payu-card-form {
background-color: #ffffff;
padding: 5px;
border-radius: 4px;
}
.card-details {
clear: both;
overflow: auto;
margin-top: 10px;
}
.card-details .expiration {
width: 50%;
float: left;
padding-right: 5%;
}
.card-details .cvv {
width: 45%;
float: left;
}
button {
border: none;
background: #438F29;
padding: 8px 15px;
margin: 10px auto;
cursor: pointer;
}
.response-success {
color: #438F29;
}
.response-error {
color: #990000;
}
If you use Typescript
in your project, just add a types definition to your project.
npm install --save @types/payu-emea-sdk
The following description refers to methods and objects available in browser-side JavaScript library, contained in JS SDK.
Loading JS SDK
Add JS SDK script to every page you want to use Secure Form on. It should always be loaded from the PayU server. You mustn't load it from your own server and then attach it to the package that is being built at the moment.
<script type="text/javascript" src="https://secure.payu.com/javascript/sdk"></script>
<script type="text/javascript" src="https://secure.snd.payu.com/javascript/sdk"></script>
JS SDK instance creation
var payu = PayU('393823');
JS SDK instance methods
var secureForms = payu.secureForms();
Possible values (default - SINGLE) | |
---|---|
SINGLE | Card not saved - token with short lifespan (11 minutes). |
SINGLE_LONGTERM | Card not saved. |
MULTI | Card saved - multi-use token will be returned after the it is charged via REST API. |
Promise, which resolves to the object containing the result.
Field | Description |
---|---|
status |
Tokenization status:
|
body |
Only for SUCCESS status. Object contains
tokenization information. |
error |
Only for ERROR status. Object
with messages array which contains
error information. Details can be found in Errors section. |
correlationId |
Only for ERROR status. |
{
"status": "SUCCESS",
"body": {
"token": "TOK_1JOQVU5KJNOV4c4O8UbZySwcfBdS",
"mask": "444433******1111"
}
}
card
form or number
, date
and
cvv
type forms.var secureForms = payu.secureForms();
cvv
. refReqId
parameter from redirectUri
field, from the response.
You can use extractRefReqId method to get
refReqId
from the URL.refReqId
parameter from URL.
https://address.page/summary/?statusCode=WARNING_CONTINUE_CVV&refReqId=7b09781ee6a3303cc86712fce16fe030
Promise, which resolves to the object containing the result.
Field | Description |
---|---|
status |
CVV sending status:
|
error |
Only for ERROR status. Object containing
error information. Details can be found in Errors section. |
correlationId |
Only for ERROR status. |
{
"status": "SUCCESS",
}
cvv
form is required. payu.sendCvv('7b09781ee6a3303cc86712fce16fe030');
refReqId
parameter from the URL. var refReqId = payu.extractRefReqId('https://secure.payu.com/cpm/threeds/proxy?refReqId=7b09781ee6a3303cc86712fce16fe030"');
SecureForms instance methods
Possible values (default - card) | |
---|---|
card | Complete card data form (card number, expiration date, CVV). |
number | Card number form. |
date | Card expiration date form. |
cvv | CVV form. |
card
when another number
, date
or
cvv
form was already added. It also occurs in the
opposite situation while trying to add number
,
date
or cvv
form when
card
form was already added. [message] array
contains details about errors. var cardNumberForm = secureForms.add('number');
SecureForm instance methods
cardNumberForm.render('#cardNumberForm');
cardNumberForm.update({lang: 'en'});
Possible values | |
---|---|
ready | Emitted when the form is displayed. |
focus | Emitted when the form gains focus. |
blur | Emitted when the form loses focus. |
change | Emitted when the value of the form is changed. |
SecureForm instance
cardNumberForm
.on('ready', function() {
// form ready
})
.on('focus', function() {
// form activated
})
.on('blur', function() {
// form deactivated
})
.on('change', function(body) {
// value of the form has changed
});
cardForm.clear();
cardForm.clear();
cardForm.remove();
All parameters are checked for their type and values correctness. Unknown and invalid parameters are ignored without information about error.
Parameter | Type | Description |
---|---|---|
fonts | array |
Custom fonts for forms. |
Fonts table
Contains list of objects defining additional fonts, which will be added to every form
using @font-face
.
family
and src
attributes are required.
Attribute | Permitted values |
---|---|
family | [-_a-zA-Z0-9 '"]+ |
src | url(.*?) format(.*?) may contain multiple
entries separated by coma |
display | (auto|block|swap|fallback|optional) |
style | (normal|italic|oblique) |
weight | ([1-9]00|normal|bold) |
unicodeRange | [-U+A-Fa-f0-9?, ]* |
{
fonts: [
{
family: 'Own Font',
src: 'url(https://ownulr.com/own_font_normal.woff2) format("woff2"), url(https://ownulr.com/own_font_normal.woff) format("woff2)',
style: 'normal',
weight: 400
},
{
family: 'Own Font',
src: 'url(https://ownulr.com/own_font_bold.woff2) format("woff2")',
style: 'normal',
weight: 'bold'
}
]
}
All parameters are checked for their type and values correctness. Unknown and invalid parameters are ignored without information about error.
Parameter | Type | Description |
---|---|---|
style | object |
Your own form style. |
placeholder | object |
Your own placeholder text in the form input fields. |
lang | string |
Two-character language code. Available languages are: pl
en
cs sk .If language is not specified, it is retrieved from the browser. For languages that are not supported, en is used.
|
disabled | boolean |
When set to true form will be blocked, otherwise
it will be active. |
cardIcon | boolean |
When set to false , card icon, next to card
number input field, is not displayed, otherwise it is
displayed. |
{
style: {
basic: {
fontColor: '#0000FF'
fontSize: '26px'
fontWeight: '700'
},
invalid: {
fontColor: '#990000'
},
placeholder: {
fontColor: '#aaaaaa'
}
},
placeholder: {
number: '',
date: 'MM / YY',
cvv: ''
},
cardIcon: true,
lang: 'en',
disabled: false
}
Style object
Groups styles for different form behaviours in objects. Each group has its permitted styles.
Styles group | Permitted styles | Description |
---|---|---|
basic | fontColor fontSize fontFamily
fontWeight letterSpacing |
Form styles |
invalid | fontColor fontWeight |
Styles for the form with invalid values. |
focus | fontColor fontWeight |
Style for the form with active focus. |
placeholder | fontColor fontWeight |
Styles for the form placeholders. |
disabled | fontColor fontWeight |
Styles for the disabled form. |
Style
Style | Descritpion | Permitted values |
---|---|---|
fontColor | font color | #[0-9a-f]{6} |
fontSize | font size | (\d+|\d*\.\d+)(px|em|%) |
fontFamily | font family | [0-9a-z\-\s]{1,50} |
fontWeight | font weight | ([1-9]00|normal|bold|lighter|bolder|inherit|initial|unset) |
letterSpacing | spacing between letters | normal|(-?)(\d+|\d*\.\d+)(px|em|%) |
Placeholder object
Field | Type | Description |
---|---|---|
number | string | Placeholder text for the card number form. |
date | string | Placeholder for the card expiration date form. |
cvv | string | Placeholderfor the card CVV form. |
Forms emit events to which you can attach your own callback using the on method.
Event ready
This event is emitted after calling render method after the form is displayed.
Event focus
This event is emitted when the form is activated.
Event blur
This event is emitted when the form is deactivated.
Event change
This event is emitted when the value of the form is changed.
Callback is
called with one object parameter with the following structure:
Field | Description |
---|---|
empty |
Indicates if the form is empty. Possible values: true
or false . |
error |
Indicates if the data entered in the form is correct.
Possible values: false when the form
contains correct data or array of objects with
errors.Possible error type is validation .
Details can be found in Errors section. |
brand |
Only for type number form.Contains information about the brand of the card. Possible values: visa , mastercard lub
maestro . |
Dynamic classes are added to the element in which the form is displayed.
Class | Description |
---|---|
payu-secure-form-empty |
Set when form is empty. |
payu-secure-form-focus |
Set when for is active (in focus). |
payu-secure-form-invalid |
Set when data entered into the form are invalid. |
error
object contains an array of objects
(messages
), which contain detailed information about the
errors.
Error object in messages array
Field | Description |
---|---|
type |
Error type. Possible values:
|
code |
Error code. |
source |
Element with possible error (only for errors with validate type).
Possible values: card , number , date ,
cvv .
|
message |
Error description in the languageof the form. In case of the
technical type errors, description in always in
english. |
parameters |
Object containing changeable error fragments. |
Error list
Error code | Description |
---|---|
validate type errors |
|
error.validation.card.empty |
Empty card number. |
error.validation.card.length |
Invalid card number length. |
error.validation.card.number |
Invalid card number. |
error.validation.card.unsupported |
Card type is not supported. Supported card types: Visa, Mastercard and Maestro. |
error.validation.expDate.empty |
Empty expiration date. |
error.validation.expDate.past |
Expiration date is in the past. |
error.validation.expDate.value |
Incorrect expiration date. |
error.validation.cvv.empty |
Empty CVV. |
error.validation.cvv.value |
Invalid CVV. |
technical type
errors |
|
error.tokenization |
Error has occured while trying to tokenize the card. Error
information can be found in the parameters object
in the error field. |
error.send.cvv |
Error has occured while sending CVV. Error information can be
found in the parameters object in the
error field. |
error.network |
A network communication error has occured. Error information can
be found in the parameters object in the
error field. |
{
"status": "ERROR",
"correlationId": "",
"error": {
"messages": [
{
"type": "validation",
"code": "error.validation.expDate.value",
"parameters": {},
"message": "Card expiration date is invalid"
},
{
"type": "validation",
"code": "error.validation.cvv.empty",
"parameters": {},
"message": "Empty CVV"
}
]
}
}
I need translation into xx
language.
Elements that are
translated are placeholder texts and error messages. Both elements you can translate
freely on your own.In case of placeholder elements we passed them in the placeholder
parameter in the form
options e.g.
{
placeholder: {
number: 'Kartennummer',
date: 'MM / JJ',
cvv: 'CVV'
}
}
In case of errors, we display message based on the error codes e.g.
var errors = {
messages: [
{
type: "validation",
code: "error.validation.card.number",
parameters: {},
message: "Nieprawidłowy numer karty"
}
]
};
var translations = {
"error.validation.card.number": "Ungültige Kartennummer"
};
var showError = function() {
errors.messages.forEach(function(message) {
console.log(translations[message.code]); // show error message
});
};
Someone has resized the browser window or flipped the phone. I want to change the font size and disable the card brand icon, so that the form fits completely on the page.
While resizing the browser window you should use the update method to update form options e.g.
// initializing code of JS SDK and SecureForms has been omitted
var cardNumber = secureForms.add('number');
var options = {
current: 'gt500',
profiles: {
gt500: {
style: {
basic: {
fontSize: '18px'
}
},
cardIcon: true
},
lt500: {
style: {
basic: {
fontSize: '14px'
}
},
cardIcon: false
}
}
};
// window size change
window.addEventListener('resize', function() {
var newProfile = window.innerWidth > 500 ? 'gt500' : 'lt500';
if (newProfile !== options.current) {
options.current = newProfile;
// form options update
cardNumber.update(options.profiles[options.current]);
}
});
This solution is deprecated. For new integrations use the Secure Form instead. If you are already using the widget and need documentation, please contact us.
This solution is deprecated. For new integrations use the Secure Form instead. If you are already using the form and need documentation, please contact us.
A device fingerprint is information collected about a remote computing device for the purpose of identification. Fingerprints can fully or partially identify devices or individual users
Fingerprint value is generated by static function Fingerprint2.get, which replaced new Fingerprint2().get. Beacuse of this the result will not be hashed anymore.
Needed libiraries can be found Here.
var options = {} Fingerprint2.get(options, function (components) { // components is array of {key: 'foo', value: 'component value'} ... }) // or Fingerprint2.getPromise(options).then(function (components) { // components is array of {key: 'foo', value: 'component value'} ... })
Fingerprint2.get(options, function (components) { var values = components.map(function (component) { return component.value }) var murmur = Fingerprint2.x64hash128(values.join(''), 31) })
The hash value should be passed to PayU in OrderCreateRequest body, see example below.
Multi-use token (TOKC_) is created after first use of single-use token (TOK_).
To obtain single-use token use Secure Form
with MULTI passed as argument to tokenize
method.
The multi-use token can either be created during purchase or separately. Below sections explain both ways in more details.
In case card is stored without making a purchase, you must not create order with total amount set to non-zero amount which is later canceled.
The above approach is forbidden by the card schemes (Visa and Mastercard). Instead, you should set total amount to 0 as described below.
Creating token during purchase is the standard and most common way to store a card.
The following requirements apply to such approach:
buyer
and
payMethod
sections where single-use token (TOK_) is used as
a value
parameter.cardOnFile
should be set to FIRST (detailed descriptions
of cardOnFile
parameter values can be found in JSON
properties section).curl -v -X POST https://secure.payu.com/api/v2_1/orders \ -H "Content-Type: application/json" \ -H "Authorization: Bearer 3e5cac39-7e38-4139-8fd6-30adc06a61bd" \ -d '{ "notifyUrl":"https://your.eshop.com/notify", "customerIp":"127.0.0.1", "merchantPosId":"145227", "description":"Laptop", "currencyCode":"PLN", "totalAmount":"15000", "cardOnFile": "FIRST", "extOrderId":"[generateExtOrderId]", "products":[ { "name": "Laptop", "unitPrice":"15000", "quantity": "1" } ], "buyer": { "email": "john.doe@example.com", "firstName": "John", "lastName": "Doe", "language": "en" }, "payMethods": { "payMethod": { "value": "TOK_1IHRPT6HKSSS3H62K0GS8pElP862", "type": "CARD_TOKEN" } }, "deviceFingerprint": "[generateFingerPrint2]" }'
Authentication methods are described in: Signing API calls parameters.
Warning! POS used in the example does not have tokenization switched on.
{ "status": { "statusCode": "WARNING_CONTINUE_3DS", "severity": "WARNING" }, "redirectUri": "{redirectUri}", "iframeAllowed": true, "threeDsProtocolVersion": "3DS2" "orderId": "ORDER_ID", "payMethods": { "payMethod": { "card": { "number": "424242******4242", "expirationMonth": "12", "expirationYear": "2017" }, "type": "CARD_TOKEN", "value": "TOKC_KPNZVSLJUNR4DHF5NPVKDPJGMX7" } } }
The above response assumes that there is need for additional payer authentication by means of 3DS. See Handling 3DS for more details.
PayU notifies you with payment status by submitting a notification to address provided
in the notifyUrl
parameter. To learn more about
notifications, please check Notifications.
Storing card without purchase is useful when you want the cardholder to store the card upfront, before any actual charge is made, like for example in case of free trial periods of a subscribed service.
This feature requires special arrangements to be made, before it is enabled in either sandbox or production enviroment. Please contact your sales representative in PayU first to find out if you can use this service.
The following requirements apply to such approach:
buyer
and
payMethod
sections where single-use token (TOK_) is used as
a value
parameter.totalAmount
set to 0 (note that
currency
still needs to be provided for the sake of API
consistency).products
object is not required.PENDING
to either
COMPLETED
or CANCELED
but never to
WAITING_FOR_CONFIRMATION
.shoppingCarts
object is
required.cardOnFile
should be set to FIRST (detailed descriptions
of cardOnFile
parameter values can be found in JSON
properties section).curl -v -X POST https://secure.payu.com/api/v2_1/orders \ -H "Content-Type: application/json" \ -H "Authorization: Bearer 3e5cac39-7e38-4139-8fd6-30adc06a61bd" \ -d '{ "notifyUrl":"https://your.eshop.com/notify", "customerIp":"127.0.0.1", "merchantPosId":"145227", "description":"Laptop", "currencyCode":"PLN", "totalAmount":"0", "cardOnFile": "FIRST", "extOrderId":"[generateExtOrderId]", "buyer": { "email": "john.doe@example.com", "firstName": "John", "lastName": "Doe", "language": "en" }, "payMethods": { "payMethod": { "value": "TOK_1IHRPT6HKSSS3H62K0GS8pElP862", "type": "CARD_TOKEN" } }, "deviceFingerprint": "[generateFingerPrint2]" }'
Authentication methods are described in: Signing API calls parameters.
Warning! POS used in the example does not have tokenization switched on.
{ "status": { "statusCode": "WARNING_CONTINUE_3DS", "severity": "WARNING" }, "redirectUri": "{redirectUri}", "iframeAllowed": true, "threeDsProtocolVersion": "3DS2" "orderId": "ORDER_ID", "payMethods": { "payMethod": { "card": { "number": "424242******4242", "expirationMonth": "12", "expirationYear": "2017" }, "type": "CARD_TOKEN", "value": "TOKC_KPNZVSLJUNR4DHF5NPVKDPJGMX7" } } }
The above response assumes that there is need for additional payer authentication by means of 3DS. See Handling 3DS for more details.
PayU notifies you with payment status by submitting a notification to address provided
in the notifyUrl
parameter. To learn more about
notifications, please check Notifications.
OrderCreateRequest should be extended by buyer
and
payMethod
sections where multi-use token (TOKC_) is used as a
value
parameter. Order created via REST API is described in:
Creating a new order.
cardOnFile
parameter,
which informs about party initializing payment:
Detailed descriptions of cardOnFile
parameter values can be found in
JSON properties section.
Setting this parameter in the correct way can increase conversion for payment cards.curl -v -X POST https://secure.payu.com/api/v2_1/orders \ -H "Content-Type: application/json" \ -H "Authorization: Bearer 3e5cac39-7e38-4139-8fd6-30adc06a61bd" \ -d '{ "notifyUrl":"https://your.eshop.com/notify", "customerIp":"127.0.0.1", "merchantPosId":"145227", "description":"Laptop", "currencyCode":"PLN", "totalAmount":"15000", "cardOnFile": "STANDARD_MERCHANT", "extOrderId":"9xl0x8nr1wk7m0i3ltqbja", "products":[ { "name": "Laptop", "unitPrice":"15000", "quantity": "1" } ], "buyer": { "email": "john.doe@example.com", "firstName": "John", "lastName": "Doe", "language": "en" }, "payMethods": { "payMethod": { "value": "TOKC_2IHRST6HKSST3H62K2GS8pElI862", "type": "CARD_TOKEN" } }, "deviceFingerprint": "0372098a4a90927db053463454491d78" }'
{ "orderId": "ORDER_ID", "payMethods": { "payMethod": { "card": { "number": "424242******4242", "expirationMonth": "12", "expirationYear": "2017" }, "type": "CARD_TOKEN", "value": "TOKC_KPNZVSLJUNR4DHF5NPVKDPJGMX7" } }, "status": { "statusCode": "SUCCESS", "statusDesc": "Request successful" } }
This response means that there is no need for additional payer authentication. Please note that it is possible that 3DS or CVV may need to provided. See Handling 3DS and Handling CVV2 for more details.
PayU informs Shop about the payment by submitting a notification to the address
provided in the orders notifyUrl
parameter. To learn more about
notifications, please read Notifications.
In case of WARNING_CONTINUE_3DS response, payer should be redirected to card
issuer page (redirectUri
parameter) for additional payment
authentication in 3D Secure process.
Authentication is currently always performed via 3DS2 protocol, indicated by the value of threeDsProtocolVersion
field.
To learn how to tackle 3DS2, please refer to 3DS 2 page.
{ "orderId": "ORDER_ID", "status": { "statusCode": "WARNING_CONTINUE_3DS", "severity": "WARNING" }, "redirectUri": "{redirectUri}", "iframeAllowed": true, "threeDsProtocolVersion": "3DS2" }
continueUrl
in
OrderCreateRequest. Additionally address in query string is extended
by two parameters:
statusCode
- values SUCCESS or WARNING_CONTINUE_CVV;refReqId
- random alfanumeric string of characters.https://your.shop.com/payment?statusCode=SUCCESS&refReqId=5c867936fbb3cc2c373820b4550b4645
When the statusCode
parameter adopts SUCCES value it means that
order has been accepted without need for another authentication of the payer and you
can wait for order status.
On the other hand whenstatusCode
parameter adopts
WARNING_CONTINUE_CVV value, then refReqId
parameter should be
taken:
refReqId=5c867936fbb3cc2c373820b4550b4645
cvv-url
parameter forwidget-type="cvv"
.redirectUri
parameter should be passed depending
on the integration type:
refReqId
with the extractRefReqId method and use the
sendCvv method to send the CVV;cvv-url
parameter for
widget-type="cvv"
.{ "orderId": "ORDER_ID", "status": { "statusCode": "WARNING_CONTINUE_CVV", "severity": "WARNING" }, "redirectUri": "{redirectUri}" }
Sample value of redirectUri
parameter:
https://secure.payu.com/api/v2/token/token.json?refReqId=11ed628ebe88ef6837d90ebb26f1a8b9
Order status will be sent after CVV2/CVC2 code has been provided by the payer.
Payment methods available for a given user should not be stored locally on merchant's server, but rather retrieved from PayU system for each payment. Retrieved are both the stored (tokenized) payments methods and generic payment methods. Using the retrieve service gives the following benefits:
- only payment methods available at the moment for the user are provided,
- payment methods stored for the user are always up to date and synchronized with user's active PayU Account.
In order to retrieve the payment methods, you need first to obtain OAuth access token.
To obtain OAuth access token, use the POST method to send request to endpoint
/pl/standard/user/oauth/authorize
.
Sample request:
curl -X POST https://secure.payu.com/pl/standard/user/oauth/authorize \ -H "Cache-Control: no-cache" -H "Content-Type: application/x-www-form-urlencoded" -d 'grant_type=trusted_merchant&client_id=[provided by PayU]&client_secret=[provided by PayU]&email=[users email]&ext_customer_id=[Id of the customer used in merchant system]'
ext_customer_id
is unique customer identifier given by merchant, it
is necessary in order to correctly generate the OAuth token.
{ "access_token": "4099c2c3-276f-488a-90e2-32620ac441dc", "token_type": "bearer", "expires_in": 43199, "grant_type": "trusted_merchant" }
Insert the access token into header and use the GET method to send request to endpoint
api/v2_1/paymethods
.
curl -X GET https://secure.payu.com/api/v2_1/paymethods \ -H "Authorization: Bearer 87ad751f-7ea5-4023-a16f-04b6647a07f5" -H "Cache-Control: no-cache"
Sample postive response (HTTP 200). Description of fields are below the sample:
{ "cardTokens":[ { "cardExpirationYear":"2017", "cardExpirationMonth":"12", "cardNumberMasked":"411111******1111", "cardBrand":"VISA", "value":"TOKC_XATB7DF8ACXYTVQIPLWTVPFRKQE", "brandImageUrl":"http://static.payu.com/images/mobile/visa.png", "preferred":true, "status":"ACTIVE" }, { "cardExpirationYear":"2014", "cardExpirationMonth":"12", "cardNumberMasked":"424242******4242", "cardBrand":"VISA", "value":"TOKC_XATB7DF8ACXYTVQIPLWTVPFRKQE", "brandImageUrl":"http://static.payu.com/images/mobile/visa.png", "preferred":false, "status":"EXPIRED" } ], "pexTokens":[ { "accountNumber":"5311...7744", "payType":"mtex", "value":"TOKE_XPJ4UKJGHVRPMQPGB6X1JJQCUSS", "name":"account name set by the user", "brandImageUrl":"http://static.payu.com/images/mobile/logos/pex_mbank.png", "preferred":false, "status":"ACTIVE" } ], "payByLinks":[ { "value":"c", "name":"Płatność online kartą płatniczą", "brandImageUrl":"http://static.payu.com/images/mobile/logos/pbl_c.png", "status":"ENABLED", "minAmount": 50, "maxAmount": 100000 }, { "value":"o", "name":"Pekao24Przelew", "brandImageUrl":"http://static.payu.com/images/mobile/logos/pbl_o.png", "status":"DISABLED", "minAmount": 50, "maxAmount": 100000 }, { "value":"ab", "name":"Płacę z Alior Bankiem", "brandImageUrl":"http://static.payu.com/images/mobile/logos/pbl_ab.png", "status":"TEMPORARY_DISABLED", "minAmount": 50, "maxAmount": 100000 } ] }
Parameter | Description |
---|---|
cardExpirationYear | YYYY |
cardExpirationMonth | MM |
cardNumberMasked | First 6 and last 4 digits of the PAN (card number). |
cardBrand | Possible values: 'VISA', 'MASTERCARD', 'MAESTRO'. Other card types are not supported, moreover 'MAESTRO' is not supported in recurring payments. VISA describes various Visa card brands, incl. Visa Electron. MASTERCARD also includes MasterCard Debit. |
value | Card token value. |
brandImageUrl | Link to card brand graphic on PayU server. |
preferred | true/false; it is set to 'true' for a cardToken or bankToken used most recently by the user. |
status | Possible values: 'ACTIVE' and 'EXPIRED'.
'EXPIRED' tokens may be skipped or presented to the user with a prompt to update or add a new card. If a token has been closed by the user or blocked for security reasons by PayU, it will not be provided in retrieve response. |
pexTokens relate to bank accounts tokenized through PayU|Express service.
Parameter | Description |
---|---|
accountNumber | First and last 4 digits of the bank account in the IBAN format. |
payType | Represents payType of the token. |
name | Name of the bank account set by the user. |
value | Bank token value. |
brandImageUrl | Link to bank logo graphic on PayU server. |
preferred | true/false; it is set to 'true' for a cardToken or bankToken used most recently by the user. |
status | Possible value: 'ACTIVE'.
If a token has been closed by the user or blocked for security reasons by PayU, it will not be provided in retrieve response. If payType of the token is not configured on merchant's POS, the token will not be provided. |
Parameter | Description |
---|---|
value | payType value. Available values are here. |
name | Name of payType set by PayU |
brandImageUrl | Link to payType logo graphic on PayU server. |
status | Possible values: 'ENABLED', 'DISABLED', 'TEMPORARY_DISABLED'. |
In case the buyer terminates the user account in your shop or chooses to remove the stored card from the user account, you need to delete the token.
In order to do it, simply send a DELETE message to https://secure.payu.com/api/v2_1/tokens/{tokenValue}
The header should contain a trusted.merchant OAuth token.
For example:curl -X DELETE https://secure.payu.com/api/v2_1/tokens/TOKC_XATB7DF8ACXYTVQIPLWTVPFRKQE \ -H "Authorization: Bearer cccbbc40-8113-443b-b4ea-c4b266272b22" -H "Cache-Control: no-cache"
Warning! This integration type is available only for POSes meeting PCI DSS requirements and requires additional configuration. Therefore, please contact your sales representative in PayU before the integration.
Standard OrderCreateRequest should be extended by
payMethods.payMethod
section containing plain card data
and cardOnFile
parameter:
Detailed descriptions of cardOnFile
parameter values can be
found in JSON properties section.
Only in case of one-time card payment this cardOnFile
parameter can
be skipped.
Setting this parameter in the correct way can increase conversion for payment cards and can guarantee transaction security.
"payMethods": { "payMethod": { "card": { "number":"5100052384536818", "expirationMonth":"11", "expirationYear":"2020", "cvv":"123" } } },
"payMethods": { "payMethod": { "card": { "number":"5100052384536818", "expirationMonth":"11", "expirationYear":"2020", "cvv":"123", "firstTransactionId": "MCC0111LL1121" } } },
Also for plain card data payments you should be prepared for handling responses with: WARNING_CONTINUE_3DS or WARNING_CONTINUE_CVV.
In case of already existing integration with provider of 3D Secure service (later
called 3DS) you can pass parameters that have been returned from 3DS handling process
in
OrderCreateRequest. Standard
OrderCreateRequest should be extended by
payMethods.threeDsData
section containing result data from 3DS process.
WARNING_CONTINUE_3DS will never be returned if the result of 3DS handling process will be delivered with Order.
"payMethods": { "payMethod": { ... }, "threeDsData": { "status3Ds": "Y", "status3DsDescription": "Authentication successful", "dsTransactionId": "3b31b19d-1c06-4ea4-a85a-00af10c66588", "eciCode": 5, "cavv": "AAABBBEAUAAAABgICABQAAAAAAA=" } } }
"payMethods": { "payMethod": { ... }, "threeDsData": { "status3Ds": "A", "status3DsDescription": "Authentication attempt", "dsTransactionId": "3b31b19d-1c06-4ea4-a85a-00af10c66588", "eciCode": 6, "cavv": "BwABCJQnYgAAACdENCdiAAAAAAA=" } } }
Parameter | Parameter type | Description |
---|---|---|
status3Ds | ENUM | 3DS status. Following values are allowed to be used:
|
status3DsDescription | string {1, 1024} |
Description related to 3DS result.
Optional field. However passing additional description with the MPI will allow better potential customer support from BOK. |
xid |
string {1, 20} - for value in plain text, string {28} - for Base64encoded value, string {40} - for HEXencoded value. |
XID - unique identifier of 3DS transaction given by the
shop. Field required within 3DS version 1 section. This field should not be sent when attempting 3DS2.x authentication. |
dsTransactionId | string {1, 36} | Field required within 3DS2.x section. This field should not be sent when attempting 3DS version 1 authentication. |
eciCode | ENUM | E-commerce Indicator / UCAF. Permitted values (below values can also be passed with "0" e.g. "05", "04", etc.):
|
cavv | string {1, 200} |
3DS cryptogram.
Optional field.It should be passed always if the MPI provided this information. |
Below you can find a handy reference of all card tokenization flow types.
cardOnFile
or recurring
param if required), insert one-time card token and submit the request. Endpoint:
/api/v2_1/orders. Method POST.redirectUri
provided in the response.continueUrl
.notifyUrl
.notifyUrl
.redirectUri
provided in the response.continueUrl
.notifyUrl
.notifyUrl
.