Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Minimal UI Payment Handlers

Minimal UI Payment Handlers

Objective

Provide a golden path, low friction experience for users that are enrolled with payment handlers that support a minimal UI.

Overview

The following conditions must be satisfied to trigger the flow.

  1. The payment handler must register for minimal UI.
try {
  // Feature detection:
  if (registration.paymentManager.setMinimalUITriggerThreshold) {
    await registration.paymentManager.setMinimalUITriggerThreshold({"USD": "2.00", "JPY": "200"});
  }
} catch (e) {
  Sentry.captureException(e);  // Upload errors to the server for analysis.
}
  1. Merchant must request payment with certain properties.
    1. A single URL-based payment method.
    2. Payment handler’s currency.
    3. Value below the minimal UI trigger threshold and account balance.
    4. Only total specified.
    5. No shipping address or contact information requested.
    6. No promise for updated details passed into the show() method.
    7. show() triggered on user gesture.
try {
  const request = new PaymentRequest(
    [{supportedMethods: "https://paypal.com"}],
    {total: {label: "Payment", amount: {currency: "USD", value: "1.00"}}});
  const response = await request.show();
  await response.complete("success");
} catch (e) {
  Sentry.captureException(e);  // Upload errors to the server for analysis.
}
  1. The payment handler must handshake in the Can Make Payment event.
self.addEventListener("canmakepayment", (evt) => {
  // Feature detection:
  if (evt.respondWithMinimalUI && evt.currency) {
    return evt.respondWithMinimalUI({
      canMakePayment: true,
      readyForMinimalUI: (evt.currency === "USD" || evt.currency == "JPY")
                          && !userNeedsToReAuthenticate,
      accountBalance: "18.00",
    });
  } else {
    return evt.respondWith(true);
  }
});

The minimal UI flow then asks the user to scan their fingerprint or tap the Pay button on the screen, if the biometrics hardware is not available. The fingerprint scan is purely a confirmation step and its data is not shared with either payment handler or merchant.

User agent disables the openWindow() method in this flow, because the payment handler always responds with the payment details directly.

The account balance from the payment handler is not shared with the merchant.

Sample UI

Proposed Android minimal UI screenshot

@matdehaast

This comment has been minimized.

Copy link

@matdehaast matdehaast commented Nov 7, 2019

@rsolomakhin There is an incorrect bracket in

if {registration.paymentManager.setMicrotransactionLimit)

The first bracket needs to be (

@rsolomakhin

This comment has been minimized.

Copy link
Owner Author

@rsolomakhin rsolomakhin commented Nov 7, 2019

Thank you, @matdehaast! Fixed.

@danyao

This comment has been minimized.

Copy link

@danyao danyao commented Feb 12, 2020

@rsolomakhin What is the difference between canMakePayment and readyForMinimalUI in respondWithMinimalUI()?

@rsolomakhin

This comment has been minimized.

Copy link
Owner Author

@rsolomakhin rsolomakhin commented Feb 12, 2020

If the user has enrolled in the minimal UI flow with the payment handler, then the payment handler should respond with canMakePayment: true, readyForMinimalUI: true. Chrome will display the minimal UI. After the user has scanned their fingerprint, Chrome will fire the "paymentrequest" event in the payment handler.

If the user has not enrolled in the minimal UI flow yet, then the payment handler should respond with canMakePayment: true: readyForMinimalUI: false. Chrome will fire the "paymentrequest" event in the payment handler, so it can open the window to enroll the user.

If payment handler does not want to handle any payments at all, then it should respond with canMakePayment: false. Chrome will reject PaymentRequest.show() with NotSupportedError.

@estark37

This comment has been minimized.

Copy link

@estark37 estark37 commented Apr 16, 2020

Someone pointed me to the Intent to Prototype for this feature. Can you elaborate on the security story a bit? In particular I notice there is no origin on the payment handler UI.

@rsolomakhin

This comment has been minimized.

Copy link
Owner Author

@rsolomakhin rsolomakhin commented Apr 16, 2020

Absence of origin was a deliberate choice at the time, but we're up for discussion. Our reasoning was:

  1. Payment handler cannot display HTML content.
  2. Merchant must request payment directly through a single payment app.
  3. Two user gestures is required for payment: one to trigger the browser UI and another one to confirm payment.
  4. Biometric information is not passed to either merchant or payment handler.
@maxlgu

This comment has been minimized.

Copy link

@maxlgu maxlgu commented Sep 13, 2021

Chrome is deleting the Minimal UI implementation in https://chromium-review.googlesource.com/c/chromium/src/+/3150591

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment