# API Authentication

> 🔐 **Important Note**: Please strictly follow the instructions in this document for API authentication and signature to ensure secure communication.


## Required Header Parameters

### Request Header Parameters

| Parameter Name  | Description | Type  | Required  |
|  --- | --- | --- | --- |
| `signature` | Request signature | String[1,500] | ✅ |
| `type` | Signature type，fixed value `RSA256` | String[1,10] | ✅ |
| `version` | API version，fixed value `v1.2` | String[1,10] | ✅ |


### Response Headers

| Parameter Name  | Description | Type  | Required  |
|  --- | --- | --- | --- |
| `signature` | Response signature | String[1,500] | ✅ |
| `type` | Signature type，fixed value `RSA256` | String[1,10] | ✅ |
| `version` | API version，fixed value `v1.2` | String[1,10] | ✅ |


## Examples

### Request Body

```json
{
    "merchant_id": "YOUR_MERCHANT_ID",
    "payment_type": "PURCHASE",
    "authorisation_type": "FINAL_AUTH",
    "capture_method": "AUTOMATIC",
    "trans_id": "t202311081113",
    "timestamp": 1700805506000,
    "amount": 445,
    "currency": "EUR",
    "notify_url": "https://www.baidu.com/notifyUrl",
    "return_url": "https://www.baidu.com/returnUrl",
    "payment": {
        "payment_method": "BANKCARD",
        "store_payment_method": false,
        "token_usage": "CARD_ON_FILE",
        "shopper_reference": "user1234567890",
        "encrypted_card_no": "string",
        "encrypted_exp_year": "string",
        "encrypted_exp_month": "string",
        "encrypted_cvv": "string"
    }
}
```

### Response Body

```json
{
  "ret_code": "000000",
  "ret_msg": "Success",
  "data": {
    "timestamp": 1700805506000,
    "merchant_id": "YOUR_MERCHANT_ID",
    "trans_id": "t202311081113",
    "order_id": "GW20598371023658327",
    "status": "AUTHORIZED",
    "authorisation_type": "FINAL_AUTH",
    "capture_method": "AUTOMATIC",
    "amount": 445,
    "currency": "EUR",
    "payment": {
      "payment_method": "BANKCARD"
    },
    "card_info": {
      "bin": "424242",
      "last4": "4242",
      "card_brand": "VISA"
    },
    "balances": {
      "authed_amount": 445,
      "captured_amount": 0,
      "able_to_capture_amount": 445,
      "voided_amount": 0,
      "able_to_void_amount": 445,
      "refunded_amount": 0,
      "able_to_refund_amount": 0
    }
  }
}
```

## Calculating the Signature

### Add Dependency

Add the following dependency to your Java project:

```xml
<dependency>
  <groupId>commons-codec</groupId>
  <artifactId>commons-codec</artifactId>
  <version>1.15</version>
</dependency>
```

### Generate Signature

Concatenate the `merchant_id`，`timestamp`，and request body `requestBody` as a string，then use your private key to generate a signature using the SHA256withRSA algorithm:

```java
private static final String FORMAT = "merchantId=%s&timestamp=%s&requestBody=%s";

String content = String.format(FORMAT, merchantId, timestamp, requestBody);
Signature signature = Signature.getInstance("SHA256withRSA");
byte[] privateKeys = Base64Utils.decodeFromString(privateKey);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeys);
PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(pkcs8EncodedKeySpec);
signature.initSign(priKey);
signature.update(content.getBytes(StandardCharsets.UTF_8));
byte[] signed = signature.sign();
String result = Base64Utils.encodeToString(signed);
String sign = URLEncoder.encode(result);
log.info("Generated signature: {}", sign);
```

### Set Request Headers

1. Set the generated signature in the `signature` request header，and ensure that the request body matches exactly.
2. Set the `type` request header to `RSA256`，indicating the signature method.
3. Set the `version` request header to `v1.2`，indicating the API version.


### Request Example

```bash
curl 'https://openapi-sandbox.paykka.com/payments' -X POST \
 -H 'Content-Type: application/json'\
 -H 'type: RSA256'\
 -H 'version: v1.2'\
 -H 'signature: SOjw%2FOwcMM2jCB7xxxxxxxxxOtFyY%2BvWE%2FFXefazBA%3D%3D'\
 -d '{"merchant_id": "YOUR_MERCHANT_ID"}'
```

## Verifying the Signature

> ⚠️ **Note**: The public key used for signature verification is the PayKKa public key.


```java
String content = String.format(FORMAT, merchantId, timestamp, requestBody);
Signature signature = Signature.getInstance("SHA256withRSA");
byte[] publicKeys = Base64Utils.decodeFromString(publicKey);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeys);
PublicKey pubKey = KeyFactory.getInstance("RSA").generatePublic(x509EncodedKeySpec);
signature.initVerify(pubKey);
signature.update(content.getBytes(StandardCharsets.UTF_8));
String channelSignature = URLDecoder.decode("signatureDataFromPayKKa", StandardCharsets.UTF_8);
boolean verified = signature.verify(Base64Utils.decodeFromString(channelSignature));
```