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
}
}