PSD2 European Compliance

Use the SDK to ease compliance with PSD2 EEA regulations.

The Payment Services Directive 2 (PSD2) is an EEA regulation that requires changes to the check-out and booking process for all transactions involving a credit card issued by an EEA state. For more information on PSD2 please see here.

1. Shop

Get availability

List<Property> propertyList = rapidClient.getAvailability(
        "YYYY-MM-DD",
        "YYYY-MM-DD",
        "USD",
        "LANGUAGE",
        "US",
        List.of("OCCUPANCY"),
        List.of("PROPERTY ID"),
        BigDecimal.ONE,
        "SALES-CHANNEL",
        "SALES-ENV",
        "CUSTOMER-IP"
);

Get price check token

String getToken(String href) throws MalformedURLException {
        URL url = new URL("ENDPOINT" + href);
        String query = url.getQuery();
        String[] split = query.split("&");
        String token = null;
        for (String params : split) {
            String prefix = "token=";
            if (params.startsWith(prefix)) {
                token = params.replaceAll(prefix, "");
            }
        }
        return token;
}

String getPriceCheckToken(PropertyAvailability propertyAvailability) throws MalformedURLException {
        return getToken(propertyAvailability.getRooms().get(0).getRates().get(0).getBedGroups().entrySet().stream().findFirst().get().getValue().getLinks().getPriceCheck().getHref());
}

Check room prices

Property property = propertyList.get(0);

if (property instanceof PropertyAvailability) {
        PropertyAvailability propertyAvailability = (PropertyAvailability) property;

        RoomPriceCheck roomPriceCheck = rapidClient.priceCheck(
                "PROPERTY ID",
                propertyAvailability.getRooms().get(0).getId(),
                propertyAvailability.getRooms().get(0).getRates().get(0).getId(),
                getPriceCheckToken(propertyAvailability)
        );
}

2. Book

Get payment session token and create payment session request

String getPaymentSessionToken(RoomPriceCheck roomPriceCheck) throws MalformedURLException {
        return getToken(roomPriceCheck.getLinks().getPaymentSession().getHref());
}

PaymentSessionsRequestCustomerAccountDetails customerAccountDetails =
        PaymentSessionsRequestCustomerAccountDetails.builder()
                .authenticationMethod(PaymentSessionsRequestCustomerAccountDetails.AuthenticationMethod.GUEST)
                .authenticationTimestamp("YYYY-MM-DDTHH:mm:00.000Z")
                .createDate("YYYY-MM-DD")
                .changeDate("YYYY-MM-DD")
                .passwordChangeDate("YYYY-MM-DD")
                .addCardAttempts(BigDecimal.ONE)
                .accountPurchases(BigDecimal.ONE)
                .build();

BillingContactRequestAddress address = 
        BillingContactRequestAddress.builder()
                .line1("LINE 1")
                .line2("LINE 2")
                .line3("LINE 3")
                .city("CITY")
                .stateProvinceCode("STATE CODE")
                .countryCode("COUNTRY CODE")
                .postalCode("POSTAL CODE")
                .build()


BillingContactRequest billingContact =
        BillingContactRequest.builder()
                .givenName("John")
                .familyName("Smith")
                .address(address)
                .build();

List<PaymentRequest> payments = List.of(
        PaymentRequest.builder()
        .type(PaymentRequest.Type.CUSTOMER_CARD)
        .number("NUMBER")
        .securityCode("SECURITY CODE")
        .expirationMonth("EXPIRATION MONTH")
        .expirationYear("EXPIRATION YEAR")
        .billingContact(billingContact)
        .enrollmentDate("ENTROLLMET DATE")
        .build()
)

PaymentSessionsRequest createPaymentSessionRequest() {
        return PaymentSessionsRequest.builder()
                .version("VERSION")
                .browserAcceptHeader("*/*")
                .encodedBrowserMetadata("BROWSER METADATA")
                .preferredChallengeWindowSize(PaymentSessionsRequest.PreferredChallengeWindowSize.MEDIUM)
                .merchantUrl("MERCHANT URL")
                .customerAccountDetails(customerAccountDetails)
                .payments(payments)
                .build();
}

