# Signature Creation

Requests for interaction with the payment system shall be signed by using **SHA256** algorithm.

To create a signature be required:

1. In case of **POST** request, requestData request body is sorted alphabetically and encoded in **BASE64**
2. In case of GET request, convert Query params to **JSON.** \
   FROM:\
   \&#xNAN;*<https://prapi.tarlanpayments.kz/transaction/api/v1/system/client/cards?merchant_id=123&project_id=124&project_client_id=999>*\
   TO:\
   \&#xNAN;*{ "merchant\_id" : 123, "project\_client\_id" : "999", "project\_id" : 124}*\
   After conversion, sort alphabetically and encode in **BASE64.**
3. Concatenate encoded request body (base64EncodedData) and secret (issued to the merchant by a payment insitution)
4. Using hashing function SHA256 hash the obtained result (dataToSign)
5. Add signature to the request header Authorization: Bearer sign

{% hint style="warning" %}
**The entire request body is included in the signature, except for fields with an empty string value ""**
{% endhint %}

{% hint style="warning" %}
**The additional\_data field is not involved in signature creating**
{% endhint %}

{% code lineNumbers="true" %}

```bash
curl --location 'https://prapi.tarlanpayments.kz/transaction/...' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer ff1a38a78ccca1b313ae172307e49112066ec2f5a1dfa2a76110104da3012896'
--data-raw '{}'
```

{% endcode %}

{% tabs %}
{% tab title="PHP" %}
{% code lineNumbers="true" %}

```php
<?php

$requestData = [
    "project_client_id" => "9999",
    "merchant_id" => 1,
    "project_id" => 1,
    "additional_data" => ["key" => "This should be excluded"]
];

$secret = "12345";

// Remove the "additional_data" field from the request data
unset($requestData["additional_data"]);

// Sort the request data by keys in alphabetical order
ksort($requestData);

// Encode the sorted request data to JSON
$sortedJson = json_encode($requestData, JSON_UNESCAPED_SLASHES);

// Encode the sorted JSON to base64
$base64EncodedData = base64_encode($sortedJson);

// Concatenate the base64-encoded data with the secret
$dataToSign = $base64EncodedData . $secret;

// Hash the result to SHA-256
$sha256Hash = hash("sha256", $dataToSign);

echo $sha256Hash;
```

{% endcode %}
{% endtab %}

{% tab title="Python3" %}
{% code lineNumbers="true" %}

```python
import json
import base64
import hashlib

request_data = {
    "project_client_id": "9999",
    "merchant_id": 1,
    "project_id": 1,
    "additional_data": {"key":"This should be excluded"}
}

secret = "12345"

# Remove the "additional_data" field from the request data
if "additional_data" in request_data:
    del request_data["additional_data"]

# Sort the request data by keys in alphabetical order
sorted_data = json.dumps(
        request_data,
        sort_keys=True,
        ensure_ascii=False,
        separators=(',', ':'),
    )

# Encode the sorted JSON to base64
base64_encoded_data = base64.b64encode(sorted_data.encode()).decode()

# Concatenate the base64-encoded data with the secret
data_to_sign = base64_encoded_data + secret

# Hash the result to SHA-256
sha256_hash = hashlib.sha256(data_to_sign.encode()).hexdigest()

print(sha256_hash)
```

{% endcode %}
{% endtab %}

{% tab title="Golang" %}

<pre class="language-go" data-line-numbers><code class="lang-go">package main

import (
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"fmt"
)  // Тело берется из создания <a data-footnote-ref href="#user-content-fn-1">транзакции </a>

type Request struct {
	ProjectClientID string `json:"project_client_id"`
	MerchantId      uint64 `json:"merchant_id"`
	ProjectId       uint64 `json:"project_id"`
	AdditionalData  map[string]string `json:"additional_data"`
}

const secret = "12345"

func main() {
	request := Request{
		ProjectClientID: "9999",
		MerchantId:      1,
		ProjectId:       1,
		AdditionalData: map[string]string{
			"key": "This should be excluded",
		},
	}

	notSortedJson, err := json.Marshal(&#x26;request)
	if err != nil {
		panic(err)
	}

	var notSorteddMap map[string]interface{}

	
	if err = json.Unmarshal(notSortedJson, &#x26;notSorteddMap); err != nil {
		panic(err)
	}

	delete(notSortedMap, "additional_data")
	
	sortedJson, err := json.Marshal(&#x26;notSorteddMap)
	if err != nil {
		panic(err)
	}

	signData := base64.StdEncoding.EncodeToString(sortedJson)
	
	sign := sha256.Sum256([]byte(signData + secret))

	fmt.Printf("%x", sign)

}
</code></pre>

{% endtab %}

{% tab title="Dart" %}

```dart
const paymentSecretKey = "123";

String hashedSecretKey({
  required Map<String, dynamic> requestData,
}) {
  // Sort the request data by keys in alphabetical order
  List<MapEntry<String, dynamic>> sortedEntries = requestData.entries.toList()
    ..sort((a, b) => a.key.compareTo(b.key));
  Map<String, dynamic> sortedData = Map.fromEntries(sortedEntries);

  // Sort the request data by keys in alphabetical order
  String encodedData = json.encode(sortedData);

  // Encode the sorted JSON to base64
  String base64EncodedData = base64.encode(Utf8Encoder().convert(encodedData));

  // Concatenate the base64-encoded data with the secret
  String dataToSign = base64EncodedData + paymentSecretKey;

  // Hash the result to SHA-256
  Digest sha256Hash = sha256.convert(Utf8Encoder().convert(dataToSign));

  final result = sha256Hash.toString();
  log('auth token $result');

  return result;
}
```

{% endtab %}
{% endtabs %}

[^1]: [https://app.gitbook.com/o/gxK1VbNmJ8bcGc8xM5wD/s/dkkz4EKtpaWVPlq7ZwsC/\~/changes/61/spravochnik-metodov-api/vzaimodeistvie-s-formoi-oplaty](broken://pages/rssHNRC5ER4AUkwJxprp)


---

# 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://docs.tarlanpayments.kz/eng/acquiring/signature-creation.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.
