• Multi Bank Virtual POS

3D Pre-Authorization Transaction General Description

The 3D pre-authorization transaction allows the balance to be blocked on the card, for the amount you specify, together with 3D Secure authentication, for a payment you wish to make via Tami.

The transaction consists of two steps: first you initiate the 3D pre-authorization transaction; when you decode the signedResponse value returned as a result of this step, you obtain the HTML content (content) contained within it. You decode this content from Base64 and redirect your customer to the resulting HTML page; after the customer enters the authentication code, the 3D authentication result is determined.

If the authentication is successful, you must call the completion service for the 3D pre-authorization transaction in order to complete the payment transaction. To collect the blocked amount, you need to call the “Pre-Authorization Capture” service within the blocking period.

Tami Test/Prod Portal Information

Before going live with your integration, you can use the Tami Test Portal to test without creating any real money movement.

Test Portal address: https://sandbox-portal.tami.com.tr

If you would like to log in to the test portal to view your transactions and perform cancellations/refunds when needed, a dedicated test portal user must be defined for you. You can reach our support team for this at TeknikDestek@tami.com.tr.

Prod Portal address: https://portal.tami.com.tr

For your production environment credentials, you can register via this address or contact our e-commerce support team.

Tami Test / Prod API Users

Two different environments are used when integrating with Tami’s APIs: Sandbox (Test) and Prod (Production).

  • Test (Sandbox) Environment

This lets you test your integration without creating any real money movement. Your requests are sent to the test endpoints and can be tracked via the Tami Test Portal above.

Below are the credentials you can use to send a test request via the API in the sandbox environment:

FieldValue
Merchant Number77006950
Terminal Number84006953
Secret Key0edad05a-7ea7-40f1-a80c-d600121ca51b
  • Prod (Production) Environment

This is the environment where live transactions take place and real payments are collected.

For your production environment credentials, you can register via https://portal.tami.com.tr or contact our e-commerce support team.

Generating the PG Auth Token

For requests sent to Virtual POS services, the PG-Auth-Token field must be included in the header.

The PG-Auth-Token is generated in the following format:

MerchantNumber:TerminalNumber:Hash

The Hash value is generated by concatenating your Merchant Number, Terminal Number, and Secret Key (in that order), hashing the result with the SHA-256 algorithm, and converting the result to Base64 format.

Below is a sample Java code block demonstrating this calculation:

public class SHA256Example { public static String sha256(Long merchantNumber, Long terminalNumber, String secretKey) { String text = merchantNumber.toString() + terminalNumber.toString() + secretKey; try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8)); String sha256Hex = DatatypeConverter.printBase64Binary(hash); return sha256Hex; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } }

You can generate the PG-Auth-Token header value by combining the Hash value you generated with your Merchant Number and Terminal Number in the format above.

About 3D Pre-Authorization Transaction Initiation

This is the first step of a 3D pre-authorization transaction. For security purposes, the information in your request is not transmitted to Tami in plain form at this step either; the request, which includes all information along with your merchant’s callbackUrl address, is signed, encrypted, and sent in the signedRequest field.

The response returned as a result of the transaction is likewise encrypted and delivered in the signedResponse field. When you decode the signedResponse value, you obtain the HTML content (content) contained within it; you decode this content from Base64 and redirect your customer to the resulting HTML page. The customer enters the authentication code here, and the 3D authentication result is determined.

3D Pre-Authorization Transaction Initiation API Information

The endpoint information to be used for initiating the 3D pre-authorization transaction is below:

You must send your requests using the POST method to the endpoint appropriate for the environment you are working in (test/production).

How the 3D Pre-Authorization Transaction Initiation Request Is Sent

When initiating the 3D pre-authorization transaction as well, the values in the body of the request sent are not expected to be transmitted in plain form; instead, a single signed and encrypted value is expected. This value is sent in the signedRequest field.

The response returned by Tami is likewise signed and encrypted, and is delivered in the signedResponse field.

In addition, the following information must also be sent in the header:

  • PG-Auth-Token: How this is calculated is explained above under “Generating the PG Auth Token.”
  • CorrelationId: A variable value that must be unique for each request.
  • PG-Api-Version: Must be sent as v4.

3D Pre-Authorization Transaction Initiation — Parameters to Be Signed and Encrypted, with Descriptions

For 3D pre-authorization transactions, the values in the request body are not sent in plain form; the encrypted value is sent in the signedRequest field.

The signedRequest value is obtained by encrypting a request constructed from the fields listed in the table below. If any field marked as mandatory (M) is missing or sent incorrectly, the transaction will result in an error.

The fields to be included in signedRequest, along with their rules, are specified in the table below:

Main parameters

Parameter NameFormatLengthO/M/CDescription
orderIdString(2-36)MA unique communication identifier used in the communication between Tami and the customer for the payment request. This value must be unique for the merchant and POS pair. The orderId field may contain alphanumeric characters along with only the ‘-’ and ‘’ characters. However, it must not contain consecutive ‘-’ or ‘’ characters.
amountDecimalMThe transaction amount. The decimal separator must be a period (.).
currencyString3MIndicates the currency code of the transaction. Example: TRY must be sent for Turkish Lira.
installmentCountNumberMThe installment information for the transaction to be made. For a single-payment transaction, 1 must be sent. Sending 0 is not accepted.
paymentGroupStringMPayment group; default is PRODUCT.
paymentChannelenumOPayment channel. Valid values are provided within the enum: WEB, MOBILE, MOBILE_WEB, MOBILE_IOS, MOBILE_ANDROID, MOBILE_WINDOWS, MOBILE_TABLET, MOBILE_PHONE
callbackUrlStringCMandatory if the transaction is to be performed as 3D. This is the address to which the 3D authentication result will be returned. It must be an address belonging to the merchant.
cardObjectMContains the details of the card used for the payment (cardholder name, card number, expiry month/year, and CVV).
billingAddressObjectOContains the billing address details. If provided, it is stored as the billing address in the transaction record.
shippingAddressObjectOContains the delivery address details. It is recommended to send this field for orders that require physical delivery.
buyerObjectMContains information about the buyer on the merchant side.
basketObjectOContains the basket details of the order, namely the list of purchased items and their details.

card

Parameter NameFormatLengthO/M/CDescription
cvvStringMThe security code of the card from which payment will be collected.
expireMonthNumber(1-12)MThe expiration month of the card from which payment will be collected.
expireYearNumber4MThe expiration year of the card from which payment will be collected.
holderNameString30MThe name and surname of the cardholder of the card from which payment will be collected.
numberString(5-35)MThe number of the card from which payment will be collected.

billingAddress

Parameter NameFormatLengthO/M/CDescription
addressString400OThe merchant’s billing address information.
emailAddressStringOThe merchant’s email information
cityString30OThe city information for the merchant’s billing address.
companyNameString100OThe merchant’s trade name information.
countryString50OThe country information for the merchant’s billing address.
contactNameString30OThe name and surname information for the merchant’s billing address.
phoneStringOThe mobile number of the recipient on the merchant side.
zipCodeString15OThe postal code of the merchant’s billing address.
districtString50OThe district information of the merchant’s billing address.

shippingAddress

Parameter NameFormatLengthO/M/CDescription
addressString400OThe merchant’s shipping address information.
emailAddressStringOThe merchant’s email information
cityString30OThe city information for the merchant’s shipping address.
countryString50OThe country information for the merchant’s shipping address.
contactNameString30OThe name and surname information for the merchant’s shipping address.
zipCodeString15OThe postal code information of the merchant’s shipping address.
districtString50OThe district information of the merchant’s shipping address.

buyer

