歐盟支付服務準則修正案 (PSD2)
歐洲經濟區支付卡法規對您業務上有何影響。
簡介
支付服務準則修正案 (Payment Services Directive 2,PSD2) 是歐洲經濟區 (EEA) 的法規,要求對於使用由 EEA 成員國核發的信用卡進行的各項交易,必須變更結帳與預訂流程以符合法規。
PSD2 提高安全且能防止詐騙,卻也完全改變了全歐洲的支付作業。根據法規,處理消費者電子支付時必須實行嚴格顧客驗證機制 (Strong Customer Authentication) 以符合規定。也就是全部發卡機構、收單機構和商店都必須支援嚴格顧客驗證機制。由於 EEA 銀行嚴格奉行此法,不符規定者將導致付款失敗。
本頁面為合作夥伴說明 Rapid API 支援的付款方式將受到哪些影響,以及您在服務旅客時可採行的做法。若想進一步了解 PSD2,請上歐洲執行委員會官方網站查詢法規細節。
合規要求
視正式商戶為何者、Rapid API 的支付方式為何,在 EEA 合法交易的做法有所不同。
當合作夥伴為正式商戶時
Expedia Affiliate Collect
使用 EAC 的預訂不受 PSD2 規定影響。付款流程和 Rapid API 整合都不需要變更,同樣能合法。然而,若您以商戶身分從旅客的信用卡、金融卡或其他符合歐盟法規的方式收費,就會受到一些影響。依法您可能必須支援符合 PSD2 的雙重身分驗證 (Two-Factor Authentication,2FA) 支付程序。請聯絡您的付款處理公司,看他們能如何幫助商戶符合 PSD2 規定、避免交易失敗。
合作夥伴支付卡
若貴公司是正式商戶,且使用 EEA 核發的公司信用卡或金融卡付款給 Rapid,則會受到 PSD2 的影響。符合 PSD2 規定的支付卡如下:
- EEA 內核發的單次使用虛擬卡。
- EEA 內核發的公司卡 (非個人卡)。
- EEA 以外核發的任一支付卡。
若您從旅客的信用卡、金融卡或其他符合 EEA 法規的方式收費,也會受到影響。依法您可能必須支援符合 PSD2 的雙重身分驗證 (Two-Factor Authentication,2FA) 支付程序。請聯絡您的付款處理公司,看他們能如何幫助商戶符合 PSD2 規定、避免交易失敗。
若貴公司不願使用上列符合 PSD2 規定的支付卡,可逕向貴公司的發卡銀行申請豁免。一旦通過豁免,則使用該卡交易不需身分驗證,但可能需以 2FA 方式進行單次線上驗證。此單次線上驗證依各銀行而異。請注意,從申請到通過豁免可能需要很長時間;此外,若發生任何詐騙交易,銀行可能會要求貴公司負責。
當 Rapid 為正式商戶時
若貴公司以 Rapid 為商戶,並把旅客的支付卡傳送給 Rapid 的話,則會受到 PSD2 規定影響。當旅客自行 (不透過零售旅行業者) 線上預訂時,依規定 Rapid 會請旅客驗證付款是否來自本人。該付款驗證方式須為雙重身分驗證 (2FA),才符合 PSD2 規定。若合作夥伴想以 Rapid 為正式商戶,且使用 EEA 核發的信用卡或金融卡付款,則必須採用 Rapid 的 2FA 解決方案。
然而,透過零售旅行業者或客服中心專員預訂的交易,則不需進行 2FA。只要註明預訂是由專人協助辦理,交易就符合規定。如有需要,可在「供應情況 API」的 sales_channel
欄位加註。
當旅宿為正式商戶時
若貴公司使用入住時付款,則可能會受到 PSD2 規定影響。某些情況下,旅宿會在旅客不在場時從其信用卡收費,例如:「預訂後未入住」的費用或訂金。若收費前沒經過雙重身分驗證 (2FA),便不符合規定。若合作夥伴想讓持 EEA 核發信用卡或金融卡的旅客使用入住時付款付款,則必須採用 Rapid 的 2FA 解決方案。
Rapid API 解決方案簡介
運作方式
若合作夥伴以 Rapid 為正式商戶,或讓旅客以支付卡透過入住時付款付費,可使用 Rapid 的 API 來產生合規的預訂。API 在預訂流程中支援以 3DS 2.0 來進行雙重身分驗證,因此符合 PSD2 規定。我們採用 3DS 2.0 基於風險控管概念的驗證機制,讓銀行決定何時以 2FA 來驗證旅客身分,減少您與旅客之間的摩擦機會。
2FA 解決方案由三大不同部分組成:
- 合作夥伴新增到付款頁面的 iframe,用來載入發卡銀行向旅客執行的 2FA,在整合相關文件中的名稱是 3DS iframe。
- 裝載於付款頁面的新用戶端 JavaScript Library,用來收集瀏覽器資料、與 iframe 溝通,並於 iframe 中提供 2FA 使用者體驗。其在整合相關文件中的名稱是 3DS Connector Library。
- Rapid 代替銀行接受付款人資料,並於通過 2FA 後完成預訂。
同時使用 JavaScript 和 Rapid 時,納入 2FA 後的預訂流程在呼叫「預訂 API」前後,即會多出一些步驟。下圖為更新後的預訂流程:
更新後的預訂流程中,上一步驟的輸出資料用做下一步驟的輸入資料。也就是資料會在瀏覽器的 JavaScript 和 Rapid 之間傳輸。
請注意:上圖為實際 API 流程的簡化版,做為初步說明之用。完整 API 流程請參閱整合相關文件。
整合所需元件詳細說明
瀏覽器 iframe
iframe 用在付款頁面中,內有來自旅客發卡銀行的 URL。該 URL 會顯示頁面讓旅客進行 2FA,並把旅客輸入的資料直接傳給銀行。iframe 一開始應設為隱藏,當旅客預訂時被要求進行 2FA,再將驗證網頁覆蓋在原頁面上。
瀏覽器 JavaScript Library
新增於付款頁面,並於預訂時調用出來支援 2FA 程序。其 API 支援以下功能:
自動收集旅客裝置上的資料
預訂前須先收集旅客裝置資料,為預訂時所需的 2FA 做準備。資料收集好後會傳送給旅客發卡銀行審查,由銀行決定交易是否需經 2FA,並確認資料顯示無誤。根據 3DS 2.x 規範,API 會從旅客的瀏覽器收集以下資料:語言、色彩深度、螢幕長寬、時區、使用者代理,和是否啟用 Java。
在瀏覽器 iframe 中讓使用者進行 2FA
進行預訂後,JavaScript Library 會用來顯示 iframe 置入的網頁,並將銀行網頁內容載入 iframe。在 2FA 過程中,銀行的內容可能會再收集旅客裝置的其他資料,以支援其風險評估。此為完成預訂的必要過程。
Rapid
Rapid 加入了幾個新的 API,可和用戶端的 JavaScript Library 接合。這些 API 目前支援以下功能:
登記旅客及付款詳情
預訂前須先收集其他旅客資料,為預訂時所需的 2FA 做準備。這些資料包括銷售點和付款等旅客帳戶詳情。資料收集好後會傳送給旅客發卡銀行審查,由銀行決定交易是否需經 2FA。詳情請見 Rapid 的「註冊付款 API」。
完成付款並確認預訂
使用 Rapid 進行預訂並於瀏覽器完成 2FA 程序後,必須再調用出 Rapid。我們會在後台確認成功通過 2FA,並確認預訂。詳情請見 Rapid 的完成付款工作階段 (Complete Payments Session)。
預訂流程
簡介
若 Partner Profile Rapid Support 中啟動了 2FA,則「價格檢查 API」會回傳連結到「註冊付款 API」,而不是到「建立預訂 API」。下圖所示為旅客下訂後的 API 所需呼叫順序,包括對 JavaScript Library 和對 Rapid 的呼叫。
雖會事先做好準備,但不是每筆預訂都需要進行 2FA。是否需要 2FA,是由旅客用來付費的信用卡發卡銀行決定。銀行會在交易過程中做出決定,結果則顯示在「建立預訂 API」的回應。
下圖所示為使用「暫停與繼續處理 API」所需的呼叫順序:
請注意:以上圖示皆為實際 API 流程的簡化版,做為初步說明之用。完整 API 流程請參閱整合相關文件。
更多資訊
若想進一步了解提供 2FA 程序所需技術,請參閱 EMVCo 的 3D 安全協定與主要功能說明。
Rapid 與雙重身分驗證整合指南
簡介
若要支援雙重身分驗證 (簡稱 2FA),需整合新的 JavaScript Library (稱為 3DS Connector) 和 Rapid。二者合併使用於付款頁面供旅客進行 2FA,並確認預訂。此解決方案支援 Expedia Collect 和入住時付款兩種商業模式。
下列為支援預訂時進行 2FA 所需的 API 呼叫順序,並於下個段落詳細說明:
- JavaScript 設定方法
- Rapid 註冊付款 API
- JavaScript 初始化工作階段方法
- Rapid 預訂 API
- JavaScript Challenge 方法
- Rapid 完成付款 API
若想允許上述呼叫順序,需由 Rapid 合作夥伴服務 (Rapid Partner Support) 幫您啟動設定檔 (Partner Profile) 裡的 2FA。
Rapid
若合作夥伴的設定啟動了 2FA,則 API 回應會變更,預訂流程也修改成包含 2FA。
供應情況 API
API 要求中 sales_channel
欄位裡的值必須正確無誤,才能在規定允許時取得 2FA 豁免。預訂過程中,支付卡發卡銀行會需要查看此 (以及其他) 欄位裡的值,以決定是否進行 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
這是為符合 PSD2 而併用 JavaScript-Rapid 修改後,預訂流程中的第二個步驟,出現在 JavaScriptsetup
方法之後。
要求中包含 PSD2 合規前預訂流程裡的付款詳情,再加上一些成功支援 2FA 的新欄位。其中兩個欄位:encoded_browser_metadata
和 version
是從 JavaScript API 的 setup method
回傳。
回應中會包括 payment_session_id
和 encoded_init_config
,並成為 JavaScript Library 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
這是為符合 PSD2 而併用 JavaScript-Rapid 修改後,預訂流程中的第四個步驟,出現在 JavaScriptinitSession
方法之後。要求中沒有因 PSD2 而新增的欄位,所需資訊都已包含在「註冊付款 API」回傳預訂連結的記號裡。若回應成功,一定會包含 itinerary_id
。單有此 ID 不表示預訂已確認,因為可能會需要經過 2FA。
如果需要 2FA,則回應還會包含 encoded_challenge_config
。從「註冊付款」回傳的 encoded_challenge_config
和 payment_session_id
必須用為參數傳入 JavaScript challenge
方法。
回應還會包括用來 complete_payment_session
的新連結。此連結應於 JavaScript Library 的 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
這是為符合 PSD2 而併用 JavaScript-Rapid 修改後,預訂流程中的第六個步驟,出現在 JavaScriptchallenge
方法之後。需要此 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 Library 和 3DS iframe
使用 PSD2 預訂流程時,付款頁面必須包含新的 iframe 和 JavaScript Library。其中 iframe (稱為 3DS iframe) 會用 3D-Secure 2.x 驗證程序顯示出,供旅客進行驗證。而 JavaScript Library (稱為 3DS Connector Library) 則負責傳送資料給發卡銀行,並把銀行的內容載入 iframe。
新增 3DS iframe 和 JavaScript Library
新增 3DS iframe
3DS iframe 應包在開始時為隱藏的容器中,當付款程序判定為必須進行驗證時,則會再顯示。
容器設計可配合裝載頁面來自訂。以下為使用 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>
iframe 的源 (source) 必須設為以下兩個值之一:
URL 類型 | URL | 備註 |
---|---|---|
正式環境 | https://static.pay.expedia.com/3ds/threeDsIframe.html | 支援 2FA 正式環境 |
測試沙箱 | https://static.pay.expedia.com/3ds/sandboxThreeDsIframe.html | 支援 2FA 測試 |
上列測試 URL 可支援測試,下文會再回到這個主題。為了在測試時限制 iframe 的內容,可在沙箱擬真環境裡測試,但必須容許以下:
sandbox = 'allow-scripts allow-forms allow-same-origin';
新增 3DS Connector JavaScript Library
3DS Connector Library 負責和 3DS iframe 溝通,並傳送資料給發卡銀行;銀行為 iframe 內容提供者。以下範例顯示如何將 3DS Connector Library 新增到付款頁面。
<head>
<script src="<<3DS connector script URL>>" integrity="<<actual integrity value>>"></script>
</head>
script 元素的 source 和 integrity 值應設為如下所示:
Library 版本 | 屬性 | 值 |
---|---|---|
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 |
請注意:日後有更新版本可用時,這裡的 source URL 和 integrity 也會變更。新版不會破壞現有的整合。舊版的 script 元素仍可存取。
使用 3DS iframe 和 JavaScript Library
JavaScript Library 需使用 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 Library 內容,旨在示範可支援資料傳輸到 API 的封套資料。
範例中使用靜態變數為參數,執行時應另行決定,如 referenceId
。
付款頁面指南
支援 2FA 的支付卡公司可能會要求把品牌名稱和商標顯示出來,以符合其公司規定。
支付卡類別 | 2FA 品牌名稱 | 商標和使用方法 |
---|---|---|
MasterCard (萬事達卡) | 萬事達卡 ID Check | (https://brand.mastercard.com/debit/mastercard-brand-mark/downloads.html))] |
Visa | Visa 驗證 | [https://www.merchantsignage.visa.com/brand_guidelines |
備註:待其他卡別的商標和使用辦法公布時會再納入此表。
3DS Connector JavaScript Library 相關文件
類別:ThreeDSConnector
建構函式 (Constructor)
new ThreeDSConnector(threeDsIFrameId, threeDsIFrameOrigin)
參數:
名稱 | 類型 | 說明 |
---|---|---|
threeDsIFrameOrigin | 字串 | 3DS iframe 的 ID。 |
threeDsIFrameOrigin | 字串 | 3DS iframe 的原點 (Origin)。在與 3DS iframe 溝通使用以傳出視窗訊息並過濾接受訊息。 |
方法
設定
透過收集後端 3DS 服務所需的瀏覽器基本資料 (如螢幕尺寸、色彩深度等) 來設定付款工作階段。
方法簽章 (Method signature):
setup(setupRequest)
參數:
名稱 | 類型 |
---|---|
setupRequest | SetupRequest |
回傳:
SetupResponse
的 Promise 物件
初始化工作階段
初始化與 3DS 間的工作階段,以進行驗證。進行初始化可能需要從瀏覽器收集其他資料。若發卡機構提出要求,iframe 可載入 3DS URL 來啟動發卡機構的存取控制伺服器 (Access Control Server),直接從瀏覽器收集資料。用戶端不必等待回呼完成,於建立命令前即可調用。
方法簽章 (Method signature):
initSession(initSessionRequest)
參數:
名稱 | 類型 |
---|---|
initSessionRequest | InitSessionRequest |
回傳:InitSessionResponse
的 Promise 物件
挑戰 (Challenge)
若發卡機構要求進行驗證,則載入 3DS 安全認證機制。
方法簽章 (Method signature):
challenge(challengeRequest)
參數:
名稱 | 類型 |
---|---|
challengeRequest | ChallengeRequest |
回傳:ChallengeResponse
的 Promise 物件
類別 (Class):SetupRequest
設定呼叫的需求架構。
性質:
名稱 | 類型 | 說明 |
---|---|---|
referenceId | string | 辨識旅客付款頁面工作階段的參考 ID,用於記錄和追蹤。請使用 APIKey 和 Customer-Session-ID 的序連字元,中間以下劃線連接,例如:[APIKey]_[SessionID] |
類別 (Class):SetupResponse
來自設定呼叫的回應。
性質:
名稱 | 類型 | 說明 |
---|---|---|
version | 字串 | 函式庫版本,和連往函式庫的 URL 所示版本相同。 |
encodedBrowserMetadata | 字串 | 編碼物件,內含從瀏覽器收集的資料。用戶端應將此視為不透明數據,無需解析即可傳給後端支付服務。 |
類別 (Class):InitSessionRequest
initSession
方法的需求架構。
性質:
名稱 | 類型 | 說明 |
---|---|---|
paymentSessionId | 字串 | 「Rapid 註冊付款 API」傳回的唯一識別碼。 |
encodedInitConfig | 字串 | 編碼物件組態清單,內含初始化所需資料,由「Rapid 註冊付款 API」傳回。 |
類別 (Class):InitSessionResponse
initSession
方法的回應結構。
性質:
名稱 | 類型 | 說明 |
---|---|---|
statusCode | 字串 | initSession 呼叫的狀態。 |
message | 字串 | 可選用。標示失敗原因。 |
statusCode
可能會有以下的值:
值 | 說明 |
---|---|
SUCCESS | 初始化成功完成。 |
SKIPPED | 沒有進行初始化。 |
FAILED | 初始化失敗。訊息欄位包含更多失敗相關的訊息。 |
TIMEOUT | 初始化未在時間內完成。時限為 10 秒。 |
備註:若需完整 initSessionresponse
statusCode
,請查看「Rapid 預訂 API」。
類別 (Class):ChallengeRequest
挑戰 (Challenge) 方法的需求架構。
性質:
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 挑戰 (Challenge) 成功完成。 |
SKIPPED | 外部應用程式錯誤。 |
FAILED | 由於持卡人無法正確回應身分驗證挑戰,故 3DS 挑戰未成功完成。 |
TIMEOUT | 挑戰未在時間內完成。時限為 1200 秒。 |
備註:若需完整 challengeResponse
statusCode
,請查看 Rapid 完成付款對話 (Complete Payment Session)。
Rapid 與雙重身分驗證測試
若想測試與 Rapid 和 3DS Connector 方法的整合,可輸入符合 API 支援特定環境的參數值進行測試。
Rapid
若要測試 Rapid,請在 HTTP 要求中加上名為 Test 的 HTTP 標頭,再使用 API 支援的其中一個值來測試所支援的環境。
在 PSD2 預訂流程中,Rapid 的測試回應也可用來測試 3DS Connector Library 方法。
註冊付款 (Register Payments)
以下測試標頭值在 API 回應中會產生不同 encoded_init_config
,以及不同 HTTP 回應碼。encoded_init_config
可傳入 JavaScript Library 的 initSession
呼叫,以啟動 3DS Connector Library 中的不同測試用例。
測試標題值 | HTTP 代碼與回應 | initSession 測試用例 |
---|---|---|
standard | 201 – 標準回應 | SUCCESS |
init_skip | 201 - 不含 encodedInitConfig 的回應 | Not supported |
init_fail | 201 – 標準回應 | FAILED |
init_timeout | 201 – 標準回應 | TIMEOUT |
internal_server_error | 500 – 內部伺服器錯誤 | |
internal_server_error | 503 - 伺服器無法使用 |
備註:init_skip
3DS Connector Library.t_config
裡的不同測試案例可傳到 initSession
,便會強行產生名為 SKIPPED 的 statusCode
。
建立預訂
除了在 Rapid 預訂測試要求為非 PSD2 預訂流程定義的不同測試標頭外,還有其他支援 PSD2 流程的測試標頭值。
測試標頭值會產生不同的 encodedChallengeConfig
值,這些值可傳入 JavaScript Library 的 challenge
呼叫,以觸發不同的測試案例。
測試標題值 | HTTP 代碼與回應 | initSession 測試用例 |
---|---|---|
complete_payment_session | 201 – 含完成付款工作階段連結的回應 | SUCCESS 無使用者 iframe 互動 |
complete_payment_session_show | 201 – 含完成付款工作階段連結的回應 | SUCCESS/FAILED 有使用者 iframe 互動 |
complete_payment_session_fail | 201 – 含完成付款工作階段連結的回應 | FAILED 無使用者 iframe 互動 |
complete_payment_session_timeout | 201 – 含完成付款工作階段連結的回應 | TIMEOUT |
complete_payment_session_error | 201 – 含完成付款工作階段連結的回應 | ERROR |
完成付款工作階段
在試著完成付款並確認預訂時,測試標頭值會產生不同錯誤情況。
測試標題值 | HTTP 代碼與回應 |
---|---|
payment_declined | 400 - 付款遭拒回應 |
price_mismatch | 409 - 房價不符回應 |
rooms_unavailable | 410 - 無空房回應 |
3DS Connector Library 和 iframe
在無外部相依關係下測試 3DS Connector 時,需使用符合支援方法回應的特定參數值。僅限 iframe 用測試沙箱 URL 載入時才支援這種做法。
初始化工作階段
InitSessionResponse statusCode
所支援的值可用變更 initSessionRequest encodedInitConfig
的方法來測試。
statusCode 值 | 測試 encodedInitConfig 值 |
---|---|
SUCCESS | W3sicHJvdmlkZXJJZCI6IDAsICJz YW5kYm94SW5pdE91dHB1dENvbmZpZyI6ICJTVUNDRVNTIn1d |
FAILED | W3sicHJvdmlkZXJJZCI6IDAsICJz YW5kYm94SW5pdE91dHB1dENvbmZpZyI6ICJGQUlMRUQifV0= |
TIMEOUT | W3sicHJvdmlkZXJJZCI6IDAsICJz YW5kYm94SW5pdE91dHB1dENvbmZpZyI6ICJUSU1FT1VUIn1d |
SKIPPED | Not supported at this time. |
注意:encoded_init_config
值也可以使用「註冊付款 API」支援的測試標頭產生。
挑戰 (Challenge)
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 範例:
用法範例
以下為執行範例,僅供參考。範例中可看到如何使用預先定義的值來測試 Library 進行 3DS 挑戰,而不需要使用者與 iframe 互動。
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 規定影響,因為是在旅客不在場時從支付卡收費。
當交易受 PSD2 影響而收款手續卻不符規定,則可能會導致交易失敗,旅宿也可能會面臨信用卡公司的罰款。
Expedia Group 為了維持與旅宿的良好關係,並繼續服務我們的合作夥伴,因此提供給旅宿另一項合規辦法:現在開始,受 PSD2 規定影響的旅宿可用 Expedia Group 的名義提供 2FA。如此一來,旅宿的業務不受影響,而 Rapid 也可繼續提供各式各樣的住宿選擇。
Rapid 在 Property Content File 和 Property Content 中提供了 <payment_registration_recommended=true>
旗標,方便您辨識出可能涉及上述情形的旅宿。
請注意:僅有位於歐洲經濟區 (簡稱 EEA) 內的旅宿才需進行 2FA,而設成需要 2FA 的旅宿並非固定不變,當有更多旅宿選擇啟用此功能時,數量就會增加。
入住時付款的 2FA 對系統整合有何影響?
合作夥伴若想提供需 2FA 的旅宿,則您的預訂路徑必須支援 2FA。若預訂路徑不支援 2FA,一旦發卡銀行決定交易需要 2FA 時 (例如 EEA 內核發的卡),則可能導致預訂失敗。
當旅宿收取未入住罰款時,是以 Rapid 為正式商戶。該筆交易列在信用卡明細上的請款商戶名稱非旅宿所能決定。請款商戶名稱係由合作夥伴來決定。若想自訂此名稱,請聯絡 Rapid 合作夥伴服務。
為符合信用卡公司及 Rapid 的啟用規定,收取未入住罰款時,請使用 Accepted Payments API 在付款頁面顯示 processing_country
。所有以 Rapid 為正式商戶時的交易都需要這項顯示;在使用 2FA 收取未入住罰款的情況下,Rapid 是交易的正式商戶。
如何減輕對系統整合的影響
若整合後的 Rapid 不支援預訂流程的 2FA,為降低失敗風險,可考慮不開放這些旅宿給旅客預訂。
請聯絡 Rapid 合作夥伴支援,將這些受影響的入住時付款旅宿從「供應情況 API」回應中移除。
根據規定,使用旅行業者工具交易時不需進行 2FA。如有需要,可在「供應情況 API」的 sales_channel
欄位加註。
錯誤處理
「建立預訂 API」和「完成付款工作階段 API」可能會產生預訂確認和付款交易。
系統整合時請考慮以下說明,以避免財物損失和客戶操作的情形。
來源 | 功能 | 建議時限 | 錯誤復原做法 | 需採取的行動 |
---|---|---|---|---|
Rapid API | 註冊付款的預訂前價格檢查記號 | 10 秒 | 重試或選擇其他住宿、客房或房價 | - |
JavaScript | 3DS Connector 設定 | 10 秒 | 重試相同的要求 | - |
Rapid API | 註冊付款工作階段 | 10 秒 | 重試相同要求,拿掉 "Expect: 100-Continue" process | - |
JavaScript | 初始化付款工作階段 | 10 秒 | 重試相同的要求 | - |
Rapid API | 建立預訂 | 90 秒 | 重試相同的要求 | 所有錯誤:用 affiliate_reference_id 取回預訂 |
JavaScript | 顯示 2FA 挑戰 | 10 秒 | 重試相同的要求 | - |
JavaScript | 等待 challenge.statusCode | 180 ~ 1200 秒 | 要求完成付款工作階段 | - |
Rapid API | 完成付款工作階段 (Complete Payment Session) | 90 秒 | 重試相同的要求 | 所有錯誤:用 affiliate_reference_id 取回預訂 |
Rapid API | 所有錯誤:用 affiliate_reference_id 取回預訂 | 30 秒 | 重試相同的要求 | 所有錯誤:等待 90 秒後再重試,用 API 回應碼 404 或 200 確認預訂最後狀態 |