Use navigator.payments singleton, factory method, or PaymentRequest constructor #16
In TAG review @triblondon said:
I prefer a constructor. I'd definitely say no to a singleton unless it was a solid certainty that we'll never want a UA to be processing multiple payments at a time, since the instance provides a means of storing state which seems like it would become more useful as the API is extended in future.
@msporny said:
To clarify, the singleton would instantiate a Promise and return it. You'd be able to run multiple payment requests in a page. I'm not strongly arguing for/against - just clarifying.
Part of the problem with using the constructor is that we have no namespaced place to hang other API methods that we are still working on for things like registration, getting the PaymentRequest and submitting the PaymentResponse as a web based payment app.
A factory pattern might be a good compromise?
Proposal
Put the PaymentRequest constructor behind a factory method.
Sample javascript:
var payment = navigator.payments.newPaymentRequest(supportedMethods, details, options, data);
payment.addEventListener("shippingaddresschange", function (changeEvent) {
// Process shipping address change
});
payment.show().then(function(paymentResponse) {
// Process paymentResponse
// paymentResponse.methodName contains the selected payment method
// paymentResponse.details contains a payment method specific response
paymentResponse.complete(true);
}).catch(function(err) {
console.error("Uh oh, something bad happened", err.message);
});Couldn't you use static methods of the PaymentRequest constructor if you wanted to create new non-instance methods in future? But regardless the factory seems fine. The web platform has pretty much no consensus or consistency in this regard so there isn't a strong convention, imho.
The web platform has pretty much no consensus or consistency in this regard so there isn't a strong convention, imho
Finding out what the recommended best practices are for details like this is a big part of the motivation of asking for close review from the TAG. But if the answer really is that there really is no consensus or consistency in this particular case, then that actually is also useful to know.
Put the PaymentRequest constructor behind a factory method.
This (interface singleton w/ factory methods) is exactly what the Web Payments Community Group spec proposal does, partly for the reasons outlined by @adrianhopebailie:
http://wicg.github.io/web-payments-browser-api/#navigatorpayment
and
http://wicg.github.io/web-payments-browser-api/#processing-a-payment-request
So, +1 for this design direction.
If folks want to -1 this, then I'd be interested in hearing where we're going to put methods to do registration, receipt storage (potential future feature), pickup of pending payee-initiated payment requests on the payment app side, etc.
Couldn't you use static methods of the PaymentRequest constructor if you wanted to create new non-instance methods in future?
Are you suggesting a style like this:
var thing = PaymentRequest.someMethod();My only reservation is that someMethod may be more generically related to payments as opposed to payment requests (eg: registration of a payment app) in which case this doesn't make sense.
I'm certainly more familiar with (and prefer) the pattern:
var thing = navigator.payments.someMethod();
var paymentRequest = navigator.payments.createRequest();I can also imagine us having API endpoints like the following that are used by web-based payment apps:
//After the payment app loads ask the browser for the current request that it must process
var paymentRequest = navigator.payments.getRequest();
//Submit back the response
paymentRequest.submitResponse(paymentResponse);Or, if the request is passed to the app as an HTTP request then:
//Submit back the response
navigator.payments.submitResponse(paymentResponse);
This issue comes from WICG/paymentrequest#42.
From the spec: