遵守强客户身份验证法规
了解在线信用卡支付的身份验证规则。
概述
监管机构和卡组织正在推出新的要求,以加强在线支付的安全性,保护消费者免受欺诈。这些法规中有很多都要求对在线支付使用强客户认证 (SCA)。
- **欧洲:**修订后的支付服务指令(PSD2)要求在线支付交易使用强客户认证(SCA),但特定豁免或 out-of-scope 情况除外。
- 日本: 日本的 SCA 强制要求对在线信用卡交易使用 3D Secure (3DS) 认证,但某些交易类型除外。
3D Secure 2 (3DS 2.0) 是由 EMVCo 和卡支付处理行业共同开发的一项技术,旨在确保合规性,同时兼顾安全性和流畅的结账体验。Rapid API 中使用的 3DS 2.0 解决方案符合强客户认证 (SCA) 法规。
本页面解释了受支持的 Rapid API 付款类型如何受到影响,以及在为旅客提供服务时,您可以采取哪些措施来遵守相关规定。
合规性要求
在需要 SCA 的国家/地区,实现合规交易的步骤会因记录商户是谁以及如何向 Rapid API 付款而有所不同。
当您的组织是登记商户时
Expedia 联盟伙伴收款
使用 Expedia Affiliate Collect 的预订不受 SCA 法规的影响。无需对 Rapid API 的支付流程或 API 集成进行任何更改即可达到合规性。
但是,如果您是登记商户,并且向旅行者的信用卡、借记卡或其他属于 SCA 法规范围的支付方式收费,则您可能会受到这些法规的影响。相关规定可能要求在支付过程中使用 3DS 2.0 作为 SCA-compliant 解决方案。请联系您的支付处理商,了解他们如何帮助商家达到 SCA 合规要求并避免交易失败。
公司卡
如果贵公司是账面商户,并且使用在实行 SCA 强制规定的国家/地区发行的信用卡或借记卡支付 Rapid API,则这些卡类型可免于 SCA 要求:
- 一次性虚拟信用卡
- 公司信用卡是发给贵公司的,而不是发给个人的。
如果列出的 SCA-exempt 卡不是您的首选,您的组织可以直接向发卡银行申请豁免。如果获得豁免,该卡上的交易将不需要身份验证,但可能需要使用 3DS 2.0 进行 one-time 在线验证。此 one-time 要求可能因银行而异。请注意,获得豁免可能是一个漫长的过程,这也意味着您的银行可能会要求您承担所有欺诈性付款的负责。
当 Rapid API 是记录商户时
如果贵公司使用 Rapid API 作为记录商户,并通过 Rapid 发送旅行卡,则可能会受到相关法规的影响。当旅客在线预订,而没有通过零售代理时,相关规定要求旅客通过强客户认证 (SCA) 对支付交易进行身份验证。针对此要求,SCA-compliant 流程是在支付过程中使用 3DS 2.0。如果您的组织希望使用 Rapid API 作为在有 SCA 强制要求的国家/地区发行的任何信用卡或借记卡的记录商户,则需要采用我们的 SCA 解决方案。
通过零售代理商或呼叫中心代理商预订的交易可免于 SCA 要求。只需明确表明预订是在客服的协助下进行,这些交易即合规。可使用房态 API 的 sales_channel 字段表明此情况。
当该房产是登记在册的商家时
如果贵公司采用财产回收方式,则可能会受到相关法规的影响。有些情况下,酒店可能会在旅客不在场的情况下尝试从旅客的信用卡中扣款,例如收取“未入住”费用或押金。这些费用不是 SCA-compliant,因为在收费之前没有进行 3DS 2.0 身份验证。如果您的组织希望对使用在有 SCA 强制要求的国家/地区发行的任何信用卡或借记卡的旅客使用财产收取功能,则需要采用我们的 SCA 解决方案。
Rapid API 解决方案
如何操作
如果您使用 Rapid API 作为记录商户,或者使用旅客卡进行物业收款,您可以采用 Rapid 的 API 解决方案来生成符合 SCA 法规的预订。我们的 API 通过在预订流程中使用 3DS 2.0 来支持 SCA 合规性。3DS 2.0 支持 risk-based 身份验证,通过赋予银行何时要求旅客进行安全身份验证的自主权,减少了旅客的摩擦。
3DS 2.0 的解决方案包含三个不同的步骤:
- 您将向用于托管发卡银行为旅行者提供的身份验证体验的 check-out 页面添加一个 iframe。在集成文档中,这被称为 3DS iframe。
- 您还将在 client-side JavaScript 页面中包含一个新的库,用于收集浏览器数据、与 iframe 通信以及在 iframe 中显示 SCA 体验。在集成文档中,这被称为 3DS 连接器库。
- Rapid API 将接受银行的付款人信息,并在安全认证完成后完成预订。
当同时使用 JavaScript 和 Rapid API 时,使用 SCA 的预订流程现在将在调用 Booking API 之前和之后增加一些步骤。下图描绘了这个更新后的预订流程。