Create payment session

PaymentSessions paymentSessions = rapidClient.postPaymentSessions(
        "CUSTOMER IP",
        getPaymentSessionToken(roomPriceCheck),
        createPaymentSessionRequest()
);

Pass the JavaScript challenge

If 2FA is required, the response will include an encodedChallengeConfig. The encodedChallengeConfig and paymentSessionId returned will need to be passed as parameters into the JavaScript challenge method.

Get post itinerary token and create itinerary request

String getPostItineraryToken(RoomPriceCheck priceCheck) throws MalformedURLException {
        return getToken(priceCheck.getLinks().getBook().getHref());
}

CreateItineraryRequest createItineraryRequest(boolean hold) {
        PhoneRequest phone =
                PhoneRequest.builder()
                        .countryCode("COUNTRY CODE")
                        .areaCode("AREA CODE")
                        .number("NUMBER")
                        .build();

        List<CreateItineraryRequestRoom> rooms = List.of(
                CreateItineraryRequestRoom.builder()
                        .givenName("John")
                        .familyName("Smith")
                        .smoking(false)
                        .specialRequest("SPECIAL REQUEST")
                        .build()
        );

        BillingContactRequestAddress address =
                BillingContactRequestAddress.builder()
                        .line1("LINE 1")
                        .line2("LINE 2")
                        .line3("LINE 3")
                        .city("CITY")
                        .stateProvinceCode("STATE CODE")
                        .countryCode("COUNTRY CODE")
                        .postalCode("POSTAL CODE")
                        .build();

        BillingContactRequest billingContact =
                BillingContactRequest.builder()
                        .givenName("John")
                        .familyName("Smith")
                        .address(address)
                        .build();

        List<PaymentRequest> payments = List.of(
                PaymentRequest.builder()
                        .type(PaymentRequest.Type.CUSTOMER_CARD)
                        .number("NUMBER")
                        .securityCode("SECURITY CODE")
                        .expirationMonth("MONTH")
                        .expirationYear("YEAR")
                        .billingContact(billingContact)
                        .enrollmentDate("ENROLLMENT_DATE")
                        .build()
        );

        return CreateItineraryRequest.builder()
                .affiliateReferenceId(UUID.randomUUID().toString().substring(0, 28))
                .hold(hold)
                .email("john@example.com")
                .phone(phone)
                .rooms(rooms)
                .payments(payments)
                .affiliateMetadata("AFFILIATE METADATA")
                .taxRegistrationNumber("TAX NUMBER")
                .travelerHandlingInstructions("INSTRUCTIONS")
                .build();
}

Create itinerary

ItineraryCreation itineraryCreation = rapidClient.postItinerary(
        "CUSTOMER IP",
        getPostItineraryToken(roomPriceCheck),
        createItineraryRequest(true)
);

Get complete payment session token

String getCompletePaymentSessionToken(ItineraryCreation itineraryCreation) throws MalformedURLException {
        return getToken(itineraryCreation.getLinks().getCompletePaymentSession().getHref());
}

Complete payment session

CompletePaymentSession completePaymentSession = rapidClient.putCompletePaymentSession(
        "CUSTOMER IP",
        itineraryCreation.getItineraryId(),
        getCompletePaymentSessionToken(itineraryCreation)
);

Get resume booking token

String getResumeBookingToken(ItineraryCreation itineraryCreation) throws MalformedURLException {
        return getToken(itineraryCreation.getLinks().getResume().getHref());
}

Resume on-hold booking

rapidClient.putResumeBooking(
        "CUSTOMER IP",
        completePaymentSession.getItineraryId(),
        getResumeBookingToken(itineraryCreation)
);
Did you find this page helpful?
How can we improve this content?
Thank you for helping us improve Developer Hub!