Parameter NameFormatLengthO/M/CDescription
ipAddressStringMThe IP address of the buyer on the merchant side. The buyer’s actual IP address must be transmitted.
buyerIdString50MThe buyer’s ID information on the merchant side.
nameString30MThe buyer’s first name information on the merchant side.
surNameString30MThe buyer’s surname information on the merchant side.
identityNumberString11OThe buyer’s identity (national ID) number on the merchant side.
cityString50OThe buyer’s city information on the merchant side.
countryString50OThe buyer’s country information on the merchant side.
emailAddressStringMThe buyer’s email information on the merchant side. The email address must be a valid and reachable address belonging to the buyer.
phoneNumberStringMThe buyer’s mobile number on the merchant side
registrationAddressString400OThe buyer’s registration address on the merchant side.
zipCodeString15OThe buyer’s postal code on the merchant side.
registrationDateDateOThe buyer’s registration date on the merchant side. The date format must be in the form 2015-09-17 23:45:06.
lastLoginDateDateOThe buyer’s last login date on the merchant side. The date format must be in the form 2015-09-17 23:45:06.

basket

Parameter NameFormatLengthO/M/CDescription
basketIdString50CThe ID of the basket on the merchant side. If an item is sent within the basket, sending basketId becomes mandatory.

basket/basketItems

Type: List (O)

Parameter NameFormatLengthO/M/CDescription
itemIdString50CThe ID of the item in the basket on the merchant side. If an item is sent within the basket, sending itemId becomes mandatory.
itemTypeString50CThe type of the item in the basket on the merchant side. Valid enum values: PHYSICAL and VIRTUAL. If an item is sent within the basket, sending itemType becomes mandatory.
nameString50CThe name of the item in the basket on the merchant side. If an item is sent within the basket, sending name becomes mandatory.
categoryString50OThe category of the item in the basket on the merchant side.
subCategoryString100OThe subcategory of the item in the basket on the merchant side.
unitPriceDecimalmin 0.0OThe unit price of the item in the basket on the merchant side.
totalPriceDecimalmin 0.0CThe total price of the item in the basket on the merchant side. It cannot be 0 or less than 0; the sum of the amounts must equal the basket amount (amount). UnitPrice * numberOfProducts must equal totalPrice. If an item is sent within the basket object, sending totalPrice becomes mandatory.
numberOfProductsNumber1-99999OThe quantity of the item in the basket on the merchant side.

Generating the Request Token (signedRequest)

For security purposes, information in requests sent by merchants is not sent in plain form. Instead, the request body is expected to contain the signedRequest value, which is generated by signing and encrypting a request built according to the fields requested by Tami.

For a detailed explanation of the signedRequest generation steps and code samples, please see the Generating the Request Token (signedRequest) page.

3D Pre-Authorization Transaction Initiation API Request Example

{ "signedRequest": "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU4R0NNIiwiYWxnIjoiZGlyIn0..2GrWLiRzNXkASeuawbuf.0vhgnz-ViiYSL_M9sFuzocajEt9WUOrGlZzJd-u0OQrQ-IiDd7PfkzOjfoDzh4QL0PiieZmHbpZ1wur5wuETbA10JzFv7wptgjxTmoZLs7RP0JdkQrVqtxRqzcmh4ifHBuxfd9..." }

The signedRequest value above has been shortened for example/test purposes. A real request contains a much longer JWE (encrypted token) value.

3D Pre-Authorization Transaction Initiation API Response Example

Response for a successful transaction:

{ "signedResponse": "eyJraWQiOiI3MTI3ZTg3MPc4MjNkWvsZzXoGsWnIjp7Inc2YzY3VmYjZ7YWVKiOiI5InZ0IiwiYWxnIjoiZGly..." }

3D Pre-Authorization Transaction Initiation — Response Parameters and Descriptions

When the transaction is successful, the response delivered by Tami contains only the signedResponse field. All other fields listed in the table below (success, systemTime, correlationId, orderId, amount, card information, threeDSHtmlContent, etc.) are not present in plain form in this case — all of them are carried in encrypted form inside the signedResponse field. You can only access these fields once the signedResponse value has been decoded. The decoding steps are described in the next heading.

When the transaction is unsuccessful, signedResponse is not returned at all; in this case success, systemTime, correlationId, errorCode, errorMessage, and errorGroup fields are returned directly in plain form.

