1.2. Card Not Present API (Mobile Device)

1.2.1. General information

Participants

Consumer would like to make payments or money transfers with Merchant’s mobile app on his mobile device.
Merchant’s app allows Consumer to process the transactions via secure Mobile Device API (DAPI) integration to Industra.
Merchant’s server or Merchant’s proxy is used to store and transfer data about user’s authentication credentials and card mapping information.
Industra processes the transactions with EFT (Electronic Funds Transfer participants - Acquirer banks, Issuer banks and Global Card Systems).
3DS flow between banks, Global card systems (Visa, MasterCard, etc) and Industra is simplified on the schemes below, please see 3-D Secure (3DS) for details.

Quick integration guide

  1. Optional consumer authentication is used to create {accessToken}, which is required in integration of any transaction type.
  2. Transaction types supported in DAPI at the moment: Card verification, Sale, Money transfer.
  3. Signature computation contains information and debugging tool for request-response signatures in DAPI.
  4. Merchant Callbacks implementation is the most appropriate way to get transaction’s status for Merchant’s server.
  5. Depending on the integration, Alternative cardholder authentication (non3D) can be used for cards without support of 3-D Secure technology. For details, please contact your Support manager.
  6. Example code and SDK contains integration solutions for Merchant’s server, Android and iOS platforms.

Optional consumer authentication

To perform authentication of Consumer in Merchant’s app, Merchant can use any method which fits best to his needs.
As a result, Merchant’s server generates {accessToken} and provides it to Merchant’s app. This parameter will be used to start and continue session for all transaction types supported by DAPI.

title Mobile Device - Optional consumer authentication
skinparam ParticipantPadding 70
participant client as "Consumer"
participant mobile as "Mobile App"
participant merchant as "Merchant's Server"
mobile <-> client : Authentication
merchant <- mobile : Request access token
note left
token credentials
end note
mobile <-- merchant
note right
accessToken
end note

This step is not displayed on the integration schemes below.

Alternative cardholder authentication (non3D)

DAPI supports alternative methods for cardholder authentication if 3DS enrollment request to EFT returns negative response.
Those methods can be used for all types of transactions supported by DAPI, depending on the integration.
One of such methods is random sum check. In this method, Industra addresses directly to Acquirer Bank to hold a random small amount on cardholder’s account, then sends redirect url to Merchant’s app.
Merchant’s app then opens the browser for Consumer to enter the amount being held in Industra special form.
If the amount is correct, Industra continues to process the initial transaction. The small amount hold is cancelled automatically by Acquirer Bank.

title Mobile Device - Random sum cardholder authentication (alternative method)
skinparam ParticipantPadding 70
participant client as "Consumer"
participant mobile as "Mobile App"
participant merchant as "Merchant's Server"
participant pne as "Industra"
participant bank as "Bank Acquirer"
pne <- bank : 3DS enrollment negative response
loop until final status is sent
mobile -> pne: Status request
note left
session token
end note
mobile <-- pne
note right
state = PROCESSING
end note
end
pne -> bank: Random sum request (preauth)
pne <-- bank: Random sum response
mobile <- pne: Open browser and redirect to random sum check html form
activate mobile
client <-- mobile
client -> mobile: The cardholder provides auth data
mobile -> pne
pne -> pne: Validate auth data
pne --> mobile: Close browser request
destroy mobile
merchant <-> pne: Card mapping
note right
server card id
end note
mobile <-- pne: Status response
note left
state = APPROVED|DECLINED
end note

1.2.2. Card verification

DAPI allows Consumer to make transfer and sale transactions easier with a single verification process. During the process, the card is being validated by Industra, authenticated with 3DS/non-3DS by EFT and then mapped to reference on Merchant’s server. It allows Consumer to avoid entering card data for each transfer or sale transaction. Integration is based on HTTP POST requests/responses with JSON data. You may see the general flow process below:

title Mobile Device - 3-D Secure card verification
skinparam ParticipantPadding 70
participant client as "Consumer"
participant mobile as "Mobile App"
participant merchant as "Merchant's Server"
participant pne as "Industra"
participant bank as "EFT"
client -> mobile: Start verification
merchant <-> mobile: Initiate verification
mobile -> pne: Perform validation
pne -> pne: check signature
mobile <-- pne: Status info
note right
session token
end note
pne <-> merchant : Check verification
pne <-> bank : Check 3DS enrollment
loop until final status is sent
mobile -> pne: Verification status request
note left
session token
end note
mobile <-- pne
note right
state = PROCESSING
end note
end
mobile <- pne: Open browser and redirect to EFT
note right
ACS url
PA Request
Term url
Merchant data
end note
activate mobile
mobile -> bank
mobile <-- bank: Response with 3DS html form
client <-- mobile
client -> mobile: The cardholder provides auth data
mobile -> bank
mobile <-- bank: Redirect browser back to Industra
note right
PA Response
Merchant data
end note
mobile --> pne: Verification status update
pne --> mobile: Close browser request
destroy mobile
pne <-> bank: 3DS auth result
note left
PA Response
end note
note right
cavv
eci
status
end note
pne <-> bank: process preauth
merchant <-> pne: Verification card mapping notification
note right
server card id
end note
mobile <-- pne: Verification status response
note left
state = APPROVED|DECLINED
end note

Initiate verification

To initiate card verification, Merchant’s app sends {accessToken} with other device parameters to Merchant’s server. These parameters are used to start a session with unique random {nonce} and encrypted {signature}. In response Merchant’s server also provides information about {invoiceId} in merchant’s system and {endpointId} in Industra.

Initiate verification request is sent by Merchant’s app through HTTPS POST to URL in the following format (provided by merchant)

https://proxy.merchantserver.com/verification/initiate-verification

Request body

In the request body, supply data with the following structure:

{
  "consumer": {
    "device": {
      "imei": "string",
      "serialNumber": "string"
    },
    "ipAddresses": ["string"]
  },
  "location": {
    "lat": "double",
    "lng": "double"
  },
  "session": {
    "accessToken": "string"
  },
  "transaction": {
    "currency": "string"
  }
}
Property name Value Description
Required properties
consumer object  
consumer.device object  
consumer.device.serialNumber string(1-50) Consumer’s device serial number
transaction object  
transaction.currency string(3) Upper case letters (ISO 4217 alpha code)
session object  
session.accessToken string(32-128) Access token key received in Optional consumer authentication
Optional properties
consumer.device.imei string(14-16) Consumer’s device international mobile equipment identity
location object  
location.lat double The latitude specified in the range of -90.0 through +90.0, both inclusive
location.lng double The longitude specified in the range -180.0 through +180.0, both inclusive
consumer.ipAddresses list Consumer’s IP addresses
consumer.ipAddresses[] string(7-15) Consumer’s IP address

Initiate verification response

If successful, this method should return the following response body:

{
  "endpointId": "string",
  "invoiceId": "string",
  "session": {
    "nonce": "string",
    "signature": "string"
  }
}
Property name Value Description
endpointId string Entry point identifier for verification transaction
invoiceId string Verification transaction identifier
session object  
session.nonce string Unique random string generated by Merchant’s server
session.signature string Checksum generated by hmac-sha1 (see Signature computation) from the concatenation of accessToken, consumer.device.serialNumber, endpointId, session.nonce, invoiceId and transaction.currency

If failed, this method should return the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  }
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: FILTERED, INVALID_REQUEST, SERVER_FAILED, SERVER_UNAVAILABLE
error.code string The unique error code
error.message string Description of the error

Perform validation

On this stage Merchant’s app sends cardholder, device, session data and other parameters straight to Industra to check the card for being valid.
A lot of criteria checks and filters may be applied, such as BIN, currency, country, blacklisted or not, etc. Depending on the integration, these settings may be customizable. For details please contact Industra.
For integration purposes use staging environment sandbox.ecom.industra.finance instead of production ecom.industra.finance.
You can use the debug for “perform validation request” presented below.

Perform validation request is sent by Merchant’s app through HTTPS POST to URL

https://ecom.industra.finance/paynet/dapi/v1/verification/{endpointId}/{invoiceId}

Request body

In the request body, supply data with the following structure:

