Merchant Identity Validation SSL/TLS Error

Hello All,


I was hoping someone here might be able to help with an issue I am having trying to validate the merchants identity for apple pay on the web.

Currently when I try to call the validation url that comes from the session.onvalidatemerchant event I get an error message saying "The request was aborted: Could not create SSL/TLS secure channel"


I call the validation url by passing to a C# .Net Framework 4.7.1 Web API. The API setups an HttpClient with the Merchant Identity Validation Certificate found in my apple account and calls the validation url passing in the required Json Validation Object. When I call PostAsync() I get an exception with the above error message (Please see code below for a clearer view of what I am doing).

I have done several searches all of which tell me to setup the ServerCertificateValidationCallback to always return or to setup the SecurityProtocol to be TLS12, both of which do not work for me. I am able to test this locally on my computer and from our development server, both of which have the Merchant Identity Validation Certificate installed and are setup to support SSL/TLS


Does anyone have any other idea what could be causing this error.


Thank you,

Josh


Please note that sending of the data to and from the Web api works fine I am able to get valid reponse and send requests to our API our issue is more in the API I am just showing JS code to help clearify where the data is coming from.

JS Code:

applePayRequest = {
     countryCode: 'US',
     currencyCode: 'USD',
     supportedNetworks: ['visa', 'masterCard', 'amex', 'discover'],
     merchantCapabilities: ['supports3DS'],
     total: {
          label: merchantInfo.MerchantName,
          amount: parseFloat(total).toFixed(2).toString()
     },
     lineItems: [{
          label: "TestOrder",
          type: "final",
          amount: parseFloat(total).toFixed(2).toString()
     }],
     supportedCountries: ['US'],
     requiredBillingContactFields: [],
     requiredShippingContactFields: [],
     shippingType: "shipping",
     shippingMethods: [],
}

var session = new ApplePaySession(3, applePayRequest);
session.onvalidatemerchant = function (event) {
     var applePayValidationRequest = {
          'display_name': displayname,
          'domain_name': domain,
          'validation_url': event.validationURL,
     };

     $.ajax({
          type: 'POST',
          url: "",
          data: JSON.stringify(applePayValidationRequest),
          contentType: 'application/json',
          dataType: 'json',
          success: function(response) { 
          console.log(JSON.stringify(response));
                    session.completeMerchantValidation(response);
          },
          error: function(status) {
               console.log(JSON.stringify(status));
               session.abort();
          }
     });
};


C# Web API Code:

protected ValidationResponse ValidateApplePay(ApplePayValidationRequestrequest)
{
ServicePointManager.ServerCertificateValidationCallback = 
     delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };

try
{
     X509Certificate2 identifierCert = null;
     X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
     store.Open(OpenFlags.ReadOnly);
     try
     {
          identifierCert = store.Certificates.Find(X509FindType.FindBySerialNumber, ApplePayCertificateSerialNumber, false)?.OfType().FirstOrDefault();
     }
     catch (Exception ex)
     {
         return null;//Actually returns error infomration
     }
     finally
     {
          store.Close();
     }
     
     if (identifierCert == null)
     {
          return null; //Actually returns error message
     }

     HttpClientHandler requestHandler = new HttpClientHandler();
     requestHandler.ClientCertificates.Add(identifierCert);

     var handler = new WebRequestHandler();
     handler.ClientCertificates.Add(identifierCert);

     //Set security protocol to TLS 1.2 only (REQUIRED by Apple Pay)
     ServicePointManager.Expect100Continue = true;
     ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

     using (var client = new HttpClient(requestHandler, true))
     {
          if (!Uri.TryCreate(appleRequest.ValidationURL, UriKind.Absolute, out Uri requestUri))
          {
               return null;//Returns error information
          }


          client.BaseAddress = requestUri;
          client.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
          client.DefaultRequestHeaders.Add("Keep-Alive", "36000");


          string identifier = string.Empty;
          try
          {
               // This OID returns the ASN.1 encoded merchant identifier
               X509Extension extension = identifierCert.Extensions[ApplePayCertificateExtensionIdentifier];
               if (extension == null)
               {
                    return null;//Returns error information
               }

               // Convert the raw ASN.1 data to a string containing the ID
               identifier = Encoding.ASCII.GetString(extension.RawData).Substring(2);
          }
          catch(Exception ex)
          {
               return null;//Returns error information
          }

          var jsonData = JsonConvert.SerializeObject(new {
               merchantIdentifier = identifier,
               domainName = appleRequest.DomainName,
               displayName = appleRequest.DisplayName,
          });

          using (var content = new StringContent(jsonData, Encoding.UTF8, "application/json"))
          {
               using (var response = client.PostAsync("paymentSession", content).Result)//Gives Could not create SSL/TLS secure channel
               {
                    var merchantSessionJson = response.Content.ReadAsStringAsync().Result;
                    var merchantSession = JObject.Parse(merchantSessionJson);

                    return new ApplePayValidationResponse()
                         {
                              Success = response.IsSuccessStatusCode,
                              ErrorCode = 0,
                              MerchantSession = merchantSession.ToString(Formatting.None),
                          };
                }
          }
     }
}
catch (Exception e)
{
     return null;//Return error information
}
}

Replies

Hi,

I am facing the exact same issue. Were you able to resolve this?

Thank you!

Hi, I faced with the same issue. I prepared a merchant ID, verified my domain, create a merchand identity cert and so on. I get the error: Could not create SSL/TLS secure channel. I have another merchant identity cert and domain and if I try it everything works. The same code and the different cert/merchant info pair. Why???