在修订后预订流程的每个步骤中,一个步骤的输出中包含着用作下一步输入的数据。数据将需要在浏览器上的 JavaScript 和 Rapid 之间传递。
注:上图是实际 API 的简化流程,旨在用于介绍。请参考集成文档,了解有关完整 API 流程的更多信息。
集成组件详细信息
浏览器内嵌框架
放置在 check-out 体验中的 iframe 托管了旅行者的 card-issuing 银行拥有的 URL。此 URL 将向用户显示身份验证体验,并将任何 traveler-supplied 信息直接传输到他们的银行。Iframe 最初应该隐藏,但在预订尝试后需要进行身份验证时,可以将其覆盖在页面上方。
浏览器 JavaScript 库
该库已添加到 check-out 页面,并在预订时调用以支持身份验证过程。该库的 API 支持下述功能。
自动收集旅客的设备信息
在尝试预订之前,必须收集有关旅行者设备的信息,以便准备预订进行身份验证。该信息将发送到旅行者的 issuing-bank 进行审核,以便银行评估风险,决定交易是否需要 3DS 2.0 认证,并确保其正确显示。根据 3DS 2.0 规范,将从旅行者的浏览器收集以下数据:语言、颜色深度、屏幕高度、屏幕宽度、时区、用户代理以及是否启用 Java。
在浏览器 iframe 中显示身份验证体验
尝试预订后,该库用于显示内嵌框架覆盖并将银行的内容加载到内嵌框架中。在身份验证过程中,银行可能会收集有关旅行者设备的其他信息,以支持其风险评估。完成预订需要此流程。
Rapid API
Rapid API 包含与 client-side JavaScript 库协同工作的 API。这些 API 现在支持下述功能。
旅客及付款详情注册
在尝试预订之前,必须收集有关旅行者的其他信息,以便准备预订进行身份验证。这些数据包括旅客在销售网站的账户和旅客付款的详细信息,之后,这些数据会发送到旅行者的 issuing-bank 进行审核,以便银行评估风险并决定交易是否需要安全认证。了解更多信息,请查看注册支付 API,它是以下组件的一部分:快速预订 API。
完成付款和确认预订
使用 Rapid API 进行预订尝试后,浏览器上的 SCA 流程已完成,必须再次调用 Rapid。在后台,我们会确认身份验证是否成功,以便确认预订。请查看“完整付款流程”了解更多信息。快速预订 API。
预订流程
如果在合作伙伴配置文件快速支持中启用了 3DS 2.0,则价格查询API 将返回一个链接注册付款使用 API 而不是创建预订 API。以下是旅客发起预订后所需的 API 调用序列图。该序列涉及对 JavaScript 库和 Rapid 的调用。

准备进行身份验证的预订信息可能并非总是需要验证的。是否需要进行身份验证由用于支付的信用卡的发卡银行决定。此判断是在交易过程中进行的,并在创建预订 API 响应中指示。
以下是使用保留与继续功能时所需的 API 调用序列图。

