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.
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.
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.
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.
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.
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.
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.
@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.
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.
@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:
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.
@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?
@adamroach +1 with a minor change, I'd change the member to paymentRequestId or just requestId.
@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.
+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鈥檚 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)
+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.
Most helpful comment
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.