w3c / payment-request

Payment Request API
https://www.w3.org/TR/payment-request/
Other
489 stars 135 forks source link

Clarify when the user can abort the payment request algorithm #796

Closed aestes closed 5 years ago

aestes commented 5 years ago

The user aborts the payment request algorithm says this:

If the request.[[updating]] is true, then terminate this algorithm and take no further action. The user agent user interface SHOULD ensure that this never occurs.

I believe this is because user agents are expected to disable the payment UI while merchants are updating details.

In Apple Pay, we do prevent the user from authorizing payment while the merchant is updating, but we don't completely disable the interface. Notably, we don't disable the "cancel" button. So that means the user could abort a transaction in the midst of a details update.

To comply with the spec as-written, WebKit defers processing a user abort until the pending details update promise settles (see https://trac.webkit.org/r236922).

Should the spec acknowledge that some implementations might allow the user to abort in the midst of updating? Should it allow an abort during details update, or suggest that implementors defer the abort until the details settle?

cc: @marcoscaceres

marcoscaceres commented 5 years ago

Should the spec acknowledge that some implementations might allow the user to abort in the midst of updating?

I think it should... if it's the reality of how things are implemented.

Should it allow an abort during details update, or suggest that implementors defer the abort until the details settle?

Chrome allows this... you can hit "esc" at any time I think, including during update and payment "processing". @rsolomakhin can you confirm that this is correct? I just tried in Canary, and that seems to be the case.

Firefox right now doesn't allow the user to abort. The only option is for the user to hit the "Refresh" button to stop... but kills everything. @mnoorenberghe do you have some thoughts here?

I'm inclined to say that the user can cancel at any time, the pending showPromise, retryPromise, or completePromise rejects with an AbortError.

marcoscaceres commented 5 years ago

Ignore the completePromise bit above... that one doesn't matter.

marcoscaceres commented 5 years ago

Ok, just want to clarify something here... as I alluded to above, there are two cases we need to deal with:

  1. updateWith() / retry() - use same update logic.
  2. Before complete() is called (i.e., "...processing...") stage.

About 2, the spec says (my emphasis):

After the payment request has been accepted and the PaymentResponse returned to the caller but before the caller calls complete() the payment request user interface remains in a pending state. At this point the user interface ought not offer a cancel command because acceptance of the payment request has been returned.

So, at I mentioned above:

The annoying part of 2 is that it can get stuck (hence the timeout):

For this reason, implementations MAY impose a timeout for developers to call complete(). If the timeout expires then the implementation will behave as if complete() was called with no arguments.

I think we can all agree that cancelling during 1 should be ok.

So, question is, should a user be allowed to cancel by prior to calling .complete()? It should it be only by timeout (in which case, Chrome might be accidentally doing it wrong)

rsolomakhin commented 5 years ago

Should it allow an abort during details update, or suggest that implementors defer the abort until the details settle?

Chrome allows this... you can hit "esc" at any time I think, including during update and payment "processing". @rsolomakhin can you confirm that this is correct? I just tried in Canary, and that seems to be the case.

Confirmed. This is intended to let the user close the sheet for a website that's taking too long to respond.

aestes commented 5 years ago

Ok, just want to clarify something here... as I alluded to above, there are two cases we need to deal with:

  1. updateWith() / retry() - use same update logic.
  2. Before complete() is called (i.e., "...processing...") stage.

Not sure that retry() needs to be dealt with, actually. Once you retry() the request becomes interactive again, and I think the user abort algorithm already does the right thing in that state.

Here is how I think of these two cases:

  1. request.[[updating]] is true
  2. request.[[state]] is "closed"
  • Safari? @aestes?

Safari does seem to allow users to cancel during (2). I'll learn more about why this is.

The annoying part of 2 is that it can get stuck (hence the timeout):

For this reason, implementations MAY impose a timeout for developers to call complete(). If the timeout expires then the implementation will behave as if complete() was called with no arguments.

You can get stuck in (1) as well, since it's up to the merchant to resolve the PaymentDetailsUpdate promise. Safari imposes a timeout there too.

So, question is, should a user be allowed to cancel by prior to calling .complete()? It should it be only by timeout (in which case, Chrome might be accidentally doing it wrong)

I think users should not be allowed to cancel after they accept the payment. Once a PaymentResponse is returned to the merchant it's probably too late to expect the user abort to be honored in all cases, so users shouldn't be made to think otherwise.

Of course if the merchant calls retry() instead of complete(), then cancel should be allowed again until the next time the user accepts.

marcoscaceres commented 5 years ago

@aestes wrote:

You can get stuck in (1) as well, since it's up to the merchant to resolve the PaymentDetailsUpdate promise. Safari imposes a timeout there too.

Ok, that makes sense. I'll update the spec to:

  1. Allow a timeout.
  2. Make it clear that the browser may provide a means to abort the payment, even if the pay button and other input fields are disabled.

I think users should not be allowed to cancel after they accept the payment. Once a PaymentResponse is returned to the merchant it's probably too late to expect the user abort to be honored in all cases, so users shouldn't be made to think otherwise.

Ok, would it be possible to report back on 2? If both Chrome and Safari allow it, we might need to revise the spec text (or rephrase this as a SHOULD). Firefox currently conforms to the spec.

marcoscaceres commented 5 years ago

Sent first part here (handling updateWith() via timeout or via "esc" or cancel button): https://github.com/w3c/payment-request/pull/810

We had most of the right bits in place.

mnoorenberghe commented 5 years ago

Firefox right now doesn't allow the user to abort. The only option is for the user to hit the "Refresh" button to stop... but kills everything. @mnoorenberghe do you have some thoughts here?

Allowing the user to cancel at any time is something I have thought about supporting and makes sense from a UX standpoint. The UA can communicate to the user that the payment is in an unknown state, if they wish.

aestes commented 5 years ago

@marcoscaceres wrote:

Ok, would it be possible to report back on 2?

Yes, will do.

marcoscaceres commented 5 years ago

Firefox bug allowing canceling while waiting for complete: https://bugzilla.mozilla.org/show_bug.cgi?id=1510019

marcoscaceres commented 5 years ago

@aestes, was hoping to hear back about being able to cancel which waiting for complete.