沙盒苹果支付测试握手失败
Sandbox apple pay testing handshake failure
我在 Apple Pay 沙箱环境中验证商家时遇到问题。取自 https://developer.apple.com/reference/applepayjs/applepaysession#2166532,一旦我的 server then calls the Start Session endpoint at the provided URL
,我得到一个 500 错误。
我查了一下,这个 500 错误发生在网络层的某个地方。正如苹果页面(https://developer.apple.com/reference/applepayjs/)所列,我需要满足以下要求:
- 所有包含 Apple Pay 的页面都必须通过 HTTPS 提供。 完成,服务器 ssl/https 全站
- 要启用商家验证,您的服务器必须允许通过 HTTPS(端口 443 上的 TCP)访问下面清单 1 中提供的 Apple Pay IP 地址。 完成,服务器对端口 443 上的所有 ips 开放
- 您的服务器必须支持传输层安全 (TLS) 1.2 协议和 Table 1 中列出的密码套件之一。服务器支持 tls 1.2,因为我在 tls 上发送请求1.2 到apple pay的开发服务器(下)
我一直在使用 Wireshark 检查发生了什么,一旦服务器发回密码规范后,服务器处于 ChangeCipherSpec 阶段,我似乎就失败了给客户。 (ssl 过程参考:https://support.f5.com/csp/article/K15292)。正如您从我的图像中看到的那样,我正在与 apple pay 沙箱服务器通信,传递错误提示的相同受支持的 tls 协议和密码套件 -> Handshake Failure (40)
,所以发生了其他事情,我不知道去哪里看
如果您查看 ServerHello 消息,您可以看到服务器找到并接受了与客户端匹配的密码套件,这也与 apple pay 支持的所需密码之一匹配
我可以根据需要添加其他详细信息
问题是我们的服务器没有默认启用 TLS 1.2。启用 TLS 1.2 并禁用 TLS 1.0 解决了这个问题 - Win 2008
编辑
有几件事需要发生。我们的服务器在 .net 4.5 上,默认情况下不使用 tls 1.2(苹果要求使用 tls 1.2)。因此,我们将解决方案升级到 .net 4.6,并针对我们的请求强制使用 tls 1.2。此外,我们必须在我们对苹果的请求中包含商家 ID 证书(文档中没有很好地提及)。
您可以找到我在此处使用的源代码的 github 存储库 (https://github.com/justeat/ApplePayJSSample),但这是我需要放入我的解决方案以使事情正常运行的代码(我也有从我的 mac 的钥匙串中导出我的商家证书,它给了我一个 .p12 文件。我将这个 .p12 文件导入到我服务器的 计算机 证书存储中)
[System.Web.Http.HttpPost]
public async Task<ContentResult> GetApplePaySession([FromBody] string url)
{
//
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// Load the merchant certificate for two-way TLS authentication with the Apple Pay server.
var certificate = LoadMerchantCertificate();
// Get the merchant identifier from the certificate to send in the validation payload.
var merchantIdentifier = GetMerchantIdentifier(certificate);
// Create the JSON payload to POST to the Apple Pay merchant validation URL.
var payload = new ApplePayRequest()
{
merchantIdentifier = merchantIdentifier,
domainName = System.Web.HttpContext.Current.Request.Url.Host,
displayName = "[display name from apple developer portal]"
};
JObject merchantSession;
// Create an HTTP client with the merchant certificate
// for two-way TLS authentication over HTTPS.
using (var httpClient = CreateHttpClient(certificate))
{
var jsonPayload = JsonConvert.SerializeObject(payload);
using (var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"))
{
// POST the data to create a valid Apple Pay merchant session.
using (var response = await httpClient.PostAsync(url, content))
{
response.EnsureSuccessStatusCode();
// Read the opaque merchant session JSON from the response body.
var merchantSessionJson = await response.Content.ReadAsStringAsync();
merchantSession = JObject.Parse(merchantSessionJson);
}
}
}
// Return the merchant session as JSON.
return Content(merchantSession.ToString(), "application/json");
}
#region Apple Pay helper methods
private X509Certificate2 LoadMerchantCertificate()
{
X509Certificate2 certificate;
// Load the certificate from the current user's certificate store. This
// is useful if you do not want to publish the merchant certificate with
// your application, but it is also required to be able to use an X.509
// certificate with a private key if the user profile is not available,
// such as when using IIS hosting in an environment such as Microsoft Azure.
using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadOnly);
// when using thumbprint from mmc, look at:
//
// there is a hidden character that you must delete
var certificates = store.Certificates.Find(
X509FindType.FindByThumbprint,
"[thumbprint]",
validOnly: false);
if (certificates.Count < 1)
{
throw new InvalidOperationException(
// ReSharper disable once UseStringInterpolation
string.Format(
"Could not find Apple Pay merchant certificate with thumbprint '{0}' from store '{1}' in location '{2}'.",
"[thumpprint]", store.Name, store.Location));
}
certificate = certificates[0];
}
return certificate;
}
private string GetMerchantIdentifier(X509Certificate2 certificate)
{
// This OID returns the ASN.1 encoded merchant identifier
var extension = certificate.Extensions["1.2.840.113635.100.6.32"];
// Convert the raw ASN.1 data to a string containing the ID
return extension == null ? string.Empty : Encoding.ASCII.GetString(extension.RawData).Substring(2);
}
private HttpClient CreateHttpClient(X509Certificate2 certificate)
{
var handler = new WebRequestHandler();
handler.ClientCertificates.Add(certificate);
return new HttpClient(handler, disposeHandler: true);
}
#endregion
我最近刚经历过这个。对我来说,我必须将 PEM 和 KEY 文件合并到 PFX 中。然后我能够 运行 使用 .net core 2.1
从 ubuntu 16.04 开始会话调用
private HttpClient CreateHttpClient()
{
var handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.SslProtocols = SslProtocols.Tls12;
handler.ClientCertificates.Add(new X509Certificate2(@"/path/yourcombinedpfx.pfx"));
return new HttpClient(handler); ;
}
我在 Apple Pay 沙箱环境中验证商家时遇到问题。取自 https://developer.apple.com/reference/applepayjs/applepaysession#2166532,一旦我的 server then calls the Start Session endpoint at the provided URL
,我得到一个 500 错误。
我查了一下,这个 500 错误发生在网络层的某个地方。正如苹果页面(https://developer.apple.com/reference/applepayjs/)所列,我需要满足以下要求:
- 所有包含 Apple Pay 的页面都必须通过 HTTPS 提供。 完成,服务器 ssl/https 全站
- 要启用商家验证,您的服务器必须允许通过 HTTPS(端口 443 上的 TCP)访问下面清单 1 中提供的 Apple Pay IP 地址。 完成,服务器对端口 443 上的所有 ips 开放
- 您的服务器必须支持传输层安全 (TLS) 1.2 协议和 Table 1 中列出的密码套件之一。服务器支持 tls 1.2,因为我在 tls 上发送请求1.2 到apple pay的开发服务器(下)
我一直在使用 Wireshark 检查发生了什么,一旦服务器发回密码规范后,服务器处于 ChangeCipherSpec 阶段,我似乎就失败了给客户。 (ssl 过程参考:https://support.f5.com/csp/article/K15292)。正如您从我的图像中看到的那样,我正在与 apple pay 沙箱服务器通信,传递错误提示的相同受支持的 tls 协议和密码套件 -> Handshake Failure (40)
,所以发生了其他事情,我不知道去哪里看
如果您查看 ServerHello 消息,您可以看到服务器找到并接受了与客户端匹配的密码套件,这也与 apple pay 支持的所需密码之一匹配
我可以根据需要添加其他详细信息
问题是我们的服务器没有默认启用 TLS 1.2。启用 TLS 1.2 并禁用 TLS 1.0 解决了这个问题 - Win 2008
编辑
有几件事需要发生。我们的服务器在 .net 4.5 上,默认情况下不使用 tls 1.2(苹果要求使用 tls 1.2)。因此,我们将解决方案升级到 .net 4.6,并针对我们的请求强制使用 tls 1.2。此外,我们必须在我们对苹果的请求中包含商家 ID 证书(文档中没有很好地提及)。
您可以找到我在此处使用的源代码的 github 存储库 (https://github.com/justeat/ApplePayJSSample),但这是我需要放入我的解决方案以使事情正常运行的代码(我也有从我的 mac 的钥匙串中导出我的商家证书,它给了我一个 .p12 文件。我将这个 .p12 文件导入到我服务器的 计算机 证书存储中)
[System.Web.Http.HttpPost]
public async Task<ContentResult> GetApplePaySession([FromBody] string url)
{
//
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// Load the merchant certificate for two-way TLS authentication with the Apple Pay server.
var certificate = LoadMerchantCertificate();
// Get the merchant identifier from the certificate to send in the validation payload.
var merchantIdentifier = GetMerchantIdentifier(certificate);
// Create the JSON payload to POST to the Apple Pay merchant validation URL.
var payload = new ApplePayRequest()
{
merchantIdentifier = merchantIdentifier,
domainName = System.Web.HttpContext.Current.Request.Url.Host,
displayName = "[display name from apple developer portal]"
};
JObject merchantSession;
// Create an HTTP client with the merchant certificate
// for two-way TLS authentication over HTTPS.
using (var httpClient = CreateHttpClient(certificate))
{
var jsonPayload = JsonConvert.SerializeObject(payload);
using (var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"))
{
// POST the data to create a valid Apple Pay merchant session.
using (var response = await httpClient.PostAsync(url, content))
{
response.EnsureSuccessStatusCode();
// Read the opaque merchant session JSON from the response body.
var merchantSessionJson = await response.Content.ReadAsStringAsync();
merchantSession = JObject.Parse(merchantSessionJson);
}
}
}
// Return the merchant session as JSON.
return Content(merchantSession.ToString(), "application/json");
}
#region Apple Pay helper methods
private X509Certificate2 LoadMerchantCertificate()
{
X509Certificate2 certificate;
// Load the certificate from the current user's certificate store. This
// is useful if you do not want to publish the merchant certificate with
// your application, but it is also required to be able to use an X.509
// certificate with a private key if the user profile is not available,
// such as when using IIS hosting in an environment such as Microsoft Azure.
using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadOnly);
// when using thumbprint from mmc, look at:
//
// there is a hidden character that you must delete
var certificates = store.Certificates.Find(
X509FindType.FindByThumbprint,
"[thumbprint]",
validOnly: false);
if (certificates.Count < 1)
{
throw new InvalidOperationException(
// ReSharper disable once UseStringInterpolation
string.Format(
"Could not find Apple Pay merchant certificate with thumbprint '{0}' from store '{1}' in location '{2}'.",
"[thumpprint]", store.Name, store.Location));
}
certificate = certificates[0];
}
return certificate;
}
private string GetMerchantIdentifier(X509Certificate2 certificate)
{
// This OID returns the ASN.1 encoded merchant identifier
var extension = certificate.Extensions["1.2.840.113635.100.6.32"];
// Convert the raw ASN.1 data to a string containing the ID
return extension == null ? string.Empty : Encoding.ASCII.GetString(extension.RawData).Substring(2);
}
private HttpClient CreateHttpClient(X509Certificate2 certificate)
{
var handler = new WebRequestHandler();
handler.ClientCertificates.Add(certificate);
return new HttpClient(handler, disposeHandler: true);
}
#endregion
我最近刚经历过这个。对我来说,我必须将 PEM 和 KEY 文件合并到 PFX 中。然后我能够 运行 使用 .net core 2.1
从 ubuntu 16.04 开始会话调用private HttpClient CreateHttpClient()
{
var handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.SslProtocols = SslProtocols.Tls12;
handler.ClientCertificates.Add(new X509Certificate2(@"/path/yourcombinedpfx.pfx"));
return new HttpClient(handler); ;
}