Parameter NameFormatWhere It AppearsDescription
successStringInside signedResponse (plain if transaction unsuccessful)If True, the transaction was successful; if False, an error was received. Error details are shared in the errorCode and errorMessage fields.
systemTimedateTimeInside signedResponse (plain if transaction unsuccessful)Indicates the date and time the response was generated by Tami.
correlationIdStringInside signedResponse (plain if transaction unsuccessful)Transaction number
transactionDatedateTimeInside signedResponseIndicates the date and time the transaction took place.
orderIdStringInside signedResponseOrder number
amountNumberInside signedResponseTransaction amount
currencyStringInside signedResponseTransaction currency
installmentCountNumberInside signedResponseNumber of installments for the transaction
card/binNumberStringInside signedResponseFirst 8 digits of the card
card/maskedNumberStringInside signedResponseMasked card number
card/cardBrandStringInside signedResponseCard brand
card/cardOrganizationStringInside signedResponseCard organization
card/cardTypeStringInside signedResponseCard type
threeDSHtmlContentStringInside signedResponseThe HTML content that will redirect to the 3D authentication page. The content is obtained as HTML by decoding it from Base64.
errorCodeStringPlain (only when success:false)Error code
errorMessageStringPlain (only when success:false)Error message
errorGroupStringPlain (only when success:false)Indicates the group of the relevant error. Merchants can manage their own rules by making use of the error code and error groups.

3D Authentication

Through the HTML content obtained as a result of the 3D pre-authorization transaction initiation step, the cardholder is shown the 3D authentication screen belonging to their card’s issuing bank. After the cardholder enters the password sent to their mobile phone, the authentication result is POSTed by Tami to the address you specified in the callbackUrl parameter.

A successful 3D authentication does not mean that an amount has yet been blocked on the card. When the success field returned in the response is true, you must call the 3D pre-authorization transaction completion service, which is the next step, in order to block the balance. No blocking takes place on the card until this step is completed.

For the purpose of ensuring transaction security, Tami adds a hashedData value to this callback response. You must recalculate this value on your own side using the method described under the “HashedData Calculation” heading below, and compare it with the value delivered by Tami.

When the value you calculate matches the hashedData value delivered by Tami, it is confirmed that the relevant response is secure and came from the correct source, and you can proceed to the 3D completion step. Performing this verification and confirming transaction security is the merchant’s responsibility.

If the mdStatus value returned in the authentication response is 2, 3, or 4, the transaction has been authenticated by the bank as half secure. For these transactions, it is the merchant’s responsibility to decide whether to proceed to the 3D completion step; the merchant may send the completion request if they wish to proceed with the transaction.

Note: This step is not a request going to the Tami API, but a notification coming from the bank to the merchant. For this reason, it falls outside the signedRequest / signedResponse and PG-Auth-Token mechanism; the parameters below and the hashedData calculation remain unchanged.

3D Authentication Response Parameters and Descriptions

Response parameters

Parameter NameFormatDescription
cardBrandStringCard brand
cardOrganizationStringCard organization
cardTypeStringCard type
currencyCodeStringTransaction currency
hashedDataStringThe value to be used to verify the integrity of the information returned in the response
hashParamsStringConveys the information and order of the parameters that make up the hashedData value. The order specified in this field must be used when calculating hashedData.
installmentCountNumberNumber of installments for the transaction
maskedNumberNumberThe card number in masked form
mdStatusStringThe mdStatus value returned for informational purposes. It can be returned as 1 for successful cases, 2, 3, or 4 for half secure cases, and 0, 5, 6, 7, or 8 for unsuccessful cases.
orderIdStringOrder number
successStringReports the outcome of the 3D authentication performed. Returns true if the transaction was successful, false if it was erroneous.
systemTimeDateTimeTransaction date
txnAmountNumberTransaction amount

mdStatus values

If the success field returned in the 3D Authentication response is false, the table below will help regarding the cause of the error.

mdStatusDescription
mdStatus = 0The 3-D Secure signature is invalid or authentication failed
mdStatus = 2Cardholder or their bank is not enrolled in the system
mdStatus = 3The card’s issuing bank is not enrolled in the system
mdStatus = 4Authentication attempt; the cardholder has chosen to enroll in the system at a later time
mdStatus = 5Authentication cannot be performed
mdStatus = 63-D Secure error
mdStatus = 7System error
mdStatus = 8Unknown card number

