# API Integration

## Description

* The physical card API provides access to the underlying capabilities of the bank.
* Merchants need to handle token deposits themselves.

## Environment Information

Test Environment: <https://test-physicalcard-api.prepaidify.com>

Production Environment: <https://physicalcard-api.prepaidify.com>

## Document Description

### 1. Overview

This document provides explanations for third-party integration interfaces. Target audience: technical developers.

### 2. Common Interface Parameters

| Field Name     | Variable Name | Required | Type   | Base64 Encoding | Description                                                          |
| -------------- | ------------- | -------- | ------ | --------------- | -------------------------------------------------------------------- |
| Partner ID     | agentId       | Y        | string | N               | Partner ID assigned by the institution                               |
| Request String | reqData       | Y        | string | N               | Request RSA encrypted data, encoded after encryption with URLEncoder |
| Language       | language      | N        | string | N               | zh, en                                                               |
| Signature      | signature     | Y        | string | N               | MD5 signature string                                                 |

### 3. Common Interface Response

| Field Name           | Variable Name | Required | Type   | Base64 Encoding | Description                  |
| -------------------- | ------------- | -------- | ------ | --------------- | ---------------------------- |
| Response Code        | respCode      | Y        | string | N               | 00: Success, Others: Failure |
| Response Description | respMsg       | N        | string | N               | Exists in case of failure    |
| Request String       | respData      | N        | string | N               | Response RSA encrypted data  |

### 4. Interface Invocation Details

> Interfaces typically include three request parameters: agentId, reqData, signature.

**Signature Generation Rule**

Convert the body to a JSON string + md5Key, then encrypt it using MD5.

For example:

```
```

```
str = {"name":"xxx","age":"18"}123453333
md5(str)
```

**repData Generation Rule**

Similarly, convert the body to a JSON string, then encrypt it using an RSA public key to obtain an encrypted string, and then base64 encode it.

For example:

```
```

```
def encrypt(message: str, pub_key: str) -> str | None:
    try:
        pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(pub_key.encode())
        message_bytes = message.encode()
        chunks = [message_bytes[i:i + CHUNK_SIZE] for i in range(0, len(message_bytes), CHUNK_SIZE)]
        crypto = b"".join([rsa.encrypt(chunk, pubkey) for chunk in chunks])
        return base64.b64encode(crypto).decode()
    except Exception as e:
        print(f"Error encrypting message: {e}")
        return None
```

**Example of Usage**

> Note that the format should be application/x-www-form-urlencoded instead of application/json.

```
```

```
curl -X POST https://test.xxx.com/api/mastercard/holderQuery.html \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "agentId=888666000100201&reqData=2%2FCgBnwbtXQRR2XVmLu9uOiBCfjnd1pwq59LtPhufF6VtjbKcArfHE9Cqff575EFbIEBanPKlXbilnJj2Gz4AnEs1BOZOUEO85UIcD7YBBXdt1BC3vX8hzWXrsnPbC1ZW4589r7B40h0lL9NAOjs%2BJaDIN3nmpdqvFHJ4hF1rb0%3D&signature=e5c3ca8eba4de85f44262f8d34ac21ee"

```

**Response Example**

> Normally, all interface data needs to be decrypted using an RSA private key when receiving data from the server.

```
```

```
{"respCode":"00","respMsg":"","respData":"nnTq5O+k89BsneEN1+SUKxj6PlNSsBzeF29IeEkNQjWrRATjW+dtYPONKFO9YfG5dlLg1qZH5PBRbEWB44Q9wmvT5PLoJNdM5Uk1zhhLQ0sJA186BSiwxwMYty0wgWgC6lsY4QQzuNR/aAsr8DxLR7vsTxaPB3m5qAzO8i7D/Xu22OX52CxxDeNizXwg1+0iyKU6S5AOEKCkF52iJY8OucVOt2sq9q1aX2wBijG12ZWyuh6iVHMtJxrxEOTYpp1h481ixBvt809hte2J26mn0hbWPW8v14X/LsS+5Mf5/0CcHm72tZ+EELyeDGI4TeZQeTw3Yf97KZfQ83cO15Ggzg=="}
```

Example of Decryption:

```
```

```
def decrypt(encrypted_data: str, private_key: str) -> str:
    private_key_bytes = private_key.encode('utf-8')
    encrypted_data = base64.b64decode(encrypted_data)

    # Deserialize the private key from PEM format
    private_key_obj = serialization.load_pem_private_key(private_key_bytes, password=None, backend=default_backend())

    # Determine the appropriate chunk size based on the private key size
    key_size_bytes = private_key_obj.key_size // 8  # Convert bits to bytes
    decrypted_data = b""

    # Decrypt the data in chunks based on the key size
    for offset in range(0, len(encrypted_data), key_size_bytes):
        chunk = encrypted_data[offset:offset + key_size_bytes]
        decrypted_chunk = private_key_obj.decrypt(chunk, padding.PKCS1v15())
        decrypted_data += decrypted_chunk

    return decrypted_data.decode('utf-8')
```