{
  "billing": {
    "address": {
      "city": "string",
      "country": "string",
      "postcodeZip": "string",
      "state": "string",
      "street": "string",
      "street2": "string"
    },
    "phone": "string"
  },
  "consumer": {
    "birthDay": "string",
    "device": {
      "imei": "string",
      "serialNumber": "string"
    },
    "email": "string",
    "ipAddresses": ["string"]
  },
  "location": {
    "lat": "double",
    "lng": "double"
  },
  "order": {
    "description": "string",
    "siteUrl": "string",
    "purpose": "string"
  },
  "session": {
    "accessToken": "string",
    "nonce": "string",
    "signature": "string"
  },
  "sourceCard": {
    "expiry": {
      "month": "integer",
      "year": "integer"
    },
    "holder":{
      "firstName": "string",
      "lastName": "string"
    },
    "number": "string",
    "securityCode": "string"
  },
  "transaction": {
    "currency": "string"
  }
}
Property name Value Description
Required properties
consumer object  
consumer.device object  
consumer.device.serialNumber string(1-50) Consumer’s device serial number
consumer.email string(3-128) Сonsumer’s email address
session object  
session.accessToken string(32-128) Access token key received in Optional consumer authentication
session.nonce string(32-128) Value received in Initial verification response
session.signature string(32-128) Value received in Initial verification response
sourceCard object  
sourceCard.expiry object  
sourceCard.expiry.month integer(2) Source Card expiration month
sourceCard.expiry.year integer(4) Source Card expiration year
sourceCard.holder object  
sourceCard.holder.firstName string(1-50) Cardholder’s first name
sourceCard.holder.lastName string(1-50) Cardholder’s last name
sourceCard.holder.printedName string(1-50) Cardholder’s printed name (first and last name together). May be used instead of firstName + lastName
sourceCard.number string(9-19) Source card number (PAN)
sourceCard.securityCode string(3-4) Source card security code (CVV)
transaction object  
transaction.currency string(3) Upper case letters (ISO 4217 alpha code)
Optional properties
location object  
location.lat double The latitude specified in the range of -90.0 through +90.0, both inclusive
location.lng double The longitude specified in the range -180.0 through +180.0, both inclusive
billing object  
billing.address object  
billing.address.city string(1-100) City name
billing.address.country string(3) ISO alpha3 country code
billing.address.postcodeZip string(1-10) ZIP post code
billing.address.state string(2-3) State is used if present. For example, Los Angeles is in CA state
billing.address.street string(1-50) Street is used for district names and street names
billing.address.street2 string(1-50) Street 2 is used for long addresses. Usually it contains apartment and building №
billing.phone string(1-20) Customer’s contact phone number
consumer.birthDay string(8) Сonsumer’s birth day in “ddMMyyyy” format
consumer.device.imei string(14-16) Сonsumer’s device international mobile equipment identity
consumer.ipAddresses list Сonsumer’s IP addresses
consumer.ipAddresses[] string(7-15) Сonsumer’s IP address
order object  
order.description string(128) Brief transaction description. May be mandatory for certain Acquirer Banks
order.siteUrl string(128) URL of website associated with the transaction
order.purpose string(128) May be used for better transaction control or additional checks

Perform validation response

If successful, this method returns the following response body:

{
  "invoiceId": "string",
  "session": {
    "token": "string"
  }
}
Property name Value Description
invoiceId string Verification transaction identifier
session object  
session.token string The session token of verification transaction

If failed, this method returns the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: INVALID_REQUEST, INVALID_CONFIGURATION, INTERNAL_ERROR, PROCESSING_FAILED
error.code string The unique error code
error.message string Description of the error
invoiceId string Verification transaction identifier

Perform validation debug

For integration purposes you may use E-Commerce test cards to generate random card numbers. Parameters with light red background are mandatory.

Endpoint Id
Invoice Id Generated by Merchant's server in "Initiate verification"
Device serial number
Device imei
E-mail
Birthday
Ip Address
accessToken Generated by Merchant's server in "Consumer authentication"
nonce Generated by Merchant's server in "Initiate verification"
signature Generated by Merchant's server in "Initiate verification"
Card number
Security Code (cvv)
Card expiry month
Card expiry year
First name
Last name
Currency ISO 4217 alpha three-letter code
Loc. Latitude
Loc. Longitude
City
Country
ZIP Postcode
State
Street
Street2
Phone
Order description
Order site Url

			
			
			
			

Check verification

Check verification is used for security purposes and allows Industra to compare the data sent by Merchant’s app with the data stored on Merchant’s server.
It is highly recommended to respond with the actual information stored on Merchant’s server.

Check verification request is sent by Industra through HTTPS POST to URL (provided by merchant)

https://proxy.merchantserver.com/verification/{invoiceId}/check

Request body

In the request body, data is supplied with the following structure:

{
  "consumer": {
    "device": {
      "serialNumber": "string"
    }
  },
  "session": {
    "accessToken": "string",
    "nonce": "string",
    "signature": "string",
    "token": "string"
  }
}
Property name Value Description
consumer object  
consumer.device object  
consumer.device.serialNumber string(1-50) Consumer’s device serial number
session object  
session.accessToken string(32-128) Consumer’s access token key sent by Merchant’s app
session.nonce string(32-128) Value sent by Merchant’s app
session.signature string(32-128) Value sent by Merchant’s app
session.token string(16-36) The session token of verification transaction

Check verification response

If successful, this method should return the following response body:

{
  "billing": {
    "address": {
      "city": "string",
      "country": "string",
      "postcodeZip": "string",
      "state": "string",
      "street": "string",
      "street2": "string"
    },
    "phone": "string"
  },
  "consumer": {
    "birthDay": "string",
    "email": "string",
    "ipAddresses": ["string"]
  },
  "invoiceId": "string",
  "session": {
    "checkSignature": "string",
    "nonce": "string",
    "token": "string"
  },
  "transaction": {
    "currency": "string",
    "randomSumCentis": "integer"
  }
}
Property name Value Description
Required properties
invoiceId string Verification transaction identifier
session object  
session.checkSignature string Checksum generated by hmac-sha1 (see Signature computation) from the concatenation of consumer.device.serialNumber, session.nonce, endpointId and invoiceId
session.nonce string Unique random string generated by Merchant’s server in Initiate verification response
session.token string The session token of verification transaction
Optional properties
billing object  
billing.address object  
billing.address.city string City name
billing.address.country string ISO alpha3 country code
billing.address.postcodeZip string ZIP post code
billing.address.state string State is used if present. For example, Los Angeles is in CA state
billing.address.street string Street is used for district names and street names
billing.address.street2 string Street 2 is used for long addresses. Usually it contains apartment and building №
billing.phone string Customer’s contact phone number
consumer.birthDay string Consumer’s birth day in “ddMMyyyy” format
consumer.email string Consumer’s email address
consumer.ipAddresses list Consumer’s IP addresses
consumer.ipAddresses[] string Consumer’s IP address
transaction.currency string Upper case letters (ISO 4217 alpha code)
transaction.randomSumCentis integer Random sum amount (for random sum check), 1.00 EUR = 100 centis

If failed, this method should return the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: FILTERED, INVALID_REQUEST, SERVER_FAILED, SERVER_UNAVAILABLE
error.code string The unique error code
error.message string Description of the error
invoiceId string Verification transaction identifier

Verification status

Verification status request is made by Merchant’s app to Industra to get the status of verification transaction.
It is recommended to send Verification status request for a period of 2-3 minutes with interval of 3-5 seconds between requests.
Merchant’s server should rely on the callback for final status.
For integration purposes use staging environment sandbox.ecom.industra.finance instead of production ecom.industra.finance.
You can use the debug for “Verification status request” presented below.

Verification status request is sent by Merchant’s app through HTTPS POST to URL

https://ecom.industra.finance/paynet/dapi/v1/verification/{endpointId}/{invoiceId}/status

Request body

In the request body, supply data with the following structure:

{
  "session": {
    "accessToken": "string",
    "token": "string"
  }
}
Property name Value Description
Required properties
session object  
session.accessToken string(32-128) The access token key received in Optional consumer authentication
session.token string(16-36) The session token of verification transaction

Verification status response

If successful, this method returns the following response body:

{
  "bankOrderId": "string",
  "invoiceId": "string",
  "redirectUrl": "string",
  "session": {
    "token": "string"
  },
  "state": "enum"
}
Property name Value Description
invoiceId string Verification transaction identifier
session object  
session.token string The session token of verification transaction
state enum Possible values: PROCESSING, REDIRECT_REQUEST, APPROVED, DECLINED
Conditional properties
bankOrderId string(128) Required if state is APPROVED or DECLINED
redirectUrl string(128) Required if state is REDIRECT_REQUEST
Optional properties
errorCode integer Decline reason code, may present if state is DECLINED
errorMessage string(128) Decline reason message, may present if state is DECLINED
secure3DAuthStatus enum Possible values: AUTHENTICATED, NOT_AUTHENTICATED, UNSUPPORTED UNSUPPORTED means that card does not support 3-D Secure or 3DS authentication process finished with an unknown status
randomSumAuthStatus enum Possible values: AUTHENTICATED, NOT_AUTHENTICATED

