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

GetAvailabilityOperationParams getAvailabilityOperationParams = GetAvailabilityOperationParams.builder()
    .checkin("YYYY-MM-DD")
    .checkout("YYYY-MM-DD")
    .currency("USD")
    .language("en_US")
    .countryCode("US")
    .occupancy(List.of("OCCUPANCY"))
    .propertyId(List.of("PROPERTY ID"))
    .customerIp("127.0.0.1")
    .ratePlanCount(BigDecimal.ONE)
    .salesChannel("SALES CHANNEL")
    .salesEnvironment("SALES ENVIRONMENT")
    .build();

GetAvailabilityOperation getAvailabilityOperation = new GetAvailabilityOperation(getAvailabilityOperationParams);
Response<List<Property>> propertiesResponse = rapidClient.execute(getAvailabilityOperation);

Get price check token

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

Check room prices

Property property = propertiesResponse.getBody().get(0);

if (property instanceof PropertyAvailability) {
    PropertyAvailability propertyAvailability = (PropertyAvailability)property;
    PriceCheckOperationParams priceCheckOperationParams = PriceCheckOperationParams.builder()
        .propertyId("PROPERTY ID")
        .roomId(propertyAvailability.getRooms().get(0).getId())
        .rateId(propertyAvailability.getRooms().get(0).getRates().get(0).getId())
        .token(getPriceCheckToken(propertyAvailability))
        .build();
    Response<RoomPriceCheck> response = rapidClient.execute(new PriceCheckOperation(priceCheckOperationParams));
    RoomPriceCheck roomPriceCheck = response.getBody();
}

2. Book

Get payment session token and create payment session request

String getPaymentSessionToken(RoomPriceCheck roomPriceCheck) throws MalformedURLException {
        return rapidClient.helpers.extractToken(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

PostPaymentSessionsOperationParams paymentSessionsParams = PostPaymentSessionsOperationParams
    .builder()
    .customerIp("CUSTOMER IP")
    .token(getPaymentSessionToken(roomPriceCheck))
    .build();

PostPaymentSessionsOperation paymentSessionsOperation = new PostPaymentSessionsOperation(createPaymentSessionRequest(), getpaymentSessionsParams);
Response<PaymentSessions> paymentSessionsResponse = rapidClient.execute(paymentSessionsOperation);
PaymentSessions paymentSessions = paymentSessionsResponse.getBody();

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 rapidClient.helpers.extractToken(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

PostItineraryOperationParams itineraryCreationParams = PostItineraryOperationParams
    .builder()
    .customerIp("CUSTOMER IP")
    .token(getPostItineraryToken(roomPriceCheck))
    .build();

PostItineraryOperation itineraryCreationOperation = new PostItineraryOperation(createItineraryRequest(true), itineraryCreationParams);

Response<ItineraryCreation> response = rapidClient.execute(itineraryCreationOperation);
ItineraryCreation itineraryCreationResponse = response.getBody();

Get complete payment session token

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

Complete payment session

PutCompletePaymentSessionOperationParams completePaymentSessionParams = PutCompletePaymentSessionOperationParams
    .builder()
    .customerSessionId("CUSTOMER IP")
    .itineraryId(itineraryCreationResponse.getItineraryId())
    .token(getCompletePaymentSessionToken(itineraryCreation))
    .build();

PutCompletePaymentSessionOperation completePaymentSessionOperation = new PutCompletePaymentSessionOperation(completePaymentSessionParams);
Response<CompletePaymentSession> completePaymentSessionResponse = rapidClient.execute(completePaymentSessionOperation);
CompletePaymentSession completePaymentSession = completePaymentSessionResponse.getBody();

Get resume booking token

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

Resume on-hold booking

PutResumeBookingOperationParams putResumeBookingParams = PutResumeBookingOperationParams
    .builder()
    .customerIp("CUSTOMER IP")
    .itineraryId(completePaymentSession.getItineraryId())
    .token(getResumeBookingToken(itineraryCreation))
    .build();

PutResumeBookingOperation putResumeBookingOperation = new PutResumeBookingOperation(putResumeBookingParams);
rapidClient.execute(putResumeBookingOperation);
Did you find this page helpful?
How can we improve this content?
Thank you for helping us improve Developer Hub!