Generating Reservation Codes
Reservation code allows to accept transaction using API, similarly to user's PIN code. Each reservation code is unique and is valid for only one transaction.
To generate reservation codes, data is needed for seeding the generator. Generating reservation codes follows this flow:
- Client requests for reservation code seed data;
- SMS or email is sent to the user with random code;
- User provides this code to the client;
- Client sends the code to the API, getting seed data as a response;
- Client generates first reservation code from seed data, all other codes from the previous generated code;
- Reservation codes are used by the client to accept transactions or to be provided as QR code or barcode for other clients.
Sending user request for reservation code seed data
This method initiates SMS or email for the user with confirmation code to initialize generator. This request must be made using OAuth access token, by which user is determined.
Request
POST https://wallet.paysera.com/rest/v1/generator/code
Request body structure
Request body is optional in this request.
link
{code}
, which will be
replaced with code, needed for initial generator data.
scopes
convert_currency
- lets the same code to be used with token refresh to extend current access token scope with
convert_currency
Response data structure
valid_until
Errors
rate_limit_exceeded
Example request
POST /rest/v1/generator/code HTTP/1.1 Host: wallet.paysera.com Content-Type: application/json;charset=utf-8 User-Agent: Paysera WalletApi PHP library Authorization: MAC id="wkVd93h2uS", ts="1343811600", nonce="nQnNaSNyubfPErjRO55yaaEYo9YZfKHN", mac="Xtfj2zavWXLcUKWcm0G5j/+X+Ng+fV4dmplXOpvAoFQ=", ext="body_hash=XqUMu%2B1I2uXJtMXZhK%2Fc4nr0DXZ88ca63KYuehJmkqU%3D"
{ "link": "my_app://generator/{code}" }
Example response
HTTP/1.1 200 OK Content-type: application/json;charset=utf-8
{ "valid_until": 1355314332 }
Requesting initial generator data
This method exchanges code, received from the user, to initial data, needed for generating reservation codes.
Request
POST https://wallet.paysera.com/rest/v1/generator
Request body structure
code
Response data structure
id
status
valid
, invalid
. Latter means that reservation codes,
related to this generator, will not be valid for reserving transactions. Generator must be re-initialised
for further reservation code generation.
expires_in
identifiers
seed
type
pbkdf2-sha256
is available
params
type
parameter. See bellow for
more information.
Identifier data structure
identifier
wallet_id
Parameters data structure for pbkdf2-sha256 algorithm
secret_iterations
secret_length
sign_iterations
sign_length
Errors
rate_limit_exceeded
, invalid_code
Example request
POST /rest/v1/generator HTTP/1.1 Host: wallet.paysera.com Content-Type: application/json;charset=utf-8 User-Agent: Paysera WalletApi PHP library Authorization: MAC id="wkVd93h2uS", ts="1343811600", nonce="nQnNaSNyubfPErjRO55yaaEYo9YZfKHN", mac="4QMxznZfLYKNtBlcmEuda1VUUeUxtyfhiEOl1LNFvxE=", ext="body_hash=gKf8N9VnifXglboUYFyvOdYX6siZ5yYhfRuGctAoVSY%3D"
{ "code": "758604" }
Example response
HTTP/1.1 200 OK Content-type: application/json;charset=utf-8
{ "id": 8754, "status": "valid", "expires_in": 3600, "identifiers": [ { "identifier": 2147483782, "wallet_id": 6 }, { "identifier": 2147483784, "wallet_id": 94 } ], "seed": "m1ZSFUArP1iN/xc1/iGCCci7B8QQ1SEu9JCnBz22Dss=", "type": "pbkdf2-sha256", "params": { "secret_iterations": 1024, "secret_length": 32, "sign_iterations": 1024, "sign_length": 4 } }
Getting generator data by ID
This method gets generator data by it's ID. It can be used for checking expires_in
field or
status of the generator
Request
GET https://wallet.paysera.com/rest/v1/generator/:generatorId
Parameters
generatorId - ID of the generator
Response data structure
Response is the same as when getting initial generator data, except missing fields, related to the
generation algorithm: seed
, type
and params
.
Reservation code generation algorithm
When generating reservation code, process consists of three steps:
- Getting current secret key, used for signing;
- Encoding information, identifying this reservation code;
- Generating signature for this information, using the generated secret key.
Process can be provided as a set of functions:
salt(index) = index == 1 ? base64_decode(response.seed) : secret(index - 1) secret(index) = generateSecret(accessTokenSecretKey, salt(index), response.parameters) info(index) = encodeInfo(identifier, lifetime, constraints) signature(index) = generateSignature(secret(index), info(index), response.parameters) reservationCode(index) = info(index) || signature(index)
index
- Index starts with 1
and increases by 1
with each generated reservation code
response - Response data for generator request
accessTokenSecretKey
- mac_key
related to the access token, used in generator request. If access token changes (after refresh), this parameter does not. Thus it should be saved together with other generator data and kept secret even after disposing related access token.
identifier - Identifier from generator initial data, depending on the wallet. Reservation code will be related to this generator data and specific wallet by this identifier
lifetime - Seconds passed after issuing the generator data
constraints - Constraints, related to the reservation code. For example, maximum sum for transaction, reserved by this code
generateSecret
and generateSignature
functions depend on type
parameter, for which only pbkdf2-sha256
is supported at the time.
In the description of the algorithm function PBKDF2(P, S, c, dkLen)
is used, which is described in
RFC2898,
where pseudorandom function PRF
is SHA-256
.
Function generateSecret(secret, seed, parameters)
is defined in the following way:
PBKDF2(secret, seed, parameters.secret_iterations, parameters.secret_length)
Function generateSignature(secret, info, parameters)
is defined in the following way:
PBKDF2(secret, info, parameters.sign_iterations, parameters.sign_length)
Function encodeInfo(identifier, lifetime, constraints)
is defined in the following way:
be4(identifier) || be3(lifetime) || extensions
Here be4
and be3
are functions, encoding integer number in big-endian format with
4 bytes and 3 bytes result accordingly. extensions
are optional and described bellow.
In another words, be4
is four-octet encoding of an integer, most significant octet first.
Information extensions
Extensions are optional and can be appended to the information data in any order. Each extension is identified by an integer ID and can contain additional information.
Setting maximum sum for reservation code
There are 2 extensions for each of supported currencies. Each extension consists of 2 bytes - extension identifier and maximum sum identifier. Each byte is encoded in big-endian format. Value of second byte is multiplied by specified multiplier to get the actual sum in cents.
Extension ID, currency and multipliers are provided in the table bellow.
x40x1F
means maximum of 31.00 AUD
x41x1F
means maximum of 310,000.00 BYR
x42x1F
means maximum of 31.00 CAD
x43x1F
means maximum of 31.00 CHF
x44x1F
means maximum of 310.00 CZK
x45x1F
means maximum of 31.00 DKK
x46x1F
means maximum of 31.00 EUR
x47x1F
means maximum of 31.00 GBP
x48x1F
means maximum of 3,100.00 HUF
x49x1F
means maximum of 3,100.00 JPY
x4Cx1F
means maximum of 310.00 NOK
x4Dx1F
means maximum of 31.00 PLN
x4Ex1F
means maximum of 310.00 RUB
x4Fx1F
means maximum of 310.00 SEK
x50x1F
means maximum of 31.00 USD
x60x1F
means maximum of 310.00 AUD
x61x1F
means maximum of 3,100,000.00 BYR
x62x1F
means maximum of 310.00 CAD
x63x1F
means maximum of 310.00 CHF
x64x1F
means maximum of 3,100.00 CZK
x65x1F
means maximum of 310.00 DKK
x66x1F
means maximum of 310.00 EUR
x67x1F
means maximum of 310.00 GBP
x68x1F
means maximum of 31,000.00 HUF
x69x1F
means maximum of 31,000.00 JPY
x6Cx1F
means maximum of 3,100.00 NOK
x6Dx1F
means maximum of 310.00 PLN
x6Ex1F
means maximum of 3,100.00 RUB
x6Fx1F
means maximum of 3,100.00 SEK
x70x1F
means maximum of 310.00 USD
Allowing reservation code to be used with allowances
By default, transactions with allowances cannot be accepted using reservation codes. For reservation code to be valid on transactions, including allowances, this extension must be included.
This extension is defined as one byte, indicating extension ID: %01
in URL-encoded format,
AQ==
in base64-encoded format.
Encoding reservation code
Before sending reservation code to API or encoding into QR code or barcode, it must be encoded into format, easily used in any of these use-cases. Reservation code is string in ASCII symbols of decimal representation of binary reservation code result. Big-endian encoding is used for converting binary data to decimal representation.
Encoding example
Bellow there are examples of random binary data encoded in base64 format and in format, used for reservation code.
First example in base64
- PcJKPsUUN4kUytE=
First example in decimal representation
- 74661983676274174854482641
Second example in base64
- Pw2q40XZFOKbat0rqyXoRUsEmw==
Second example in decimal representation
- 1406137557324345164655494461243726425100059803
Encoding reservation code as a QR code
Reservation code can be encoded as a QR code. It's encoded as an ASCII string, adding prefix
PAYSERA$
.
Encoding reservation code as a barcode
Reservation code can be encoded as a barcode of type Code128. It's encoded as an ASCII string, adding prefix
9999
. As only ASCII encoded digits are used in the barcode, only C code table should be used.
Also for smallest barcode possible, 0
should be added in front of reservation code
before adding prefix, if reservation code length is odd.
rp7X/eHUSn/w
PAYSERA$3221179364949818507248
Bar:
99993221179364949818507248
+9HTizWCgbFNnA==
PAYSERA$1189184600047884648402332
Bar:
999901189184600047884648402332
hD4APgOzxeNEwOg=
PAYSERA$159870999379681886848991464
Bar:
99990159870999379681886848991464
Reservation code generation example
Example response
HTTP/1.1 200 OK Content-type: application/json;charset=utf-8
{ "id": 8754, "status": "valid", "expires_in": 3600, "identifiers": [ { "identifier": 2147483782, "wallet_id": 6 }, { "identifier": 2147483784, "wallet_id": 94 } ], "seed": "m1ZSFUArP1iN/xc1/iGCCci7B8QQ1SEu9JCnBz22Dss=", "type": "pbkdf2-sha256", "params": { "secret_iterations": 512, "secret_length": 32, "sign_iterations": 1024, "sign_length": 4 } }
In example, it is assumed, that mac_key
for current access token is
NlNypbXcTGxK10fy8BsYAFtD9mP39uzL
, time passed after generator response is 2113
seconds (35 minutes and 13 seconds) and one more minute before generating second code,
selected wallet ID is 94
for first code, 6
for the second one.
secret(1)
- Generation algorithm: PBKDF2('NlNypbXcTGxK10fy8BsYAFtD9mP39uzL', base64_decode('m1ZSFUArP1iN/xc1/iGCCci7B8QQ1SEu9JCnBz22Dss='), 512, 32)
. Result when base64 encoded: MhhNKPdt3gGuNb3iRCfiWuN3eXred/uVnOKfw3iMfog=
info(1)
- Generation parameters: 2147483784
, 2113
. Result when base64 encoded: gAAAiAAIQQ==
signature(1)
- Result when base64 encoded: hxVs/Q==
reservationCode(1)
- Result: 0154742514710514401052814589
secret(2)
- Generation algorithm: PBKDF2('NlNypbXcTGxK10fy8BsYAFtD9mP39uzL', base64_decode('MhhNKPdt3gGuNb3iRCfiWuN3eXred/uVnOKfw3iMfog='), 512, 32)
. Result when base64 encoded: BULycPtSHbzpXnucmEpZszA9Rom3NEBVJEblsOurrJA=
info(2)
- Generation parameters: 2147483782
, 2173
. Also extensions are used: maximum sum is restricted to 12.00 USD and allowance is allowed. Result when base64 encoded: gAAAhgAIfVAMAQ==
signature(2)
- Result when base64 encoded: zNbTHw==
reservationCode(2)
- Result when base64 encoded: 2596148591263630246308602000626463
Generating long-term transaction authorisation code
This method allows client to create authorisation code attached to specific amount and wallet. It can be used to authorise specific transaction
Create AuthorisationCode
POST /authorisation-code/rest/v1/authorisation-codes HTTP/1.1 Host: wallet.paysera.com User-Agent: Paysera WalletApi PHP library Authorization: MAC id="wkVd93h2uS", ts="1343811600", nonce="nQnNaSNyubfPErjRO55yaaEYo9YZfKHN", mac="PJ9DW82J3Pk5j3GGQ8r3aRwkRmOik5CX3sU3+UFiZ3s="
Request body structure
description
valid_until
authorised_amount
Example request
POST /authorisation-code/rest/v1/authorisation-codes HTTP/1.1 Host: wallet.paysera.com Content-Type: application/json;charset=utf-8 User-Agent: Paysera WalletApi PHP library Authorization: MAC id="wkVd93h2uS", ts="1343811600", nonce="nQnNaSNyubfPErjRO55yaaEYo9YZfKHN", mac="KgVIpVqlRBbwziBwTryv58rX/yRE6+ABr8Gue9Nnw0I=", ext="body_hash=Zm3nvOGqbglham9zf83gr4y%2FNtwXQvx51tnCokuSG6k%3D"
{ "description": "some description", "valid_until": 1234567890, "authorised_amount": { "amount": 100, "currency": "EUR" } }
Response body structure
id
description
valid_until
authorised_amount
status
new
, used
, expired
code
Example response
HTTP/1.1 200 OK Content-type: application/json;charset=utf-8
{ "id": 8754, "description": "some description", "valid_until": 1234567890, "authorised_amount": { "amount": 100, "currency": "EUR", "amount_decimal": "1.00" }, "status": "new", "code": "AC_KDFDFDFSD6PTSN" }
Get created AuthorisationCode
GET https://wallet.paysera.com//authorisation-code/rest/v1/authorisation-codes/:id
Response body structure
Response body structure is same as in Create Authorisation Code
Delete created AuthorisationCode
DELETE https://wallet.paysera.com//authorisation-code/rest/v1/authorisation-codes/:id
Response structure
HTTP/1.1 204 AcceptedNo content will be returned on success.