If failed, this method returns the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: FILTERED, INVALID_REQUEST, INTERNAL_ERROR, PROCESSING_FAILED, ORDER_NOT_FOUND
error.code string The unique error code
error.message string Description of the error
invoiceId string Verification transaction identifier

Verification status debug

Endpoint Id
Invoice Id Generated by Merchant's server in "Initiate verification"
session.accessToken Generated by Merchant's server in "Consumer authentication"
session.token Obtained in "Perform validation" response

			
			
			
			

Verification card mapping notification

Card mapping notification is used to allow Consumer credentials (phone, email, billing address, twitter name, etc) for mapping to card data. Card mappings can be used later in transfer or sale transactions instead of card numbers and other cardholder information. Industra sends Verification card mapping notification request to Merchant’s server/proxy with created on its side card reference - {serverCardId}.
Merchant’s server maps this {serverCardId} to {clientCardId}, created on its side. This {clientCardId} can then be mapped in Merchant’s app or on Merchant’s server to any Consumer’s data from the initial Perform validation request. This allows Merchant’s app to process sale or transfer transactions by Consumer’s email, phone number, etc.
{uniqueReferenceCardId} remains the same if Consumer makes another verification with the same card number but different expiry date, for example. It can be used by Merchant for loyalty programs or fraud control.

Verification card mapping notification request is sent by Industra through HTTPS POST to URL (provided by merchant)

https://proxy.merchantserver.com/verification/notification

Request body

In the request body, data is supplied with the following structure:

{
  "consumer": {
    "device": {
      "serialNumber": "string"
    }
  },
  "reference": {
    "serverCardId": "string",
    "uniqueReferenceCardId": "integer"
  },
  "sourceCard": {
    "bin": "integer"
  },
  "session": {
    "accessToken": "string",
    "token": "string"
  }
}
Property name Value Description
consumer object  
consumer.device object  
consumer.device.serialNumber string(1-50) Consumer’s device serial number
reference object  
reference.serverCardId string(1-64) The card reference identifier (on server side)
reference.uniqueReferenceCardId integer The card identifier (on server side)
session object  
session.accessToken string(32-128) Consumer’s access token key
session.token string(16-36) The session token of verification transaction
sourceCard object  
sourceCard.bin integer The Source card BIN

Card mapping notification response

If successful, this method should return the following response body:

{
  "invoiceId": "string",
  "session": {
    "checkSignature": "string",
    "nonce": "string",
    "token": "string"
  }
}
Property name Value Description
invoiceId string Verification transaction identifier
session object  
session.checkSignature string Checksum generated by hmac-sha1 (see Signature computation) from the concatenation of the session.nonce, the endpointId and the invoiceId
session.nonce string Unique random string generated by Merchant’s server
session.token string The session token of verification transaction

If failed, this method should return the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: FILTERED, INVALID_REQUEST, SERVER_FAILED, SERVER_UNAVAILABLE
error.code string The unique error code
error.message string Description of the error
invoiceId string Verification transaction identifier

1.2.3. Sale

Sale transaction can be performed with cardholder data or with card reference, previously made with Card verification process or in previous transfer/sale transactions. You may see the general flow process for sale transaction below.

title Mobile Device - 3-D Secure sale
skinparam ParticipantPadding 70
participant client as "Consumer"
participant mobile as "Mobile App"
participant merchant as "Merchant's Server"
participant pne as "Industra"
participant bank as "EFT"
client -> mobile: Start sale transaction
merchant <-> mobile: Initiate sale
mobile -> pne: Perform sale
pne -> pne: check signature
mobile <-- pne: Status info
note right
session token
end note
pne <-> merchant : Check sale
pne <-> bank : Check 3DS enrollment
loop until final status is sent
mobile -> pne: Sale status request
note left
session token
end note
mobile <-- pne
note right
state = PROCESSING
end note
end
mobile <- pne: Open browser and redirect to EFT
note right
ACS url
PA Request
Term url
Merchant data
end note
activate mobile
mobile -> bank
mobile <-- bank: Response with 3DS html form
client <-- mobile
client -> mobile: The cardholder provides auth data
mobile -> bank
mobile <-- bank: Redirect browser back to Industra
note right
PA Response
Merchant data
end note
mobile --> pne: Sale status update
pne --> mobile: Close browser request
destroy mobile
pne <-> bank: 3DS auth result
note left
PA Response
end note
note right
cavv
eci
status
end note
pne <-> bank: Process sale
note right
bankorder id
end note
    merchant <-> pne: Sale card mapping notification
note right
server card id
end note
mobile <-- pne: Sale status response
note left
bankorder id
state = APPROVED|DECLINED
end note

Initiate sale

To initiate sale, Merchant’s app sends {accessToken} with transaction amount and other device parameters to Merchant’s server, which are used to start a session with unique random {nonce} and encrypted {signature}.
In response Merchant’s server also provides information about invoice in merchant’s system and endpoint in Industra.

Initiate sale request is sent by Merchant’s app through HTTPS POST to URL in the following format (provided by merchant)

https://proxy.merchantserver.com/transfer/initiate-sale

Request body

In the request body, supply data with the following structure:

{
  "consumer": {
    "device": {
      "imei": "string",
      "serialNumber": "string"
    },
    "ipAddresses": ["string"]
  },
  "location": {
    "lat": "double",
    "lng": "double"
  },
  "session": {
    "accessToken": "string"
  },
  "transaction": {
    "amountCentis": "integer",
    "currency": "string"
  }
}
Property name Value Description
Required properties
consumer object  
consumer.device object  
consumer.device.serialNumber string(1-50) Consumer’s device serial number
transaction object  
transaction.amountCentis integer Transaction amount, 1.00 EUR = 100 centis
transaction.currency string(3) Upper case letters (ISO 4217 alpha code)
session object  
session.accessToken string(32-128) Access token key received in Optional consumer authentication
Optional properties
consumer.device.imei string(14-16) Consumer’s device international mobile equipment identity
location object  
location.lat double The latitude specified in the range of -90.0 through +90.0, both inclusive
location.lng double The longitude specified in the range -180.0 through +180.0, both inclusive
consumer.ipAddresses list Consumer’s IP addresses
consumer.ipAddresses[] string(7-15) Consumer’s IP address

Initiate sale response

If successful, this method should return the following response body:

{
  "endpointId": "string",
  "invoiceId": "string",
  "session": {
    "nonce": "string",
    "signature": "string"
  }
}
Property name Value Description
Required properties
endpointId string Entry point identifier for sale transaction
invoiceId string Transfer transaction identifier
session object  
session.nonce string Unique random string generated by Merchant’s server
session.signature string Checksum generated by hmac-sha1 (see Signature computation) from the concatenation of the accessToken, consumer.device.serialNumber, endpointId, session.nonce, invoiceId, transaction.amountCentis and the transaction.currency

If failed, this method should return the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  }
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: FILTERED, INVALID_REQUEST, SERVER_FAILED, SERVER_UNAVAILABLE
error.code string The unique error code
error.message string Description of the error

Perform sale

On this stage Merchant’s app sends cardholder, device, session data and other parameters straight to Industra to perform sale transaction.
A lot of criteria checks and filters may be applied, such as BIN, currency, country, blacklisted or not, etc. Depending on the integration, these settings may be customizable. For details please contact Industra.
For integration purposes use staging environment sandbox.ecom.industra.finance instead of production ecom.industra.finance
You can use the debug for “Perform sale request” presented below.

Perform sale request is sent by Merchant’s app through HTTPS POST to URL

https://ecom.industra.finance/paynet/dapi/v1/sale/{endpointId}/{invoiceId}

Request body

In the request body, supply data with the following structure:

