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

PaymentDetails should include a transaction ID #287

Closed
halindrome opened this issue Sep 23, 2016 · 15 comments
Closed

PaymentDetails should include a transaction ID #287

halindrome opened this issue Sep 23, 2016 · 15 comments

Comments

@halindrome
Copy link
Contributor

Currently the payment details method does not include a transaction ID. In order to facilitate future work (e.g., receipts) and to help Payment Apps track user's transactions, I think it would be good to have merchants get used to including this information in their payment requests.

As to sending it to the Payment App, I will raise a separate issue for that, but in this model the transactionID (a DOMString) would be included in the Payment App Request Data object along with the origin and other information. In this way a Payment App could correlate origin / transaction IDs and assist with future related transactions such as returns or order status queries.

If there is support for this, I am happy to supply a PR.

@nickjshearer
Copy link

Presumably many payment instruments will provide their own transaction identifiers upon successful payment in their own formats (like a PayPal confirmation number, for example)? It seems potentially confusing to have both. A merchant could still generate and use an identifier, I'm just not sure of the value of passing it through the payment request.

@adrianhopebailie
Copy link
Collaborator

I see this identifier as a "request" identifier and not a "transaction" identifier.

It's value is in reconciling the original request (from website to browser) with other phases of the flow.

I see value in defining this at the top-level because it allows everyone further on in the flow to depend on it.

If we wait for this to be generated later in the flow (e.g. by the browser or payment app) then it only allows reconciliation of data/state between those later phases.

@rsolomakhin
Copy link
Collaborator

I think the merchant can generate the "request" identifier on the server side and then pass that into PaymentRequest's method-specific data. Browser passes that information to the payment app unmodified, so the payment app is free to depend on this data presence.

@burdges
Copy link

burdges commented Sep 23, 2016

Yeah, I'd think a transaction id should originate with the merchant's first offer when they call show, that's what we do in Taler anyways.

@adrianhopebailie
Copy link
Collaborator

adrianhopebailie commented Sep 23, 2016

That is one way to solve this (an ID per payment method) but in this case I think we can do "better" to make the developer's life easier and because it will make our lives easier if we consider multi-tender in future.

@dlongley
Copy link

A merchant could still generate and use an identifier, I'm just not sure of the value of passing it through the payment request.

The merchant may need to use this merchant-specific reference identifier to check on the status of the transaction should communication channels fail for any reason during the purchase.

@dlongley
Copy link

@adrianhopebailie,

That is one way to solve this (an ID per payment method) but in this case I think we can do "better" to make the developer's life easier and because it will make our lives easier if we consider multi-tender in future.

I'm all for doing "better", but we may find that improvements should come via back channel communication between the Payment App and the merchant site vs. passing through the mediator.

@halindrome
Copy link
Contributor Author

I don't like the idea of this in the payment method data. That data is opaque to the payment app, which means the payment app cannot then help its user out with correlating things later.

I don't hate the idea of a request ID rather than a transaction ID. Just some top level unique identifier from the merchant that stays around through the flow.

@adamroach
Copy link
Contributor

adamroach commented Sep 23, 2016

@halindrome

I don't like the idea of this in the payment method data. That data is opaque to the payment app, which means the payment app cannot then help its user out with correlating things later.

This came up in break-time conversations earlier this week, too. The fundamental problem is that we're conflating payment-specific transaction identifiers (which might have meaning outside the browser context, such as auditing with a third party that a payment has occurred) and transaction identifiers that are purely a matter of local concern to the payment request/payment app APIs.

If we're going to allow payee websites to ask about existing transactions, we need an identifier -- of concern only inside the browser -- that lets it indicate which transaction it's talking about. It would be a horrible mistake to try to mix this up with an identity that meant something to the payment method.

So, we're basically given three options:

  1. Let the payee choose the browser-scoped transaction ID
  2. Let the payment app choose the browser-scoped transaction ID
  3. Let the mediator (browser) choose the browser-scoped transaction ID

Option 1 has the drawback that it imposes the unnecessary task of generating a unique ID on the myriad payee apps, to no benefit.

Option 2 has that same drawback for the payment app, with the additional flaw that it requires a new id-providing call altogether when the app is first invoked.

So I like option 3.

Concretely, what I would propose is: at the time the constructor to PaymentRequest is called, part of its construction is adding a (randomly generated, probably UUID) read-only transactionId attribute to the object. On the payment app side, this same value would also appear in a read-only transactionId attribute at the top level (i.e., as a peer to the data attribute) of the PaymentRequestEvent object.

