# PayWizard Open Platform API Signature Guide V3

This document details the process for generating and verifying signatures for PayWizard Open Platform API requests using version 3 of our signature scheme. This process ensures the integrity and authenticity of API requests.

API request messages are signed using a **SHA256-HMAC** algorithm with your unique **developer secret key**.

### Signature Generation Steps:

The general procedure for generating the `signValue` is as follows:

{% stepper %}
{% step %}

### **Obtain Request Body (`stringA`)**:

The raw JSON string from the request body constitutes `stringA`. Ensure no whitespace or reordering of keys is introduced if the original JSON string is obtained directly from the request.

```json
{
    "clientId": "client12345",
    "merchantId": "10800000003",
    "posId": "D31231234567890",
    "terminalId": "12345678",
    "terminalSn": "WP123987987897"
}
```

{% endstep %}

{% step %}

### **Construct Signature String (`stringSignTemp`)**:&#x20;

Concatenate the following string `&clientId={clientId}&clientSecret={clientSecret}` to the end of `stringA`. The resulting string is `stringSignTemp`.

{% code overflow="wrap" %}

```
{"clientId":"client12345","merchantId":"10800000003","posId":"D31231234567890","terminalId":"12345678","terminalSn":"WP123987987897"}&clientId=client12345&clientSecret=9fb645400aabaa33ee0e423405d8c676
```

{% endcode %}
{% endstep %}

{% step %}

### **Apply HMAC-SHA256 Hashing**

Perform an **HMAC-SHA256 hash calculation** on `stringSignTemp` using your designated **developer secret key**. The hexadecimal representation of the resulting hash value is the `signValue`.

{% hint style="info" %}
The `clientId` and `clientSecret` used in `stringSignTemp` are your unique API credentials provided by PayWizard for signature generation.
{% endhint %}
{% endstep %}

{% step %}

### **Include Signature in Request Header**

The calculated `signValue` must be included in the request header under the parameter name `sign`.
{% endstep %}
{% endstepper %}

### Example Request:

Below is an illustrative `curl` command demonstrating a signed API request:

```bash
curl --location --request POST 'https://uat.paywizard.biz/ovstrade/openVarSheet/queryStatus' \
--header 'jwt-token: BIKE195JVXTN7WA5DXZISQ11GPEUYI7A' \
--header 'Content-Type: application/json' \
--header 'sign: 57ba54072ed2aaa4b2905c41e7c91fd1395ef8f6f76e6e7cdbefe7a88437de6c' \
--data-raw '{
    "clientId": "825420368247390208",
    "pushId":"942783670425616384"
}'
```

***

### Sample Code for Encrypt:

{% code overflow="wrap" lineNumbers="true" %}

```java
/**
* Encrypts data using HmacSHA256.
* @param data The string to be encrypted.
* @param key The secret key.
* @return java.lang.String The encrypted string in hexadecimal format.
**/
public static String sha256Hmac(String data, String key) {
    String cipher = "";
    try {
        byte[] byteList = key.getBytes(StandardCharsets.UTF_8);
        // Construct a secret key from the given byte array for a specified algorithm name,
        // in this case, generating a key specific to HmacSHA256.
        SecretKey secretKey = new SecretKeySpec(byteList, "HmacSHA256");

        // Get a Mac object for a specified MAC algorithm.
        Mac mac = Mac.getInstance("HmacSHA256");
        // Initialize the Mac object with the given secret key.
        mac.init(secretKey);
        byte[] text = data.getBytes(StandardCharsets.UTF_8);
        byte[] encryptByte = mac.doFinal(text);
        cipher = bytesToHexStr(encryptByte);
    } catch (NoSuchAlgorithmException | InvalidKeyException e) {
        e.printStackTrace();
    }
    return cipher;
}

/**
* Converts a byte array to a hexadecimal string.
* @param bytes The byte array to convert.
* @return java.lang.String The resulting hexadecimal string.
**/
public static String bytesToHexStr(byte[] bytes) {
    StringBuilder hexStr = new StringBuilder();
    for (byte b : bytes) {
        String hex = Integer.toHexString(b & 0xFF);
        if (hex.length() == 1) {
            hex = '0' + hex;
        }
        hexStr.append(hex);
    }
    return hexStr.toString();
}

/**
* Generates a signature.
* @param paramsStr The data to be sent.
* @param clientId The developer ID.
* @param clientSecret The developer secret key.
* @return java.lang.String The generated signature.
**/
public static String generateSign(String paramsStr, String clientId, String clientSecret) {
    String str = StrUtil.format("{}&clientId={}&clientSecret={}", paramsStr, clientId, clientSecret);
    log.info("paramsStr:{}", str);
    return sha256Hmac(str, clientSecret);
}

public static void main(String[] args) {
    JSONObject params = new JSONObject();
    params.put("clientId", "825429536610058240");
    params.put("merchantId", "10800000003");
    params.put("posId", "D31231234567890");
    String str = JSON.toJSONString(params);
    System.out.println(generateSign(str, "825429536610058240", "K8VZMX99LTVHZW9IJZXE3BIIWU3QJZD2"));
}
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://smartpossdk.gitbook.io/paywizard-open-api/cloud-api/paywizard-open-platform-api-signature-guide-v3.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