{
  "billing": {
    "address": {
      "city": "string",
      "country": "string",
      "postcodeZip": "string",
      "state": "string",
      "street": "string",
      "street2": "string"
    },
    "phone": "string"
  },
  "consumer": {
    "birthDay": "string",
    "device": {
      "imei": "string",
      "serialNumber": "string"
    },
    "email": "string",
    "ipAddresses": ["string"]
  },
  "location": {
    "lat": "double",
    "lng": "double"
  },
  "order": {
    "description": "string",
    "siteUrl": "string",
    "purpose": "string"
  },
  "session": {
    "accessToken": "string",
    "nonce": "string",
    "signature": "string"
  },
  "sourceOfFunds": {
    "card": {
      "expiry": {
        "month": "integer",
        "year": "integer"
      },
      "holder":{
        "firstName": "string",
        "lastName": "string"
      },
      "number": "string",
      "securityCode": "string"
    },
    "reference": {
      "clientCardId": "string",
      "securityCode": "string"
    }
  },
  "transaction": {
    "amountCentis": "integer",
    "currency": "string"
  }
}
Property name Value Description
Required properties
consumer object  
consumer.device object  
consumer.device.serialNumber string(1-50) Consumer’s device serial number
consumer.email string(3-128) Сonsumer’s email address, if sent in original card mapping transaction and card reference is being used instead of cardholder data
session object  
session.accessToken string(32-128) Access token key received in Optional consumer authentication
session.nonce string(32-128) Value received in initiate sale response
session.signature string(32-128) Value received in initiate sale response
sourceOfFunds object  
sourceOfFunds.card object Only one of these subtypes (card, reference) should be used
sourceOfFunds.card.expiry object  
sourceOfFunds.card.expiry.month integer(2) Source Card expiration month
sourceOfFunds.card.expiry.year integer(4) Source Card expiration year
sourceOfFunds.card.holder object  
sourceOfFunds.card.holder.firstName string(1-50) Cardholder’s first name
sourceOfFunds.card.holder.lastName string(1-50) Cardholder’s last name
sourceOfFunds.card.holder.printedName string(1-50) Cardholder’s printed name (first and last name together). May be used instead of firstName + lastName
sourceOfFunds.card.number string(9-19) Source card number (PAN)
sourceOfFunds.card.securityCode string(3-4) Source card security code (CVV)
sourceOfFunds.reference object only one of these subtypes (card, reference) should be used
sourceOfFunds.reference.clientCardId string(1-128) Source card reference identifier (on client side)
sourceOfFunds.reference.securityCode string(3-4) Source card security code (CVV)
transaction object  
transaction.amountCentis integer Transaction amount, 1.00 EUR = 100 centis
transaction.currency string(3) Upper case letters (ISO 4217 alpha code)
Optional properties
location object  
location.lat double The latitude specified in the range of -90.0 through +90.0, both inclusive
location.lng double The longitude specified in the range -180.0 through +180.0, both inclusive
billing object  
billing.address object  
billing.address.city string(1-100) City name
billing.address.country string(3) ISO alpha3 country code
billing.address.postcodeZip string(1-10) ZIP post code
billing.address.state string(2-3) State is used if present. For example, Los Angeles is in CA state
billing.address.street string(1-50) Street is used for district names and street names
billing.address.street2 string(1-50) Street 2 is used for long addresses. Usually it contains apartment and building №
billing.phone string(1-20) Сonsumer’s contact phone number
consumer.birthDay string(8) Сonsumer’s birth day in “ddMMyyyy” format
consumer.device.imei string(14-16) Сonsumer’s device international mobile equipment identity
consumer.ipAddresses list Сonsumer’s IP addresses
consumer.ipAddresses[] string(7-15) Сonsumer’s IP address
order object  
order.description string(128) Brief transaction description. May be mandatory for certain Acquirer Banks
order.siteUrl string(128) URL of website associated with the transaction
order.purpose string(128) May be used for better transaction control or additional checks

Perform sale response

If successful, this method returns the following response body:

{
  "invoiceId": "string",
  "session": {
    "token": "string"
  }
}
Property name Value Description
invoiceId string Sale transaction identifier
session object  
session.token string The session token of sale transaction

If failed, this method returns the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: INVALID_REQUEST, INVALID_CONFIGURATION, INTERNAL_ERROR, PROCESSING_FAILED
error.code string The unique error code
error.message string Description of the error
invoiceId string Sale transaction identifier

Perform sale debug

For integration purposes you may use E-Commerce test cards to generate random card numbers.

Endpoint Id
Invoice Id Generated by Merchant's server in "Initiate sale"
Device serial number
Device imei
E-mail
Birthday
Ip Address
accessToken Generated by Merchant's server in "Consumer authentication"
nonce Generated by Merchant's server in "Initiate sale"
signature Generated by Merchant's server in "Initiate sale"
Source Card number Use either card number or clientCardId, not both
CVV for a new card Leave empty if clientCardId is being used
Card expiry month Leave empty if clientCardId is being used
Card expiry year Leave empty if clientCardId is being used
First name Leave empty if clientCardId is being used
Last name Leave empty if clientCardId is being used
Source Card reference Use either card number or clientCardId, not both
CVV for the reference Leave empty if new card is being used
Sale amount Will be calculated to centis in generated string
Currency ISO 4217 alpha three-letter code
Loc. Latitude
Loc. Longitude
City
Country
ZIP Postcode
State
Street
Street2
Phone
Order description
Order site Url

            
            
            
            

Check sale

Check sale is used for security purposes and allows Industra to compare the data sent by Merchant’s app with the data stored on Merchant’s server.
It is highly recommended to respond with the actual information stored on Merchant’s server.

Check sale request is sent by Industra through HTTPS POST to URL (provided by merchant)

https://proxy.merchantserver.com/sale/{invoiceId}/check

Request body

In the request body, data is supplied with the following structure:

{
  "consumer": {
    "device": {
      "serialNumber": "string"
    }
  },
  "session": {
    "accessToken": "string",
    "nonce": "string",
    "signature": "string",
    "token": "string"
  },
  "sourceOfFunds": {
    "reference": {
      "clientCardId": "string"
    }
  }
}
Property name Value Description
Required properties
consumer object  
consumer.device object  
consumer.device.serialNumber string(1-50) Consumer’s device serial number
session object  
session.accessToken string(32-128) Consumer’s access token key sent by Merchant’s app
session.nonce string(32-128) Value sent by Merchant’s app
session.signature string(32-128) Value sent by Merchant’s app
session.token string(16-36) The session token of sale transaction
Optional properties
sourceOfFunds object  
sourceOfFunds.reference object  
sourceOfFunds.reference.clientCardId string(1-128) The source card reference identifier (on client side) if sent in Perform sale request

Check sale response

If successful, this method should return the following response body:

{
  "consumer": {
    "email": "string"
  },
  "invoiceId": "string",
  "session": {
    "checkSignature": "string",
    "nonce": "string",
    "token": "string"
  },
  "sourceOfFunds": {
    "card": {
      "expiry": {
        "month": "integer",
        "year": "integer"
      },
      "holder":{
        "firstName": "string",
        "lastName": "string"
      },
      "number": "string"
    },
    "reference": {
      "serverCardId": "string",
    }
  },
  "transaction": {
    "currency": "string",
    "randomSumCentis": "integer"
  }
}
Property name Value Description
Required properties
invoiceId string Sale transaction identifier
session object  
session.checkSignature string Checksum generated by hmac-sha1 (see Signature computation) from the concatenation of the consumer.device.serialNumber, session.nonce, endpointId, invoiceId, sourceOfFunds.reference.serverCardId (if present)
session.nonce string Unique random string generated by Merchant’s server in Initiate sale response
session.token string The session token of sale transaction
Optional properties
consumer.email string Сonsumer’s email address, if sent in original card mapping transaction
sourceOfFunds object  
sourceOfFunds.reference object  
sourceOfFunds.reference.serverCardId string The source card reference identifier (on server side)
transaction.currency string Upper case letters (ISO 4217 alpha code)
transaction.randomSumCentis integer Random sum amount (for random sum check), 1.00 EUR = 100 centis

If failed, this method should return the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: FILTERED, INVALID_REQUEST, SERVER_FAILED, SERVER_UNAVAILABLE
error.code string The unique error code
error.message string Description of the error
invoiceId string Sale transaction identifier

Sale status

Sale status request is made by Merchant’s app to Industra to get the status of sale transaction.
It is recommended to send Sale status request for a period of 2-3 minutes with interval of 3-5 seconds between requests.
Merchant’s server should rely on the callback for final status.
For integration purposes use staging environment sandbox.ecom.industra.finance instead of production ecom.industra.finance.
You can use the debug for “Sale status request” presented below.

Sale status request is sent by Merchant’s app through HTTPS POST to URL

https://ecom.industra.finance/paynet/dapi/v1/sale/{endpointId}/{invoiceId}/status

Request body

In the request body, supply data with the following structure:

{
  "session": {
    "accessToken": "string",
    "token": "string"
  }
}
Property name Value Description
session object  
session.accessToken string(32-128) The access token key received in Optional consumer authentication
session.token string(16-36) The session token of sale transaction

Sale status response

If successful, this method returns the following response body:

{
  "bankOrderId": "string",
  "invoiceId": "string",
  "redirectUrl": "string",
  "session": {
    "token": "string"
  },
  "state": "enum"
}
Property name Value Description
invoiceId string Sale transaction identifier
session object  
session.token string The session token of sale transaction
state enum Possible values: PROCESSING, REDIRECT_REQUEST, APPROVED, DECLINED
Conditional properties
bankOrderId string(128) Required if state is APPROVED or DECLINED
redirectUrl string(128) Required if state is REDIRECT_REQUEST
orderId string Order identifier in payment processing system
transaction object  
transaction.amountCentis integer Amount of money transfered in centis, 1.00 EUR = 100 centis
transaction.commissionCentis integer Amount of commission held in centis (depends on the integration)
transaction.orderCreatedDate string Order creation date in payment processing system
transaction.transactionCreatedDate string Transaction creation date in payment processing system
Optional properties
errorCode integer Decline reason code, may present if state is``DECLINED``
errorMessage string(128) Decline reason message, may present if state is DECLINED
secure3DAuthStatus enum Possible values: AUTHENTICATED, NOT_AUTHENTICATED, UNSUPPORTED UNSUPPORTED means that card does not support 3-D Secure or 3DS authentication process finished with an unknown status
randomSumAuthStatus enum Possible values: AUTHENTICATED, NOT_AUTHENTICATED

If failed, this method returns the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: FILTERED, INVALID_REQUEST, INTERNAL_ERROR, PROCESSING_FAILED, ORDER_NOT_FOUND
error.code string The unique error code
error.message string Description of the error
invoiceId string Sale transaction identifier

Sale status debug

Endpoint Id
Invoice Id Generated by Merchant's server in "Initiate sale"
session.accessToken Generated by Merchant's server in "Consumer authentication"
session.token Obtained in "Perform sale" response

			
			
			
			

Sale card mapping notification

Card mapping notification is used to allow Consumer credentials (phone, email, billing address, twitter name, etc) for mapping to card data. Card mappings can be used later in transfer or sale transactions instead of card numbers and other cardholder information. Industra sends Sale card mapping notification request to Merchant’s server/proxy with created on its side card reference - {serverCardId}.
Merchant’s server maps this {serverCardId} to {clientCardId}, created on its side. This {clientCardId} can then be mapped in Merchant’s app or on Merchant’s server to any Consumer’s data from the initial Perform sale request. This allows Merchant’s app to process sale or transfer transactions by Consumer’s email, phone number, etc.
{uniqueReferenceCardId} remains the same if Consumer makes another transaction with the same card number but different expiry date, for example. It can be used by Merchant for loyalty programs or fraud control.
Merchant’s app makes new sale requests using {clientCardId} instead of source card data. Industra sends this {clientCardId} to Merchant’s server in “Check sale request” and gets mapped to it {serverCardId} in “Check sale response” from Merchant’s server, which is used to continue the processing of this transaction.
{serverCardId} of source or verified card can be used for new sale transactions and both as source or destination for new transfer transactions.

Sale card mapping notification request is sent by Industra through HTTPS POST to URL (provided by merchant)

https://proxy.merchantserver.com/sale/notification

Request body

In the request body, data is supplied with the following structure:

{
  "consumer": {
    "device": {
      "serialNumber": "string"
    }
  },
  "session": {
    "accessToken": "string",
    "token":"string"
  },
  "sourceCard": {
    "bin": "integer",
    "reference": {
      "serverCardId": "string",
      "uniqueReferenceCardId": "integer"
    }
  }
}
Property name Value Description
Required properties
consumer object  
consumer.device object  
consumer.device.serialNumber string(1-50) Consumer’s device serial number
session object  
session.accessToken string(32-128) Consumer’s access token key
session.token string(16-36) The session token of sale transaction
Optional properties
sourceCard object  
sourceCard.bin integer The Source card BIN
sourceCard.reference object  
sourceCard.reference.serverCardId string(1-64) The Source card reference identifier (on server side)
sourceCard.reference.uniqueReferenceCardId integer The Source card unique identifier (on server side)

Sale card mapping notification response

If successful, this method should return the following response body:

{
  "invoiceId": "string",
  "session": {
    "checkSignature": "string",
    "nonce": "string",
    "token": "string"
  }
}
Property name Value Description
invoiceId string Sale transaction identifier
session object  
session.checkSignature string Checksum generated by hmac-sha1 (see Signature computation) from the concatenation of session.nonce, endpointId and invoiceId
session.nonce string Unique random string generated by Merchant’s server
session.token string The session token of sale transaction

If failed, this method should return the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Сause of the error. Possible values: FILTERED, INVALID_REQUEST, SERVER_FAILED, SERVER_UNAVAILABLE
error.code string The unique error code
error.message string Description of the error
invoiceId string Sale transaction identifier

Repeat sale

After successful Card mapping procedure, new sale transactions with the same cardholder data can be done easier for Consumer.
Merchant’s app makes new sale requests using {clientCardId} instead of cardholder data. Industra sends this {clientCardId} to Merchant’s server in “Check sale request” and gets mapped to it {serverCardId} in “Check sale response” from Merchant’s server. This {serverCardId} is used to continue the processing of sale transaction.
Transaction flow remains the same: Initiate sale -> Perform sale -> Check sale.
If there is no need to change Consumer’s data (such as address, phone, etc.), “Perform sale request” for Repeat sale may be sent without any optional parameters. If Consumer’s data has to be changed, new source card reference must be created.
If {clientCardId} is used in “Perform sale request”, {serverCardId} must be included in “Check sale response” and signature.
If {clientCardId} was mapped to {serverCardId} in transaction with included {consumer.email} value, new “Perform sale request” and “Check sale response” with this {clientCardId} must also contain the same {consumer.email} value.
You can see the card reference management on the scheme below:

title Mobile Device - Card references for Repeat sale
participant mobile as "Mobile App"
participant merchant as "Merchant's Server"
participant pne as "Payneteasy"
skinparam ParticipantPadding 80
... Last part of previous transaction ...
merchant <- pne: Card mapping notification request
note right
serverCardId
end note
merchant --> pne: Card mapping notification response
merchant --> merchant: Create clientCardId for serverCardId
group optional
merchant -> mobile: Store reference in app or send it by request
note right
clientCardId
end note
end
... New sale ...
mobile <-> merchant: Initiate sale
mobile -> pne: Perform sale request
note left
clientCardId
end note
mobile <-- pne: Perform sale response
merchant <- pne: Check sale request
note right
clientCardId
end note
merchant --> pne: Check sale response
note left
serverCardId
end note
pne -> pne: Process sale
...

For source of funds in “Repeat sale” use:
  1. {sourceOfFunds.reference.clientCardId}
  2. {sourceOfFunds.reference.securityCode}
Instead of:
  1. {sourceOfFunds.card.expiry.month}
  2. {sourceOfFunds.card.expiry.year}
  3. {sourceOfFunds.card.holder}
  4. {sourceOfFunds.card.holder.firstName}
  5. {sourceOfFunds.card.holder.lastName}
  6. {sourceOfFunds.card.number}
  7. {sourceOfFunds.card.securityCode}

1.2.4. Money transfer

Money transfer can be performed with cardholder data of sender and receiver of funds or with card reference, previously made with Card verification process or in previous transfer/sale transactions. You may see the general flow process for money transfer below.

title Mobile Device - 3-D Secure card funds transfer
skinparam ParticipantPadding 70
participant client as "Consumer"
participant mobile as "Mobile App"
participant merchant as "Merchant's Server"
participant pne as "Industra"
participant bank as "EFT"
client -> mobile: Start transfer transaction
merchant <-> mobile: Initiate transfer
mobile -> pne: Perform transfer
pne -> pne: check signature
mobile <-- pne: Status info
note right
session token
end note
pne <-> merchant : Check transfer
pne <-> bank : Check 3DS enrollment
loop until final status is sent
mobile -> pne: Transfer status request
note left
session token
end note
mobile <-- pne
note right
state = PROCESSING
end note
end
mobile <- pne: Open browser and redirect to EFT
note right
ACS url
PA Request
Term url
Merchant data
end note
activate mobile
mobile -> bank
mobile <-- bank: Response with 3DS html form
client <-- mobile
client -> mobile: The cardholder provides auth data
mobile -> bank
mobile <-- bank: Redirect browser back to Industra
note right
PA Response
Merchant data
end note
mobile --> pne: Transfer status update
pne --> mobile: Close browser request
destroy mobile
pne <-> bank: 3DS auth result
note left
PA Response
end note
note right
cavv
eci
status
end note
pne <-> bank: process transfer
note right
bankorder id
end note
    merchant <-> pne: Transfer card mapping notification
note right
server card id
end note
mobile <-- pne: Transfer status response
note left
bankorder id
state = APPROVED|DECLINED
end note

Initiate transfer

To initiate funds transfer, Merchant’s app sends {accessToken} with transaction amount and other device parameters to Merchant’s server, which are used to start a session with unique random {nonce} and encrypted {signature}.
In response Merchant’s server also provides information about invoice in merchant’s system and endpoint in Industra.
The Merchant’s server may also respond with the transaction’s commission.

Initiate transfer request is sent by Merchant’s app through HTTPS POST to URL in the following format (provided by merchant)

