欧洲 PSD2 合规

了解新的欧洲经济区 (EEA) 卡支付法规会对您的业务产生哪些影响

概述

《支付服务指令 2 (PSD2)》是一项 EEA 法规,要求对涉及 EEA 国家发行的信用卡的所有交易的付款和预订流程进行变更。

PSD2 提高了安全性并减少了欺诈,但它也从根本上改变了整个欧洲的支付方式。作为这些法规的一部分,在法规范围内处理电子消费者支付时,需要采用一种强客户身份验证解决方案。所有发卡机构、收单银行和商户都必须支持这种强客户身份验证解决方案。由于 EEA 内的银行正在践行该法规,不遵守规定将导致付款失败。

本页说明了受支持的 Rapid 付款类型受到怎样的影响,以及合作伙伴在为旅客提供服务时可以采取哪些措施以遵守规定。如果您想更详细地了解该指令,请访问欧盟委员会官方网站查看该法规。

合规性要求

在 EEA 中实现合规交易的步骤会因记录商户及如何向 Rapid 付款而有所不同。

合作伙伴为记录商户

Expedia 联盟伙伴收款

使用 EAC 的预订不受 PSD2 法规的影响。无需因合规要求而变更与 Rapid 的付款流程或 API 集成。但是,如果您是记录商户并在欧盟法规范围内向旅客的信用卡、借记卡或其他付款方式收取费用,则可能会受到该法规的影响。该法规可能会要求您在付款流程中支持符合 PSD2 规定的双重身份验证 (2FA)。请联系您的付款处理方,详细了解他们具备哪些能力,可帮助商户符合 PSD2 规定并避免交易失败。

合作伙伴卡

如果贵公司为记录商户且使用贵公司所有、EEA 发行的信用卡或借记卡向 Rapid 付款,您可能会受到该法规的影响。符合 PSD2 规定的卡有:

  • 在 EEA 发行的一次性虚拟卡。
  • 在 EEA 发行给贵公司而非个人的公司卡。
  • 在 EEA 外发行的任何卡。

如果您在 EEA 法规范围内向旅客的信用卡、借记卡或其他付款方式收取费用,则可能也会受到该法规的影响。该法规可能会要求您在付款流程中支持符合 PSD2 规定的双重身份验证 (2FA)。请联系您的付款处理方,详细了解他们具备哪些能力,可帮助商户符合 PSD2 规定并避免交易失败。

如果上述符合 PSD2 规定的合作伙伴卡不是首选,贵组织可以直接向发行您合作伙伴卡的银行申请豁免。如果获得豁免,该卡上的交易将不需要身份验证,除非可能会使用 2FA 进行一次性在线验证。这种一次性验证要求可能因银行而异。请注意,获得豁免可能是一个漫长的过程,这也意味着您的银行可能会要求您承担所有欺诈性付款的负责。

Rapid 为记录商户

如果贵公司将旅客的卡发送给 Rapid,使用 Rapid 作为记录商户,您可能会受到该法规的影响。当旅客在无零售客服介入的情况下在线预订时,该法规要求 Rapid 需让旅客验证他们是否发起了付款。针对此要求,符合 PSD2 规定的流程是在付款流程中采用双重身份验证 (2FA)。想要通过 EEA 发行的任意信用卡或借记卡将 Rapid 作为记录商户使用,合作伙伴将需要采用 Rapid v2.2+ 中提供的针对 2FA 的 Rapid 解决方案。

但是,通过零售客服或呼叫中心客服预订的交易不需要满足 2FA 要求。只需明确表明预订是在客服的协助下进行,这些交易即符合规定。表明可使用房态 API 的 sales_channel 字段。

住宿为记录商户

如果贵公司使用住宿收款,您可能会受到该法规的影响。在一些情况下,住宿可能会在旅客不在场的情况下尝试从旅客的卡中收取费用,例如“预订后未入住”费用或押金。如果在收费之前没有进行双重身份验证或 2FA,这些收费都是不合规的。想要通过 EEA 发行的信用卡或借记卡针对旅客使用住宿收款,合作伙伴将需要采用 Rapid v2.2+ 中提供的针对 2FA 的 Rapid 解决方案。

Rapid 解决方案概述

如何运作

使用 Rapid 记录商户或住宿收款向旅客卡收费的合作伙伴可以采用 Rapid 的 API 解决方案来生成符合该法规的预订。API 在预订流程中支持 3DS 2.0 的双重身份验证,从而符合 PSD2 的规定。借助 3DS 2.0,我们可支持基于风险的身份验证,通过授权银行自行决定何时需要或不需要使用 2FA 验证旅客,来减少与旅客的矛盾。

