Re: [webpayments] What is the appropriate conversational pattern for the API? (#55)

@adrianhopebailie,

> Not if the next step that the browser must perform is dependent on the response from the website.

So I think the question is whether or not we can design this API so it works like the other APIs that use this event + Promise pattern.

So, to understand how this pattern is used in other APIs, let's look at the ServiceWorker API. When using `respondWith` in this API, you're modifying something that will always happen. When a request is sent out, you'll always get a response. Installing an event handler simply allows you to modify that response by instructing the fetch call to respond with something else when it's time to respond (and when the response you've prepared is ready, this is the Promise-based part).

In more detail, my understanding is that the interaction with the `FetchEvent` in [ServiceWorker API](https://www.w3.org/TR/service-workers/#respond-with-method) works like this:

1. A call to fetch is made by a webpage.
1. A `fetch` event is dispatched.
1. An event handler in a ServiceWorker may optionally call `respondWith` to modify the response. If `respondWith` is called, then fetch's default behavior is disabled. Only one handler may call `respondWith`, if another call is made an InvalidState error is triggered.
1. Once event dispatching has completed, if `respondWith` was called, it will wait for its Promise to settle and use its response. If it wasn't, the default response will be used. So a response will happen whether or not `respondWith` was called, it's merely a modifier.

With the Checkout API, we want to be able to do things like make shipping options depend on the shipping address selected. What we're exploring essentially works like this:

1. A Checkout object is created by a webpage.
1. A call to `send` the line item estimate is made on the Checkout object. This call essentially just sets "options" that will be read once the checkout is started.
1. A call to `request` shipping address is made on the Checkout object. Again, this call is like setting options as it simply "indicates" that a shipping address is requested. It won't do anything until the checkout is started.
1. A call to start checkout is made on the Checkout object. This returns a Promise that will settle once the user clicks "Buy".
1. The browser UI opens and sees the line item estimate and displays it. It sees that shipping was requested, so it knows to show the user a shipping address selection UI. The "Buy" button will be disabled.
1. The user selects a shipping address and a `shippingAddressChanged` event is dispatched.
1. An event handler may optionally call `request` to request shipping option selection along with a list of possible shipping options (or a Promise that resolves to such a list).
1. Once event dispatching has completed, if `request` was called, it will wait for its Promise to settle and then display the shipping options in the UI, keeping the "Buy" button disabled. Otherwise, there's nothing to wait on and the "Buy" button will be enabled.
1. The user selects a shipping option and a `shippingOptionChanged` event is dispatched.
1. An event handler may optionally call `send` to send updated checkout details such as new calculated line items that include, eg: shipping, tax. Again, this information can be sent as a Promise, to enable the website to generate this information asynchronously. Similarly, `request` can also be called to request other information at this point (that depended on shipping option selection).
1. Once event dispatching has completed, if `request` was called, it will wait for its Promise to settle and then display the UI for whatever was requested this time, keeping the "Buy" button disabled. Otherwise, there's nothing to wait on and the "Buy" button will be enabled.
1. The user clicks "Buy" and the Promise for `checkout.start` resolves.
1. The webpage generates a payment request message and passes it to `checkout.finish`.
1. The browser UI shows the Payment App selection screen to complete the purchase.

Again, I think everything can progress forward regardless of whether or not extra calls to `request` are made. In writing that down, however, I do see at least one problem. If the user selects a shipping address that has N shipping options -- and then they change that shipping address selection, we want to be able to clear those shipping options from the UI. I think that can be easily solved with a call to `send('shippingOption', null)` or `send('shippingOption', theOnlyOne)` when handling the shipping address change, though.

---
Reply to this email directly or view it on GitHub:
https://github.com/w3c/webpayments/issues/55#issuecomment-184757875

Received on Tuesday, 16 February 2016 16:38:15 UTC