简体   繁体   中英

Stripe Payments Add Payment Source / Card / Method using NodeJS / Vue

I am building a simple SaaS application with recurring payments using NodeJS with Express for the API and Vue for the UI. I have code written to add a customer and link a subscription and plan as well as a few other routines. We allow users to sign up without entering a payment method so now, I need to add a way for a user to add a payment method. I have been through so much documentation that my head is spinning and Stripe support (or lack thereof) has been no help.

I have tried everything from createSource, createToken, and createPaymentMethod in the UI and then submitted that to the API where I have tried using everything from stripeapi.customers.createSource to stripe.paymentMethods.create and nothing works. Everything returns an error about either something missing in the object or the object being incorrect. I have attempted to look at the payment intents API however, this seems like overkill to just simply add a card to a customer.

Here is my latest code.

UI : Create Element

this.stripe = await loadStripe('pk_test_');
let stripeElem = this.stripe.elements();

this.card = stripeElem.create('card', { hideIcon: true, hidePostalCode: false, style: { base: { color: '#363636', fontSize: '22px', fontSmoothing: 'antialiased' }}});
this.card.mount(this.$refs.card);

UI: Submit to API

await this.stripe.createSource(this.card, { type: 'card' } ).then((source) => {
  this.$http.post(`/api/route`, source).then((response) => {
    if (response.status === 200) {

    } else {

    }
  }).catch(() => {

  });

API

await stripeapi.customers.createSource(customer_id, { source: card });

This code produces this object:

{ source:
   { id: 'src_1HLFsEDfvqoM1TxYXmFvlcK9',
     object: 'source',
     amount: null,
     card:
      { exp_month: 1,
        exp_year: 2022,
        last4: '4242',
        country: 'US',
        brand: 'Visa',
        address_zip_check: 'unchecked',
        cvc_check: 'unchecked',
        funding: 'credit',
        three_d_secure: 'optional',
        name: null,
        address_line1_check: null,
        tokenization_method: null,
        dynamic_last4: null },
     client_secret: 'src_client_secret_VILuqM6ZikLzp9nMq4gizfN8',
     created: 1598653002,
     currency: null,
     flow: 'none',
     livemode: false,
     metadata: {},
     owner:
      { address: [Object],
        email: null,
        name: null,
        phone: null,
        verified_address: null,
        verified_email: null,
        verified_name: null,
        verified_phone: null },
     statement_descriptor: null,
     status: 'chargeable',
     type: 'card',
     usage: 'reusable' } }

This code and object produce this error:

(node:352976) UnhandledPromiseRejectionWarning: Error: The source hash must include an 'object' key indicating what type of source to create.
    at Function.generate (/data/api/node_modules/stripe/lib/Error.js:39:16)
    at IncomingMessage.res.once (/data/api/docroot/node_modules/stripe/lib/StripeResource.js:190:33)
    at Object.onceWrapper (events.js:286:20)
    at IncomingMessage.emit (events.js:203:15)
    at IncomingMessage.EventEmitter.emit (domain.js:448:20)
    at endReadableNT (_stream_readable.js:1145:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)

All I want to do is take an element, create a payment source/method (whatever it's called) and then associate that with a customer. Any help is appreciated. I have look at so many examples but nothing has worked for me. Everything seems to produce an error about the object or what not.

After more hours of development I finally figured it out! The API reference is severely lacking but this article here explains what to do: https://stripe.com/docs/payments/save-card-without-authentication

Essentially, you create and mount the element. Then, you use the createPaymentMethod in the UI and pass the card element to it. From there, you submit the paymentMethod.id string to your API and then use strip.paymentMethods.attach to attach it to a customer by passing the paymentMethod.id and the Stripe customer ID.

Front End HTML

<div ref="card" class="credit-card"></div>

Front End Create and Mount

this.stripe = await loadStripe('pk_test_YOURKEY');
let stripeElem = this.stripe.elements();

this.card = stripeElem.create('card', { hideIcon: true, hidePostalCode: false, style: { base: { color: '#363636', fontSize: '22px', fontSmoothing: 'antialiased' }}});
this.card.mount(this.$refs.card);

Front End Create Payment Method and Submit to Back End

await this.stripe.createPaymentMethod({ type: 'card', card: this.card }).then((method) => {
  this.$http.post(`/users/billing/cards`, { id: method.paymentMethod.id }).then((response) => {

  }).catch(() => {

  });
}).catch(() => {

});

Please note: this code is NOT complete, it's just meant to give you an example for those that have struggled like I have.

The NodeJS error message reads:

The source hash must include an 'object' key indicating what type of source to create.

It can also be found here , but I'm not certain, if not this is a bogus error message. If this should indeed apply, it would be object: 'card' instead of object: 'source' ; but I don't think so.


With Stripe there sometimes is more than one way to get something done:

The source should definitely be a client-side generated card token,
but your client-side doesn't have any code that would token-ize the card.

For reference, these would have to be combined:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM