Search code examples
c#asp.net-core-mvc.net-6.0nopcommerce

"The SSL connection could not be established, see inner exception." For POST Request(.net 6)


First of all the title of the question may seem like a duplicate. But I tried all possible solutions at SO and nothing works. Most interestingly the same code is working for .net framework-4.x.

The certificate and the key is valid as the same code with same .crt and .key is working.

var certPath = _fileProvider.Combine(_fileProvider.MapPath("~/Plugins/Payments.CityBankApi/"), "othoba.crt");
var keyPath = _fileProvider.Combine(_fileProvider.MapPath("~/Plugins/Payments.CityBankApi/"), "othoba.key");
    
    
string certificateText = File.ReadAllText(certPath);
string privateKeyText = File.ReadAllText(keyPath);
    
    
    
ICertificateProvider provider = new CertificateFromFileProvider(certificateText, privateKeyText, true);
    
var certificate = provider.Certificate;
string accessTokenUrl = string.Empty;
accessTokenUrl = "https://sandbox.thecitybank.com:7788/transaction/token";
    
    
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(certificate);
handler.ServerCertificateCustomValidationCallback +=(sender, certificate, chain, errors) => {
                        return true;
                    };
string json = JsonConvert.SerializeObject(new
{
   userName = _cityBankPaymentSettings.UserName,
   password = _cityBankPaymentSettings.Password
});
var httpContent = new StringContent(json, Encoding.UTF8, "application/json");    
var client = new HttpClient(handler);
var result = client.PostAsync(accessTokenUrl, httpContent).GetAwaiter().GetResult();

Solution

  •           try
                {
                    var pfxPath = _fileProvider.Combine(_fileProvider.MapPath("~/Plugins/Payments.CityBankApi/"), "othoba.pfx");
                    var certPath = _fileProvider.Combine(_fileProvider.MapPath("~/Plugins/Payments.CityBankApi/SandBoxCrt/"), "othoba.crt");
                    var keyPath = _fileProvider.Combine(_fileProvider.MapPath("~/Plugins/Payments.CityBankApi/SandBoxCrt/"), "othoba.key");
    
    
                    string tokenUrl = "https://ecomm-webservice.thecitybank.com:7788/transaction/token";
                    string crtPassword = _cityBankPaymentSettings.CrtPasswordProduction;
    
                    if (!_cityBankPaymentSettings.ProductionMode)
                    {
                        tokenUrl = "https://sandbox.thecitybank.com:7788/transaction/token";
                        crtPassword = _cityBankPaymentSettings.CrtPasswordSandBox;
                        pfxPath = _fileProvider.Combine(_fileProvider.MapPath("~/Plugins/Payments.CityBankApi/SandBoxCrt/"), "createorder.pfx");
                        certPath = _fileProvider.Combine(_fileProvider.MapPath("~/Plugins/Payments.CityBankApi/SandBoxCrt/"), "createorder.crt");
                        keyPath = _fileProvider.Combine(_fileProvider.MapPath("~/Plugins/Payments.CityBankApi/SandBoxCrt/"), "createorder.key");
    
                    }
    
                    var certificate = await LoadPemCertificate(certPath, keyPath);
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
                    var handler = new HttpClientHandler();
                    handler.ClientCertificates.Add(certificate);
                    handler.ServerCertificateCustomValidationCallback = (e, r, c, n) => true;
    
                    string json = JsonConvert.SerializeObject(new
                    {
                        userName = _cityBankPaymentSettings.UserName,
                        password = _cityBankPaymentSettings.Password
                    });
                    var httpContent = new StringContent(json, Encoding.UTF8, "application/json");
                    var client = new HttpClient(handler);
                    var result = await client.PostAsync(tokenUrl, httpContent);
                    var jsonString = await result.Content.ReadAsStringAsync();
                    cityBankAccessToken = JsonConvert.DeserializeObject<CityBankAccessTokenResponeModel>(jsonString);
    
                    await _logger.InformationAsync("cityBankAccessToken:" + cityBankAccessToken);
    
                }
                catch (Exception ex)
                {
                    await _logger.ErrorAsync("CityResponseAccessTokenExc:" + ex.Message, ex);
                }
    

    Load Certificate method.

      public async Task<X509Certificate2> LoadPemCertificate(string certificatePath, string privateKeyPath)
            {
                using var publicKey = new X509Certificate2(certificatePath);
    
                var privateKeyText = await File.ReadAllTextAsync(privateKeyPath);
                var privateKeyBlocks = privateKeyText.Split("-", StringSplitOptions.RemoveEmptyEntries);
                var privateKeyBytes = Convert.FromBase64String(privateKeyBlocks[1]);
                using var rsa = RSA.Create();
    
                if (privateKeyBlocks[0] == "BEGIN PRIVATE KEY")
                {
                    rsa.ImportPkcs8PrivateKey(privateKeyBytes, out _);
                }
                else if (privateKeyBlocks[0] == "BEGIN RSA PRIVATE KEY")
                {
                    rsa.ImportRSAPrivateKey(privateKeyBytes, out _);
                }
    
                var keyPair = publicKey.CopyWithPrivateKey(rsa);
                var Certificate = new X509Certificate2(keyPair.Export(X509ContentType.Pfx));
    
                return Certificate;
            }
    

    For Linux(Ubuntu 20.04)

    Adding this to the top of /etc/ssl/openssl.cnf:
    
    openssl_conf = default_conf
    and this to the bottom of it:
    
    [default_conf]
    ssl_conf = ssl_sect
    
    [ssl_sect]
    system_default = system_default_sect
    
    [system_default_sect]
    MinProtocol = TLSv1.2
    CipherString = DEFAULT:@SECLEVEL=1
    

    helpful link