/api/user/subscriptions/create-payment-method (POST)
await global.api.user.subscriptions.CreatePaymentMethod.post(req) Located in Stripe Subscriptions module API
Returns object
Exceptions
These exceptions are thrown (NodeJS) or returned as JSON (HTTP) if you provide incorrect data or do not meet the requirements:
Exception | Circumstances |
---|---|
invalid querystring customerid | |
invalid-customerid | missing querystring customerid |
invalid-account | ineligible accessing account |
Receives
API routes may receive parameters from the URL and POST supporting simple and multipart:
Field | Value | Required | Type |
---|---|---|---|
cvc | string | configurable as required | POST |
exp_month | string | configurable as required | POST |
exp_year | string | configurable as required | POST |
name | string | configurable as required | POST |
number | string | configurable as required | POST |
token | string | configurable as required | POST |
NodeJS source (edit on github)
If you see a problem with the source submit a pull request on Github.
const subscriptions = require('../../../../../index.js')
const stripeCache = require('../../../../stripe-cache.js')
module.exports = {
post: async (req) => {
if (!req.query || !req.query.customerid) {
throw new Error('invalid-customerid')
}
const customer = await global.api.user.subscriptions.Customer.get(req)
if (!customer) {
throw new Error('invalid-customer')
}
if (!global.stripeJS) {
if (!req.body || !req.body.name || !req.body.name.length) {
throw new Error('invalid-name')
}
if (!req.body.number || !req.body.number.length) {
throw new Error('invalid-number')
}
if (!req.body.cvc || req.body.cvc.length !== 3) {
throw new Error('invalid-cvc')
}
try {
const intValue = parseInt(req.body.cvc, 10)
if (intValue.toString() !== req.body.cvc) {
throw new Error('invalid-cvc')
}
} catch (error) {
throw new Error('invalid-cvc')
}
if (!req.body.exp_month || !req.body.exp_month.length) {
throw new Error('invalid-exp_month')
}
try {
const intValue = parseInt(req.body.exp_month, 10)
if (intValue.toString() !== req.body.exp_month) {
throw new Error('invalid-exp_month')
}
if (intValue < 1 || intValue > 12) {
throw new Error('invalid-exp_month')
}
} catch (error) {
throw new Error('invalid-exp_month')
}
if (!req.body.exp_year || !req.body.exp_year.length) {
throw new Error('invalid-exp_year')
}
try {
const intValue = parseInt(req.body.exp_year, 10)
if (intValue.toString() !== req.body.exp_year) {
throw new Error('invalid-exp_year')
}
const now = parseInt(new Date().getFullYear().toString().substring(2), 10)
if (intValue < now || intValue > now + 10) {
throw new Error('invalid-exp_year')
}
} catch (error) {
throw new Error('invalid-exp_year')
}
} else if (global.stripeJS === 2 || global.stripeJS === 3) {
if (!req.body || !req.body.token || !req.body.token.length) {
throw new Error('invalid-token')
}
}
const cardInfo = {}
if (!global.stripeJS) {
cardInfo.number = req.body.number
cardInfo.cvc = req.body.cvc
cardInfo.exp_month = req.body.exp_month
cardInfo.exp_year = req.body.exp_year
} else if (global.stripeJS === 2 || global.stripeJS === 3) {
cardInfo.token = req.body.token
}
const billingInfo = {
name: req.body.name,
address: {}
}
for (const field of ['line1', 'line2', 'city', 'state', 'zip', 'country']) {
if (req.body[field] && req.body[field].length) {
billingInfo.address[field] = req.body[`address_${field}`]
}
}
const paymentMethodInfo = {
type: 'card',
card: cardInfo,
metadata: {
appid: req.appid,
accountid: req.account.accountid
}
}
if (global.stripeJS === false) {
paymentMethodInfo.billing_details = billingInfo
}
let paymentMethod = await stripeCache.execute('paymentMethods', 'create', paymentMethodInfo, req.stripeKey)
paymentMethod = await stripeCache.execute('paymentMethods', 'attach', paymentMethod.id, {
customer: req.query.customerid
}, req.stripeKey)
const setupIntent = await stripeCache.execute('setupIntents', 'create', {
customer: req.query.customerid,
payment_method: paymentMethod.id,
usage: 'off_session'
}, req.stripeKey)
await stripeCache.update(setupIntent)
if (req.body.default === 'true') {
const customerNow = await stripeCache.execute('customers', 'update', req.query.customerid, {
invoice_settings: {
default_payment_method: paymentMethod.id
}
}, req.stripeKey)
await stripeCache.update(customerNow)
}
await stripeCache.update(paymentMethod)
await subscriptions.StorageList.addMany({
[`${req.appid}/paymentMethods`]: paymentMethod.id,
[`${req.appid}/customer/paymentMethods/${req.query.customerid}`]: paymentMethod.id,
[`${req.appid}/account/paymentMethods/${req.account.accountid}`]: paymentMethod.id,
[`${req.appid}/setupIntents`]: setupIntent.id,
[`${req.appid}/customer/setupIntents/${req.query.customerid}`]: setupIntent.id,
[`${req.appid}/account/setupIntents/${req.account.accountid}`]: setupIntent.id
})
return paymentMethod
}
}
Test source (edit on github)
Tests perform real HTTP requests against a running Dashboard server.
/* eslint-env mocha */
const assert = require('assert')
const TestHelper = require('../../../../../test-helper.js')
describe('/api/user/subscriptions/create-payment-method', () => {
describe('exceptions', () => {
describe('invalid-customerid', () => {
it('missing querystring customerid', async () => {
global.stripeJS = false
const user = await TestHelper.createUser()
const req = TestHelper.createRequest('/api/user/subscriptions/create-payment-method')
req.account = user.account
req.session = user.session
let errorMessage
try {
await req.post()
} catch (error) {
errorMessage = error.message
}
assert.strictEqual(errorMessage, 'invalid-customerid')
})
it('invalid querystring customerid', async () => {
global.stripeJS = false
const user = await TestHelper.createUser()
const req = TestHelper.createRequest('/api/user/subscriptions/create-payment-method?customerid=invalid')
req.account = user.account
req.session = user.session
let errorMessage
try {
await req.post()
} catch (error) {
errorMessage = error.message
}
assert.strictEqual(errorMessage, 'invalid-customerid')
})
})
describe('invalid-account', () => {
it('ineligible accessing account', async () => {
const user = await TestHelper.createUser()
await TestHelper.createCustomer(user, {
email: user.profile.contactEmail,
description: user.profile.firstName
})
const user2 = await TestHelper.createUser()
const req = TestHelper.createRequest(`/api/user/subscriptions/create-payment-method?customerid=${user.customer.id}`)
req.account = user2.account
req.session = user2.session
req.body = {
name: `${user2.profile.firstName} ${user2.profile.lastName}`,
cvc: '111',
number: '4111111111111111',
exp_month: '1',
exp_year: (new Date().getFullYear() + 1).toString().substring(2),
address_line1: 'A street address',
address_city: 'City',
address_state: 'NY',
address_zip: '90120',
address_country: 'US',
default: 'true'
}
let errorMessage
try {
await req.post()
} catch (error) {
errorMessage = error.message
}
assert.strictEqual(errorMessage, 'invalid-account')
})
})
})
describe('receives', () => {
it('optionally-required posted name', async () => {
global.stripeJS = false
const user = await TestHelper.createUser()
await TestHelper.createCustomer(user, {
email: user.profile.contactEmail,
description: user.profile.firstName
})
const req = TestHelper.createRequest(`/api/user/subscriptions/create-payment-method?customerid=${user.customer.id}`)
req.account = user.account
req.session = user.session
req.body = {
email: user.profile.contactEmail,
description: 'description',
name: '',
cvc: '111',
number: '4111111111111111',
exp_month: '1',
exp_year: (new Date().getFullYear() + 1).toString().substring(2)
}
let errorMessage
try {
await req.post()
} catch (error) {
errorMessage = error.message
}
assert.strictEqual(errorMessage, 'invalid-name')
})
it('optionally-required posted cvc', async () => {
global.stripeJS = false
const user = await TestHelper.createUser()
await TestHelper.createCustomer(user, {
email: user.profile.contactEmail,
description: user.profile.firstName
})
const req = TestHelper.createRequest(`/api/user/subscriptions/create-payment-method?customerid=${user.customer.id}`)
req.account = user.account
req.session = user.session
req.body = {
email: user.profile.contactEmail,
description: 'description',
name: `${user.profile.firstName} ${user.profile.lastName}`,
cvc: '0',
number: '4111111111111111',
exp_month: '1',
exp_year: (new Date().getFullYear() + 1).toString().substring(2)
}
let errorMessage
try {
await req.post()
} catch (error) {
errorMessage = error.message
}
assert.strictEqual(errorMessage, 'invalid-cvc')
})
it('optionally-required posted number', async () => {
global.stripeJS = false
const user = await TestHelper.createUser()
await TestHelper.createCustomer(user, {
email: user.profile.contactEmail,
description: user.profile.firstName
})
const req = TestHelper.createRequest(`/api/user/subscriptions/create-payment-method?customerid=${user.customer.id}`)
req.account = user.account
req.session = user.session
req.body = {
email: user.profile.contactEmail,
description: 'description',
name: `${user.profile.firstName} ${user.profile.lastName}`,
cvc: '123',
number: '',
exp_month: '1',
exp_year: (new Date().getFullYear() + 1).toString().substring(2)
}
let errorMessage
try {
await req.post()
} catch (error) {
errorMessage = error.message
}
assert.strictEqual(errorMessage, 'invalid-number')
})
it('optionally-required posted exp_month', async () => {
global.stripeJS = false
const user = await TestHelper.createUser()
await TestHelper.createCustomer(user, {
email: user.profile.contactEmail,
description: user.profile.firstName
})
const req = TestHelper.createRequest(`/api/user/subscriptions/create-payment-method?customerid=${user.customer.id}`)
req.account = user.account
req.session = user.session
req.body = {
email: user.profile.contactEmail,
description: 'description',
name: `${user.profile.firstName} ${user.profile.lastName}`,
cvc: '123',
number: '4111111111111111',
exp_month: '',
exp_year: (new Date().getFullYear() + 1).toString().substring(2)
}
let errorMessage
try {
await req.post()
} catch (error) {
errorMessage = error.message
}
assert.strictEqual(errorMessage, 'invalid-exp_month')
})
it('optionally-required posted exp_year', async () => {
global.stripeJS = false
const user = await TestHelper.createUser()
await TestHelper.createCustomer(user, {
email: user.profile.contactEmail,
description: user.profile.firstName
})
const req = TestHelper.createRequest(`/api/user/subscriptions/create-payment-method?customerid=${user.customer.id}`)
req.account = user.account
req.session = user.session
req.body = {
email: user.profile.contactEmail,
description: 'description',
name: `${user.profile.firstName} ${user.profile.lastName}`,
cvc: '123',
number: '4111111111111111',
exp_month: '1',
exp_year: ''
}
let errorMessage
try {
await req.post()
} catch (error) {
errorMessage = error.message
}
assert.strictEqual(errorMessage, 'invalid-exp_year')
})
it('optionally-required posted token', async () => {
global.stripeJS = 2
const user = await TestHelper.createUser()
await TestHelper.createCustomer(user, {
email: user.profile.contactEmail,
description: user.profile.firstName
})
const req = TestHelper.createRequest(`/api/user/subscriptions/create-payment-method?customerid=${user.customer.id}`)
req.account = user.account
req.session = user.session
req.body = {
email: user.profile.contactEmail,
description: 'description',
name: `${user.profile.firstName} ${user.profile.lastName}`,
token: ''
}
let errorMessage
try {
await req.post()
} catch (error) {
errorMessage = error.message
}
assert.strictEqual(errorMessage, 'invalid-token')
})
})
describe('returns', () => {
it('object', async () => {
global.stripeJS = false
const user = await TestHelper.createUser()
await TestHelper.createCustomer(user, {
email: user.profile.contactEmail,
description: user.profile.firstName
})
const req = TestHelper.createRequest(`/api/user/subscriptions/create-payment-method?customerid=${user.customer.id}`)
req.account = user.account
req.session = user.session
req.body = {
name: `${user.profile.firstName} ${user.profile.lastName}`,
cvc: '111',
number: '4111111111111111',
exp_month: '1',
exp_year: (new Date().getFullYear() + 1).toString().substring(2),
address_line1: 'A street address',
address_city: 'City',
address_state: 'NY',
address_zip: '90120',
address_country: 'US',
default: 'true'
}
req.filename = __filename
req.saveResponse = true
const paymentMethod = await req.post()
assert.strictEqual(paymentMethod.object, 'payment_method')
})
})
describe('configuration', () => {
it('environment STRIPE_JS', async () => {
global.stripeJS = 2
const user = await TestHelper.createUser()
await TestHelper.createCustomer(user, {
email: user.profile.contactEmail,
description: user.profile.firstName
})
const req = TestHelper.createRequest(`/api/user/subscriptions/create-payment-method?customerid=${user.customer.id}`)
req.account = user.account
req.session = user.session
req.body = {
name: `${user.profile.firstName} ${user.profile.lastName}`,
cvc: '111',
number: '4111111111111111',
exp_month: '1',
exp_year: (new Date().getFullYear() + 1).toString().substring(2),
address_line1: 'A street address',
address_city: 'City',
address_state: 'NY',
address_zip: '90120',
address_country: 'US',
default: 'true'
}
let errorMessage
try {
await req.post()
} catch (error) {
errorMessage = error.message
}
assert.strictEqual(errorMessage, 'invalid-token')
})
})
})