Skip to content

Use navigator.payments singleton, factory method, or PaymentRequest constructor #16

Open
adrianba opened this Issue Mar 3, 2016 · 8 comments
@adrianba
adrianba commented Mar 3, 2016

This issue comes from WICG/paymentrequest#42.

From the spec:

There is an open issue about how a payment request is initiated. The options proposed include using a singleton at navigator.payments, using a factory method to create an instance, or using a constructor as currently described in the specification.

@mattsaxon mattsaxon added the Technical label Mar 21, 2016
@mattsaxon mattsaxon added this to the Priority: Medium milestone Mar 21, 2016
@adrianhopebailie

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.

@adrianhopebailie

@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.

@adrianhopebailie

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);
});
@triblondon

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.

@sideshowbarker
World Wide Web Consortium member

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.

@triblondon
@msporny
msporny commented Apr 8, 2016

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.

@adrianhopebailie

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);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.