99 lines
3.4 KiB
JavaScript
99 lines
3.4 KiB
JavaScript
|
/**
|
|||
|
* openStripeCheckout()
|
|||
|
*
|
|||
|
* Open the Stripe Checkout modal dialog and resolve when it is closed.
|
|||
|
*
|
|||
|
* -----------------------------------------------------------------
|
|||
|
* @param {String} stripePublishableKey
|
|||
|
* @param {String} billingEmailAddress
|
|||
|
* @param {String} headingText (optional)
|
|||
|
* @param {String} descriptionText (optional)
|
|||
|
* @param {String} buttonText (optional)
|
|||
|
* -----------------------------------------------------------------
|
|||
|
* @returns {Dictionary?} (or undefined if the form was cancelled)
|
|||
|
* e.g.
|
|||
|
* {
|
|||
|
* stripeToken: '…',
|
|||
|
* billingCardLast4: '…',
|
|||
|
* billingCardBrand: '…',
|
|||
|
* billingCardExpMonth: '…',
|
|||
|
* billingCardExpYear: '…'
|
|||
|
* }
|
|||
|
* -----------------------------------------------------------------
|
|||
|
* Example usage:
|
|||
|
* ```
|
|||
|
* var billingInfo = await openStripeCheckout(
|
|||
|
* 'pk_test_Qz5RfDmVV5IunTFAHtDqDWn4',
|
|||
|
* 'foo@example.com'
|
|||
|
* );
|
|||
|
* ```
|
|||
|
*/
|
|||
|
|
|||
|
parasails.registerUtility('openStripeCheckout', async function openStripeCheckout(stripePublishableKey, billingEmailAddress, headingText, descriptionText, buttonText) {
|
|||
|
|
|||
|
// Cache (& use cached) "checkout handler" globally on the page so that we
|
|||
|
// don't end up configuring it more than once (i.e. so Stripe.js doesn't
|
|||
|
// complain).
|
|||
|
var CACHE_KEY = '_cachedStripeCheckoutHandler';
|
|||
|
if (!window[CACHE_KEY]) {
|
|||
|
window[CACHE_KEY] = StripeCheckout.configure({
|
|||
|
key: stripePublishableKey,
|
|||
|
});
|
|||
|
}
|
|||
|
var checkoutHandler = window[CACHE_KEY];
|
|||
|
|
|||
|
// Track whether the "token" callback was triggered.
|
|||
|
// (If it has NOT at the time the "closed" callback is triggered, then we
|
|||
|
// know the checkout form was cancelled.)
|
|||
|
var hasTriggeredTokenCallback;
|
|||
|
|
|||
|
// Build a Promise & send it back as our "thenable" (AsyncFunction's return value).
|
|||
|
// (this is necessary b/c we're wrapping an api that isn't `await`-compatible)
|
|||
|
return new Promise((resolve, reject)=>{
|
|||
|
try {
|
|||
|
// Open Stripe checkout.
|
|||
|
// (https://stripe.com/docs/checkout#integration-custom)
|
|||
|
checkoutHandler.open({
|
|||
|
name: headingText || 'NEW_APP_NAME',
|
|||
|
description: descriptionText || 'Link your credit card.',
|
|||
|
panelLabel: buttonText || 'Save card',
|
|||
|
email: billingEmailAddress,//« So that Stripe doesn't prompt for an email address
|
|||
|
locale: 'auto',
|
|||
|
zipCode: false,
|
|||
|
allowRememberMe: false,
|
|||
|
closed: ()=>{
|
|||
|
// If the Checkout dialog was cancelled, resolve undefined.
|
|||
|
if (!hasTriggeredTokenCallback) {
|
|||
|
resolve();
|
|||
|
}
|
|||
|
},
|
|||
|
token: (stripeData)=>{
|
|||
|
|
|||
|
// After payment info has been successfully added, and a token
|
|||
|
// was obtained...
|
|||
|
hasTriggeredTokenCallback = true;
|
|||
|
|
|||
|
// Normalize token and billing card info from Stripe and resolve
|
|||
|
// with that.
|
|||
|
let stripeToken = stripeData.id;
|
|||
|
let billingCardLast4 = stripeData.card.last4;
|
|||
|
let billingCardBrand = stripeData.card.brand;
|
|||
|
let billingCardExpMonth = String(stripeData.card.exp_month);
|
|||
|
let billingCardExpYear = String(stripeData.card.exp_year);
|
|||
|
|
|||
|
resolve({
|
|||
|
stripeToken,
|
|||
|
billingCardLast4,
|
|||
|
billingCardBrand,
|
|||
|
billingCardExpMonth,
|
|||
|
billingCardExpYear
|
|||
|
});
|
|||
|
}//Œ
|
|||
|
});//_∏_
|
|||
|
} catch (err) {
|
|||
|
reject(err);
|
|||
|
}
|
|||
|
});//_∏_
|
|||
|
|
|||
|
});
|