Transaction Inquiry


Valify offers an API to retrieve transaction results, any time after the service has been called. This API receives a reference to the transaction being inquired, either the Transaction ID returned in the service's response, or the Access Token used to call the API, and returns the service's data.

This is a very sensitive API, as it allows access to data for all your transactions. Therefore, to secure your data, it is a requirement that the Transaction Inquiry response is encrypted in transit and decrypted on the recipient's side.

To gain access to this API, you need to contact Valify to avail this service. You also need to generate an RSA 4096 key pair. The private key is stored on the recipient side, and the public key is provided to Valify to be stored. This way, the API response payload can be encrypted for you to decrypt it on your side. Please contact techsupport@valify.me for more information.

The RSA 4096 key pair can be generated using the following commands:

  • With Passphrase:

$ openssl genrsa -des3 -out private.pem 4096 $ openssl rsa -in private.pem -outform PEM -pubout -out public.pem

  • Without Passphrase:

$ openssl genrsa -out private.pem 4096 $ openssl rsa -in private.pem -outform PEM -pubout -out public.pem

The encryption process works as follows:

  1. Each time this API is called, a new AES 256 key is generated.

  2. The response data (JSON string) is encrypted with the AES key.

  3. The AES key is then encrypted with the public key provided to Valify.

  4. The encrypted key and encrypted data are encoded into base64 format is sent in the API response.

  5. The response recipient should then decode the base64-encoded key and data, decrypt the AES key using their RSA private key, and use the decrypted AES key to decrypt the transaction data, producing a JSON string.

The transaction reference options are:

  • Transaction ID: can be found in the Service API response. Only the data for this particular transaction is returned. The response would look like this:

{ 'transaction_id': <str>, 'token': '<str>', 'time': '<dd/MM/yy hh:mm:ss', 'status': <bool>, 'service': <str>, 'data': { ... } }

  • Access Token: token used to authenticate one or more Valify service API calls. In this case, the API returns a list of all transactions called using this access token. The response would look like this:

{ 'transactions': [ { 'transaction_id': <str>, 'token': '<str>', 'time': '<dd/MM/yy hh:mm:ss', 'status': <bool>, 'service': <str>, 'data': { ... } }, ... ] }

Note: The access token used to authenticate the Transaction Inquiry API call (added to the header), is different from the access token added to the request body, which references the transaction(s) being inquired by this API call.

Transaction Inquire (Transaction ID)

POST https://<base-url>/api/v1/transaction/inquire/

Headers

Request Body

{
    'key': '<string>',
    'data': '<string>'
}

Transaction Inquire (Access Token)

POST https://<base-url>/api/v1/transaction/inquire/

Headers

Request Body

{
    'key': '<string>',
    'data': '<string>'
}

Code Snippets

from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import base64
import json
import requests

private_key_str = "<rsa 4096 private key>"
private_key_bytes = str.encode(private_key_str)
private_key = serialization.load_pem_private_key(
        private_key_bytes,
        password=None,
        backend=default_backend()
    )
    
def unpad(s): return s[0:-s[-1]]

def decrypt_aes_key(encrypted_aes_key):
    aes_key = private_key.decrypt(
        encrypted_aes_key,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    return aes_key

def decrypt_data(enc_data, key, iv):
    backend = default_backend()
    sha256 = algorithms.AES(key)
    cipher = Cipher(sha256, modes.CBC(iv), backend=backend)
    decryptor = cipher.decryptor()

    dec_data = decryptor.update(enc_data)
    return unpad(dec_data)

def request_data():
    token = "<token>"
    data = {
        "bundle_key": "<bundle key>",
        "transaction_id": "<str>"
    }

    r = requests.post("https://<base-url>/api/v1/transaction/inquire/",
            json=data,
            headers={'Authorization' :'Bearer %s' % token}
        )
    return r.json()

response = request_data()
encrypted_data = base64.b64decode(response['data'])
encrypted_aes_key = base64.b64decode(response['key'])
iv = base64.b64decode(response['iv'])

aes_key = decrypt_aes_key(encrypted_aes_key)
decrypted_data = decrypt_data(encrypted_data, aes_key, iv)
data = json.loads(decrypted_data)

Postman Collection

Last updated