2FA 的解决方案由三个不同部分组成:

  • 合作伙伴添加到付款页面的内嵌框架,用于为旅客提供发卡银行的 2FA 体验。在集成文档中,它称之为 3DS 内嵌框架。
  • 一个驻留在付款页面上的新客户端 JavaScript 库,用于收集浏览器数据、与内嵌框架通信以及在内嵌框架中显示 2FA 体验。在集成文档中,它称之为 3DS 连接器库。
  • Rapid 接受银行的付款人信息并在执行 2FA 后完成预订。

当同时使用 JavaScript 和 Rapid 时,采用 2FA 的预订流程现在将在调用预订 API 前后增加一些步骤。下图描绘了这个更新后的预订流程。

准备预订包括在 Rapid API 上注册付款及在 JavaScript API 上收集数据。下一步是在 Rapid API 上预订。最后的完成预订步骤:首先要在 JavaScript API 上显示 2FA,然后在 Rapid API 上完成预订。

在修订后预订流程的每个步骤中,一个步骤的输出中包含着用作下一步输入的数据。数据将需要在浏览器上的 JavaScript 和 Rapid 之间传递。

注:上图是实际 API 的简化流程,旨在用于介绍。请参考集成文档,了解有关完整 API 流程的更多信息。

集成组件详细信息

浏览器内嵌框架

付款体验中的内嵌框架托管一个归旅客发卡银行所有的 URL。此 URL 将向用户显示 2FA 体验,并将旅客提供的任何信息直接传输给他们的银行。内嵌框架最初应该隐藏,当尝试预订后需要 2FA 挑战时,可以将其覆盖在页面上。

浏览器 JavaScript 库

该库被添加到付款页面,在预订时调用以支持 2FA 流程。该库的 API 支持下述功能。

自动收集旅客的设备信息

在尝试预订之前,必须收集旅客设备的有关信息以针对 2FA 做好预订准备。这些信息随后将发送给旅客的发卡银行进行审核,以便银行评估风险,决定交易是否需要进行 2FA,并确保其正确显示。根据 3DS 2.x 规范,将从旅客的浏览器收集以下数据:语言、色彩深度、屏幕高度、屏幕宽度、时区、用户代理以及是否启用 Java。

在浏览器内嵌框架中显示 2FA 体验

尝试预订后,该库用于显示内嵌框架覆盖并将银行的内容加载到内嵌框架中。在 2FA 流程中,银行的内容可能会收集有关旅客设备的其他信息,以支持他们的风险评估。完成预订需要此流程。

Rapid

Rapid v2.2 及更高版本包含可与客户端 JavaScript 库结合使用的新 API。这些 API 现在支持下述功能。

旅客及付款详情注册

在尝试预订之前,必须收集有关旅客的更多信息以针对 2FA 做好预订准备。这些数据包括旅客在销售网站的账户和旅客付款的详细信息,随后将发送给旅客的发卡银行进行审核,以便银行评估风险,决定交易是否需要进行 2FA。请查看 Rapid v2.2+ 中的注册付款 API,了解更多信息。

完成付款和确认预订

在使用 Rapid 进行预订尝试并在浏览器上完成 2FA 流程后,必须再次调用 Rapid。在后台,我们将确认 2FA 切实成功,因此预订才可以得到确认。请查看 Rapid v2.2+ 中的完成付款会话,了解更多信息。

预订流程

概述

如果合作伙伴配置文件 Rapid 支持中启用了 2FA,那么价格检查 API 将返回注册付款 API 而不是创建预订 API 的链接。以下是旅客发起预订后所需的 API 调用序列图。该序列涉及对 JavaScript 库和 Rapid 的调用。

首先初始化 JavaScript 库,然后使用 Rapid API 创建付款会话。此流程会返回 JavaScript 以初始化付款会话,然后使用 Rapid API 预订。如果不需要 2FA,则预订完成。如果需要 2FA,则使用 JavaScript 通过内嵌框架显示 2FA,最后使用 Rapid API 完成付款会话。

针对 2FA 准备预订时,可能并不总是需要 2FA。是否需要 2FA 由用于付款的信用卡的发卡银行决定。决定会在交易期间做出,并在创建预订 API 响应中指示。

以下是使用保留与继续功能时所需的 API 调用序列图。

首先初始化 JavaScript 库,然后使用 Rapid API 创建付款会话。接下来使用 JavaScript API 初始化付款会话,然后使用 Rapid API 预订。如果不需要 2FA,请继续使用 Rapid API 继续预订。如果需要 2FA,则通过 JavaScript API 使用内嵌框架显示 2FA,使用 Rapid API 完成付款会话,最后使用 Rapid API 继续预订。

注:上图是实际 API 的简化流程,旨在用于介绍。请参考集成文档,了解有关完整 API 流程的更多信息。

更多信息

有关 2FA 体验的技术要求的更多信息,请查看 EMVCo 的 3D 安全协议和核心功能规范

Rapid 和双重身份验证集成指南

概述

支持双重身份验证 (2FA) 将需要与新的 JavaScript 库(称为 3DS 连接器)和 Rapid 集成。两者结合使用,可在付款页面上显示 2FA 并确认预订。这种解决方案同时支持 Expedia 收款和住宿收款业务模式。

支持 2FA 预订所需的 API 调用序列概述如下,并在以下部分中做了详细说明。

  1. JavaScript 设置方法
  2. Rapid 注册付款信息 API
  3. JavaScript 初始化会话方法
  4. Rapid 预订 API
  5. JavaScript 挑战方法
  6. Rapid 完成付款 API

要支持此序列,Rapid 合作伙伴支持必须为各个合作伙伴配置文件启用 2FA。

Rapid

如果为合作伙伴配置文件启用了双重身份验证,API 响应将有所不同,支持采用 2FA 的修改后的预订流程。

房态 API

API 请求中 sales_channel 字段的值必须准确,才能在法规允许的情况下获得 2FA 豁免。该值及许多其他因素会由发卡银行进行审核,在预订时做出决定。只有客服工具才可免于进行 2FA。要指明这一点,请将 sales_channel 的值设置为 agent_tool

价格检查 API

API 响应将包含指向注册付款 API 而不是创建预订 API 的链接。

启用 2FA 时的响应示例:

{
    "status": "matched",
    "occupancies": {
        //...(example omitted for length)
    },
    "links": {
        "payment_session": {
            "method": "POST",
            "href": "/v3/payment-sessions?token=QldfCGlcUAVgBDRwdWXBBL"
        }
    }
}

注册付款 API

这将是 JavaScript-Rapid PSD2 预订流程的第二步,发生在 JavaScript setup 方法之后。

该请求将包含属于非 PSD2 预订流程一部分的详细付款信息以及支持成功执行 2FA 的新字段。其中两个字段 encoded_browser_metadataversion 是从 JavaScript API 的 setup method 返回的。

响应将包含 payment_session_idencoded_init_config。这些被指定为 JavaScript 库 initSession 方法的输入。响应中包含的预订链接应在 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

这将是 JavaScript-Rapid PSD2 预订流程的第四步,发生在 JavaScript initSession 方法之后。该请求不会包含任何用于 PSD2 的新字段,所有需要的信息都包含在注册付款 API 返回的预订链接的令牌中。如果成功,响应将始终包含 itinerary_id。但是,仅此并不表示预订已确认,因为可能需要 2FA。

如果需要 2FA,响应还将包含 encoded_challenge_config。注册付款返回的 encoded_challenge_configpayment_session_id 将需要作为参数传递给 JavaScript challenge 方法。

响应还将包含一个 complete_payment_session 的新链接。此链接应在 JavaScript 库的 challenge 方法之后使用。

如果不需要 2FA,则确认预订并且响应将包含 retrievecancel 和可选的 resume 链接。
如果需要 2FA,则创建预订响应的示例如下:

{
    "itinerary_id": "8999989898988",
    "links": {
        "complete_payment_session": {
            "method": "PUT",
            "href": "/v3/itineraries/8999989898988/payment-sessions?token=MY5S3j36cOcLfLBZjPYQ1abhfc8CqmjmFVzkk7euvWaunE57LLeDgaxm516m"
        }
    },
    "encoded_challenge_config": "ABElifsiejfacies2@033asfe="
}

完成付款会话 API

这将是 JavaScript-Rapid PSD2 预订流程的第六步,发生在 JavaScript challenge 方法之后。要完成付款并通知 Rapid 2FA 尝试已完成(无论成功与否),需要此 API。

请求将不包含任何用于 PSD2 的新字段。

如果成功,响应将包含 itinerary_id,以及 retrievecancel 和 可选的 resume 链接。响应若成功则表明预订已确认。

响应示例:

