129 lines
3.6 KiB
JavaScript
129 lines
3.6 KiB
JavaScript
// License: LGPL-3.0-or-later
|
|
// Include the cards/fields partial to use with this.
|
|
// Call appl.card_form.create(card_obj) to start the card creation process.
|
|
// Use the appl.card_form.on_fail callback to handle failures.
|
|
// Use the appl.card_form.on_complete callback to handle completion.
|
|
// This does not create any donations -- do the donation creation inside appl.card_form.on_complete.
|
|
|
|
// Not namespacing card_form; only show one card form on the page at any time
|
|
|
|
var request = require('../common/super-agent-promise')
|
|
var format_err = require('../common/format_response_error')
|
|
|
|
module.exports = create_card
|
|
|
|
// UI state defaults
|
|
appl.def('card_form', {
|
|
loading: false,
|
|
error: false,
|
|
status: '',
|
|
on_complete: function() {},
|
|
on_fail: function() {},
|
|
progress_width: '0%' // Width of the progress bar
|
|
})
|
|
|
|
// Define some status messages and progress bar widths for each step of the process
|
|
var statuses = {
|
|
before_tokenization: {
|
|
progress_width: '20%',
|
|
status: 'Double-checking your card...'
|
|
},
|
|
before_create: {
|
|
progress_width: '75%',
|
|
status: 'Looks good! Sending the carrier pigeons...'
|
|
},
|
|
on_complete: {
|
|
progress_width: '100%',
|
|
status: 'Processing payment...'
|
|
}
|
|
}
|
|
|
|
// Tokenize with stripe, then save to our db.
|
|
// The first argument must be a holder object that has 'type' and 'id' keys.
|
|
// eg: {holder: {type: 'Nonprofit', id: 1}}
|
|
function create_card(holder, card_obj, options) {
|
|
options = options || {}
|
|
if(appl.card_form.loading) return
|
|
appl.def('card_form', { loading: true, error: false })
|
|
appl.def('card_form', statuses.before_tokenization)
|
|
|
|
// Delete the cvc key from card_obj if
|
|
// the value of cvc is a blank string.
|
|
// Otherwise, Stripe will return an error for
|
|
// incorrect security code.
|
|
if(card_obj.cvc === '') {
|
|
delete card_obj['cvc']
|
|
}
|
|
|
|
// First, tokenize the card with Stripe.js
|
|
return tokenize_with_stripe(card_obj)
|
|
.catch(display_stripe_err)
|
|
// Then, save a Card record in our db
|
|
.then(function(stripe_resp) {
|
|
appl.def('card_form', statuses.before_create)
|
|
return create_record(holder, stripe_resp, options)
|
|
})
|
|
.then(function(resp) {
|
|
appl.def('card_form', statuses.on_complete)
|
|
return resp.body
|
|
})
|
|
.catch(display_err)
|
|
}
|
|
|
|
// Post to stripe to get back a stripe_card_token
|
|
function tokenize_with_stripe(card_obj) {
|
|
return new Promise(function(resolve, reject) {
|
|
Stripe.card.createToken(card_obj, function(status, resp) {
|
|
if(resp.error) reject(resp)
|
|
else resolve(resp)
|
|
})
|
|
})
|
|
}
|
|
|
|
// Save a record of the card in our own db
|
|
function create_record(holder, stripe_resp, options={}) {
|
|
var output = {card: {
|
|
holder_type: holder.type,
|
|
holder_id: holder.id,
|
|
email: holder.email,
|
|
cardholders_name: stripe_resp.name,
|
|
name: stripe_resp.card.brand + ' *' + stripe_resp.card.last4,
|
|
stripe_card_token: stripe_resp.id,
|
|
stripe_card_id: stripe_resp.card.id
|
|
}}
|
|
if (options['event_id'])
|
|
{
|
|
output['event_id'] = options['event_id']
|
|
}
|
|
|
|
return request.post(options.path || '/cards')
|
|
.send(output)
|
|
.perform()
|
|
}
|
|
|
|
// Set UI state to display an error in the card form.
|
|
function display_err(resp) {
|
|
if(resp && resp.body) {
|
|
appl.def('card_form', {
|
|
loading: false,
|
|
error: true,
|
|
status: format_err(resp),
|
|
progress_width: '0%'
|
|
})
|
|
appl.def('loading', false)
|
|
}
|
|
}
|
|
|
|
function display_stripe_err(resp) {
|
|
if(resp && resp.error) {
|
|
appl.def('card_form', {
|
|
loading: false,
|
|
error: true,
|
|
status: resp.error.message,
|
|
progress_width: '0%'
|
|
})
|
|
appl.def('loading', false)
|
|
|
|
throw new Error()
|
|
}
|
|
}
|