Generating reservation codes

Info This feature is not available by default and is enabled only for some clients

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

About

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.

Parameter Type Remarks Description
link string optional Link to include in SMS or email for quick confirmation. Must include {code}, which will be replaced with code, needed for initial generator data.
scopes array of string optional Additional permissions to relate with sent code. Currently supported 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

Parameter Type Remarks Description
valid_until integer always Date in UNIX timestamp until when this code is valid.

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="1343822400", nonce="nQnNaSNyubfPErjRO55yaaEYo9YZfKHN", mac="NHP3hra6mnObsq0BpHVqwxSmsYOMeEzh2knIVUnHxN0=", 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

About

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

Parameter Type Remarks Description
code string required Code received from the user

Response data structure

Parameter Type Remarks Description
id integer always ID of this generator, used when generating the reservation codes
status string always One of the following: 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 integer always Time in seconds until generator expires. Expiration time is extended by this size every time reservation code is used for accepting the transaction (even if it's used by some other client)
identifiers array of objects always Reservation code identifiers for each wallet of current user. See bellow for more information.
seed string Only in response for code exchange request Initial data for generating first reservation code. Must be kept secret. Given in base64-encoded format, should be decoded before using in generator
type string Only in response for code exchange request Type of algorithm used when generating reservation codes. Currently only pbkdf2-sha256 is available
params object Only in response for code exchange request Parameters for generation algorithm. Structure depends on type parameter. See bellow for more information.

Identifier data structure

Parameter Type Remarks Description
identifier integer always Identifier to use if generating code for this wallet
wallet_id integer always ID of the wallet, related to this identifier

Parameters data structure for pbkdf2-sha256 algorithm

Parameter Type Remarks Description
secret_iterations integer always Iterations used while generating next secret key
secret_length integer always Length of the secret key in bytes
sign_iterations integer always Iterations used while generating signature
sign_length integer always Length of the signature in bytes

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="1343822400", nonce="nQnNaSNyubfPErjRO55yaaEYo9YZfKHN", mac="p04L5xhjENSkwrnALAbB8MF07CP0WydZcQE33tveeRY=", 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

About

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.

Currency Extension ID Multiplier Example
AUD 64 100 x40x1F means maximum of 31.00 AUD
BYR 65 1000000 x41x1F means maximum of 310000.00 BYR
CAD 66 100 x42x1F means maximum of 31.00 CAD
CHF 67 100 x43x1F means maximum of 31.00 CHF
CZK 68 1000 x44x1F means maximum of 310.00 CZK
DKK 69 100 x45x1F means maximum of 31.00 DKK
EUR 70 100 x46x1F means maximum of 31.00 EUR
GBP 71 100 x47x1F means maximum of 31.00 GBP
HUF 72 10000 x48x1F means maximum of 3100.00 HUF
JPY 73 10000 x49x1F means maximum of 3100.00 JPY
NOK 76 1000 x4Cx1F means maximum of 310.00 NOK
PLN 77 100 x4Dx1F means maximum of 31.00 PLN
RUB 78 1000 x4Ex1F means maximum of 310.00 RUB
SEK 79 1000 x4Fx1F means maximum of 310.00 SEK
USD 80 100 x50x1F means maximum of 31.00 USD
AUD 96 1000 x60x1F means maximum of 310.00 AUD
BYR 97 10000000 x61x1F means maximum of 3100000.00 BYR
CAD 98 1000 x62x1F means maximum of 310.00 CAD
CHF 99 1000 x63x1F means maximum of 310.00 CHF
CZK 100 10000 x64x1F means maximum of 3100.00 CZK
DKK 101 1000 x65x1F means maximum of 310.00 DKK
EUR 102 1000 x66x1F means maximum of 310.00 EUR
GBP 103 1000 x67x1F means maximum of 310.00 GBP
HUF 104 100000 x68x1F means maximum of 31000.00 HUF
JPY 105 100000 x69x1F means maximum of 31000.00 JPY
NOK 108 10000 x6Cx1F means maximum of 3100.00 NOK
PLN 109 1000 x6Dx1F means maximum of 310.00 PLN
RUB 110 10000 x6Ex1F means maximum of 3100.00 RUB
SEK 111 10000 x6Fx1F means maximum of 3100.00 SEK
USD 112 1000 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.

Reservation code in base64 Contents Example QR code Example barcode
rp7X/eHUSn/w QR: PAYSERA$3221179364949818507248
Bar: 99993221179364949818507248
+9HTizWCgbFNnA== QR: PAYSERA$1189184600047884648402332
Bar: 999901189184600047884648402332
hD4APgOzxeNEwOg= QR: 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

About

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="1343822400", nonce="nQnNaSNyubfPErjRO55yaaEYo9YZfKHN", mac="bizchsF5q6iEoge7kStRSGLRmd9ketMQ87qw5rXD/5U="

Request body structure

Parameter Type Remarks Description
description string optional Some description for this authorisation code
valid_until integer required Timestamp until this authorisation code is valid
authorised_amount Money object required Object, containing authorised "amount" (float) and "currency" (string) keys

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="1343822400", nonce="nQnNaSNyubfPErjRO55yaaEYo9YZfKHN", mac="YcSnePyCtEkfHWjCM2dm+XYKSDtd3BUq3B681CB5IMg=", ext="body_hash=Zm3nvOGqbglham9zf83gr4y%2FNtwXQvx51tnCokuSG6k%3D"
{
    "description": "some description",
    "valid_until": 1234567890,
    "authorised_amount": {
        "amount": 100,
        "currency": "EUR"
    }
}

Response body structure

Parameter Type Remarks Description
id integer always Identifier of this authorisation code
description string only if provided Some description for this authorisation code
valid_until integer always Timestamp until this authorisation code is valid
authorised_amount Money object always Object, containing authorised "amount" (float) and "currency" (string) keys
status string always Status of this authorisation code, possible values: new, used, expired
code string always The authorisation code itself

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"
    },
    "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 AuthorisationCode

Delete created AuthorisationCode

DELETE https://wallet.paysera.com//authorisation-code/rest/v1/authorisation-codes/:id

Response structure

HTTP/1.1 204 Accepted
No content will be returned on success.