Skip to content

Commit

Permalink
Add PaymentRequest.prototype.hasEnrolledInstrument() (#833)
Browse files Browse the repository at this point in the history
  • Loading branch information
danyao authored and marcoscaceres committed May 3, 2019
1 parent 72de3ba commit 6f2565b
Showing 1 changed file with 124 additions and 60 deletions.
184 changes: 124 additions & 60 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,8 @@ <h2>
Promise&lt;void&gt; abort();
[NewObject]
Promise&lt;boolean&gt; canMakePayment();
[NewObject]
Promise&lt;boolean&gt; hasEnrolledInstrument();

readonly attribute DOMString id;
readonly attribute PaymentAddress? shippingAddress;
Expand Down Expand Up @@ -1312,56 +1314,39 @@ <h2>
<h2>
<dfn>canMakePayment()</dfn> method
</h2>
<div class="note" title="canMakePayment() vs hasEnrolledInstrument()">
<p>
The <a>canMakePayment()</a> method can be used by the developer to
determine if the <a>user agent</a> has support for one of the
desired <a>payment methods</a>. See <a href="#canMakePayment-privacy">
privacy considerations</a>.
</p>
<p>
A true result from <a>canMakePayment()</a> does not imply that the
user has a provisioned instrument ready for payment. For that, use
<a>hasEnrolledInstrument()</a> instead.
</p>
</div>
<p data-tests="payment-request-canmakepayment-method.https.html">
The <a>canMakePayment()</a> method MUST run the <a>can make payment
algorithm</a> with |checkForInstruments| set to false.
</p>
</section>
<section data-dfn-for="PaymentRequest" data-link-for="PaymentRequest">
<h2>
<dfn>hasEnrolledInstrument()</dfn> method
</h2>
<p class="note">
The <a>canMakePayment()</a> method can be used by the developer to
determine if the <a>PaymentRequest</a> object can be used to make a
payment, before they call <a>show()</a>. It returns a <a>Promise</a>
that will be fulfilled with true if the <a>user agent</a> supports
any of the desired <a>payment methods</a> supplied to the
<a>PaymentRequest</a> constructor, and false if none are supported.
If the method is called too often, the user agent might instead
return <a>a promise rejected with</a> a "<a>NotAllowedError</a>"
<a>DOMException</a>, at its discretion.
The <a>hasEnrolledInstrument()</a> method can be used by the developer
to determine if the <a>user agent</a> has support for one of the
desired <a>payment methods</a> and if a <a>payment handler</a> has an
instrument ready for payment. See
<a href="#canmakepayment-protections"></a>.
</p>
<p data-tests="payment-request-canmakepayment-method.https.html">
The <a>canMakePayment()</a> method MUST act as follows:
<p data-tests="payment-request-hasenrolledinstrument-method.https.html">
The <a>hasEnrolledInstrument()</a> method MUST run the <a>can make
payment algorithm</a> with |checkForInstruments| set to true.
</p>
<ol class="algorithm">
<li>Let |request| be the <a>PaymentRequest</a> object on which the
method was called.
</li>
<li>If |request|.<a>[[\state]]</a> is not "<a>created</a>", then
return <a>a promise rejected with</a> an "<a>InvalidStateError</a>"
<a>DOMException</a>.
</li>
<li data-tests=
"payment-request/payment-request-canmakepayment-method-protection.https.html">
Optionally, at the <a>top-level browsing context</a>'s discretion,
return <a>a promise rejected with</a> a "<a>NotAllowedError</a>" <a>
DOMException</a>. As described in section <a href=
"#canmakepayment-protections"></a>, the user agent may limit the
rate at which a page can call <a>canMakePayment()</a>.
</li>
<li>Let |hasHandlerPromise| be <a>a new promise</a>.
</li>
<li>Return |hasHandlerPromise|, and perform the remaining steps <a>in
parallel</a>.
</li>
<li>For each |paymentMethod| tuple in
|request|.<a>[[\serializedMethodData]]</a>:
<ol>
<li>Let |identifier| be the first element in the |paymentMethod|
tuple.
</li>
<li>If the user agent has a <a>payment handler</a> that supports
handling payment requests for |identifier|, resolve
|hasHandlerPromise| with true and terminate this algorithm.
</li>
</ol>
</li>
<li>Resolve |hasHandlerPromise| with false.
</li>
</ol>
</section>
<section data-dfn-for="PaymentRequest" data-link-for="PaymentRequest">
<h2>
Expand Down Expand Up @@ -4216,6 +4201,90 @@ <h2>
</li>
</ol>
</section>
<section>
<h2>
Can make payment algorithm
</h2>
<p>
The <dfn>can make payment algorithm</dfn> checks if the <a>user
agent</a> supports making payment with the <a>payment methods</a> with
which the <a>PaymentRequest</a> was constructed. It takes a boolean
argument, |checkForInstruments|, that specifies whether the
algorithm checks for existence of enrolled instruments in addition to
supporting a <a>payment method</a>.
</p>
<ol class="algorithm">
<li>Let |request| be the <a>PaymentRequest</a> object on
which the method was called.
</li>
<li>If |request|.<a>[[\state]]</a> is not "<a>created</a>",
then return <a>a promise rejected with</a> an
"<a>InvalidStateError</a>" <a>DOMException</a>.
</li>
<li data-tests=
"payment-request-hasenrolledinstrument-method-protection.https.html, payment-request-canmakepayment-method-protection.https.html">
Optionally, at the <a>top-level browsing context</a>'s discretion,
return <a>a promise rejected with</a> a "<a>NotAllowedError</a>"
<a>DOMException</a>.
<p class="note" data-link-for="PaymentRequest">
This allows user agents to apply heuristics to detect and prevent
abuse of the calling method for fingerprinting purposes, such as
creating <a>PaymentRequest</a> objects with a variety of supported
<a>payment methods</a> and triggering the <a>can make payment
algorithm</a> on them one after the other. For example, a user
agent may restrict the number of successful calls that can be made
based on the <a>top-level browsing context</a> or the time period
in which those calls were made.
</p>
</li>
<li>Let |hasHandlerPromise| be <a>a new promise</a>.
</li>
<li>Return |hasHandlerPromise|, and perform the remaining steps
<a>in parallel</a>.
</li>
<li>For each |paymentMethod| tuple in |request|.
<a>[[\serializedMethodData]]</a>:
<ol>
<li>Let |identifier| be the first element in the |paymentMethod|
tuple.
</li>
<li>If |checkForInstruments| is false, and the user agent has a
<a>payment handler</a> that supports handling payment requests for
|identifier|, resolve |hasHandlerPromise| with true and terminate
this algorithm.
</li>
<li>If |checkForInstruments| is true:
<ol>
<li>Let |data| be the result of <a data-cite=
"ECMASCRIPT#sec-json.parse">JSON-parsing</a> the second
element in the |paymentMethod| tuple.
</li>
<li>If required by the specification that defines the
|identifier|, then <a>convert</a> |data| to an IDL value.
Otherwise, <a>convert</a> to <a>object</a>.
</li>
<li>Let |handlers| be a <a>list</a> of registered
<a>payment handlers</a> that are authorized and can handle
payment request for |identifier|.
</li>
<li>For each |handler| in |handlers|:
<ol>
<li>Let |hasEnrolledInstrument| be the result of running
|handler|'s <a>steps to check if a payment can be made</a>
with |data|.
</li>
<li>If |hasEnrolledInstrument| is true, resolve
|hasHandlerPromise| with true and terminate this algorithm.
</li>
</ol>
</li>
</ol>
</ol>
</li>
<li>Resolve |hasHandlerPromise| with false.
</li>
</ol>
</section>
<section>
<h2>
Shipping address changed algorithm
Expand Down Expand Up @@ -5206,24 +5275,19 @@ <h2 id="canmakepayment-protections">
<code>canMakePayment()</code> protections
</h2>
<p data-link-for="PaymentRequest">
The <a>canMakePayment()</a> method enables the payee to determine —
before calling <a>show()</a> — whether the user agent knows of any
<a>payment handlers</a> available to the user that support the
<a>payment methods</a> provided to the <a>PaymentRequest</a>
<a data-lt="PaymentRequest.PaymentRequest()">constructor</a>. If no
<a>payment handlers</a> support the <a>payment methods</a>, this
enables the payee to fall back to a legacy checkout experience. Because
this method shares some potentially unique information with the payee,
user agents are expected to protect the user from abuse of the method.
For example, user agents can reduce user fingerprinting by:
The <a>canMakePayment()</a> and <a>hasEnrolledInstrument()</a> methods
have the potential to expose user information that could be abused for
fingerprinting purposes. User agents are expected to protect the user
from abuse of the method. For example, user agents can reduce user
fingerprinting by:
</p>
<ul data-link-for="PaymentRequest">
<li>Allowing the user to configure the user agent to turn off
<a>canMakePayment()</a>, which would return <a>a promise rejected
<a>canMakePayment()</a> and <a>hasEnrolledInstrument()</a>, which would
return <a>a promise rejected
with</a> a "<a>NotAllowedError</a>" <a>DOMException</a>.
</li>
<li>Rate-limiting the frequency of calls to <a>canMakePayment()</a>
with different parameters.
<li>Rate-limiting the frequency of calls with different parameters.
</li>
</ul>
<p>
Expand Down

0 comments on commit 6f2565b

Please sign in to comment.