Verifying the 3D Authentication Response (hashedData)

The response returned to the callbackUrl value after 3D authentication contains the hashedData and hashParams fields. You must verify this hash to ensure that the response genuinely came from Tami and was not altered in transit.

In brief, the process works as follows: the hashParams value returned in the response is parsed by the + character to obtain the field names. Then, the corresponding value in the response for each field name is concatenated, in the order given in hashParams, to form the hashItems text (the values are concatenated, not the field names; an empty string is used instead of an empty value). Finally, this text is passed through the HMAC-SHA256 algorithm using the terminal’s secretKey value and encoded in Base64, and the resulting value is compared with the hashedData in the response. If the values match, it means the integrity of the response has been verified; if they do not match, the transaction should be examined.

Note: For single-payment transactions, the installmentCount information is expected to be sent as 1. If this information is present in hashParams, it is also added to hashItems.

Because the field order is not fixed, if Tami adds or removes a field in hashParams in the future, you do not need to change your calculation logic; it is sufficient to always base it on the order returned in the hashParams field in the response.

Verification is performed in the following 3 steps:

1. Parsing hashParams

The hashParams value returned in the response is parsed by the + character. An example hashParams value:

cardOrganization+cardBrand+cardType+maskedNumber+installmentCount+currencyCode+txnAmount+orderId+callbackUrl+systemTime+success

2. Concatenating the values in order

For each parsed field name, the corresponding value in the response is appended in the same order (an empty string is used if a value is absent).

