Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

complete() should take a string argument not boolean #17

Closed
adrianba opened this issue Mar 3, 2016 · 20 comments
Closed

complete() should take a string argument not boolean #17

adrianba opened this issue Mar 3, 2016 · 20 comments

Comments

@adrianba
Copy link
Contributor

adrianba commented Mar 3, 2016

This issue comes from WICG/paymentrequest#67 and WICG/paymentrequest#54. It was discussed briefly at the F2F.

This issue is that, at the time complete() is called, your ability to say success (true) or failure (false) may depend on the payment method. There may be other values besides success or failure that can be conveyed (e.g. pending).

Payment Transaction Message Specifications will have to define what values are allowed. We should probably specify some predefined values for success and failure.

@mattsaxon
Copy link
Contributor

How we update the specification for Basic Card Response should probably be the following; "Authorised", "PendingCapture", "Captured" and "Failed". An authorisation is where the funds have not been requested, but have been held, e.g. hotel room deposit. A captured transaction is when the funds have been requested from the Issuer. "PendingCapture" is where they been requested from the acquirer, but not passed onto the Issuer yet.

However, I'd like to explore the possibility of having a standard set of responses for all payment types. These would be similar to cards, but in addition have "Settled" (the money is with the merchants FI), and some more "Pending" statuses, e.g. "PendingSettlement" to replaced "Captured" if we think this is a more descriptive and generic term. Also a general "Pending" status where the funds are held for a specific reason that may need some corrective action to be taken, e.g pre-fund an account.

There are further payment statuses such a "Cancelled", "Refunded" etc. which are outside the scope of this API at present.

Whilst I wouldn't suggest that other payment methods might not want to extend this, it seem to me sensible to have a base set of statuses.

@jnormore
Copy link
Member

From my current understanding, the purpose of the complete() action is to allow the merchant to tell the payment app that the payment has been processed / checkout is complete and let it close any UI associated with it.

A couple things:

  1. In the case of a successful payment, the UI would almost always need to be closed so this works. In the case of a failed payment, the payment app will most likely want to let the customer know what the reason for that failure was and retry from the last step (validation error is a good example), so providing just a failure response isn't going to work, there needs to be some extra information provided, specific to the payment method that the payment app would know how to handle.
  2. I'm not sure what use a payment app would have with knowing whether it was an auth, capture, auth/capture, settled, etc, that would be a merchant concern from my experience. I would think a payment app only wants to know what to do next at this step, not what type of transaction a merchant processed, this may come from the status of the transaction but in the end it's up to the merchant to determine what it wants the payment app to do (close UI, show error, retry, etc). I think we should consider making these codes more of instructions for the payment app, from the merchant, rather than codes that are specific to the payment method.

@adrianhopebailie
Copy link
Collaborator

allow the merchant to tell the payment app that the payment has been processed

You are making an implicit assumption that it will be possible for the user agent to pass a message back to the payment app after the payment app has responded to the initial payment request. I don't think we can make this assumption unless we get some clarity on how payment apps (and the interface between them and the user agent) will be implemented.

Up to now the assumption has been that the request passed to the payment app and response is a one off to avoid complex UI and state management.

I proposed a possible solution to this but the consensus seemed to be that this was not necessary as a standard at this time due to a lack of use cases to justify it [1] however I think that this and a few other open issues suggest it's worth looking at again [2].

  1. Should we standardise a callback mechanism for payment apps to communicate to 3rd parties? webpayments#76
  2. Should we standardise a callback mechanism for payment apps to communicate to 3rd parties? #109

@burdges
Copy link

burdges commented Mar 31, 2016

I'd expect that depends upon the nature of the payment app. I'd expect a web based payment app cannot do this for the same reason it cannot really do it now. There is however only really one way to arrive on the payees fulfillment page, and the payee can employ communication not mediated by the browser. An browser extension can do post fulfillment interaction in more ways. And a native app can circumvent the browser entirely.

@adrianhopebailie
Copy link
Collaborator

I'd expect that depends upon the nature of the payment app.

