PSD2 유럽 규정 준수
새로운 EEA 카드 결제 규정이 비즈니스에 미치는 영향을 이해합니다.
개요
결제 서비스 지침 2(PSD2)는 EEA 국가에서 발급된 신용카드를 사용한 모든 거래의 결제 및 예약 절차에 대한 변경을 요구하는 EEA 규정입니다.
PSD2는 보안을 강화하고 사기 행위를 줄이는 데 도움이 되지만, 유럽 전역에서 결제가 이루어지는 방식을 근본적으로 바꿉니다. 이 규정에서는 규정 범위 내에서 전자 소비자 결제를 처리할 때 철저한 고객 인증 솔루션을 필요로 합니다. 모든 카드 발급사, 청구 은행 및 판매자는 강력한 고객 인증 솔루션을 지원해야 합니다. EEA 내 은행에서는 규정을 시행하므로 규정을 준수하지 않으면 결제가 이루어지지 않습니다.
이 페이지에서는 지원되는 Rapid API 결제 유형이 어떤 영향을 받는지, 여행객에게 서비스를 제공하는 파트너가 규정을 준수하기 위해 어떤 조치를 취할 수 있는지 설명합니다. 지침에 대해 더 자세히 알아보려면 유럽 위원회 공식 사이트에서 관련 법령을 검토해 주세요.
규정 준수 요구 사항
EEA에서 규정 준수 거래를 지원하는 단계는 MOR(Merchant of Record)이 누구이고 Rapid API에 결제가 이루어지는 방식에 따라 달라집니다.
파트너가 MOR(Merchant of Record)인 경우
Expedia Affiliate Collect
EAC를 사용하는 예약은 PSD2 규정의 영향을 받지 않습니다. 규정을 준수하기 위해 Rapid를 통한 API 통합이나 결제 절차에 변경이 필요하지 않습니다. 그러나 파트너가 MOR(Merchant of Record)이고 EU 규정의 범위 내에서 여행객의 신용카드, 직불카드 또는 기타 결제 수단에 비용을 청구하는 경우 규정이 적용될 수 있습니다. 규정에 따라 결제 절차에서 PSD2를 준수하는 2단계 인증(2FA) 버전을 지원해야 할 수 있습니다. 판매자가 PSD2를 준수하고 거래 실패를 방지하는 데 도움이 되는 기능에 대해 자세히 알아보려면 결제 처리자에게 문의해 주세요.
파트너 카드
회사가 MOR(Merchant of Record)이고 회사 소유의 EEA 발급 신용카드 또는 직불카드로 Rapid에 결제하는 경우 규정의 영향을 받을 수 있습니다. PSD2 준수 카드 목록은 다음과 같습니다.
- EEA에서 발급된 일회용 가상 카드
- EEA에서 개인이 아닌 회사를 대상으로 발급된 법인 카드
- EEA 외부에서 발급된 모든 카드
EEA 규정의 범위 내에서 여행객의 신용카드, 직불카드 또는 기타 결제 수단에 비용을 청구하는 경우에도 규정의 영향을 받을 수 있습니다. 규정에 따라 결제 절차에서 PSD2를 준수하는 2단계 인증(2FA) 버전을 지원해야 할 수 있습니다. 판매자가 PSD2를 준수하고 거래 실패를 방지하는 데 도움이 되는 기능에 대해 자세히 알아보려면 결제 처리자에게 문의해 주세요.
위의 PSD2 준수 파트너 카드를 사용하고 싶지 않은 경우 조직에서 파트너 카드를 발급한 은행에 직접 면제를 요청할 수 있습니다. 면제가 승인되면 2FA를 사용하여 진행할 수 있는 일회성 온라인 인증을 제외하고 해당 카드의 거래에 인증이 필요하지 않습니다. 이 일회성 요건은 은행마다 다를 수 있습니다. 면제를 받는 데 시간이 오래 걸릴 수 있으며, 은행에서 사기성 결제에 대해 책임을 물을 수도 있습니다.
Rapid가 MOR(Merchant of Record)인 경우
회사에서 여행객 카드 정보를 Rapid에 전송하여 Rapid를 MOR(Merchant of Record)로 사용하는 경우 규정의 영향을 받을 수 있습니다. 여행객이 소매 여행사를 거치지 않고 온라인으로 예약하는 경우 규정에 따라 Rapid에서 여행객이 결제를 시작했는지를 확인해야 합니다. 이 요건에 대한 PSD2 준수 절차로 결제 처리 중 2단계 인증(2FA)을 거쳐야 합니다. EEA에서 발급한 신용카드 또는 직불카드를 사용하여 Rapid를 MOR(Merchant of Record)로 사용하려는 파트너는 2FA용 Rapid 솔루션을 도입해야 합니다.
단, 소매 여행사나 콜센터 상담원을 통해 예약한 거래는 2FA 요건에서 제외됩니다. 이러한 거래에서 규정을 준수하려면 예약이 여행사나 상담원의 도움으로 이루어졌다는 명시적인 표시만 있으면 됩니다. 이를 표시하려면 예약 가능 여부 API의 sales_channel
필드를 사용해 주세요.
숙박 시설이 MOR(Merchant of Record)인 경우
회사에서 Property Collect를 사용하는 경우 규정의 영향을 받을 수 있습니다. 숙박 시설에서 여행객이 오지 않았는데 여행객 카드에 요금을 청구하는 상황이 있습니다(예: '노쇼' 수수료 또는 보증금). 이러한 청구는 청구 전에 2단계 인증(2FA)을 수행해야 규정을 준수할 수 있습니다. EEA에서 발급한 신용카드 또는 직불카드를 사용하는 여행객을 대상으로 Property Collect를 사용하려는 파트너는 2FA용 Rapid 솔루션을 도입해야 합니다.
Rapid API 솔루션 개요
작동 방식
여행객 카드로 Property Collect 또는 Rapid MOR(Merchant of Record)을 사용하는 파트너는 Rapid의 API 솔루션을 도입하여 규정을 준수하는 예약을 생성할 수 있습니다. API는 예약 흐름에서 3DS 2.0과 함께 2단계 인증을 사용할 수 있도록 하여 PSD2 규정 준수를 지원합니다. 3DS 2.0을 통해 위험 기반 인증이 지원되며, 이 인증은 2FA로 여행객에게 추가적인 요구를 할 때와 그렇지 않을 때를 은행 재량으로 결정하도록 하여 여행객과의 마찰을 줄입니다.
2FA용 솔루션은 3가지 개별 구성 요소로 이루어집니다.
- 파트너가 결제 페이지에 추가하는 iframe: 발급 은행에서 여행객을 위한 2FA 환경을 호스팅하는 데 사용되며, 통합 설명서에서는 3DS iframe이라고 합니다.
- 결제 페이지에 있는 새로운 클라이언트 측 JavaScript 라이브러리: 브라우저 데이터를 수집하고, iframe과 통신하고, iframe 내에서 2FA 환경을 표시하는 데 사용됩니다. 통합 설명서에서는 3DS Connector 라이브러리라고 합니다.
- Rapid는 은행의 결제자 정보를 받아들여 2FA 후 예약을 완료합니다.
이제 JavaScript와 Rapid를 함께 사용할 때 2FA를 통한 예약 흐름에 예약 API가 호출되기 전후 몇 가지 단계가 추가됩니다. 아래의 다이어그램은 업데이트된 예약 흐름입니다.
변경된 예약 흐름의 각 단계에서는 한 단계의 출력 정보가 다음 단계의 입력 데이터로 사용됩니다. 데이터가 브라우저의 JavaScript와 Rapid 간에 전달되어야 합니다.
참고: 위의 다이어그램은 소개 목적으로 실제 API 흐름을 단순화한 것입니다. 전체 API 흐름을 자세히 알아보려면 통합 설명서를 참조해 주세요.
통합 구성 요소 세부 정보
브라우저 iframe
결제 페이지 환경에 포함된 iframe은 여행객의 카드 발급 은행이 소유한 URL을 호스팅합니다. 이 URL은 사용자에게 2FA 환경을 표시하고 여행객이 제공한 모든 정보를 은행으로 바로 전송합니다. iframe은 처음에는 숨겨져 있다가 예약 시도 후 2FA 챌린지가 필요할 때 페이지 상단에 오버레이됩니다.
브라우저 JavaScript 라이브러리
이 라이브러리는 결제 페이지에 추가되며, 예약 시 호출되어 2FA 절차를 지원합니다. 라이브러리의 API는 아래에 설명된 기능을 지원합니다.
여행객의 기기 정보 자동 수집
예약을 시도하기 전에 여행객의 기기 정보를 수집하여 2FA 예약을 준비해야 합니다. 이 정보는 추후 검토를 위해 여행객의 발급 은행으로 보내지며, 은행은 이를 바탕으로 위험을 평가하고, 거래에 2FA가 필요한지 결정하고, 올바르게 표시되는지 확인할 수 있습니다. 3DS 2.x 사양에 따라 여행객의 브라우저에서 언어, 색상 심도, 화면 높이, 화면 너비, 시간대, 사용자 에이전트 및 Java 활성화 여부와 같은 데이터가 수집됩니다.
브라우저 iframe에 2FA 환경 표시
예약 시도 후 라이브러리는 iframe 오버레이를 표시하고 은행의 콘텐츠를 iframe에 로드하는 데 사용됩니다. 2FA 절차가 진행되는 동안 은행의 콘텐츠가 위험 평가를 지원하기 위해 여행객의 기기에 대한 추가 정보를 수집할 수 있습니다. 이 절차는 예약을 완료하는 데 필요합니다.
Rapid
Rapid에는 클라이언트 측 JavaScript 라이브러리와 함께 작동하는 API가 포함되어 있습니다. API는 아래에 설명된 기능을 지원합니다.
여행객 등록 및 결제 정보
예약을 시도하기 전에 여행객에 대한 추가 정보를 수집하여 2FA 예약을 준비해야 합니다. 데이터에는 POS(Point of Sale)와 여행객의 결제 정보가 포함된 여행객 계정의 세부 정보가 포함됩니다. 이 데이터는 추후 검토를 위해 여행객의 발급 은행으로 보내지며, 은행은 이를 바탕으로 위험을 평가하고, 거래에 2FA가 필요한지 결정할 수 있습니다. 자세한 내용은 Rapid의 결제 등록 API를 참조해 주세요.
결제 완료 및 예약 확인
Rapid로 예약을 시도하고 브라우저에서 2FA 절차가 완료된 후 Rapid를 다시 한 번 호출해야 합니다. 백그라운드에서 2FA가 실제로 성공했는지 확인하여 예약이 확정됩니다. 자세한 내용은 Rapid의 결제 세션 완료를 참조해 주세요.
예약 흐름
개요
파트너 프로필 Rapid 지원에서 2FA가 활성화되면 요금 확인 API에서 예약 생성 API가 아닌 결제 등록 API 링크를 반환합니다. 다음 다이어그램은 여행객이 예약을 시작한 후에 필요한 API 호출 시퀀스입니다. 시퀀스에는 JavaScript 라이브러리 및 Rapid에 대한 호출이 모두 포함됩니다.
예약이 2FA를 거칠 준비를 마쳤더라도 2FA가 필요하지 않을 수 있습니다. 2FA를 진행할지는 결제에 사용된 신용카드의 발급 은행에서 결정합니다. 이 결정은 거래 중에 이루어지며 예약 생성 API 응답에 표시됩니다.
다음 다이어그램은 보류 및 재개 사용 시 필요한 API 호출 시퀀스를 나타냅니다.
참고: 위의 다이어그램은 소개 목적으로 실제 API 흐름을 단순화한 것입니다. 전체 API 흐름을 자세히 알아보려면 통합 설명서를 참조해 주세요.
추가 정보
2FA 환경을 위한 기술 요구 사항을 자세히 알아보려면 EMVCo의 3D 보안 프로토콜 및 핵심 기능 사양을 검토해 주세요.
Rapid 및 2단계 인증 통합 가이드
개요
2단계 인증(2FA)을 지원하려면 3DS Connector로 알려진 새로운 JavaScript 라이브러리와 Rapid의 통합이 필요합니다. 두 개가 함께 사용되어 결제 페이지에 2FA를 표시하고 예약을 확인합니다. 이 솔루션은 Expedia Collect 및 Property Collect 비즈니스 모델을 모두 지원합니다.
2FA로 예약을 지원하는 데 필요한 API 호출 시퀀스는 아래에 나와 있으며, 다음 섹션에서 자세히 설명합니다.
- JavaScript 설정 메서드
- Rapid 결제 등록 API
- JavaScript 세션 초기화 메서드
- Rapid 예약 API
- JavaScript 챌린지 메서드
- Rapid 결제 완료 API
이 시퀀스를 지원하려면 Rapid 파트너 지원 팀에서 개별 파트너 프로필에 대해 2FA를 활성화해야 합니다.
Rapid
파트너 프로필에 대해 2단계 인증이 활성화된 경우 2FA로 변경된 예약 흐름을 지원하기 위해 API 응답이 달라집니다.
예약 가능 여부 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_metadata
및 version
필드는 JavaScript API의 setup method
에서 반환됩니다.
응답에는 payment_session_id
및 encoded_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_config
및 payment_session_id
는 JavaScript challenge
메서드에 매개변수로 전달되어야 합니다.
응답에는 complete_payment_session
에 대한 새 링크도 포함됩니다. 이 링크는 JavaScript 라이브러리의 challenge
메서드 후에 사용해야 합니다.
2FA가 필요하지 않은 경우 예약이 확정되고 응답에 retrieve
, cancel
및 필요에 따라 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
메서드 후에 발생합니다. 이 API는 결제를 마치고 Rapid에 2FA 시도가 완료되었는지를 알리는 데 필요합니다.
요청에는 PSD2에 대한 새 필드가 포함되지 않습니다.
성공 시 응답에는 itinerary_id
와 retrieve
, cancel
및 필요에 따라 resume
링크가 포함됩니다. 예약이 확정되었다는 성공적인 응답입니다.
응답 예:
{
"itinerary_id": "8999989898988",
"links": {
"retrieve": {
"method": "GET",
"href": "/v3/itineraries/8999989898988?token=MY5S3j36cOcLfLBZjPYQ1abhfc8CqmjmFVzkk7euvWaunE57LLeDgaxm516m"
}
}
}
3DS Connector JavaScript 라이브러리 및 3DS iframe
PSD2 예약 워크플로를 사용하는 경우 결제 페이지에 새로운 iframe 및 JavaScript 라이브러리가 포함되어야 합니다. 3DS iframe이라고 하는 iframe은 여행객에게 3D-Secure 2.x를 사용한 인증 환경을 표시합니다. 3DS Connector 라이브러리라고 하는 JavaScript 라이브러리는 발급 은행으로 정보 전송을 지원하고 은행의 콘텐츠를 iframe에 로드합니다.
3DS iframe 및 JavaScript 라이브러리 추가
3DS iframe 추가
3DS iframe은 처음에는 숨겨져 있다가 결제를 처리하기 위해 인증 요청이 필요할 때 표시될 수 있는 컨테이너에 있어야 합니다.
컨테이너 디자인은 호스팅 페이지에 맞게 사용자 설정할 수 있습니다. 아래는 부트스트랩 모달을 사용하여 안내용으로 제작된 구현 예시입니다.
<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>
iframe의 소스는 다음 두 값 중 하나로 설정되어야 합니다.
URL 유형 | URL | 참고 |
---|---|---|
프로덕션 | https://static.pay.expedia.com/3ds/threeDsIframe.html | 프로덕션 2FA 지원 |
샌드박스 테스트 | https://static.pay.expedia.com/3ds/sandboxThreeDsIframe.html | 2FA 테스트 지원 |
테스트 URL은 테스트를 지원하며, 이 주제는 문서 후반부에서 다룹니다. 테스트 중에 iframe 콘텐츠를 제한하려면 샌드박스를 사용하여 iframe에 속성을 지정할 수 있습니다. 단, 다음을 허용해야 합니다.
sandbox = 'allow-scripts allow-forms allow-same-origin';
3DS Connector 및 JavaScript 라이브러리 추가
3DS Connector 라이브러리는 3DS iframe과 통신하고 iframe 콘텐츠를 제공하는 발급 은행에 데이터를 전송합니다. 아래는 결제 페이지에 라이브러리를 추가하는 방법의 예입니다.
<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 iframe 및 JavaScript 라이브러리 사용
라이브러리에서는 JavaScript Promise를 사용해야 합니다. 다음은 안내를 위한 구현 예시이며, 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 Connector 라이브러리의 일부가 아닙니다. 이는 API로의 정보 전송을 지원하는 래퍼를 보여 주기 위한 것입니다.
예제에서는 런타임 시 정해져야 하는 매개변수에 대해 정적 값을 사용합니다(예: referenceId
).
결제 페이지 가이드라인
2FA를 지원하는 카드 브랜드는 지침에 따라 로고와 브랜딩을 표시하도록 요구할 수 있습니다.
카드 브랜드 | 2FA 브랜딩 | 로고 및 지침 |
---|---|---|
Mastercard | Mastercard Identity Check | (https://brand.mastercard.com/debit/mastercard-brand-mark/downloads.html)) |
Visa | Visa Secure | [https://www.merchantsignage.visa.com/brand_guidelines] |
참고: 다른 카드 브랜드의 로고 및 지침은 제공되는 대로 포함될 예정입니다.
3DS Connector JavaScript 라이브러리 설명서
클래스: ThreeDSConnector
구성자
new ThreeDSConnector(threeDsIFrameId, threeDsIFrameOrigin)
매개변수:
이름 | 유형 | 설명 |
---|---|---|
threeDsIFrameOrigin | string | 3DS iframe의 ID입니다. |
threeDsIFrameOrigin | string | 3DS iframe의 소스입니다. 3DS iframe과 통신할 때 발신 창 메시지를 대상으로 하고 수신 메시지를 필터링하는 데 사용됩니다. |
메서드
설정
화면 크기, 색상 심도 등 백엔드 3DS 서비스에 필요한 브라우저에 대한 기본 세부 정보를 수집하여 결제 세션을 설정합니다.
메서드 서명:
setup(setupRequest)
매개변수:
이름 | 유형 |
---|---|
setupRequest | SetupRequest |
반환:
SetupResponse
에 대한 Promise
세션 초기화
3DS를 통한 인증을 위해 세션을 초기화합니다. 초기화 과정에서 추가 데이터가 브라우저에서 수집될 수 있습니다. 카드 발급사에서 요구하는 경우 3DS 메서드 URL을 iframe에 로드하여 카드 발급사의 액세스 제어 서버가 브라우저에서 직접 데이터를 수집하도록 지원할 수 있습니다. 클라이언트는 주문을 생성하기 전에 완료 콜백이 호출될 때까지 기다리지 않아도 됩니다.
메서드 서명:
initSession(initSessionRequest)
매개변수:
이름 | 유형 |
---|---|
initSessionRequest | InitSessionRequest |
반환: InitSessionResponse
에 대한 Promise
챌린지
카드 발급사가 요구하는 경우 3DS 인증 환경을 로드합니다.
메서드 서명:
challenge(challengeRequest)
매개변수:
이름 | 유형 |
---|---|
challengeRequest | ChallengeRequest |
반환: ChallengeResponse
에 대한 Promise
클래스: SetupRequest
설정 호출의 요청 구조입니다.
속성:
이름 | 유형 | 설명 |
---|---|---|
referenceId | string | 여행객의 결제 세션을 식별하기 위한 참조 ID입니다. 로깅 및 추적에 사용됩니다. 밑줄을 사용하여 연결된 APIKey와 Customer-Session-ID 를 사용합니다. 예: [APIKey]_[SessionID] |
클래스: SetupResponse
설정 호출의 응답입니다.
속성:
이름 | 유형 | 설명 |
---|---|---|
version | string | 라이브러리의 버전으로, 라이브러리로의 URL 경로에 있는 버전과 동일합니다. |
encodedBrowserMetadata | string | 수집된 브라우저 세부 정보를 포함하는 인코딩된 개체입니다. 클라이언트는 이를 구문 분석하지 않고 불분명한 데이터로 처리하여 백엔드 결제 서비스에 전달해야 합니다. |
클래스: InitSessionRequest
initSession
메서드의 요청 구조입니다.
속성:
이름 | 유형 | 설명 |
---|---|---|
paymentSessionId | string | Rapid 결제 등록 API에서 반환하는 고유 ID입니다. |
encodedInitConfig | string | Rapid 결제 등록 API에서 반환하는 초기화에 필요한 데이터가 포함된 config 개체의 인코딩된 목록입니다. |
클래스: InitSessionResponse
initSession
메서드에 대한 응답 구조입니다.
속성:
이름 | 유형 | 설명 |
---|---|---|
statusCode | string | initSession 호출의 상태입니다. |
message | string | 선택 사항으로, 실패 이유를 나타냅니다. |
가능한 statusCode
값:
값 | 설명 |
---|---|
SUCCESS | 초기화가 성공적으로 완료되었습니다. |
SKIPPED | 초기화가 수행되지 않았습니다. |
FAILED | 초기화에 실패했습니다. 메시지 필드에는 실패와 관련된 추가 정보가 나와 있습니다. |
TIMEOUT | 허용 시간 내에 초기화가 완료되지 않았습니다. 제한 시간은 10초입니다. |
참고: 모든 initSessionresponse
statusCode
값에 대해 Rapid 예약 API를 진행해 주세요.
클래스: ChallengeRequest
챌린지 메서드의 요청 구조입니다.
속성:
statusCode 값 | encoded_Challenge_config 값 테스트 | 설명 |
---|---|---|
SUCCESS | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlNVQ0NFU1MifV0 | 사용자 iframe 상호 작용 없음 |
SUCCESS/FAILED | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlNIT1cifV0 | 사용자 iframe 상호 작용 없음 |
FAILED | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIkZBSUxFRCJ9XQ | 사용자 iframe 상호 작용 없음 |
TIMEOUT | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlRJTUVPVVQifV0 | |
ERROR | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmdlT3V0cHV0Q29uZmlnIjogIkVSUk9SIn1d |
가능한 statusCode 값
값 | 설명 |
---|---|
SUCCESS | 3DS 챌린지가 성공적으로 완료되었습니다. |
SKIPPED | 외부 애플리케이션 오류가 발생했습니다. |
FAILED | 카드 소유자가 인증 챌린지에 올바르게 응답하지 못하여 3DS 챌린지가 제대로 완료되지 않았습니다. |
TIMEOUT | 허용 시간 내에 챌린지가 완료되지 않았습니다. 제한 시간은 1,200초입니다. |
참고: 모든 challengeResponse
statusCode
값에 대해 결제 세션 완료용 Rapid를 진행해 주세요.
Rapid 및 2단계 인증을 통한 테스트
API에서 지원하는 특정 시나리오에 해당하는 입력 매개변수 값을 사용하여 Rapid 및 3DS Connector 메서드와의 통합을 테스트할 수 있습니다.
Rapid
Rapid를 테스트하려면 HTTP 요청에 test라는 추가 HTTP 헤더를 포함하고, 해당 API에 대해 사용 가능한 값 중 하나로 지원되는 시나리오를 테스트합니다.
PSD2 예약 흐름 내에서 Rapid의 테스트 응답을 사용하여 3DS Connector 라이브러리 메서드를 테스트할 수도 있습니다.
결제 등록
다음 테스트 헤더 값은 API 응답과 다른 HTTP 응답 코드에서 상이한 encoded_init_config
값을 산출합니다. encoded_init_config
는 JavaScript 라이브러리의 initSession
호출에 전달되어 3DS Connector 라이브러리 내에서 다양한 테스트 사례를 트리거할 수 있습니다.
테스트 헤더 값 | HTTP 코드 및 응답 | initSession 테스트 사례 |
---|---|---|
standard | 201 – Standard Response | SUCCESS |
init_skip | 201 - Response Without encodedInitConfig | 지원되지 않음 |
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 |
참고: init_skip
은 3DS Connector Library.t_config
내에서 initSession
으로 전달될 수 있는 다양한 테스트 사례를 건너뛰며, 강제로 statusCode
를 SKIPPED로 설정합니다.
예약 생성
PSD2 미적용 예약 흐름에 대해 Rapid 예약 테스트 요청에 정의된 테스트 헤더 외에도, PSD2 워크플로에 추가 테스트 헤더 값이 지원됩니다.
테스트 헤더 값은 서로 다른 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 Connector 라이브러리 및 iframe
특정 매개변수 값이 지원되는 메서드 응답과 일치해야 외부 종속성 없이 3DS Connector를 테스트할 수 있습니다. 이 동작은 iframe이 테스트 샌드박스 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 | 사용자 iframe 상호 작용 없음 |
SUCCESS/FAILED | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlNIT1cifV0 | 사용자 iframe 상호 작용 없음 |
FAILED | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIkZBSUxFRCJ9XQ | 사용자 iframe 상호 작용 없음 |
TIMEOUT | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmd lT3V0cHV0Q29uZmlnIjogIlRJTUVPVVQifV0 | |
ERROR | W3sicHJvdmlkZXJJZCI6IDA sICJzYW5kYm94Q2hhbGxlbmdlT3V0cHV0Q29uZmlnIjogIkVSUk9SIn1d |
참고: encodedInitConfig
값은 예약 API의 PSD2 흐름에 지원되는 테스트 헤더를 사용하여 생성될 수도 있습니다.
참고: iframe을 통한 사용자 입력을 기반으로 SUCCESS 또는 FAILED 챌린지 상태 코드 값을 테스트할 때 iframe에서 시뮬레이션된 인증 UI가 완료될 때까지 챌린지 메서드 응답이 대기합니다.
3DS iframe의 UI 예:
사용 예
아래는 안내용으로 제작된 구현 예입니다. 이 예에서는 사전 정의된 매개변수 값을 통해 사용자가 iframe과 상호 작용할 필요 없이 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
});
2단계 인증 및 Property Collect
Property Collect용 2단계 인증 정보
Property Collect 예약 시 Expedia는 카드에 요금을 청구하지 않고 처리를 위해 숙박 시설로 전송합니다. 숙박 시설에서는 이 정보를 바탕으로 체크인 전에 카드를 인증할 수 있습니다. 체크인 시 여행객이 직접 지불해야 합니다.
그러나 여행객이 체크인하지 못하는 상황이 발생할 수 있는데, 이 경우 숙박 시설은 노쇼 수수료를 부과할 수 있습니다. 이러한 요금은 여행객이 방문하지 않은 상태에서 카드에 비용을 청구해야 하기 때문에 PSD2 규정의 영향을 받을 수 있습니다.
거래가 영향을 받는 경우 결제에 실패할 수 있고, 청구가 규정을 준수하지 않으면 카드 브랜드에서 숙박 시설에 위약금을 부과할 수 있습니다.
숙박 시설과의 관계를 보호하고 파트너에게 지속적으로 서비스를 제공할 수 있도록 Expedia Group은 숙박 시설에 규정 준수를 위한 옵션을 제공합니다. 영향을 받는 숙박 시설은 이제 Expedia Group이 대신 2FA를 제공하도록 할 수 있습니다. 이를 통해 숙박 시설은 비즈니스를 보호하고 Rapid는 다양한 숙박 시설을 계속 제공할 수 있습니다.
Rapid에서는 숙박 시설 콘텐츠 파일 및 숙박 시설 콘텐츠에 <payment_registration_recommended=true>
플래그를 제공하여 프로젝트의 적용을 받을 가능성이 있는 숙박 시설을 식별할 수 있습니다.
참고: 유럽 경제 지역(EEA)에 소재한 숙박 시설만 2FA 대상이 됩니다. 2FA가 필요할 수 있는 숙박 시설은 고정되어 있지 않습니다. 다른 숙박 시설에서 이 기능을 사용하기로 설정하면 수가 늘어날 수 있습니다.
Property Collect용 2FA가 통합에 미치는 영향
파트너가 2FA를 필요로 하는 숙박 시설을 제공하려는 경우 예약 경로에서 2FA를 지원해야 합니다. 2FA를 지원하지 않으면 EEA에서 발급된 카드처럼 카드 발급 은행에서 거래에 2FA가 필요하다고 판단하는 경우 숙박 시설을 예약하지 못할 수도 있습니다.
숙박 시설에서 노쇼 수수료를 부과하는 경우 Rapid가 MOR(Merchant of Record)이 됩니다. 카드 청구 명세서의 청구 설명자는 숙박 시설에서 정할 수 없습니다. 설명자 값은 파트너에서 정의합니다. 이 텍스트를 사용자 지정하려면 Rapid 파트너 지원 팀에 문의해 주세요.
카드 브랜드의 요구 사항 및 Rapid 시행 절차를 준수하려면 노쇼가 발생하는 경우 결제 수락 API를 사용하여 결제 페이지에 processing_country
를 표시합니다. 이는 Rapid가 MOR(Merchant of Record)인 모든 거래에서 필수이며, 2FA를 사용하고 노쇼가 일어나는 경우 적용될 수 있습니다.
통합에 미치는 영향을 완화하는 방법
Rapid 통합이 예약 흐름에서 2FA를 지원하지 않는 경우 예약 실패 위험을 줄이려면 숙박 시설을 판매하지 않으면 됩니다.
영향을 받는 Property Collect 요금을 예약 가능 여부 API 응답에서 삭제하려면 Rapid 파트너 지원 팀에 문의해 주세요.
상담원 도구를 사용하는 경우 규정에 따라 거래에 2FA를 적용하지 않아도 됩니다. 이를 표시하려면 예약 가능 여부 API의 sales_channel
필드를 사용해 주세요.
오류 처리
예약 생성 API 및 결제 세션 완료 API를 사용하면 예약 및 결제 거래를 확정할 수 있습니다.
재정 손실을 방지하고 고객 운영 문제를 피하려면 통합 시 다음 지침을 고려해야 합니다.
소스 | 기능 | 추천 시간 제한 설정 | 오류 복구 절차 | 필요한 조치 |
---|---|---|---|---|
Rapid API | 결제 등록 토큰을 위한 사전 예약 요금 확인 | 10초 | 다시 시도하거나 다른 숙박 시설, 객실 또는 요금 선택 | - |
JavaScript | 3DS Connector 설정 | 10초 | 동일한 요청 재시도 | - |
Rapid API | 결제 세션 등록 | 10초 | "Expect: 100-Continue" 프로세스 없이 동일한 요청 재시도 | - |
JavaScript | 결제 세션 시작 | 10초 | 동일한 요청 재시도 | - |
Rapid API | 예약 생성 | 90초 | 동일한 요청 재시도 | 모든 오류의 경우 affiliate_reference_id 로 예약 검색 |
JavaScript | 2FA 챌린지 표시 | 10초 | 동일한 요청 재시도 | - |
JavaScript | challenge.statusCode 대기 | 180~1,200초 | 결제 세션 완료 요청 | - |
Rapid API | 결제 세션 완료 | 90초 | 동일한 요청 재시도 | 모든 오류의 경우 affiliate_reference_id 로 예약 검색 |
Rapid API | 모든 오류의 경우 affiliate_reference_id 로 예약 검색 | 30초 | 동일한 요청 재시도 | 모든 오류의 경우: API 응답 코드 404 또는 200으로 예약의 최종 상태를 확인하려면 재시도 전에 90초 대기 |