• Multi Bank Virtual POS

Security Hash Generation

The request bodies transmitted to the services are signed with JWK file, token is generated and expected to be sent in the securtyHash input field. The following data is calculated and shown according to a workplace in the test environment.

When you want to experiment from a different workplace in a test/prod environment, you can proceed by making calculations with appropriate data.

JWK File example:

{\n \"kty\": \"oct\", // fixed value used\n \"use\": \"sig\", // fixed value used\n \"kid\": \"kid-value\", // is calculated with the following algorithm\n \"k\": \"k-value\", // is calculated with the following algorithm\n \"alg\": \"HS512\" // fixed value used\n}

The “kid” and “k” values in the jwk file are unique values.

1. Step:

While generating “Kid” value, “secretKey” value and “fixed_kid_value” value provided to workplaces are used.

Below “fixed_kid_value” value is transmitted as a fixed value for the test environment. In the production environment, you can calculate the "fixed_kid_value" value with the fixed value given below.

Example code fragment:

String FIXED_KID_VALUE = \"00ff6ea8-3511-4d04-946c-ba569208306f\";\n\nprivate String generateKidValue(String secretKey) {\n byte[] result = null;\n try {\n MessageDigest digest = MessageDigest.getInstance(SHA512);\n String input = secretKey + FIXED_KID_VALUE;\n result = digest.digest(input.getBytes(StandardCharsets.UTF_8));\n } catch (NoSuchAlgorithmException e) {\n log.error(\"Kid cannot be generated\", e);\n }\n return DatatypeConverter.printBase64Binary(result);\n}

Sample Kid Value:

Merchant Number Terminal Number SecretKey Caclulated Kid
77006866 84006869 8e6883ba-e73b-4de2-b58c-aad37d34bc72  nKWRE20dTXl75S/O3KPLRiGVn/EnC4mVl5DHAqONGCTziUxUXK5KprQ2KVMIfFU6DysTjTpKom+nfHiRld7MEA==

2. Step:

When generating the “k” value, merchantNumber - terminalNumber - secretKey - fixed_k_value is used.

String FIXED_K_VALUE = \"87919a8f-957b-427b-ae12-167622ab52b5\";\n\nprivate String generateKValue(Long merchantNumber, Long terminalNumber, String secretKey) {\n byte[] result = null;\n try {\n MessageDigest digest = MessageDigest.getInstance(SHA512);\n String input = secretKey + FIXED_K_VALUE + merchantNumber + terminalNumber;\n result = digest.digest(input.getBytes(StandardCharsets.UTF_8));\n } catch (NoSuchAlgorithmException e) {\n log.error(\"K cannot be generated\", e);\n }\n return DatatypeConverter.printBase64Binary(result);\n}

Sample K Value:

Merchant Number Terminal Number SecretKey Caclulated K Value
77006866 84006869  8e6883ba-e73b-4de2-b58c-aad37d34bc72  TgAzw6MiALsdjAcug8BKL73l/deKBj6+ust4bAAFvAk/16iwhLHfnOQB5DmoUY4xYVKuySXzXjtHQFlSsjYE4w==

3. Step:

The generated “k” and “kid” values are set to the fields in the jwk file and used when signing the request body. The appropriate request body must be used for the operation to be performed.

Note: When creating the securityHash value, the securityHash value in the body should not be taken into account.

public String generateJWKSignature(\n Long merchantNumber, Long terminalNumber, String secretKey, String input)\n throws ParseException, JOSEException {\n\n JWKResource jwkResource = getJWKResource(merchantNumber, terminalNumber, secretKey);\n JWK jwk = JWK.parse(new Gson().toJson(jwkResource));\n JWSObject jws = new JWSObject(\n new JWSHeader.Builder(JWSAlgorithm.HS512)\n .keyID(jwk.getKeyID())\n .type(JOSEObjectType.JWT)\n .build(),\n new Payload(input));\n jws.sign(new MACSigner(jwk.toOctetSequenceKey()));\n return jws.serialize();\n}\n\nprivate JWKResource getJWKResource(Long merchantNumber, Long terminalNumber, String secretKey) {\n JWKResource jwkResourceTmp = new JWKResource();\n jwkResourceTmp.setKty(\"oct\");\n jwkResourceTmp.setUse(\"sig\");\n jwkResourceTmp.setAlg(\"HS512\");\n jwkResourceTmp.setKid(generateKidValue(secretKey));\n jwkResourceTmp.setK(generateKValue(merchantNumber, terminalNumber, secretKey));\n return jwkResourceTmp;\n}

4. Step:

The generated hash is fed in the securityHash field requested in the body request of the services.

In the Headers section when requesting all services;

  • The “PG-Api-Version” parameter must be sent with the value “v2”.
  • The “PG-Auth-Token” parameter must be passed. This parameter consists of “merchantNumber:terminalNumber:hash” values.
  • The correlationId parameter must be passed with a unique value for each transaction.

5. Example Request :  

{\n \"amount\": 30,\n \"orderId\": \"tamitest08\",\n \"currency\": \"TRY\",\n \"installmentCount\": 1,\n \"card\": {\n \"holderName\": \"Ad Soyad\",\n \"cvv\": \"\",\n \"expireMonth\": 4,\n \"expireYear\": 2026,\n \"number\": \"4824910501747014\"\n },\n \"buyer\": {\n \"ipAddress\": \"12.55.77.8\",\n \"surName\": \"Soyisim\",\n \"name\": \"Soyisim\",\n \"emailAddress\": \"email@email.com\",\n \"buyerId\": \"78494949\",\n \"phoneNumber\": \"5346484700\"\n },\n \"paymentGroup\": \"PRODUCT\",\n \"securityHash\": \"eyJraWQiOiJuS1dSRTIwZFRYbDc1Uy9PM0tQTFJpR1ZuL0VuQzRtVmw1REhBcU9OR0NUemlVeFVYSzVLcHJRMktWTUlmRlU2RHlzVGpUcEtvbStuZkhpUmxkN01FQT09IiwidHlwIjoiSldUIiwiYWxnIjoiSFM1MTIifQ.ewogICJhbW91bnQiOiAzMCwKICAib3JkZXJJZCI6ICJ0YW1pdGVzdDA4IiwKICAiY3VycmVuY3kiOiAiVFJZIiwKICAiaW5zdGFsbG1lbnRDb3VudCI6IDEsCiAgImNhcmQiOiB7CiAgICAiaG9sZGVyTmFtZSI6ICJBZCBTb3lhZCIsCiAgICAiY3Z2IjogIiIsCiAgICAiZXhwaXJlTW9udGgiOiA0LAogICAgImV4cGlyZVllYXIiOiAyMDI2LAogICAgIm51bWJlciI6ICI0ODI0OTEwNTAxNzQ3MDE0IgogIH0sCiAgImJ1eWVyIjogewogICAgImlwQWRkcmVzcyI6ICIxMi41NS43Ny44IiwKICAgICJzdXJOYW1lIjogIlNveWlzaW0iLAogICAgIm5hbWUiOiAiU295aXNpbSIsCiAgICAiZW1haWxBZGRyZXNzIjogImVtYWlsQGVtYWlsLmNvbSIsCiAgICAiYnV5ZXJJZCI6ICI3ODQ5NDk0OSIsCiAgICAicGhvbmVOdW1iZXIiOiAiNTM0NjQ4NDcwMCIKICB9LAogICJwYXltZW50R3JvdXAiOiAiUFJPRFVDVCIKfQ.z_KRDnDxgFJtafIe9Jk45VA31-6rjTVQtZSfF8Tz3C2HJ5oeNYj6YyHBfq7M7MwkZ_tpEBAVkpQBoCiT6HMSmA\"\n}

Example curl command:

curl --location 'https://sandbox-paymentapi.tami.com.tr/payment/auth' \\\n--header 'Accept-Language: tr' \\\n--header 'correlationId: correlation0a46293f-44ac-4fdc-984d-0c291772a4a4' \\\n--header 'PG-Auth-Token: 77006866:84006869:ZFBhgSvnJ62QuX1x/siUxeTR9uDwAPdiJNgIiqcV6E4=' \\\n--header 'PG-Api-Version: v2' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n\"amount\": 30,\n\"orderId\": \"tamitest08\",\n\"currency\": \"TRY\",\n\"installmentCount\": 1,\n\"card\": {\n\"holderName\": \"Ad Soyad\",\n\"cvv\": \"\",\n\"expireMonth\": 4,\n\"expireYear\": 2026,\n\"number\": \"4824910501747014\"\n},\n\"buyer\": {\n\"ipAddress\": \"12.55.77.8\",\n\"surName\": \"Soyisim\",\n\"name\": \"Soyisim\",\n\"emailAddress\": \"email@email.com\",\n\"buyerId\": \"78494949\",\n\"phoneNumber\": \"5346484700\"\n},\n\"paymentGroup\": \"PRODUCT\",\n\"securityHash\": \"eyJraWQiOiJuS1dSRTIwZFRYbDc1Uy9PM0tQTFJpR1ZuL0VuQzRtVmw1REhBcU9OR0NUemlVeFVYSzVLcHJRMktWTUlmRlU2RHlzVGpUcEtvbStuZkhpUmxkN01FQT09IiwidHlwIjoiSldUIiwiYWxnIjoiSFM1MTIifQ.ewogICJhbW91bnQiOiAzMCwKICAib3JkZXJJZCI6ICJ0YW1pdGVzdDA4IiwKICAiY3VycmVuY3kiOiAiVFJZIiwKICAiaW5zdGFsbG1lbnRDb3VudCI6IDEsCiAgImNhcmQiOiB7CiAgICAiaG9sZGVyTmFtZSI6ICJBZCBTb3lhZCIsCiAgICAiY3Z2IjogIiIsCiAgICAiZXhwaXJlTW9udGgiOiA0LAogICAgImV4cGlyZVllYXIiOiAyMDI2LAogICAgIm51bWJlciI6ICI0ODI0OTEwNTAxNzQ3MDE0IgogIH0sCiAgImJ1eWVyIjogewogICAgImlwQWRkcmVzcyI6ICIxMi41NS43Ny44IiwKICAgICJzdXJOYW1lIjogIlNveWlzaW0iLAogICAgIm5hbWUiOiAiU295aXNpbSIsCiAgICAiZW1haWxBZGRyZXNzIjogImVtYWlsQGVtYWlsLmNvbSIsCiAgICAiYnV5ZXJJZCI6ICI3ODQ5NDk0OSIsCiAgICAicGhvbmVOdW1iZXIiOiAiNTM0NjQ4NDcwMCIKICB9LAogICJwYXltZW50R3JvdXAiOiAiUFJPRFVDVCIKfQ.z_KRDnDxgFJtafIe9Jk45VA31-6rjTVQtZSfF8Tz3C2HJ5oeNYj6YyHBfq7M7MwkZ_tpEBAVkpQBoCiT6HMSmA\"\n}'

We are here for all your questions and support requests.

Ask a Question Ask a Question