{
    "itinerary_id": "8999989898988",
    "links": {
        "retrieve": {
            "method": "GET",
            "href": "/v3/itineraries/8999989898988?token=MY5S3j36cOcLfLBZjPYQ1abhfc8CqmjmFVzkk7euvWaunE57LLeDgaxm516m"
        }
    }
}

3DS 连接器 JavaScript 库和 3DS 内嵌框架

使用 PSD2 预订工作流程时,付款页面必须包含新的内嵌框架和 JavaScript 库。内嵌框架又称 3DS 内嵌框架,将使用 3D-Secure2.x 向旅客展示身份验证体验。JavaScript 库又称 3DS 连接器库,将支持向发卡银行传输信息并将银行的内容加载到内嵌框架

添加 3DS 内嵌框架和 JavaScript 库

添加 3DS 内嵌框架

应将 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 为测试提供支持,本文档后面会回顾此主题。要在测试期间限制内嵌框架的内容,内嵌框架可具备沙盒的属性,但必须支持以下内容:

sandbox = 'allow-scripts allow-forms allow-same-origin';

添加 3DS 连接器 JavaScript 库

3DS 连接器库与 3DS 内嵌框架通信并将数据发送到提供内嵌框架内容的发卡银行。下面的例子展示了如何将库添加到付款页面的示例。

<head>
    <script src="<<3DS connector script URL>>" integrity="<<actual integrity value>>"></script>
</head>

脚本元素的源和 integrity 值应设置为以下值:

库版本属性
1.3.39srchttps://static.pay.expedia.com/3ds/1.3.39/pay-3ds-js-libs-connector.min.js
integritysha384-par0I4Q5cfljwzqw2mAggM4dKdYzGyj4uZiL4cMviGjI3qVzEgWGuZ2075mYutbT
1.3.65srchttps://static.pay.expedia.com/3ds/1.3.65/pay-3ds-js-libs-connector.min.js
integritysha384-gYopPw6xE5DZwnZXGavkwnvs3NkDOobnHqjroUnSHpGXvs/J9xjHX/8aGzKtSgWI

注:随着未来新版本的推出和采用,源 URL 和 integrity 将发生变化。较新的版本应该不会破坏现有的集成。较旧版本的脚本仍然可以访问。

使用 3DS 内嵌框架和 JavaScript 库

库需要使用 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

付款页面指南

支持 2FA 的信用卡品牌可能需要按照其指南展示其徽标和品牌。

信用卡品牌2FA 品牌徽标和指南
万事达卡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)

参数:

名称类型说明
threeDsIFrameOrigin字符串3DS 内嵌框架的 ID。
threeDsIFrameOrigin字符串3DS 内嵌框架的源。用于在与 3DS 内嵌框架通信时以传出窗口消息为目标和筛选传入消息。

方法

设置

通过收集后端 3DS 服务所需的浏览器基本详细信息(如屏幕尺寸、色彩深度等)来设置付款会话。

方法签名:

setup(setupRequest)

参数:

名称类型
setupRequestSetupRequest

返回:

承诺一个 SetupResponse

初始化会话

初始化会话以使用 3DS 进行身份验证。作为初始化的一部分,可能会从浏览器收集其他数据。如果发卡机构要求,可以将 3DS 方法 URL 加载到内嵌框架中,以使发卡机构的访问控制服务器能够直接从浏览器收集数据。客户端不需要等待调用完成回调,就可以创建订单。

方法签名:

initSession(initSessionRequest)

参数:

名称类型
initSessionRequestInitSessionRequest

回报:承诺 InitSessionResponse

挑战

如果发卡机构要求,则需要加载 3DS 身份验证体验。

方法签名:

challenge(challengeRequest)

参数:

名称类型
challengeRequestChallengeRequest

回报:承诺 ChallengeResponse

类:SetupRequest

设置调用的请求结构。

属性:

名称类型说明
referenceIdstring用于标识旅客付款会话的参考 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 预订 API。

等级:ChallengeRequest

挑战方法的请求结构。

属性:

statusCode 值测试 encoded_Challenge_config 值说明
SUCCESSW3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlNVQ0NFU1MifV0没有用户内嵌框架互动
SUCCESS/FAILEDW3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlNIT1cifV0没有用户内嵌框架互动
FAILEDW3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIkZBSUxFRCJ9XQ没有用户内嵌框架互动
TIMEOUTW3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlRJTUVPVVQifV0
ERRORW3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmdlT3V0cHV0Q29uZmlnIjogIkVSUk9SIn1d

statusCode 的可能值

说明
SUCCESS3DS 挑战成功完成。
SKIPPED外部应用程序错误。
FAILED由于持卡人无法正确响应身份验证挑战,3DS 挑战未成功完成。
TIMEOUT挑战未在有效时间内完成。超时持续时间为 1200 秒。

注:对于所有的 challengeResponse statusCode 值,请继续使用适用完成付款会话的 Rapid。

使用 Rapid 和双重身份验证进行测试

您与 Rapid 和 3DS 连接器方法的集成可以使用与 API 支持的特定场景相对应的输入参数值来进行测试。

Rapid

要测试 Rapid,请在 HTTP 请求中包含一个名为 Test 的额外 HTTP 标头,并使用该 API 支持的一个值来测试支持的场景。

在 PSD2 预订流程中,Rapid 的测试响应也可用于测试 3DS 连接器库方法。

注册付款

以下测试标头值会在 API 响应中产生不同的 encoded_init_config 值和不同的 HTTP 响应代码。encoded_init_config 可以传递到 JavaScript 库的 initSession 调用中,以触发 3DS 连接器库中的不同测试案例。

测试标头值HTTP 代码和响应initSession 测试案例
standard201 – Standard ResponseSUCCESS
init_skip201 - Response Without encodedInitConfig不支持
init_fail201 – Standard ResponseFAILED
init_timeout201 – Standard ResponseTIMEOUT
internal_server_error500 – Internal Server Error
internal_server_error503 - Server Unavailable

注:3DS 连接器 Library.t_config 中不同的 init_skip 测试案例可以传递给 initSession 并强制执行 SKIPPED 的 statusCode

创建预订

除了 Rapid 预订测试请求中为非 PSD2 预订流程定义的测试标头之外,PSD2 工作流程还支持其他测试标头值。

测试标头值会产生不同的 encodedChallengeConfig 值,这些值可以传递至 JavaScript 库的 challenge 调用中,以触发不同的测试案例。

测试标头值HTTP 代码和响应initSession 测试案例
complete_payment_session201 – Response with Complete Payment Session linkSUCCESS without user iframe Interaction
complete_payment_session_show201 – Response with Complete Payment Session linkSUCCESS/FAILED with user iframe Interaction
complete_payment_session_fail201 – Response with Complete Payment Session linkFAILED without user iframe Interaction
complete_payment_session_timeout201 – Response with Complete Payment Session linkTIMEOUT
complete_payment_session_error201 – Response with Complete Payment Session linkERROR

完成付款会话

测试标头值会产生不同错误案例,可能会在尝试完成付款和确认预订时发生。

测试标头值HTTP 代码和响应
payment_declined400 - Payment Declined Response
price_mismatch409 - Price Mismatch Response
rooms_unavailable410 - Rooms Unavailable Response

3DS 连接器库和内嵌框架

要在没有外部依赖因素的情况下测试 3DS 连接器,特定的参数值应对应于支持的方法响应。仅当内嵌框架使用测试沙盒 URL 加载时才支持此行为。

初始化会话

InitSessionResponse statusCode 的受支持值可以通过改变 initSessionRequest encodedInitConfig 来进行测试。

statusCode 值测试 encodedInitConfig 值
SUCCESSW3sicHJvdmlkZXJJZCI6IDAsICJz YW5kYm94SW5pdE91dHB1dENvbmZpZyI6ICJTVUNDRVNTIn1d
FAILEDW3sicHJvdmlkZXJJZCI6IDAsICJz YW5kYm94SW5pdE91dHB1dENvbmZpZyI6ICJGQUlMRUQifV0=
TIMEOUTW3sicHJvdmlkZXJJZCI6IDAsICJz YW5kYm94SW5pdE91dHB1dENvbmZpZyI6ICJUSU1FT1VUIn1d
SKIPPED目前不支持。

注:encoded_init_config 值也可以使用注册付款 API 的受支持测试标头生成。

挑战

challengeResponse statusCode 的受支持值可以通过改变 challengeRequest encondedChallengeConfig 来进行测试。

statusCode 值测试 encoded_Challenge_config 值说明
SUCCESSW3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlNVQ0NFU1MifV0没有用户内嵌框架互动
SUCCESS/FAILEDW3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlNIT1cifV0没有用户内嵌框架互动
FAILEDW3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIkZBSUxFRCJ9XQ没有用户内嵌框架互动
TIMEOUTW3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlRJTUVPVVQifV0
错误W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmdlT3V0cHV0Q29uZmlnIjogIkVSUk9SIn1d

注:encodedInitConfig 值也可以使用预订 API PSD2 流程的受支持测试标头生成。

注:当 SUCCESS 或 FAILED 的挑战状态代码值测试基于使用内嵌框架的用户输入时,挑战方法响应将等待内嵌框架中的模拟身份验证 UI 完成。

3DS 内嵌框架中的 UI 示例:

3DS 内嵌框架示例

示例用法

以下例子展示了一个实施示例,仅作参考。该例子演示了如何使用预定义的参数值来针对 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
    });

双重身份验证和住宿收款

关于住宿收款的双重身份验证

当使用住宿收款预订时,Expedia 不会从卡上扣款,而只是将其发送给住宿进行处理。住宿可能会在客户入住前使用此信息验证卡。在办理入住时,旅客应亲自付款。

但是,有时旅客无法办理入住,住宿可能会收取预订后未入住费用。这些费用可能会受到 PSD2 法规的影响,因为它们涉及到在旅客不在场的情况下对卡进行收费。

如果交易受到影响,付款可能会失败,如果收费不符合规定,住宿也可能会面临信用卡品牌方的处罚。

为了保护我们与住宿之间的关系并继续为我们的合作伙伴服务,Expedia Group 为住宿提供了一条可选的合规途径。受影响的住宿现在可以利用 Expedia Group 代表他们提供 2FA。这样一来,住宿便可以保护他们的业务,确保 Rapid 可以继续提供同样的多样化住宿。

Rapid 2.4+ 在住宿内容文件和住宿内容中提供了 <payment_registration_recommended=true> 的标记,可以帮助您识别项目中可能涉及的住宿。

注:只有欧洲经济区 (EEA) 内的住宿才有资格使用 2FA。

注:可能需要 2FA 的住宿集不是静态的,可能会随着其他住宿选择启用此功能而增长。住宿的这一属性在 Rapid 内容 v.2.4 中可用。

住宿收款的 2FA 会对集成带来怎样的影响?

如果合作伙伴想要提供可能需要 2FA 的住宿,那么预订路径应支持 2FA。在不支持 2FA 的情况下,如果发卡银行确定交易需要 2FA(例如在 EEA 发行的卡),预订这些住宿可能会失败。

如果住宿收取了预订后未入住费用,Rapid 将为记录商户。卡账单汇总上的收费描述符不会由住宿定义。描述符的值会由合作伙伴定义。要自定义此文本,请联系 Rapid 合作伙伴支持。
为遵守信用卡品牌和 Rapid 上线流程的要求,请在预订后未入住的情况下使用已接受付款 API 在付款页面上显示 processing_country。这对于 Rapid 为记录商户的所有交易来说都是必需的,如果使用 2FA 并且出现预订后未入住的情况,就可能会发生这种情况。

如何减轻对集成的影响

如果 Rapid 集成在预订流程中不支持 2FA,则可以通过不售卖住宿来降低预订失败的风险。

请联系 Rapid 合作伙伴支持团队,从房态 API 响应中删除这些受影响的住宿收款价格。

使用客服工具时,根据规定,交易可免于 2FA。可使用房态 API 的 sales_channel 字段表明此情况。

错误处理

创建预订 API 和完成付款会话 API 可能会导致确认的预订和付款交易。

您的集成应考虑以下说明,以避免财务损失和客户操作案例:

来源功能建议的超时设置错误恢复过程所需操作
Rapid API注册付款令牌的预订前价格检查10 秒重试或选择其他住宿、房型或房价-
JavaScript3DS 连接器设置10 秒重试相同的请求-
Rapid API注册付款会话10 秒在没有“Expect: 100-Continue”流程的情况下重试相同的请求-
JavaScript启动付款会话10 秒重试相同的请求-
Rapid API创建预订90 秒重试相同的请求对于所有错误:使用 affiliate_reference_id 检索预订
JavaScript显示 2FA 挑战10 秒重试相同的请求-
JavaScript等待 challenge.statusCode180 ~ 1200 秒请求完成付款会话-
Rapid API完成付款会话90 秒重试相同的请求对于所有错误:使用 affiliate_reference_id 检索预订
Rapid API对于所有错误:使用 affiliate_reference_id 检索预订30 秒重试相同的请求对于所有错误:等待 90 秒后再重试,以通过 API 响应代码 404 或 200 确认预订的最终状态
您觉得这个页面有用吗?
我们该如何改进这些内容?
感谢您帮助我们改进 Developer Hub!