https://proxy.merchantserver.com/transfer/initiate-transfer

Request body

In the request body, supply data with the following structure:

{
  "consumer": {
    "device": {
      "imei": "string",
      "serialNumber": "string"
    },
    "ipAddresses": ["string"]
  },
  "location": {
    "lat": "double",
    "lng": "double"
  },
  "session": {
    "accessToken": "string"
  },
  "transaction": {
    "amountCentis": "integer",
    "currency": "string"
  }
}
Property name Value Description
Required properties
consumer object  
consumer.device object  
consumer.device.serialNumber string(1-50) Consumer’s device serial number
transaction object  
transaction.amountCentis integer Transaction amount, 1.00 EUR = 100 centis
transaction.currency string(3) Upper case letters (ISO 4217 alpha code)
session object  
session.accessToken string(32-128) Access token key received in Optional consumer authentication
Optional properties
consumer.device.imei string(14-16) Consumer’s device international mobile equipment identity
location object  
location.lat double The latitude specified in the range of -90.0 through +90.0, both inclusive
location.lng double The longitude specified in the range -180.0 through +180.0, both inclusive
consumer.ipAddresses list Consumer’s IP addresses
consumer.ipAddresses[] string(7-15) Consumer’s IP address
fromBin string(6) Source of funds card BIN (first 6 digits of card number) may be used to display pre-calculated commission
toBin string(6) Destination of funds card BIN (first 6 digits of card number) may be used to display pre-calculated commission

Initiate transfer response

If successful, this method should return the following response body:

{
  "endpointId": "string",
  "invoiceId": "string",
  "rates": {
    "min": "string",
    "max": "string"
  },
  "session": {
    "nonce": "string",
    "signature": "string"
  }
}
Property name Value Description
Required properties
endpointId string Entry point identifier for transfer transaction
invoiceId string Transfer transaction identifier
session object  
session.nonce string Unique random string generated by Merchant’s server
session.signature string Checksum generated by hmac-sha1 (see Signature computation) from the concatenation of the accessToken, consumer.device.serialNumber, endpointId, session.nonce, invoiceId, transaction.amountCentis and the transaction.currency
Optional properties
rates object  
rates.min string Possible minimum commission amount
rates.max string Possible maximum commission amount

If failed, this method should return the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  }
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: FILTERED, INVALID_REQUEST, SERVER_FAILED, SERVER_UNAVAILABLE
error.code string The unique error code
error.message string Description of the error

Perform transfer

On this stage Merchant’s app sends cardholder, device, session data and other parameters straight to Industra to perform funds transfer from card to card
A lot of criteria checks and filters may be applied, such as BIN, currency, country, blacklisted or not, etc. Depending on the integration, these settings may be customizable. For details please contact Industra.
For integration purposes use staging environment sandbox.ecom.industra.finance instead of production ecom.industra.finance
You can use the debug for “Perform transfer request” presented below.

Perform transfer request is sent by Merchant’s app through HTTPS POST to URL

https://ecom.industra.finance/paynet/dapi/v1/transfer/{endpointId}/{invoiceId}

Request body

In the request body, supply data with the following structure:

{
  "billing": {
    "address": {
      "city": "string",
      "country": "string",
      "postcodeZip": "string",
      "state": "string",
      "street": "string",
      "street2": "string"
    },
    "phone": "string"
  },
  "consumer": {
    "birthDay": "string",
    "device": {
      "imei": "string",
      "serialNumber": "string"
    },
    "email": "string",
    "ipAddresses": ["string"]
  },
  "destinationOfFunds": {
    "card": {
      "number": "string",
    },
    "reference": {
      "clientCardId": "string"
    }
  },
  "location": {
    "lat": "double",
    "lng": "double"
  },
  "order": {
    "description": "string",
    "siteUrl": "string",
    "purpose": "string"
  },
  "session": {
    "accessToken": "string",
    "nonce": "string",
    "signature": "string"
  },
  "sourceOfFunds": {
    "card": {
      "expiry": {
        "month": "integer",
        "year": "integer"
      },
      "holder":{
        "firstName": "string",
        "lastName": "string"
      },
      "number": "string",
      "securityCode": "string"
    },
    "reference": {
      "clientCardId": "string",
      "securityCode": "string"
    }
  },
  "transaction": {
    "amountCentis": "integer",
    "currency": "string"
  }
}
Property name Value Description
Required properties
consumer object  
consumer.device object  
consumer.device.serialNumber string(1-50) Consumer’s device serial number
consumer.email string(3-128) Сonsumer’s email address, if sent in original card mapping transaction and card reference is being used instead of cardholder data
destinationOfFunds object  
destinationOfFunds.card object Only one of these subtypes (card, reference) should be used
destinationOfFunds.card.number string(9-19) Destination card number (PAN)
destinationOfFunds.reference object Only one of these subtypes (card, reference) should be used
destinationOfFunds.reference.clientCardId string(1-128) Destination card reference identifier (on client side)
session object  
session.accessToken string(32-128) Access token key received in Optional consumer authentication
session.nonce string(32-128) Value received in Initiate transfer response
session.signature string(32-128) Value received in Initiate transfer response
sourceOfFunds object  
sourceOfFunds.card object Only one of these subtypes (card, reference) should be used
sourceOfFunds.card.expiry object  
sourceOfFunds.card.expiry.month integer(2) Source Card expiration month
sourceOfFunds.card.expiry.year integer(4) Source Card expiration year
sourceOfFunds.card.holder object  
sourceOfFunds.card.holder.firstName string(1-50) Cardholder’s first name
sourceOfFunds.card.holder.lastName string(1-50) Cardholder’s last name
sourceOfFunds.card.holder.printedName string(1-50) Cardholder’s printed name (first and last name together). May be used instead of firstName + lastName
sourceOfFunds.card.number string(9-19) Source card number (PAN)
sourceOfFunds.card.securityCode string(3-4) Source card security code (CVV)
sourceOfFunds.reference object only one of these subtypes (card, reference) should be used
sourceOfFunds.reference.clientCardId string(1-128) Source card reference identifier (on client side)
sourceOfFunds.reference.securityCode string(3-4) Source card security code (CVV)
transaction object  
transaction.amountCentis integer Transaction amount, 1.00 EUR = 100 centis
transaction.currency string(3) Upper case letters (ISO 4217 alpha code)
Optional properties
location object  
location.lat double The latitude specified in the range of -90.0 through +90.0, both inclusive
location.lng double The longitude specified in the range -180.0 through +180.0, both inclusive
billing object  
billing.address object  
billing.address.city string(1-100) City name
billing.address.country string(3) ISO alpha3 country code
billing.address.postcodeZip string(1-10) ZIP post code
billing.address.state string(2-3) State is used if present. For example, Los Angeles is in CA state
billing.address.street string(1-50) Street is used for district names and street names
billing.address.street2 string(1-50) Street 2 is used for long addresses. Usually it contains apartment and building №
billing.phone string(1-20) Сonsumer’s contact phone number
consumer.birthDay string(8) Сonsumer’s birth day in “ddMMyyyy” format
consumer.device.imei string(14-16) Сonsumer’s device international mobile equipment identity
consumer.ipAddresses list Сonsumer’s IP addresses
consumer.ipAddresses[] string(7-15) Сonsumer’s IP address
order object  
order.description string(128) Brief transaction description. May be mandatory for certain Acquirer Banks
order.siteUrl string(128) URL of website associated with the transaction
order.purpose string(128) May be used for better transaction control or additional checks

Perform transfer response

If successful, this method returns the following response body:

{
  "invoiceId": "string",
  "session": {
    "token": "string"
  }
}
Property name Value Description
invoiceId string Transfer transaction identifier
session object  
session.token string The session token of transfer transaction

If failed, this method returns the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: INVALID_REQUEST, INVALID_CONFIGURATION, INTERNAL_ERROR, PROCESSING_FAILED
error.code string The unique error code
error.message string Description of the error
invoiceId string Transfer transaction identifier

Perform transfer debug

For integration purposes you may use E-Commerce test cards to generate random card numbers.

Endpoint Id
Invoice Id Generated by Merchant's server in "Initiate transfer"
Device serial number
Device imei
E-mail
Birthday
Ip Address
accessToken Generated by Merchant's server in "Consumer authentication"
nonce Generated by Merchant's server in "Initiate transfer"
signature Generated by Merchant's server in "Initiate transfer"
Source Card number Use either card-number or clientCardId, not both
CVV for a new card Leave empty if clientCardId is being used
Card expiry month Leave empty if clientCardId is being used
Card expiry year Leave empty if clientCardId is being used
First name Leave empty if clientCardId is being used
Last name Leave empty if clientCardId is being used
Source Card reference Use either card-number or clientCardId, not both
CVV for the reference Leave empty if new card is being used
Destination Card number Use either card-number or clientCardId, not both
Destination Card reference Use either card-number or clientCardId, not both
Transfer amount Will be calculated to centis in generated string
Currency ISO 4217 alpha three-letter code
Loc. Latitude
Loc. Longitude
City
Country
ZIP Postcode
State
Street
Street2
Phone
Order description
Order site Url

			
			
			
			

Check transfer

Check transfer is used for security purposes and allows Industra to compare the data sent by Merchant’s app with the data stored on Merchant’s server.
It is highly recommended to respond with the actual information stored on Merchant’s server.

Check transfer request is sent by Industra through HTTPS POST to URL (provided by merchant)

https://proxy.merchantserver.com/transfer/{invoiceId}/check

Request body

In the request body, data is supplied with the following structure:

{
  "consumer": {
    "device": {
      "serialNumber": "string"
    }
  },
  "destinationOfFunds": {
    "reference": {
      "clientCardId": "string"
    }
  },
  "session": {
    "accessToken": "string",
    "nonce": "string",
    "signature": "string",
    "token": "string"
  },
  "sourceOfFunds": {
    "reference": {
      "clientCardId": "string"
    }
  }
}
Property name Value Description
Required properties
consumer object  
consumer.device object  
consumer.device.serialNumber string(1-50) Consumer’s device serial number
session object  
session.accessToken string(32-128) Consumer’s access token key sent by Merchant’s app
session.nonce string(32-128) Value sent by Merchant’s app
session.signature string(32-128) Value sent by Merchant’s app
session.token string(16-36) The session token of transfer transaction
Optional properties
sourceOfFunds object  
sourceOfFunds.reference object  
sourceOfFunds.reference.clientCardId string(1-128) The source card reference identifier (on client side) if sent in Perform Transfer request
destinationOfFunds object  
destinationOfFunds.reference object  
destinationOfFunds.reference.clientCardId string(1-128) The destination card reference identifier (on client side) if sent in Perform Transfer request

Check transfer response

If successful, this method should return the following response body:

{
  "consumer": {
    "email": "string"
  },
  "destinationOfFunds": {
    "card": {
      "number": "string"
    },
    "reference": {
      "serverCardId": "string"
    }
  },
  "invoiceId": "string",
  "session": {
    "checkSignature": "string",
    "nonce": "string",
    "token": "string"
  },
  "sourceOfFunds": {
    "card": {
      "expiry": {
        "month": "integer",
        "year": "integer"
      },
      "holder":{
        "firstName": "string",
        "lastName": "string"
      },
      "number": "string"
    },
    "reference": {
      "serverCardId": "string",
    }
  },
  "transaction": {
    "currency": "string",
    "randomSumCentis": "integer"
  }
}
Property name Value Description
Required properties
invoiceId string Transfer transaction identifier
session object  
session.checkSignature string Checksum generated by hmac-sha1 (see Signature computation) from the concatenation of the consumer.device.serialNumber, session.nonce, destinationOfFunds.reference.serverCardId (if present), endpointId, invoiceId, sourceOfFunds.reference.serverCardId (if present)
session.nonce string Unique random string generated by Merchant’s server in Initiate transfer response
session.token string The session token of transfer transaction
Optional properties
consumer.email string Consumer’s email address
destinationOfFunds object  
destinationOfFunds.reference object  
destinationOfFunds.reference.serverCardId string The destination card reference identifier (on server side)
sourceOfFunds object  
sourceOfFunds.reference object  
sourceOfFunds.reference.serverCardId string The source card reference identifier (on server side)
transaction.currency string Upper case letters (ISO 4217 alpha code)
transaction.randomSumCentis integer Random sum amount (for random sum check), 1.00 EUR = 100 centis

If failed, this method should return the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: FILTERED, INVALID_REQUEST, SERVER_FAILED, SERVER_UNAVAILABLE
error.code string The unique error code
error.message string Description of the error
invoiceId string Transfer transaction identifier

Transfer status

Funds transfer status request is made by Merchant’s app to Industra to get the status of transfer transaction.
It is recommended to send Transfer status request for a period of 2-3 minutes with interval of 3-5 seconds between requests.
Merchant’s server should rely on the callback for final status.
For integration purposes use staging environment sandbox.ecom.industra.finance instead of production ecom.industra.finance.
You can use the debug for “Transfer status request” presented below.

Transfer status request is sent by Merchant’s app through HTTPS POST to URL

https://ecom.industra.finance/paynet/dapi/v1/transfer/{endpointId}/{invoiceId}/status

Request body

In the request body, supply data with the following structure:

{
  "session": {
    "accessToken": "string",
    "token": "string"
  }
}
Property name Value Description
session object  
session.accessToken string(32-128) The access token key received in Optional consumer authentication
session.token string(16-36) The session token of transfer transaction

Transfer status response

If successful, this method returns the following response body:

{
  "bankOrderId": "string",
  "invoiceId": "string",
  "redirectUrl": "string",
  "session": {
    "token": "string"
  },
  "state": "enum"
}
Property name Value Description
invoiceId string Transfer transaction identifier
session object  
session.token string The session token of transfer transaction
state enum Possible values: PROCESSING, REDIRECT_REQUEST, APPROVED, DECLINED
Conditional properties
bankOrderId string(128) Required if state is APPROVED or DECLINED
redirectUrl string(128) Required if state is REDIRECT_REQUEST
orderId string Order identifier in payment processing system
transaction object  
transaction.amountCentis integer Amount of money transfered in centis, 1.00 EUR = 100 centis
transaction.commissionCentis integer Amount of commission held in centis
transaction.orderCreatedDate string Order creation date in payment processing system
transaction.transactionCreatedDate string Transaction creation date in payment processing system
Optional properties
errorCode integer Decline reason code, may present if state is``DECLINED``
errorMessage string(128) Decline reason message, may present if state is DECLINED
secure3DAuthStatus enum Possible values: AUTHENTICATED, NOT_AUTHENTICATED, UNSUPPORTED UNSUPPORTED means that card does not support 3-D Secure or 3DS authentication process finished with an unknown status
randomSumAuthStatus enum Possible values: AUTHENTICATED, NOT_AUTHENTICATED

If failed, this method returns the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: FILTERED, INVALID_REQUEST, INTERNAL_ERROR, PROCESSING_FAILED, ORDER_NOT_FOUND
error.code string The unique error code
error.message string Description of the error
invoiceId string Transfer transaction identifier

Transfer status debug

Endpoint Id
Invoice Id Generated by Merchant's server in "Initiate transfer"
session.accessToken Generated by Merchant's server in "Consumer authentication"
session.token Obtained in "Perform transfer" response

			
			
			
			

Transfer card mapping notification

Card mapping notification is used to allow Consumer credentials (phone, email, billing address, twitter name, etc) for mapping to card data. Card mappings can be used later in transfer or sale transactions instead of card numbers and other cardholder information. Industra sends Transfer card mapping notification request to Merchant’s server/proxy with created on its side card reference - {serverCardId}.
Merchant’s server maps this {serverCardId} to {clientCardId}, created on its side. This {clientCardId} can then be mapped in Merchant’s app or on Merchant’s server to any Consumer’s data from the initial Perform transfer request. This allows Merchant’s app to process sale or transfer transactions by Consumer’s email, phone number, etc.
{uniqueReferenceCardId} remains the same if Consumer makes another verification with the same card number but different expiry date, for example. It can be used by Merchant for loyalty programs or fraud control.
Merchant’s app makes new transfer requests using {clientCardId} instead of source or destination card data. Industra sends this {clientCardId} to Merchant’s server in “Check transfer request” and gets mapped to it {serverCardId} in “Check transfer response” from Merchant’s server, which is used to continue processing the transfer transaction.
{serverCardId} of source or verified card can be used both as source or destination for new transfer and sale transactions; {serverCardId} of destination card can be used only as destination for new transfers.

Transfer card mapping notification request is sent by Industra through HTTPS POST to URL (provided by merchant)

https://proxy.merchantserver.com/transfer/notification

Request body

In the request body, data is supplied with the following structure:

{
  "consumer": {
    "device": {
      "serialNumber": "string"
    }
  },
  "destinationCard": {
    "bin": "integer",
    "reference": {
      "serverCardId": "string",
      "uniqueReferenceCardId": "integer"
      }
    },
  "session": {
    "accessToken": "string",
    "token":"string"
  },
  "sourceCard": {
    "bin": "integer",
    "reference": {
      "serverCardId": "string",
      "uniqueReferenceCardId": "integer"
    }
  }
}
Property name Value Description
Required properties
consumer object  
consumer.device object  
consumer.device.serialNumber string(1-50) Consumer’s device serial number
session object  
session.accessToken string(32-128) Consumer’s access token key
session.token string(16-36) The session token of transfer transaction
Optional properties
destinationCard object  
destinationCard.bin integer The Destination card BIN
destinationCard.reference object  
destinationCard.reference.serverCardId string(1-64) The Destination card reference identifier (on server side)
destinationCard.reference.uniqueReferenceCardId integer The Destination card unique identifier (on server side)
sourceCard object  
sourceCard.bin integer The Source card BIN
sourceCard.reference object  
sourceCard.reference.serverCardId string(1-64) The Source card reference identifier (on server side)
sourceCard.reference.uniqueReferenceCardId integer The Source card unique identifier (on server side)

Transfer card mapping notification response

If successful, this method should return the following response body:

{
  "invoiceId": "string",
  "session": {
    "checkSignature": "string",
    "nonce": "string",
    "token": "string"
  }
}
Property name Value Description
invoiceId string Transfer transaction identifier
session object  
session.checkSignature string Checksum generated by hmac-sha1 (see Signature computation) from the concatenation of session.nonce, endpointId and invoiceId
session.nonce string Unique random string generated by Merchant’s server
session.token string The session token of transfer transaction

If failed, this method should return the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Сause of the error. Possible values: FILTERED, INVALID_REQUEST, SERVER_FAILED, SERVER_UNAVAILABLE
error.code string The unique error code
error.message string Description of the error
invoiceId string Transfer transaction identifier

Repeat transfer

After successful Card mapping procedure, new transfers with the same cardholder data can be done easier for Consumer.
Merchant’s app makes new transfer requests using {clientCardId} instead of source and/or destination cardholder data. Industra sends these {clientCardId} to Merchant’s server in “Check transfer request” and gets mapped to it {serverCardId} in “Check transfer response” from Merchant’s server. These {serverCardId} are used to continue the processing of transfer transaction.
Transaction flow remains the same: Initiate transfer -> Perform transfer -> Check transfer.
If there is no need to change Consumer’s data (such as address, phone, etc.), “Perform transfer request” for Repeat transfer may be sent without any optional parameters and with card references for sender and receiver instead of cardholder data. If Consumer’s data has to be changed, new source card reference must be created.
If source and/or destination {clientCardId} are used in “Perform transfer request”, source and/or destination {serverCardId} must be included in “Transfer check response” and signature.
If source {clientCardId} was mapped to {serverCardId} in transaction with included {consumer.email} value, new “Perform transfer request” and “Check signature response” with this {clientCardId} must also contain the same {consumer.email} value.
You can see the card reference management on the scheme below:

title Mobile Device - Card references for Repeat transfer
participant mobile as "Mobile App"
participant merchant as "Merchant's Server"
participant pne as "Payneteasy"
skinparam ParticipantPadding 80
... Last part of card verification or transfer ...
merchant <- pne: Card mapping notification request
note right
serverCardId
end note
merchant --> pne: Card mapping notification response
merchant --> merchant: Create clientCardId for serverCardId
group optional
merchant -> mobile: Store reference in app or send it by request
note right
clientCardId
end note
end
... New transfer ...
mobile <-> merchant: Initiate transfer
mobile -> pne: Perform transfer request
note left
clientCardId
end note
mobile <-- pne: Perform transfer response
merchant <- pne: Check transfer request
note right
clientCardId
end note
merchant --> pne: Check transfer response
note left
serverCardId
end note
pne -> pne: Process transfer
...

For source of funds in “Repeat transfer” use:
  1. {sourceOfFunds.reference.clientCardId}
  2. {sourceOfFunds.reference.securityCode}
Instead of:
  1. {sourceOfFunds.card.expiry.month}
  2. {sourceOfFunds.card.expiry.year}
  3. {sourceOfFunds.card.holder}
  4. {sourceOfFunds.card.holder.firstName}
  5. {sourceOfFunds.card.holder.lastName}
  6. {sourceOfFunds.card.number}
  7. {sourceOfFunds.card.securityCode}
For destination of funds in “Repeat transfer” use {destinationOfFunds.reference.clientCardId} instead of {destinationOfFunds.card.number}.

Consumer defined transfer rates

Consumer defined transfer rates is an optional feature which allows the sender to choose the most suitable commission amount for his transfer transaction between several available payment gateways.
The possibility of such feature depends on the integration. Please ask your support manager for details.
When such feature is enabled, the transaction flow extends:
  1. If Check transfer has been successful, Industra pauses the processing, includes the list of possible commissions to next Transfer status response and awaits for confirmation from the Consumer.
  2. Consumer selects the most suitable commission from the list in the Merchant’s app.
  3. Merchant’s app sends the selected gate in Complete transfer request to Industra.
  4. Industra continues to process the transaction on the selected gate.

This flow is also represented on the scheme below:

title Consumer defined transfer rates
participant client as "Consumer"
participant mobile as "Mobile App"
participant pne as "Industra"
participant bank as "EFT"
... Transfer has been checked successfully ...
pne -> pne : Pause the transaction
loop until Complete transfer is sent
mobile -> pne: Transfer status request
note left
session token
end note
mobile <-- pne: Transfer status response
note right
state=TRANSFER_FEE_REQUEST
transferFeeList [...]
end note
end
mobile -> client: Ask to select the commission
mobile <-- client: Commission selected
mobile -> pne: Complete transfer request
    note left
    assignedId
    end note
mobile <-- pne: Complete transfer response
pne -> bank: Process transfer \non the selected gate
...

Transfer status response includes the state parameter with TRANSFER_FEE_REQUEST value and the transferFeeList object with a list of commissions for possible processing gates.
Each processing gate is represented by it’s own aliased name in assignedId parameter.
TRANSFER_FEE_REQUEST value in state parameter exists only in “Consumer defined transfer rates” flow.
The mentioned parameters may not be presented in first Transfer status response, so Merchant’s app should continue polling the transaction status.
When the transaction reaches TRANSFER_FEE_REQUEST state, the processing will remain paused until Complete transfer request is sent.

The following structure extends the default Transfer status response body (e.g. 2 processing gates):

{
  "state": "TRANSFER_FEE_REQUEST",
  "transferFeeList": [
    {
      "assignedId": "string",
      "commissionCentis": "integer",
      "currency": "string"
    },
    {
      "assignedId": "string",
      "commissionCentis": "integer",
      "currency": "string"
    }
  ]
}
Property name Value Description
transferFeeList object  
transferFeeList.assignedId string Aliased payment gateway name
transferFeeList.commissionCentis integer Amount of commission to be held in centis, 1.00 EUR = 100 centis
transferFeeList.currency string Upper case letters (ISO 4217 alpha code)
state string In addition to the values from Transfer status, TRANSFER_FEE_REQUEST value only exists in this flow

Complete transfer request is sent by Merchant’s app through HTTPS POST to URL

https://ecom.industra.finance/paynet/dapi/v1/transfer/{endpointId}/{invoiceId}/{assignedId}

In the request body, supply data with the following structure:

{
  "session": {
    "accessToken": "string",
    "token": "string"
  }
}

Complete transfer response

If successful, this method returns the following response body:

{
  "invoiceId": "string",
  "session": {
    "token": "string"
  }
}
Property name Value Description
invoiceId string Transfer transaction identifier
session object  
session.token string The session token of transfer transaction

If failed, this method returns the following response body:

{
  "error": {
    "cause": "enum",
    "code": "string",
    "message": "string"
  },
  "invoiceId": "string"
}
Property name Value Description
error object  
error.cause enum Cause of the error. Possible values: INVALID_REQUEST, INVALID_CONFIGURATION, INTERNAL_ERROR, PROCESSING_FAILED
error.code string The unique error code
error.message string Description of the error
invoiceId string Transfer transaction identifier

1.2.5. Development tools

Signature computation

The signature is being used to ensure that it is Merchant (and not a fraudster) who sends the information to Industra.
Signatures in DAPI are computed using HMAC_SHA1 algorithm. Key is derived in the following way:
  1. Take merchantControlKey
  2. Remove dashes from it
  3. Unhex the result to binary

You can get the correct signature values for all types of transactions supported by DAPI in the debugging tool below:

AccessToken Use your existing accessToken or make it for new transaction
Serial number
Endpoint ID
Session nonce Use your existing nonce or make it for new transaction
Merchant's invoice Use your existing invoiceId or make it for new transaction
Transaction currency ISO 4217 alpha three-letter code
Merchant control key

String to sign
Signature

Example code and SDK

There are several solutions available on GitHub, which were developed for integration with Industra on Android and iOS platforms via DAPI.
Merchant proxy server for Money transfer:
Android SDK of Java implementation for Money transfer:
iOS SDK of Objective-C implementation for Money transfer: