I’m trying to get Stripe to work using a Stimulus controller in a Rails environment. When I follow the Stripe instructions for using Checkout it works perfectly. When I’m using stimulus with (what I think!) is the same code, I’m getting the following error in the console:
Error: TypeError: Cannot read property 'stripe' of undefined
at payment_controller.js:28
Which seems to be the following line of code:
return this.stripe.redirectToCheckout({ sessionId: session.id });
Here is the full listing of the stimulus code:
import { Controller } from "stimulus"
export default class extends Controller {
connect() {
console.log("I am loaded")
let stripeMeta = document.querySelector('meta[name="stripe-key"]')
if (stripeMeta === null) { return }
let stripeKey = stripeMeta.getAttribute("content")
this.stripe = Stripe(stripeKey)
this.csrf = document.querySelector("meta[name='csrf-token']").getAttribute("content");
}
loadstripe() {
fetch('/create-checkout-session', {
method: 'POST',
headers: {
'X-CSRF-Token': this.csrf,
},
})
.then(function(response) {
return response.json();
})
.then(function(session) {
console.log(session.id)
console.log(this.stripe)
return this.stripe.redirectToCheckout({ sessionId: session.id });
})
.then(function(result) {
// If `redirectToCheckout` fails due to a browser or network
// error, you should display the localized error message to your
// customer using `error.message`.
if (result.error) {
alert(result.error.message);
}
})
.catch(function(error) {
console.error('Error:', error);
});
}
}
Which seems to be the same as:
<script type="text/javascript">
// Create an instance of the Stripe object with your publishable API key
var stripeKey = document.querySelector('meta[name="stripe-key"]').getAttribute("content")
var stripe = Stripe(stripeKey);
var checkoutButton = document.getElementById('checkout-button');
checkoutButton.addEventListener('click', function() {
// Create a new Checkout Session using the server-side endpoint you
// created in step 3.
fetch('/create-checkout-session', {
method: 'POST',
headers: {
'X-CSRF-Token': document.querySelector("meta[name='csrf-token']").getAttribute("content"),
},
})
.then(function(response) {
return response.json();
})
.then(function(session) {
return stripe.redirectToCheckout({ sessionId: session.id });
})
.then(function(result) {
// If `redirectToCheckout` fails due to a browser or network
// error, you should display the localized error message to your
// customer using `error.message`.
if (result.error) {
alert(result.error.message);
}
})
.catch(function(error) {
console.error('Error:', error);
});
});
</script>
Here is the code from Rails (which seems to be working):
def create_checkout_session
session = Stripe::Checkout::Session.create(
payment_method_types: ['card'],
line_items: [{
price_data: {
currency: 'aud',
product_data: {
name: 'Hamper',
},
unit_amount: 10000,
},
quantity: 1,
}],
mode: 'payment',
success_url: "https://localhost:5000/payment_success.html",
cancel_url: "https://localhost:5000/payment_failed.html",
)
render json: { id: session.id }
end
Thanks in advance for any help you can give to shed light on why this isn’t working