C#

NestPay Payten 3D-1004 - Guvenlik Kodu hatali. Çözümü

3D-1004 - Guvenlik Kodu hatali. Çözümü - Hash Version 3 - SHA512;

 /// <summary>
 /// EstNestPay için 3D Secure form data hazırlama (NestPay dokümanına göre)
 /// </summary>
 public static Dictionary<string, string> Prepare3DFormData(
     PaymentRequest request,
     BankPOSSettings posSettings,
     string callbackBaseUrl,
     string bankCode)
 {
     var amount = request.Amount.ToString("F2", System.Globalization.CultureInfo.InvariantCulture);
     var expiryYear = request.ExpiryYear.Length == 4 ? request.ExpiryYear : $"20{request.ExpiryYear}";
     var expiryYearShort = expiryYear.Substring(2); // Son 2 rakam
     var expiryMonth = request.ExpiryMonth.PadLeft(2, '0'); // 2 haneli ay
     
     var okUrl = $"{callbackBaseUrl}/NestPayCallback3D?bank={bankCode}&status=success&transactionId={request.TransactionId}";
     var failUrl = $"{callbackBaseUrl}/NestPayCallback3D?bank={bankCode}&status=failed&transactionId={request.TransactionId}";
     
     // Rastgele dize oluştur (20 karakter)
     var rnd = Guid.NewGuid().ToString("N").Substring(0, 20);

     // NestPay dokümanına göre parametreler
     var formData = new Dictionary<string, string>
     {
         ["clientid"] = posSettings.MerchantId,
         ["storetype"] = "3D",
         ["islemtipi"] = "Auth",
         ["amount"] = amount,
         ["currency"] = "949", // TRY
         ["oid"] = request.OrderId,
         ["okUrl"] = okUrl,
         ["failUrl"] = failUrl,
         ["lang"] = "tr", // Türkçe
         ["rnd"] = rnd,
         ["pan"] = request.CardNumber,
         ["Ecom_Payment_Card_ExpDate_Year"] = expiryYearShort,
         ["Ecom_Payment_Card_ExpDate_Month"] = expiryMonth,
         ["hashAlgorithm"] = "ver3"
     };

     // İsteğe bağlı parametreler
     if (request.Installments > 1) 
         formData["taksit"] = request.Installments.ToString(); 
     else 
         formData["taksit"] = ""; 

     // CVV varsa ekle
     if (!string.IsNullOrEmpty(request.CVV))
     {
         formData["cv2"] = request.CVV;
     }
  
     // Hash hesapla (Hash Version 3 - SHA512)
     // Hash hesaplamasından önce hash parametresini eklememeliyiz
     var hash = CalculateHash3D(formData, posSettings.SecretKey);
     
     formData["hash"] = hash;

     return formData;
 }

        

         /// <summary>
        /// EstNestPay için hash hesaplama (Hash Version 3 - SHA512)
        /// NestPay Hash Version 3 dokümanına göre:
        /// 1. Tüm parametreler (storeKey hariç) alfabetik olarak sıralanır
        /// 2. Parametre değerlerindeki "|" -> "\|", "\" -> "\\" escape edilir
        /// 3. Parametreler arasına "|" konulur
        /// 4. Sonuna "|" ile storeKey eklenir
        /// 5. "encoding" ve "hash" parametreleri hash hesaplamasına dahil edilmez
        /// </summary>
        public static string CalculateHash3D(Dictionary<string, string> parameters, string storeKey)
        {
            // "encoding" ve "hash" parametrelerini hash hesaplamasından çıkar
            var hashParams = parameters
                .Where(p => !string.Equals(p.Key, "encoding", StringComparison.OrdinalIgnoreCase) &&
                           !string.Equals(p.Key, "hash", StringComparison.OrdinalIgnoreCase))
                .OrderBy(p => p.Key, StringComparer.OrdinalIgnoreCase)
                .ToList();

            // Hash string'i oluştur
            var hashParts = new List<string>();
            
            foreach (var param in hashParams)
            {
                // Parametre değerindeki özel karakterleri escape et
                var escapedValue = EscapeHashValue(param.Value ?? "");
                hashParts.Add(escapedValue);
            }

            // Sonuna storeKey ekle
            var hashString = string.Join("|", hashParts) + "|" + storeKey;

            // SHA-512 ile hash hesapla ve Base64 encode et
            using var sha512 = SHA512.Create();
            var hashBytes = sha512.ComputeHash(Encoding.ASCII.GetBytes(hashString));
            return Convert.ToBase64String(hashBytes);
        }

       

        /// <summary>
        /// Hash hesaplaması için parametre değerlerindeki özel karakterleri escape eder
        /// "|" -> "\|", "\" -> "\\"
        /// </summary>
        private static string EscapeHashValue(string value)
        {
            if (string.IsNullOrEmpty(value))
                return value;

            // Önce "\" karakterlerini "\\" olarak escape et
            value = value.Replace("\\", "\\\\");
            // Sonra "|" karakterlerini "\|" olarak escape et
            value = value.Replace("|", "\\|");
            
            return value;
        }