Lloydinator
Lloydinator

Reputation: 303

"Received unknown parameter" with Stripe Elements and SetupIntent in Nuxt/Vue

Ok so I'm trying to confirm a SetupIntent so I can save a card for later payments. I have Laravel on the backend and Nuxt on the front end. I'm just trying to have Vue save my card. My system is set up that I save the clientSecret in the database when I make a new account. Then when I'm trying to add a card to the client's account, I use axios to retrieve the clientSecret and use it in the confirmCardSetup method as described here. When I try to actually save the card, it's returning an error. I think it may be that I'm writing the Vue code wrong. This is how I do it:

import {mapGetters} from 'vuex'
import Message from '~/components/Message'

export default {
    middleware: 'auth',
    name: 'account',
    data(){
        return {
            userData: {},
            error: null,
            success: null,
            intent: '',
            clientSecret: '',
            elements: null,
            card: null,
        };
    },
    components: {
        Message,
    },
    computed: {
        ...mapGetters(['loggedInUser'])
    },
    mounted(){
        this.elements = this.$stripe.import().elements()
        this.card = this.elements.create('card', {})
        this.card.mount(this.$refs.card)
        console.log(this.elements)
        console.log(this.card)

        this.getIntent()
    },   
    methods: {
        paymentIntent(){
            //evt.preventDefault()

            self.$stripe.import().confirmCardSetup(
                this.intent,
                {
                    payment_method: {
                        card: this.elements,
                        billing_details: {
                            name: this.$auth.$state.user.name,
                        },
                    },
                }
            )
            .then(
                res => {
                    if (res.error){
                        console.log(res.error)
                    }
                    else {
                        console.log(res)
                    }
                }
            )
        },
        async getIntent(){
            self = this
            self.$axios.get(`account/setup-intent/${self.$auth.$state.user.id}`,
                {
                    header: {
                        'Authorization': self.$auth.getToken('local')
                    }
                }
            )
            .then(
                res => {
                    self.intent = res.data.intent
                }
            )
            .catch(error => console.log(error))
        },...

This is the object I get back:

code: "parameter_unknown"
doc_url: "https://stripe.com/docs/error-codes/parameter-unknown"
message: "Received unknown parameters: _elements, _id, _timings, _controller, _pendingFonts, _commonOptions"
param: "payment_method_data[card][_elements]"
setup_intent: {id: "seti_1HlLvp2sfYHW6zV6gKlH4wRg", object: "setup_intent", cancellation_reason: null, client_secret: "seti_1HlLvp2sfYHW6zV6gKlH4wRg_secret_IM43ctpYc92lw7x7qgXIehrMVNOjML8", created: 1604872817, …}
type: "invalid_request_error"
__proto__: Object

Finally, this is how I have my card:

<!-- card -->
<p class="mt-4 mb-4 text-gray-800 border-b border-black font-medium">Payment information</p>
<div ref="card"></div>
<button 
    type="submit" 
    id="card-button"
    @click="paymentIntent"
    >Add Card
</button>

What am I doing wrong?

Upvotes: 0

Views: 2703

Answers (2)

Lloydinator
Lloydinator

Reputation: 303

I was using the nuxt-stripe library from WilliamDaSilva. I'm sure it was a great library, but apparently Stripe updates caused a lot of things to break. Putting Stripe in the header (nuxt.config.js file) and then following the setupIntent docs solved it for me rather quickly. Should've just went with the first-party solution first.

import {mapGetters} from 'vuex'
import Message from '~/components/Message'

export default {
    middleware: 'auth',
    name: 'account',
    data(){
        return {
            userData: {},
            error: null,
            success: null,
            clientSecret: '',
            card: null,
            stripe: Stripe(process.env.PUB_KEY),
        };
    },
    components: {
        Message,
    },
    computed: {
        ...mapGetters(['loggedInUser'])
    },
    
    mounted(){
        var elements = this.stripe.elements()
        this.card = elements.create('card')
        this.card.mount(this.$refs.cardelement)
        this.getIntent()
    },
    methods: {
        setupIntent(){
            this.stripe.confirmCardSetup(
                this.clientSecret,
                {
                    payment_method: {
                        card: this.card,
                        billing_details: {
                            name: this.$auth.$state.user.name,
                        },
                    },
                }
            )
            .then(
                res => {
                    if (res.error){
                        console.log(res.error)
                    }
                    else {
                        console.log(res)
                    }
                }
            )
        },
...

Upvotes: 0

floatingLomas
floatingLomas

Reputation: 8737

You should be using this.card not this.elements here:

        self.$stripe.import().confirmCardSetup(
            this.intent,
            {
                payment_method: {
                    card: this.elements,
                    billing_details: {
                        name: this.$auth.$state.user.name,
                    },
                },
            }
        )

Upvotes: 1

Related Questions