ectoflow / vue-stripe-elements

A Vue 2 component collection for Stripe.js
MIT License
530 stars 124 forks source link

Can't add card holder name #122

Closed hendrikeng closed 3 years ago

hendrikeng commented 3 years ago

Hey there, i am slightly confused , everything works but i can't add the cardHolder name:

    async submitPaymentForm() {
              const groupComponent = this.$refs.elms;
              const cardComponent = this.$refs.card;
              const cardElement = cardComponent.stripeElement;
              // wont work
              // this.cardOptions.name = `${this.cardFirstName} ${this.cardLastName}`;
              // wont work
              // this.cardOptions.billing_details.name = `${this.cardFirstName} ${this.cardLastName}`;
              // Access instance methods, e.g. createToken();
              await groupComponent.instance
                  .createToken(cardElement)
                  .then(result => {
                      this.token = result.token.id;
                  })
                  .catch(error => {
                      this.stripeError = error;
                  });
            }

it usually worked in the beta version, what am i missing?

softbeehive commented 3 years ago

Hi @hendrikeng, it seems that you hit Vue 2 nested object reactivity limitations, try definingcardOptions structure in data first

data() {
  return {
    // ...
    cardOptions: {
      name: '',
      billing_details: {
        name: ''
      }
    }
  }
}

and then set props as you like

this.cardOptions.name = `${this.cardFirstName} ${this.cardLastName}`

Hope it helps https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

hendrikeng commented 3 years ago

@softbeehive thank you for the quick reply, yes I thought the same, but somehow it's not the issue. It won't work if set it in the method either.

   data: () => ({
        instanceOptions: {
            // https://stripe.com/docs/js/initializing#init_stripe_js-options
            locale: document.documentElement.lang.substr(0, 2),
        },
        elementsOptions: {
            // https://stripe.com/docs/js/elements_object/create#stripe_elements-options
        },
        cardOptions: {
            name: 'test',
            billing_details: {
                name: 'test2',
            },
            // https://stripe.com/docs/stripe.js#element-options
            hidePostalCode: true,
        },
        stripeError: null,
    }),
  methods: {
    async submitPaymentForm() {
        const groupComponent = this.$refs.elms;
        const cardComponent = this.$refs.card;
        const cardElement = cardComponent.stripeElement;
        this.cardOptions.name = `not via data`;
        // Access instance methods, e.g. createToken();
        await groupComponent.instance
            .createToken(cardElement)
            .then(result => {
                this.token = result.token.id;
            })
            .catch(error => {
                this.stripeError = error;
            });
       },
  }
softbeehive commented 3 years ago

Please share your template, I'll check it tomorrow

hendrikeng commented 3 years ago

@softbeehive thank you very much!

<template>
    <div>
        <form method="post">
            <input v-model="cardFirstName" type="text" />
            <input v-model="cardLastName" type="text" />
            >
            <StripeElements
                :stripe-key="data.stripePublishableApiKey"
                :instance-options="instanceOptions"
                :elements-options="elementsOptions"
                #default="{ elements }"
                ref="elms"
            >
                <StripeElement
                    type="card"
                    :elements="elements"
                    :options="cardOptions"
                    ref="card"
                />
            </StripeElements>
            <input type="submit" value="submit" @click="submitPaymentForm" />
        </form>
    </div>
</template>

<script>
import { StripeElements, StripeElement } from 'vue-stripe-elements-plus';

export default {
    name: 'CheckoutPayment',
    data: () => ({
        token: '',
        cardFirstName: '',
        cardLastName: '',
        instanceOptions: {
            // https://stripe.com/docs/js/initializing#init_stripe_js-options
            locale: document.documentElement.lang.substr(0, 2),
        },
        elementsOptions: {
            // https://stripe.com/docs/js/elements_object/create#stripe_elements-options
        },
        cardOptions: {
            name: 'test',
            billing_details: {
                name: 'test2',
            },
            // https://stripe.com/docs/stripe.js#element-options
            hidePostalCode: true,
        },
        stripeError: null,
    }),
    props: {
        data: Object,
    },
    components: { StripeElements, StripeElement },
    methods: {
        async submitPaymentForm() {
            const groupComponent = this.$refs.elms;
            const cardComponent = this.$refs.card;
            this.cardOptions.name = `asdsad asdasd`;
            const cardElement = cardComponent.stripeElement;
            // Access instance methods, e.g. createToken();
            await groupComponent.instance
                .createToken(cardElement)
                .then(result => {
                    this.token = result.token.id;
                })
                .catch(error => {
                    this.stripeError = error;
                });
        },
    },
};
</script>
softbeehive commented 3 years ago

Hey, I quickly tried it. Stripe gives a proper warning when unsupported props are used in cardOptions.

Unrecognized create() parameter: name is not a recognized parameter. This may cause issues with your integration in the future.

https://stripe.com/docs/js/elements_object/create_element?type=card#elements_create-options-value


It looks like you may want to add name and other data when creating a token:

await groupComponent.instance
  .createToken(cardElement, { name: 'John Dean' })

createToken data docs


In regards to billing_details, it doesn't seem to be a part of card element creation API. Check createPaymentMethod(paymentMethodData)

hendrikeng commented 3 years ago

well...next time i should read the docs more carefully...thank you very much :) @softbeehive

softbeehive commented 3 years ago

Not at all, I've been there too. Constantly checking Stripe API is pretty challenging, because you have to keep context in your memory instead of having this context in your editor.