public static String buildHashItems(Map<String, String> responseMap) { String hashParams = responseMap.get("hashParams"); StringBuilder builder = new StringBuilder(); for (String param : hashParams.split("\\+")) { String value = responseMap.get(param); // the VALUE is appended, not the field NAME builder.append(value != null ? value : ""); } return builder.toString(); }

3. Calculating and comparing the hash

The resulting text is passed through HMAC-SHA256 using the terminal secretKey value, and the result is encoded in Base64. The resulting value must match the hashedData in the response:

expectedHash = Base64( HmacSHA256(hashItems, secretKey) )

If it matches, the integrity of the response has been verified and you may proceed with the transaction. If it does not match, the response should not be processed, and you should contact the support team.

About 3D Pre-Authorization Transaction Completion

You must call this service to block the balance on a transaction with successfully completed 3D authentication. If this service is not called and the transaction is not completed, no amount will have been blocked on the card. Once the balance has been blocked, you must call the “Pre-Authorization Capture” service for collection.

3D Pre-Authorization Transaction Completion API Information

The endpoint information to be used for completing the 3D pre-authorization transaction is below:

You must send your requests using the POST method to the endpoint appropriate for the environment you are working in (test/production).

How the 3D Pre-Authorization Transaction Completion Request Is Sent

When completing the 3D pre-authorization transaction as well, the values in the body of the request sent are not expected to be transmitted in plain form; instead, a single signed and encrypted value is expected. This value is sent in the signedRequest field.

The response returned by Tami is likewise signed and encrypted, and is delivered in the signedResponse field.

In addition, the following information must also be sent in the header:

  • PG-Auth-Token: How this is calculated is explained above under “Generating the PG Auth Token.”
  • CorrelationId: A variable value that must be unique for each request.
  • PG-Api-Version: Must be sent as v4.

3D Pre-Authorization Transaction Completion — Parameters to Be Signed and Encrypted, with Descriptions

When completing the 3D pre-authorization transaction, the values in the request body are not sent in plain form; the encrypted value is sent in the signedRequest field.

The signedRequest value is obtained by encrypting a request constructed from the field listed in the table below. If the field marked as mandatory (M) is missing or sent incorrectly, the transaction will result in an error. Abbreviations: (O) Optional, (M) Mandatory.

FieldFormatLengthO/MDescription
orderIdString(2-36)MThe order number information for which 3D authentication has been successfully completed.

3D Pre-Authorization Transaction Completion API Request Example

{ "signedRequest": "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU4R0NNIiwiYWxnIjoiZGlyIn0..5KtYNjSAPZmCUfuawbuf.3wjikb-XkkASN_O1tGzwpkbzcWGuCx0XTNrHlZxLf-w2SRsR-JjFd9SgkALijfpEyi5Sn7baPG0mb2vtkgzbddMkiZj5xrpygkxWoqbTt9SekLctTsxSs0jrngIaxif..." }

The signedRequest value above has been shortened for example/test purposes. A real request contains a much longer JWE (encrypted token) value.

3D Pre-Authorization Transaction Completion API Response Example

Response for a successful transaction:

{ "signedResponse": "eyJraWQiOiI4MjM4ZTk4MQd4OTM0ZXt0a1l0WoGoWmIjp7InQ3Y3Y3VnYjZ4YWVKiOiIwInZ0IiwiYWxnIjoiZGly..." }

3D Pre-Authorization Transaction Completion — Response Parameters and Descriptions

When the transaction is successful, the response delivered by Tami contains only the signedResponse field. All other fields listed in the table below (success, systemTime, correlationId, orderId, amount, card information, etc.) are not present in plain form in this case — all of them are carried in encrypted form inside the signedResponse field. You can only access these fields once the signedResponse value has been decoded. The decoding steps are described in the next heading.

When the transaction is unsuccessful, signedResponse is not returned at all; in this case success, systemTime, correlationId, errorCode, errorMessage, and errorGroup fields are returned directly in plain form.

Parameter NameFormatWhere It AppearsDescription
successStringInside signedResponse (plain if transaction unsuccessful)If True, the transaction was successful; if False, an error was received. Error details are shared in the errorCode and errorMessage fields.
systemTimedateTimeInside signedResponse (plain if transaction unsuccessful)Indicates the date and time the response was generated by Tami.
correlationIdStringInside signedResponse (plain if transaction unsuccessful)Transaction number
transactionDatedateTimeInside signedResponseIndicates the date and time the transaction took place.
orderIdStringInside signedResponseOrder number
amountNumberInside signedResponseTransaction amount
currencyStringInside signedResponseTransaction currency
installmentCountNumberInside signedResponseNumber of installments for the transaction
card/binNumberStringInside signedResponseFirst 8 digits of the card
card/maskedNumberStringInside signedResponseMasked card number
card/cardBrandStringInside signedResponseCard brand
card/cardOrganizationStringInside signedResponseCard organization
card/cardTypeStringInside signedResponseCard type
errorCodeStringPlain (only when success:false)Error code
errorMessageStringPlain (only when success:false)Error message
bankAuthCodeStringInside signedResponseBank authorization code
bankReferenceNumberStringInside signedResponseRetrieval reference number (RetRef) for the transaction
errorGroupStringPlain (only when success:false)Indicates the group of the relevant error. Merchants can manage their own rules by making use of the error code and error groups.

Decoding the Response Token (signedResponse)

The steps required to decode the value delivered in the signedResponse field in order to access the parameters above will be provided in this section. These steps are the same as the signedResponse decoding logic described above for the “Initiation” step.

For a detailed explanation of the decoding steps and code samples, please see the Decoding the Response Token (signedResponse) page.

Code Examples

Below are links to code samples written in various programming languages. Through the link for your preferred programming language, you can examine in detail code written with pre-defined example values.

These samples contain code covering the relevant transaction type, and since they are written in different languages, it is also possible to observe various approaches and practices. This gives you the opportunity to work with clearer and more authentic examples suited to your preferred programming language.

  • For C# Code Samples, click here.
  • For VB.Net Code Samples, click here.
  • For Java Code Samples, click here.
  • For PHP Code Samples, click here.
  • For NodeJS Code Samples, click here.

Please note that these samples are written with pre-defined values, and the necessary adaptation and security measures may need to be taken for their use in real projects.

Error Codes

You can access the list of error codes on this page.

Test Cards

You can access the list of test cards on this page.

We are here for all your questions and support requests.

Ask a Question Ask a Question