[Constructor(sequence<PaymentMethodData> methodData, PaymentDetails details, optional PaymentOptions options),
 SecureContext]
interface PaymentRequest : EventTarget {
    Promise<PaymentResponse> show();
    Promise<void>            abort();

    readonly attribute PaymentAddress?      shippingAddress;
    readonly attribute DOMString?           shippingOption;
    readonly attribute PaymentShippingType? shippingType;

    readonly attribute DOMString            transactionId;

    // Supports "shippingaddresschange" event 
             attribute EventHandler         onshippingaddresschange;

    // Supports "shippingoptionchange" event 
             attribute EventHandler         onshippingoptionchange;
};
interface PaymentRequestEvent : ExtendableEvent {
    readonly attribute PaymentAppRequestData data;
    readonly attribute DOMString transactionId;
    void respondWith((Promise<PaymentResponse> or PaymentResponse) r);
};

To be clear: if the app and/or the payee want to correlate some payment-specific payment request identifier with the browser-scoped payment ID, that's trivial:

bobpayPaymentAuditToken[request.transactionId] = auditToken

I think this is simple to implement, imposes no additional load on payment methods/attributes/apps that don't care about it, and allows for all of the correlation use cases that have been described so far.

TO BE CRYSTAL CLEAR: IF THERE IS A PAYMENT-METHOD-SPECIFIC TRANSACTION ID THAT MEANS ANYTHING TO ANYTHING OUTSIDE THE BROWSER, IT IS A DIFFERENT THING AND IS SENT IN THE OPAQUE data FIELD. This proposal in no way attempts to replace those mechanisms. Any correlation between payment-method-specific identifiers and the browser-specific identifiers is done by the payee and payment apps in whatever means, if any, they find it appropriate to do so.

@dlongley
Copy link

@adamroach,

Thank you, that clarifies a lot. So this identifier is specific to the browser and the use of the Payment Request API and its purpose is to allow the payment app and payee website to make sure they are talking about the same transaction. Is that accurate?

@adrianhopebailie
Copy link
Collaborator

@adamroach +1 with a minor change, I'd change the member to paymentRequestId or just requestId.

@halindrome
Copy link
Contributor Author

@adamroach and @adrianhopebailie I agree with both of you here.

My understanding of this is a bit broader though. While this is an identifier the payee and the payment app can use to correlate information, in the real word it has other uses.

Today if I go into a convenience store and purchase something, my receipt has two critical pieces of information on it that have nothing to do with the payment method. These are the origin (merchant name + store identifier) and the transaction number (some unique number). These items, when used together, uniquely identify the transaction to the merchant. Any merchant worth their salt keeps track of these in a database so they can later handle returns, re-issue receipts, track spending habits... whatever.

Right now we have no way of conveying this information. WIth the addition of this simple field, the payment app can now help its user keep track of where they spent what. Feels like a win for everyone with almost no cost.

@lyverovski
Copy link

+1 to @adamroach's proposal. We support the addition of a top-level request identifier to the specification, and see it as absolutely necessary to allow payees to reconcile with payment apps for both for success and (more importantly) for failure cases. Additionally, payment apps may provide webhook notifications back to the merchant to report the outcome of the transaction. The merchant needs an easy way to match the webhook event to a payment request which they initiated.

Option 1 has the drawback that it imposes the unnecessary task of generating a unique ID on the myriad payee apps, to no benefit.

Admittedly, my initial preference was for a merchant/payee generated ID, since most payees are already accustomed to doing so.

While still +1 to the proposal, my only concern with the browser-generated UUID is if the merchant’s site goes offline in the seconds or minutes after it has served up the page, but before the user has initiated the payment request, because they were still busy looking at the page content. However, you could argue that this could be an implementation detail by the payee (i.e. abort if the UUID cannot be properly communicated back to the merchant server)

@mattsaxon
Copy link
Contributor

+1 to @halindrome's use cases. +1 to @adamroach to say we shouldn't conflate these concerns. A number of payment methods have multiple identifiers to support various use cases, take for example SEPA which has both a payee and a payer transaction identification code. I support the PaymentRequest supporting natively such capabilities. Payment Methods/Apps can choose to leverage these or not, but if they do, the user experience will be enhanced as users get consistency.

@marcoscaceres
Copy link
Member

Closed via #426

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

No branches or pull requests

10 participants