注:上图是实际 API 的简化流程,旨在用于介绍。请参考集成文档,了解有关完整 API 流程的更多信息。
有关 3DS 2.0 体验的技术要求的更多信息,请查看 EMVCo 的3D 安全协议和核心功能规范。
Rapid API 和 3DS 2.0 集成指南
支持 SCA 将需要将 Rapid API 与新的 JavaScript 库(称为 3DS 连接器)集成。两者结合使用,可在 check-out 页面上显示 3DS 2.0 并确认预订。这种解决方案同时支持预付和住宿收款业务模式。
以下概述了使用 3DS 2.0 进行预订所需的 API 调用顺序,并在以下各节中详细说明:
- JavaScript 设置方法
- Rapid 注册付款信息 API
- JavaScript 初始化会话方法
- Rapid 预订 API
- JavaScript challenge 方法
- Rapid 完成付款 API
要实现此序列,必须由 Rapid Partner Support 为各个合作伙伴配置文件启用 3DS 2.0。
Rapid API
如果为合作伙伴配置文件启用身份验证,API 响应将有所不同,以便使用 3DS 2.0 实现修订后的预订流程。
可用性 API
API 请求中的 sales_channel字段的值必须准确,才能在法规允许的情况下获得身份验证豁免。该数值以及许多其他因素,都会由发卡银行在预订时进行审核并做出决定。只有代理工具可以免于 SCA 的约束。要指明这一点,请将 sales_channel 的值设置为 agent_tool。
价格检查 API
API 响应将包含指向注册付款信息 API 而不是创建预订 API 的链接。
启用 3DS 2.0 时的示例响应:
{
"status": "matched",
"occupancies": {
//...(example omitted for length)
},
"links": {
"payment_session": {
"method": "POST",
"href": "/v3/payment-sessions?token=QldfCGlcUAVgBDRwdWXBBL"
}
}
}注册付款信息 API
这将是 SCA 预订流程中的第二步,发生在 JavaScript setup方法之后。
该请求将包含 non-SCA 预订流程中的付款详情以及支持成功身份验证的新字段。其中两个字段 encoded_browser_metadata 和 version 是从 JavaScript API 的 setup method 返回的。
响应将包含 payment_session_id 和 encoded_init_config。这些被指定为 JavaScript 库 initSession 方法的输入。响应中包含的 Booking 链接应在 initSession方法之后使用。
示例请求:
{
"version": "1",
"browser_accept_header": "*/*",
"encoded_browser_metadata": "ZW5jb2RlZF9icm93c2VyX21ldGFkYXRh",
"preferred_challenge_window_size": "medium",
"merchant_url": "https://server.adomainname.net",
"customer_account_details": {
"authentication_method": "guest",
"authentication_timestamp": "2018-02-12T11:59:00.000Z",
"create_date": "2018-09-15",
"change_date": "2018-09-17",
"password_change_date": "2018-09-17",
"add_card_attempts": 1,
"account_purchases": 1
},
"payments": [
{
"type": "customer_card",
"card_type": "VI",
"number": "4111111111111111",
"security_code": "123",
"expiration_month": "08",
"expiration_year": "2025",
"billing_contact": {
"given_name": "John",
"family_name": "Smith",
"email": "smith@example.com",
"phone": "4875550077",
"address": {
"line_1": "555 1st St",
"line_2": "10th Floor",
"line_3": "Unit 12",
"city": "Seattle",
"state_province_code": "WA",
"postal_code": "98121",
"country_code": "US"
}
},
"enrollment_date": "2018-09-15"
}
]
}响应示例:
{
"payment_session_id": "76d6aaea-c1d5-11e8-a355-529269fb1459",
"encoded_init_config": "QSBiYXNlNjQgZW5jb2RlZCBvYmplY3Qgd2hpY2ggY29udGFpbnMgY29uZmlndXJhdGlvbiBuZWVkZWQgdG8gcGVyZm9ybSBkZXZpY2UgZmluZ2VycHJpbnRpbmcgYW5kL29yIDNEUyBNZXRob2Qu",
"links": {
"book": {
"method": "POST",
"href": "/v3/itineraries?token=MY5S3j36cOcLfLBZjPYQ1abhfc8CqmjmFVzkk7euvWaunE57LLeDgaxm516m"
}
}
}创建预订 API
这将是 SCA 预订流程中的第四步,发生在 JavaScript initSession方法之后。该请求不会包含任何新的 SCA 字段——所有必要的信息都包含在注册付款 API 返回的预订链接的令牌中。如果成功,响应将始终包含 itinerary_id。然而,仅凭这一点并不能表明预订已确认,因为可能需要 3DS 2.0 认证。
如果需要,回复中还会包含一个encoded_challenge_config。注册付款返回的 encoded_challenge_config 和 payment_session_id 将需要作为参数传递给 JavaScript challenge 方法。
响应还将包含一个 complete_payment_session 的新链接。此链接应在 JavaScript 库的 challenge 方法之后使用。
如果不需要 3DS 2.0 认证,则预订将被确认,响应将包含 retrieve、cancel 和(可选的)resume 的链接。
示例:如果需要 3DS 2.0 身份验证,请创建预订响应:
{
"itinerary_id": "8999989898988",
"links": {
"complete_payment_session": {
"method": "PUT",
"href": "/v3/itineraries/8999989898988/payment-sessions?token=MY5S3j36cOcLfLBZjPYQ1abhfc8CqmjmFVzkk7euvWaunE57LLeDgaxm516m"
}
},
"encoded_challenge_config": "ABElifsiejfacies2@033asfe="
}完成付款会话 API
这将是 SCA 预订流程中的第六步,发生在 JavaScript challenge方法之后。此 API 用于完成支付并通知 Rapid API 安全身份验证尝试已完成(成功或失败)。
该请求不会包含任何新的 SCA 字段。
如果成功,响应将包含预订的确认信息,包括 itinerary_id和 retrieve、cancel 以及(可选的)resume 的链接。
响应示例:
{
"itinerary_id": "8999989898988",
"links": {
"retrieve": {
"method": "GET",
"href": "/v3/itineraries/8999989898988?token=MY5S3j36cOcLfLBZjPYQ1abhfc8CqmjmFVzkk7euvWaunE57LLeDgaxm516m"
}
}
}Iframe 和 JavaScript 库实现
使用 SCA 预订工作流程时,check-out 页面必须包含一个新的 iframe 和 JavaScript 库。该 iframe,即 3DS iframe,将使用 3D-Secure 2.0 显示身份验证体验。JavaScript 库又称 3DS 连接器库,将支持向发卡银行传输信息并将银行的内容加载到内嵌框架。
添加 iframe
应将 3DS 内嵌框架包装在一个容器中,最初为隐藏状态,但在需要身份验证挑战以处理付款时可以显示。
容器的设计可以自定义,以适应托管页面需求。以下例子展示了一个使用 bootstrap 模式窗口的实施示例,仅作参考。
<div id="threeDsIframeModal" class="modal" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body iframe-container">
<div class="embed-responsive embed-responsive-16by9">
<iframe id="threeDsIframe" src="<<3DS iframe URL>>"> </iframe>
</div>
</div>
</div>
</div>
</div>内嵌框架的源必须设置为以下两个值之一:
| URL 类型 | URL | 备注 |
|---|---|---|
| 生产 | https://static.pay.expedia.com/3ds/threeDsIframe.html | 支持生产环境身份验证 |
| 测试沙盒 | https://static.pay.expedia.com/3ds/sandboxThreeDsIframe.html | 支持身份验证测试 |
测试 URL 为测试提供支持,本文档后面会回顾此主题。为了在测试期间限制 iframe 的内容,可以给 iframe 设置沙箱机制,但必须允许以下操作:
sandbox = 'allow-scripts allow-forms allow-same-origin';添加 JavaScript 库
3DS 连接器库与 3DS 内嵌框架通信并将数据发送到提供内嵌框架内容的发卡银行。下面的例子展示了如何将库添加到付款页面的示例。
<head>
<script src="<<3DS connector script URL>>" integrity="<<actual integrity value>>"></script>
</head>脚本元素的源值和完整性值应设置为以下值。
| 库版本 | 属性 | 值 |
|---|---|---|
| 1.3.39 | src | https://static.pay.expedia.com/3ds/1.3.39/pay-3ds-js-libs-connector.min.js |
| integrity | sha384-par0I4Q5cfljwzqw2mAggM4dKdYzGyj4uZiL4cMviGjI3qVzEgWGuZ2075mYutbT | |
| 1.3.65 | src | https://static.pay.expedia.com/3ds/1.3.65/pay-3ds-js-libs-connector.min.js |
| integrity | sha384-gYopPw6xE5DZwnZXGavkwnvs3NkDOobnHqjroUnSHpGXvs/J9xjHX/8aGzKtSgWI |
**注意:**随着未来版本的发布,源 URL 和完整性将会发生变化。较新的版本应该不会破坏现有的集成。较旧版本的脚本仍然可以访问。
使用 3DS 和 JavaScript 进行 SCA
库需要使用 JavaScript Promises。下面的例子展示了一个仅供参考的实施示例,演示了数据是如何在 JavaScript 方法和 Rapid 之间交换的。
// Initialize the library
let connector = new PayThreeDSConnector.ThreeDSConnector("threedsiframe", "https://static.pay.expedia.com");
RapidIntegration.priceCheck(priceCheckLink)
.then(priceCheckResponse => {
paymentSessionLink = priceCheckResponse.links.payment_session.href;
// Setup an authentication session with the library
return connector.setup({ referenceId: ’1000’ })
}).then(setupResponse => {
console.log("Setup Response: ", setupResponse);
// Send information from setup to Rapid’s Register Payments API
return RapidIntegration.registerPayment(paymentSessionLink,
setupResponse);
}).then(paymentSessionResponse => {
console.log("Register Payments Response: ", paymentSessionResponse);
paymentSessionId = paymentSessionResponse.paymentSessionId;
bookLink = paymentSessionResponse.links.book.href;
if (paymentSessionResponse.encoded_init_config) {
// If the payment session response contains an encoded_init_config
// field, initialize an authentication session with the library
// using information returned from Rapid’s Register Payments API
connector.initSession({
paymentSessionId: paymentSessionId,
encodedInitConfig: paymentSessionResponse.encodedInitConfig
}).then(initSessionResponse => {
console.log("Init Session Response: ", initSessionResponse);
// Then create a booking with Rapid’s Book API
return RapidIntegration.createBooking(bookLink,
paymentSessionId);
})
} else {
// Otherwise, create a booking with Rapid’s Book API directly
return RapidIntegration.createBooking(bookLink, paymentSessionId);
}
}).then(createBookingResponse => {
console.log("Create Booking Response: ", createBookingResponse);
itineraryId = createBookingResponse.itinerary_id;
if (createBookingResponse.encoded_challenge_config) {
// If the Create Booking API contains an encoded_challenge_config field,
// display the authentication challenge window
$(’#threeDsIframeModal).modal(’show’);
completePaymentSessionLink = createBookingResponse.links.complete_payment_session.href;
// Perform the challenge using the information returned from Rapid’s Register Payments API
// and Create Booking API
connector.challenge({
paymentSessionId: paymentSessionId,
encodedChallengeConfig: createBookingResponse.encodedChallengeConfig
}).then(challengeResponse => {
console.log("Challenge Response: ", challengeResponse);
// Complete a booking with Rapid’s Complete Payment Session API
return RapidIntegration.completePaymentSession(completePaymentSessionLink, itineraryId);
}).then(completePaymentSessionResponse => {
console.log("Complete Payment Session Response: ", completePaymentSessionResponse);
return completePaymentSessionResponse;
}).finally(() => {
// Close the authentication challenge window
$(’#threeDsIframeModal’).modal(’hide’);
});
} else {
return createBookingResponse;
}
}).then(bookingResponse => {
...
});注:对 RapidIntegration 类的引用是示例的一部分,而不是 3DS 连接器库的一部分,旨在演示支持将信息传输到 API 的包装器。
此例子对应在运行时确定的参数使用了静态值,例如:referenceId
Check-out 页面设计指南
支持 3DS 认证的卡片品牌可能会要求按照其指南展示其标志和品牌标识。
| 信用卡品牌 | 认证品牌 | 徽标和指南 |
|---|---|---|
| 万事达卡 | Mastercard identity check | https://brand.mastercard.com/debit/mastercard-brand-mark/downloads.html |
| 维萨卡 | Visa secure | https://www.merchantsignage.visa.com/brand_guidelines |
注:其他信用卡品牌的徽标和指南一旦可用即将包含在内。
3DS 连接器 JavaScript 库文档
类:ThreeDSConnector
构造函数: new ThreeDSConnector(threeDsIFrameId, threeDsIFrameOrigin)
参数:
| 名称 | 类型 | 说明 |
|---|---|---|
threeDsIFrameId | 字符串 | 3DS 内嵌框架的 ID。 |
threeDsIFrameOrigin | 字符串 | 3DS 内嵌框架的源。用于在与 3DS 内嵌框架通信时以传出窗口消息为目标和筛选传入消息。 |
设置
通过收集后端 3DS 服务所需的浏览器基本信息(例如屏幕尺寸、颜色深度等)来设置支付会话。
方法签名: setup(setupRequest)
参数:
| 名称 | 类型 |
|---|---|
setupRequest | SetupRequest |
返回: 承诺 SetupResponse
初始化
初始化 3DS 身份验证会话。作为初始化的一部分,可能会从浏览器收集其他数据。如果发卡机构要求,可以将 3DS 方法 URL 加载到内嵌框架中,以使发卡机构的访问控制服务器能够直接从浏览器收集数据。客户端不需要等待调用完成回调,就可以创建订单。
方法签名: initSession(initSessionRequest)
参数:
| 名称 | 类型 |
|---|---|
initSessionRequest | InitSessionRequest |
返回: 承诺 InitSessionResponse
挑战
如果发卡机构要求,请加载 3DS 身份验证体验。
方法签名: challenge(challengeRequest)
参数:
| 名称 | 类型 |
|---|---|
challengeRequest | ChallengeRequest |
返回: 承诺 ChallengeResponse
类:SetupRequest
设置调用的请求结构。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
referenceId | string | 用于标识旅客付款会话的参考 ID。用于记录和跟踪。使用下划线连接您的 APIKey 和 Customer-Session-ID。示例:[APIKey]_[SessionID] |
类:SetupResponse
来自设置调用的响应。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
version | 字符串 | 此库的版本,与库的 URL 路径中显示的版本相同。 |
encodedBrowserMetadata | 字符串 | 包含收集的浏览器详细信息的编码对象。客户端应将此视为不公开数据,无需解析即可传递给后端付款服务。 |
类:InitSessionRequest
initSession 方法的请求结构。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
paymentSessionId | 字符串 | Rapid 注册付款信息 API 返回的唯一 ID。 |
encodedInitConfig | 字符串 | 包含初始化所需数据的配置对象的编码列表,由 Rapid 注册付款信息 API 返回。 |
类:InitSessionResponse
initSession 方法的响应结构。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
statusCode | 字符串 | initSession 调用的状态。 |
message | 字符串 | 可选。指明失败原因。 |
statusCode 的可能值:
| 值 | 说明 |
|---|---|
SUCCESS | 初始化成功完成。 |
SKIPPED | 没有进行初始化。 |
FAILED | 初始化失败。消息字段包含有关失败的其他信息。 |
TIMEOUT | 初始化未在有效时间内完成。超时持续时间为 10 秒。 |
注意:对于所有 initSessionresponse statusCode值,请使用 Rapid Booking API 继续。
类:ChallengeRequest
挑战方法的请求结构。
属性:
| statusCode 值 | 测试 encoded_Challenge_config 值 | 说明 |
|---|---|---|
| SUCCESS | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlNVQ0NFU1MifV0 | 没有用户内嵌框架互动 |
| SUCCESS/FAILED | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlNIT1cifV0 | 没有用户内嵌框架互动 |
| FAILED | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIkZBSUxFRCJ9XQ | 没有用户内嵌框架互动 |
| TIMEOUT | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlRJTUVPVVQifV0 | |
| ERROR | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmdlT3V0cHV0Q29uZmlnIjogIkVSUk9SIn1d |
statusCode 的可能值
| 值 | 说明 |
|---|---|
SUCCESS | 3DS 挑战成功完成。 |
SKIPPED | 外部应用程序错误。 |
FAILED | 由于持卡人无法正确响应身份验证挑战,3DS 挑战未成功完成。 |
TIMEOUT | 挑战未在有效时间内完成。超时持续时间为 1200 秒。 |
注意:对于所有 challengeResponse statusCode值,请使用 Rapid API 完成支付会话。
使用 Rapid API 和 3DS 2.0 进行测试
您可以使用与 API 支持的特定场景相对应的输入参数值来测试您与 Rapid API 和 3DS 连接器方法的集成。
Rapid API
要测试 Rapid API,请添加一个名为 Rapid API 的额外 HTTP 标头。test在 HTTP 请求中,使用该 API 支持的值之一来测试受支持的场景。
在 SCA 预订流程中,也可以使用来自 Rapid API 的测试响应来测试 3DS 连接器库方法。
注册付款
以下测试标头值会在 API 响应中产生不同的 encoded_init_config 值和不同的 HTTP 响应代码。encoded_init_config 可以传递到 JavaScript 库的 initSession 调用中,以触发 3DS 连接器库中的不同测试案例。
| 测试标头值 | HTTP 代码和响应 | initSession 测试案例 |
|---|---|---|
standard | 201 – Standard Response | SUCCESS |
init_skip | 201 - Response Without encodedInitConfig | Not supported |
init_fail | 201 – Standard Response | FAILED |
init_timeout | 201 – Standard Response | TIMEOUT |
internal_server_error | 500 – Internal Server Error | |
internal_server_error | 503 - Server Unavailable |
注:3DS 连接器 Library.t_config 中不同的 init_skip 测试案例可以传递给 initSession 并强制执行 SKIPPED 的 statusCode。
创建预订
除了在以下文件中定义的测试标头之外:快速预约测试申请对于 non-SCA 预订流程,SCA 工作流支持额外的测试标头值。
测试标头值会产生不同的 encodedChallengeConfig 值,这些值可以传递至 JavaScript 库的 challenge 调用中,以触发不同的测试案例。
| 测试标头值 | HTTP 代码和响应 | initSession 测试案例 |
|---|---|---|
complete_payment_session | 201 – Response with complete payment session link | SUCCESS without user iframe interaction |
complete_payment_session_show | 201 – Response with complete payment session link | SUCCESS/FAILED with user iframe interaction |
complete_payment_session_fail | 201 – Response with complete payment session link | FAILED without user iframe interaction |
complete_payment_session_timeout | 201 – Response with complete payment session link | TIMEOUT |
complete_payment_session_error | 201 – Response with complete payment session link | ERROR |
完成付款会话
测试标头值会产生不同错误案例,可能会在尝试完成付款和确认预订时发生。
| 测试标头值 | HTTP 代码和响应 |
|---|---|
payment_declined | 400 - Payment declined response |
price_mismatch | 409 - Price mismatch response |
rooms_unavailable | 410 - Rooms unavailable response |
3DS 连接器库和内嵌框架
要在没有外部依赖因素的情况下测试 3DS 连接器,特定的参数值应对应于支持的方法响应。仅当内嵌框架使用测试沙盒 URL 加载时才支持此行为。
初始化会话
InitSessionResponse statusCode 的受支持值可以通过改变 initSessionRequest encodedInitConfig 来进行测试。
| statusCode 值 | 测试 encodedInitConfig 值 |
|---|---|
| SUCCESS | W3sicHJvdmlkZXJJZCI6IDAsICJz YW5kYm94SW5pdE91dHB1dENvbmZpZyI6ICJTVUNDRVNTIn1d |
| FAILED | W3sicHJvdmlkZXJJZCI6IDAsICJz YW5kYm94SW5pdE91dHB1dENvbmZpZyI6ICJGQUlMRUQifV0= |
| TIMEOUT | W3sicHJvdmlkZXJJZCI6IDAsICJz YW5kYm94SW5pdE91dHB1dENvbmZpZyI6ICJUSU1FT1VUIn1d |
| SKIPPED | 目前不支持。 |
注:encoded_init_config 值也可以使用注册付款信息 API 的受支持测试标头生成。
挑战
challengeResponse statusCode 的受支持值可以通过改变 challengeRequest encondedChallengeConfig 来进行测试。
| statusCode 值 | 测试 encoded_Challenge_config 值 | 说明 |
|---|---|---|
| SUCCESS | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlNVQ0NFU1MifV0 | 没有用户内嵌框架互动 |
| SUCCESS/FAILED | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlNIT1cifV0 | 没有用户内嵌框架互动 |
| FAILED | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIkZBSUxFRCJ9XQ | 没有用户内嵌框架互动 |
| TIMEOUT | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlRJTUVPVVQifV0 | |
| ERROR | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmdlT3V0cHV0Q29uZmlnIjogIkVSUk9SIn1d |
这encodedInitConfig也可以使用 Booking API 的 SCA 流程支持的测试标头生成值。
注意:当根据 iframe 中的用户输入测试挑战状态代码值为 SUCCESS 或 FAILED 时,挑战方法响应将等待 iframe 中模拟身份验证界面的完成。
3DS 内嵌框架中的 UI 示例:

示例用法
以下例子展示了一个实施示例,仅作参考。该例子演示了如何使用预定义的参数值来针对 3DS 挑战对库进行测试,而无需用户与内嵌框架互动。
var c = new PayThreeDSConnector.ThreeDSConnector(’threedsiframe’, ’https://static.pay.expedia.com’); // change to match the 3DS iframe ID
c.setup({ referenceId: ’1000’ })
.then((setupResponse) => {
console.log(’Setup Output: ’, setupResponse);
return c.initSession({
paymentSessionId: 1,
encodedInitConfig: ’ W3sicHJvdmlkZXJJZCI6IDAsICJzYW5kYm94SW5pdE91dHB1dENvbmZpZyI6ICJTVUNDRVNTIn1d’,
}); // SUCCESS
})
.then((initResponse) => {
console.log(’InitSession Output: ’, initResponse);
$(’#threedsIframeModal’).modal(); // replace with code to show the modal containing the 3DS iframe
return c.challenge({
paymentSessionId: 1,
encodedChallengeConfig:
’ W3sicHJvdmlkZXJJZCI6IDAsICJzYW5kYm94Q2hhbGxlbmdlT3V0cHV0Q29uZmlnIjogIlNVQ0NFU1MifV0=’,
}); // SUCCESS
})
.then((challengeResponse) => {
console.log(’Challenge Output: ’, challengeResponse);
})
.finally(() => {
$(’#threedsIframeModal’).modal(’hide’); // replace with code to hide the modal containing the 3DS iframe
});3DS 认证和房产收集
使用 property collect 预订时,Expedia 不会从卡中扣款。相反,我们会将其送至物业进行处理。住宿可能会在客户入住前使用此信息验证卡。旅客需亲自前往 check-in 付款。
但是,有时旅客无法办理入住,住宿可能会收取预订后未入住费用。这些费用可能会受到强客户认证 (SCA) 法规的影响,因为它们涉及在旅行者不在场的情况下从信用卡扣款。
如果交易受到影响,付款可能会失败,如果收费不符合规定,住宿也可能会面临信用卡品牌方的处罚。
为了保护我们与住宿之间的关系并继续为我们的合作伙伴服务,Expedia Group 为住宿提供了一条可选的合规途径。受影响的物业现在可以利用 Expedia Group 代表其提供身份验证。这样一来,物业就能保护自己的业务,并确保 Rapid API 能够继续提供同样多样化的物业。
Rapid API 提供标志<payment_registration_recommended=true>在“物业内容文件”和“物业内容”中,可以帮助您识别可能与项目相关的物业。
对整合的潜在影响
如果您想提供需要安全身份验证的房源,那么预订流程应该支持 3DS。如果不支持 3DS,且 card-issuing 银行确定交易需要身份验证,则预订这些房产可能会失败。
当物业收取 no-show 费用时,Rapid API 将成为记录在案的商家。信用卡账单上的收费描述将由您的组织定义,而不是由酒店定义。要自定义此文本,请联系 Rapid 合作伙伴支持。
为了符合卡组织的要求和 Rapid API 启动流程,请使用 Accepted Payments API 来显示processing_country在 no-show 的情况下,请在 check-out 页面上查看。对于所有 Rapid API 为记录商户的交易,都需要进行此操作;如果使用 3DS 并且出现 no-show,则可能会发生这种情况。
如何减轻对融合的影响
如果 Rapid API 集成不支持预订流程中的安全身份验证,则可以通过不出售这些房产来降低预订失败的风险。请联系 Rapid Partner 支持团队,将受影响的物业收费标准从您的可用性 API 响应中移除。
使用代理工具时,根据相关规定,交易可免于强客户认证 (SCA)。可使用房态 API 的 sales_channel 字段表明此情况。
错误处理
创建预订 API 和完成付款会话 API 可能会导致确认的预订和付款交易。
您的集成应考虑以下说明,以避免财务损失和客户操作案例:
| 来源 | 功能 | 建议的超时设置 | 错误恢复过程 | 所需操作 |
|---|---|---|---|---|
| Rapid API | 注册付款令牌的预订前价格检查 | 10 秒 | 重试或选择其他住宿、房型或房价 | - |
| JavaScript | 3DS 连接器设置 | 10 秒 | 重试相同的请求 | - |
| Rapid API | 注册付款会话 | 10 秒 | 重试同一请求,但不执行“预期:100- 继续”流程](https://tools.ietf.org/html/rfc7231#section-6.2.1 ’Follow link’) | - |
| JavaScript | 启动付款会话 | 10 秒 | 重试相同的请求 | - |
| Rapid API | 创建预订 | 90 秒 | 重试相同的请求 | 对于所有错误:使用 affiliate_reference_id 检索预订 |
| JavaScript | 显示身份验证挑战 | 10 秒 | 重试相同的请求 | - |
| JavaScript | 等待 challenge.statusCode | 180 ~ 1200 秒 | 请求完成付款会话 | - |
| Rapid API | 完成付款会话 | 90 秒 | 重试相同的请求 | 对于所有错误:使用 affiliate_reference_id 检索预订 |
| Rapid API | 对于所有错误:使用 affiliate_reference_id 检索预订 | 30 秒 | 重试相同的请求 | 对于所有错误:等待 90 秒后再重试,以通过 API 响应代码 404 或 200 确认预订的最终状态 |