Hello, it seems paymentRequest.canMakePayment() always returns false, also in browsers that supports it and with credit cards added.
I've tested with both Chrome and Safari, and it turns out it never works. In fact, if I console.log the result in the callback, it is always false.
Here's my code, almost copy/pasted from the official repo:
import React from 'react'
import { injectStripe, PaymentRequestButtonElement } from 'react-stripe-elements'
class PaymentRequestForm extends React.Component {
constructor(props) {
super(props)
// For full documentation of the available paymentRequest options, see:
// https://stripe.com/docs/stripe.js#the-payment-request-object
const paymentRequest = props.stripe.paymentRequest({
country: 'US',
currency: 'usd',
total: {
label: 'Demo total',
amount: 1000
}
})
paymentRequest.on('token', ({ complete, token, ...data }) => {
console.log('Received Stripe token: ', token)
console.log('Received customer information: ', data)
complete('success')
})
paymentRequest.canMakePayment().then(result => {
console.log('canMakePayment', !!result)
this.setState({ canMakePayment: !!result })
})
this.state = {
canMakePayment: false,
paymentRequest
}
}
render() {
return this.state.canMakePayment ? (
<PaymentRequestButtonElement
paymentRequest={this.state.paymentRequest}
className="PaymentRequestButton"
style={{
// For more details on how to style the Payment Request Button, see:
// https://stripe.com/docs/elements/payment-request-button#styling-the-element
paymentRequestButton: {
theme: 'light',
height: '64px'
}
}}
/>
) : null
}
}
export default injectStripe(PaymentRequestForm)
If I console.log it, no matter what browser I'm using, it'll always print canMakePayment false in my console.
To double-check, I've tried the 'try it out' in your official documentation, and it actually works with both chrome and safari. I've done that in order to be sure my browsers were actually supporting it, and they do.
Hi there! Thanks for the report. I've tested this and it seems to work for me, so I don't believe it is an issue with this project. Could you verify that your testing environment matches what's specified here? https://stripe.com/docs/stripe-js/elements/payment-request-button#testing
A common issue in development is not using HTTPS which these payment request buttons require. Using a service like ngrok can help with this.
I'm going to close this since I don't think it's a bug with the repo, but please reopen if you have additional information and you feel otherwise. If you're still running into issues, please reach out to our support team at https://support.stripe.com/contact or come chat with us at #stripe on freenode.
Hello @oliver-stripe,
Why stripe require user saved payment card in advance? Browser native payment request does not require this.
@Jerry-Hong Our implementation is geared towards conversion usefulness, not whether it's strictly available. There's no conversion benefit to showing the payment request button if there is not already a saved payment method. Merchants generally don't want to pay the onboarding cost to add a card to the platform's wallet.
For anyone else having this problem, it may well be that you don't have a card setup for Payment Request API in chrome. (Don't trust the "payment methods" part of chrome settings, it's not the same as payment requests it seems).
You can set up a card by entering
var details = {total: {label: 'x', amount: {currency: 'GBP', value: '9.99'}}}
new PaymentRequest([{supportedMethods: ['basic-card']}], details).show()
in the console on a page with HTTPS and add a card.
After that stripe's canMakePayment API should work.
The current implementation in Chrome seems to only consider a saved card as available for the PaymentRequest API if the card number, future expiration date, and cardholder name is configured in the settings.
Apparently their goal is to also make sure a valid billing address is associated with the card, but according to our tests, this isn't currently enforced.
More information: https://www.chromestatus.com/feature/5532279906500608
So no matter what I do I can't get the Google Pay button show up, I was about to open up an issue when I see this, I've checked docs (https://stripe.com/docs/stripe-js/elements/payment-request-button#testing), Google Pay properly setup but I'm getting null from canMakePayment().
Ok, got it working now, the issue was that even though I had my credit card in place in my Google Account I did need to add it again in the browser, this is weird but fixed the problem.

Yes! That's exactly the problem I had.
There are a lot of known issues with how Chrome handles Google Pay on desktop. Unfortunately because you see a Google Pay card listed in the Chrome settings doesn't mean the card is actually available to be used through PaymentRequest.
For the longer technical explanation, there are 2 root causes:
PaymentRequest.hasEnrolledInstrument() resolves to false if the Payment Handler is not installed. This is a spec limitation that is getting resolved at the Web standards level right now.PaymentRequest object. Doing so is not possible as we wouldn't be able to check if there might also be cards saved directly in the browser along with the Payment Handler.It's a bit of a chicken and egg problem, with Chrome not being able to say that Google Pay is available until it has been available once.
There is unfortunately not much we can do about it right now. We may also be able to workaround the issue for Google Pay specifically after the fixes for some other Payment Handler bugs land in Chrome 83.
Most helpful comment
For anyone else having this problem, it may well be that you don't have a card setup for Payment Request API in chrome. (Don't trust the "payment methods" part of chrome settings, it's not the same as payment requests it seems).
You can set up a card by entering
in the console on a page with HTTPS and add a card.
After that stripe's
canMakePaymentAPI should work.