Not sure what you're referring to with this statement.

I'd expect a web based payment app cannot do this for the same reason it cannot really do it now.

I disagree. This cannot be done today because there is not payment app representing the user in this exchange. The whole technology stack is provided by the merchant and the user simply provides credentials into a UI they must trust (provided by the merchant, directly or via their PSP).

The only exception is "wallet" services like PayPal or MasterPass but the fact that the interaction between these and the merchant are not standardized means the merchant must offer a plethroa of payment options and different flows to support each payment method they consider worthwhile.

Today this results in a terrible user experience. This API should move this "match-making" and payment pre-negotiation out of the UI so that the UX is far cleaner and it's possible to introduce payment methods with complex interactions (like encrypted credentials) that are hidden from the user.

@burdges
Copy link

burdges commented Mar 31, 2016

Why does a payment app represent the user? It's that because they select it from a menu? A priori, I though some payment apps were hostile to the user, like merchant specific ones.

I'll keep an eye out for tricks to turn this into a vulnerability. There is for example a kind of super-cookie where I tell the browser the user requested payment, and only the super-tracker payment app works, which someone previously tricked the user into installing. If it does not open a menu for a request with only one payment method, then super-tracker gets control, takes its tracking actions, and send the browser right back to the original page. I suppose one avoids that my requiring that the payment app selector always appear, even if only one valid payment method exists.

@adrianhopebailie
Copy link
Collaborator

Why does a payment app represent the user?

That's the architecture. Payment apps are registered by the user and represent their agent in any payment. I agree that we need to consider scenarios where user's may be tricked into installing an agent that is not acting in their interests but that is orthogonal to this issue.

@mattsaxon
Copy link
Contributor

@jnormore as per the spec, the complete() method must "Pass the value of success to the Payment App that accepted the payment request."

This suggest the payment app can act on that data and therefore this method is not just to dismiss the dialogue. This information could allow something as simple as displaying the appropriate message to the user, e.g. "Your payment has been authorised and your account will be debited within the next 24 hours" vs "Your payment has been authorised and your account will be debited once the good have shipped"

@zkoch
Copy link
Contributor

zkoch commented Mar 31, 2016

@jnormore as per the spec, the complete() method must "Pass the value of success to the Payment App that accepted the payment request."

No, not the payment app, the user agent. See https://w3c.github.io/browser-payment-api/specs/paymentrequest.html#complete. Full text:

The complete method must be called after the user has accepted the payment request and the [[acceptPromise]] has been resolved. The complete method takes a boolean argument that indicates the payment was successfully processed if true and that processing failed if false. Calling the complete method tells the user agent that the user interaction is over (and should cause any remaining user interface to be closed).

So complete() is just an explicit way for the merchant to tell the user agent to explicitly close the UI.

@mattsaxon
Copy link
Contributor

@zkoch, just below that text, can you explain step 5 in what the specification says that complete() must do?

@zkoch
Copy link
Contributor

zkoch commented Mar 31, 2016

@zkoch, just below that text, can you explain step 5 in what the specification says that complete() must do?

Huh. Forgot about that. That should probably be removed. :)

@mattsaxon
Copy link
Contributor

Then this begs the question what the need for the Boolean param is for at all?

@zkoch
Copy link
Contributor

zkoch commented Mar 31, 2016

Then this begs the question what the need for the Boolean param is for at all?

UI purposes. It allows for a success/fail/something else animation or similar. We added the complete after a request to better support Apple Pay that relies on this call (for more, see: http://nshipster.com/apple-pay/).

@jnormore
Copy link
Member

jnormore commented Apr 1, 2016

Isn't Apple Pay considered a Payment App, just implemented by the browser? This implies some mechanism for the user agent to pass the success value to the payment app, unless we consider those implemented by the user agent to be a special case because that communication mechanism is an implementation detail.

Matt, as for the custom message displayed by the user agent, I don't think the user agent has enough context to display that message properly on behalf of either the merchant or payment app. IMO the merchant should handle any success message (and even some critical failures, for example when there's no inventory) themselves, they have that context of how to follow up with the customer after purchase.

This brings up the non critical failures, such as a validation error, where the merchant doesn't want to reset the entire checkout experience for the customer (this would be a bad experience if I just entered by CC expiry wrong for example), they only want to bring them back to the last step to re-enter the invalid payment info and try again. I'm curious if this has come up with any discussions yet?

@mattsaxon
Copy link
Contributor

IMO the merchant should handle any success message

This is obviously possible and is what is done today, however in terms of standardisation, it fall short of what we could achieve. Additionally it removes the possibility of the Payment Application maintaining a history of what has occurred, which I think could be useful for a number of usability/functionality and security reasons.

@adrianhopebailie
Copy link
Collaborator

@jnormore said:

Isn't Apple Pay considered a Payment App, just implemented by the browser?

Yes

This implies some mechanism for the user agent to pass the success value to the payment app, unless we consider those implemented by the user agent to be a special case because that communication mechanism is an implementation detail.

This is part of the conundrum we face with where we draw the line in terms of defining the integration between the user agent and payment app. We need to create a level-playing field for payment app publishers but also ensure we support the current status quo (a challenge when you consider that many of the browser vendors ALSO have a payment app).

The architecture we have proposed does attempt to address this by saying; from the perspective of the API there is only one exchange between the user agent and the payment app. That is when the user agent passes focus to the payment app and hands it a payment request. Once the response comes back from the payment app the channel is closed BUT for UI purposes the user agent may not have torn down the UI hosting the payment app (or taken focus back from the payment app), hence the need for a complete() call.

The complete() method call and various events that are raised are only exchanges between the website and the user agent. Perhaps there is an alternative way that ApplePay could acheive what's it aiming for here?

I don't think the user agent has enough context to display that message properly on behalf of either the merchant or payment app. IMO the merchant should handle any success message (and even some critical failures, for example when there's no inventory) themselves, they have that context of how to follow up with the customer after purchase.

+1 - the merchant can provide the user with necessary feedback (as is done today). I think @mattsaxon makes a fair point around the payment app wanting to know the outcome of the transaction but again I'd advocate for this being done outside the API as it doesn't need to impact on the UX. (Per #109)

This brings up the non critical failures, such as a validation error, where the merchant doesn't want to reset the entire checkout experience for the customer (this would be a bad experience if I just entered by CC expiry wrong for example), they only want to bring them back to the last step to re-enter the invalid payment info and try again. I'm curious if this has come up with any discussions yet?

The hope is that by using this model (of data being exchanged between a payment app and the website) that validation errors all but disappear. I don't think we can support the idea of returning to the payment app in the context of an existing payment request.

I'd expect the merchant to call complete() to regain focus, notify the user that there was an error and call the API again with the same payment request (probably triggered by the user hitting a retry button or similar).

@mattsaxon
Copy link
Contributor

All this conversation, underlines my view that we need a registration and payment application communication mechanism defined asap (possibly with out of band comms defined), we will resolve these issues by writing payment apps and seeing how they work.

Otherwise we keep dancing around the problems that we are hitting time and time again in separate issues.

@adrianba
Copy link
Contributor Author

adrianba commented Apr 6, 2016

Having discussed this a little, here are a couple of thoughts:

  • It may be difficult to pass this value through to a payment app - we should think about this as something that gets passed into the user agent to be used for UX
  • We could keep this as an optional Boolean with true meaning success, false meaning failure, and undefined (i.e. not present) meaning indeterminate. In other words, don't show a success or failure animation in the UI if you get undefined.

@dlongley
Copy link

dlongley commented Apr 6, 2016

-1 to using a boolean param here. See: http://ariya.ofilabs.com/2011/08/hall-of-api-shame-boolean-trap.html

Alternatives are an options object with keys that reflect the parameter names or multiple functions .succeed/.fail.

@adrianhopebailie adrianhopebailie added this to the Discuss on Call - 28 April milestone Apr 28, 2016
@adrianba
Copy link
Contributor Author

Closed in #161.

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

No branches or pull requests

7 participants