fc77ee76d6
The primary license of the project is changing to: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later The Additional Permission is designed to permit publicly distributed Javascript code to be relicensed under LGPL-3.0-or-later, but not server-side Javascript code. As such, we've relicensed here static Javscript files under LGPL-3.0-or-later, and those that run as part of build and/or server side under AGPL-3.0-or-later. Note that in future, Javascript files may be updated to be stronger copyleft license with the Additional Permission, particularly if they adapted to run on server side and/or turned into templates. Of course, we'd seek public discussion with the contributor community about such changes. This commit is one of the many steps to relicense the entire codebase. Documentation granting permission for this relicensing (from all past contributors who hold copyrights) is on file with Software Freedom Conservancy, Inc.
114 lines
3.3 KiB
JavaScript
114 lines
3.3 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)
|
|
// 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)
|
|
}
|
|
}
|