Re: Rethinking Apps Payments API, Re: Payment App API: updated flow description

Comparing the two APIs:

I'm going to use MC to refer to Marcos' spec, and PG to refer to the
payment group's.

# Registration

I like how MC makes permission explicit. In PG, it isn't really clear that
setManifest would be a permission-requiring method. However, I think
something like
https://github.com/marcoscaceres/payment-request-handler/issues/2 would be
closer to how it's defined for similar APIs like Push. I like the
integration with the permission API.

# Setting payment methods & metadata

I much prefer the MC option of having APIs to get/set parts of the payment
app, rather than have one big object specify it. Both APIs are open to some
race conditions when it comes to getting & setting a value, but this is
much more likely to cause an issue in the PG API.

With the PG example, if I wanted to add an "option", I have to get the
entire manifest, add an "option" to the returned object, then set it. If I
have one thread trying to update the icons while another is adding an
option, the reads and writes can interleave, resulting in data loss.

MC has icons per "method", whereas PG has a single set of icons for the
app. From what I understand, the icons are intended for the app as a whole,
so MC should move the definition of this somewhere else. It's another good
argument for
https://github.com/marcoscaceres/payment-request-handler/issues/2.

MC is missing somewhere to add the name of the app. I don't know if this is
intentional. If not, it could also go in the register call.

# "Can handle payment"

As Marcos pointed out, PG's use of canHandle doesn't really make sense. You
can see the fudging around step 10
https://w3c.github.io/webpayments-payment-apps-api/#matching - this would
break all kinds of expectations around closures. Also, it's kinda why
service workers were invented - MC gets this right.

The event name MC uses "canhandlepayment" doesn't sound like an event.
Maybe that doesn't matter. ev.canMakePayment could probably be better named
too, since it feels like it's "allowing" if called without any params.
respondWith(promise) might be a better model to follow. Anyway that's a
minor bit of bikeshedding.

# Handling a payment

I'd love to see some UI proposals for how a user is connected to a
particular payment app. That might help solve some of the confusion around
https://github.com/w3c/webpayments-payment-apps-api/issues/48.

This is the most important part of the spec for me, as the patterns here
will influence other APIs that call out to another API that may want to
show UI, such as the credential API, and maybe intent APIs in future.

I don't have strong opinions on the PaymentRequest (MC) vs
PaymentAppRequest (PG) objects. It comes down to if it makes sense to
expose the methods & events on the PaymentRequest object to the other
origin. The more I think about it, the PG model might make more sense.

The way MC puts openClientWindow on the event object is great - this means
the browser can link the created window to the payment process, which PG
cannot. With the MC model, the browser can automatically close the window
once the payment is complete, and return to the vendor site.

Both MC and PG rely on up to two tabs plus a service worker being in memory
to make a payment work. This may cause problems with lower-memory devices -
I'm not sure. Working around this would massively complicate the API, so
hopefully it won't be a problem.

Both models rely on postMessage to communicate with the client. I'm in two
minds about it, but there may be higher-level options that would allow the
client to produce the response itself. Eg:

addEventListener("paymentrequest", event => {
  if (canHandleWithoutUi) {
    event.respondWith(response);
    return;
  }
  event.respondWith(event.showWindow(url));
});

And the window would have something like
navigator.payments.provideResponse(response) which, when called, would
close the window, and pass the result back to the service worker. Again,
I'm in two minds about it, but it'd remove the need for the clunky
postmessage work.

Hope this helps!

On Mon, 23 Jan 2017 at 13:38 Jake Archibald <jakearchibald@google.com>
wrote:

> Before I dig in and do a full review, I'm really grateful this spec has
> extensive examples. It means I, as a reader, know how to read the spec and
> get an impression of the user flow.
>
> Not only is this useful for someone who isn't an insider to the working
> group, it provides proof that the developer experience has been considered.
> This is probably the case with the current spec, but it isn't evident from
> a glance.
>
> On Mon, 23 Jan 2017 at 09:24 Marcos Caceres <mcaceres@mozilla.com> wrote:
>
> ## tl;dr - a New Approach
> Top posting because I think we need a reformulation of the Payments Apps
> API.
> I propose a new API shape here:
>
> https://marcoscaceres.github.io/payment-request-handler/
>
> * It addresses all the same use cases/requirements.
> * It integrates with PaymentRequest - allowing implementation of
> `PaymentResponse` in Service Workers.
> * It solves the canHandle() issue.
> * It solves the identity problem (it's just origin).
> * It solves the "manifest" problem (use it if it's there!) - and doesn't
> require trashing everything any time there is an update.
> * it provides a secure way to open a payment flow window.
> * it doesn't magically fill in stuff (e.g., shipping address) - giving the
> payment handler more control over the response, and providing the ability
> to create much richer payment handling web applications.
>
> The above is just the API shape (no algorithms yet), but it shows how it
> is expected to work with the code examples.
>
> ## The long version
> Firstly, I must acknowledge that the current API (and surrounding
> discussions) have done a great job at formulating the use cases and
> requirements for this API. Thus it serves as an important foundation to
> build on.
>
> However, the current Payment API does not meet the use cases (listed
> below), it is impossible to implement, it's obsessed with the idea of
> "manifests", and has become bogged down in issues that are clearly outside
> it's scope: like, trying to change the web security model, issues of
> application identity, etc).
>
> These are tremendously important problems, but they are outside the scope
> of this work. Those are issues that we need to address universally in the
> web platform, but they are not issues that this working group can solve in
> isolation.
>
> ## Let's start with use cases and requirements
>
> The fundamental *use cases* are:
>
> 1. Register an web app, with user consent, to handle requests for payment
> of particular types (e.g., credit cards, a proprietary payment method).
> 2. Allow the end-user to manage payment methods (adding, deleting,
> modifying, etc.) - and for these methods to be available as payment options
> upon request for payment. This includes providing both visual and
> accessible representations of those payment methods (i.e., icons and text).
> 3. Allow merchants to query if those payment methods are available at
> point of sale.
>
> The *requirements** are thus:
>
> R1. Registration: Provide a means for a web application to get user
> consent to act as a payment handler (a "powerful feature", amongst other
> powerful features).
>
> R2. Payment Method Management: Where there are multiple payment methods,
> provide a means to allow the end-user to manage payment methods.
>
> R3. Payment Handling: handle "request" for payment, and facilitate
> communication between a `PaymentRequest`, the end-user (through a payment
> UI), and a `PaymentResponse` on a third party site.
>
> R4. UI to make payment: provide a means for a web application to spawn a
> window-like context in which to perform a payment method.
>
> R5. Can handle: Provide a means to check if a payment handler can handle a
> payment.
>
> Now we can look at how the current API is deficient in addressing these
> use cases - and how the new API can address the requirements.
>
> ## R1 - Registration
> The current API conflates web app manifest and payment manifest, etc. In
> relation to other powerful features afforded by the web platforms there is
> nothing special about the payments response API that requires it to have a
> manifest.
>
> How Payment Requests API solves this:
> Having a web manifest is not a requirement for "payment handlers".
> However, a web application can include a web manifest.
>
> To get permission to act as a payment handler, the new API allows the
> developer to ask for permission via the a call to:
> paymentAppManager.requestPermission()
>
> This allows the browser to intervene and negotiate with the user if the
> application can act as a payment manger.
>
> ## R2 - Payment Method Management
>
> The current API only has two methods for handling payment methods - and
> those are conflated with "manifests":
>
>  * setManifest()
>  * getManifest()
>
> This makes it impossible to manage payment methods without continuously
> trashing the existing payment methods and "the manifest". This makes it
> difficult to get at current payment methods, and modify and work with them
> individually.
>
> How the new API solves this:
> The new API introduces a `PaymentMethodMap`, which allows for asynchronous
> atomic management of payment methods (add, delete, iterate, etc). Exposed
> on window and workers.
>
> ## R3. Payment Handling
> The existing API fails to capture all the possible events sent from a
> PaymentRequest object. It then goes on to introduce new primitives instead
> of just using PaymentResponse. As such it fails to integrate fully with
> `PaymentRequest`, and fails to allow bi-directional communication between
> PaymentRequest and PaymentResponse.
>
> The new API solves this by giving PaymentResponse a constructor - allowing
> ev.respondWith() to actually respond with a PaymentResponse and by allowing
> the "onpaymentrequest" event to catch the various events resulting from
> calls to PaymentResponse - for instance:
>
>  * .onabort() can now be handled.
>  * Response.updateShippingAddress() - can notify the PaymentRequest with a
> new address, and await a response from the PaymentRequest to check if it's
> ok.
>  * Response.updateShippingOption() - as above, but with a new shipping
> option id.
>
> ## R4. UI to make payment
> The current API is hand-wavy about using clients.openWindow() in a service
> worker to perform the payment flow. This solution is inadequate (or simply
> not any better) when compared to what browser do today.
>
> The new API introduces a the ability to open a payment-specific payment
> flow window via `PaymentRequestEvent.openClientWindow()`. This allows the
> browser to bring up an appropriate payment window for the purpose of
> negotiating a request for payment.
>
> ## R5. Can handle payment
> The current API tries to define `canHandle` the the manifest - by defining
> a new type of function that appears to be transferrable across threads.
> That is: if the payment app is closed, the function is somehow magically
> supposed to still be active (!). This is impossible to implement, because
> functions are dynamic and associated with their global environment (and
> contain closures). Hence, it's not something that can be implemented - not
> without changing how JavaScript works, which is just not going to happen.
>
> The new API addresses this by adding a "canhandlepayment" event on the
> service worker instead. Registered handlers can then be woken to check if
> the payment method is supported - by performing whatever checks are
> necessary.
>
> ===
>
> Obviously, people will have a lot of questions. Let's work through those!
>
> There is lots of stuff we can take directly from the existing API too - we
> should totally do that where it makes sense.
>
> Kind regards,
> Marcos
>
>
>
>
>

Received on Monday, 23 January 2017 15:51:08 UTC