woocommerce/plugins/woocommerce-blocks/assets/js/payment-method-extensions/payment-methods/stripe/stripe-utils/utils.js

259 lines
8.0 KiB
JavaScript
Raw Normal View History

Implement Stripe CC and Stripe ApplePay payment methods (https://github.com/woocommerce/woocommerce-blocks/pull/1983) * Server side changes for payment method integrations Including adding a stripe class temporarily * update needed npm packages (and add some types) * updates to contexts * remove stepContent from payment config for payment methods * update payment method interface and typedefs Exposing a components property to pass along components that payment methods can use (so we keep styles consistent for them) * add apple pay and stripe cc integration and remove paypal * remove save payment checkbox from checkout block It is handled by payment methods. * Include an id prop for tabs * fix activePaymentMethod pass through on rendered payment method element also adds an id for the rendered tab * add styles for payment method fields If payment methods use these classes for their fields then the styles will get applied. It _could_ allow for consistent styling, we may have to provide design documentation for this? These are styles in cases where payment methods have to use elements provided by the gateway (eg. Stripe elements). In future iterations we could look at providing components to payment methods to use (if they aren’t restricted by the gateway). * fix rebase conflict * do a test payment request for applePay to determine if the current browser supports it * don’t console.error for stripe loading. * Fix placeholder errors in the editor * improve styling and add missing validation for inline card element * update pacakge-lock * rename payment-methods-demo folder to payment-methods-extension * expose checkbox control on payment method interface * export payment-methods-extension to it’s own asset build This allows us to more accurately demonstrate how payment extensions would hook in to the blocks. * don’t enqueue a style that doesn’t exist * add full stop to comments and remove obsolete comment blcok * fix spacing * switch `activeContent` to `content` for payment method registration config
2020-03-30 12:07:49 +00:00
/**
* Internal dependencies
*/
import { normalizeLineItems } from '../apple-pay/normalize';
import { errorTypes, errorCodes } from './constants';
Implement Stripe CC and Stripe ApplePay payment methods (https://github.com/woocommerce/woocommerce-blocks/pull/1983) * Server side changes for payment method integrations Including adding a stripe class temporarily * update needed npm packages (and add some types) * updates to contexts * remove stepContent from payment config for payment methods * update payment method interface and typedefs Exposing a components property to pass along components that payment methods can use (so we keep styles consistent for them) * add apple pay and stripe cc integration and remove paypal * remove save payment checkbox from checkout block It is handled by payment methods. * Include an id prop for tabs * fix activePaymentMethod pass through on rendered payment method element also adds an id for the rendered tab * add styles for payment method fields If payment methods use these classes for their fields then the styles will get applied. It _could_ allow for consistent styling, we may have to provide design documentation for this? These are styles in cases where payment methods have to use elements provided by the gateway (eg. Stripe elements). In future iterations we could look at providing components to payment methods to use (if they aren’t restricted by the gateway). * fix rebase conflict * do a test payment request for applePay to determine if the current browser supports it * don’t console.error for stripe loading. * Fix placeholder errors in the editor * improve styling and add missing validation for inline card element * update pacakge-lock * rename payment-methods-demo folder to payment-methods-extension * expose checkbox control on payment method interface * export payment-methods-extension to it’s own asset build This allows us to more accurately demonstrate how payment extensions would hook in to the blocks. * don’t enqueue a style that doesn’t exist * add full stop to comments and remove obsolete comment blcok * fix spacing * switch `activeContent` to `content` for payment method registration config
2020-03-30 12:07:49 +00:00
/**
* External dependencies
*/
import { getSetting } from '@woocommerce/settings';
import { __ } from '@wordpress/i18n';
/**
* @typedef {import('./type-defs').StripeServerData} StripeServerData
* @typedef {import('./type-defs').StripePaymentItem} StripePaymentItem
* @typedef {import('./type-defs').StripePaymentRequest} StripePaymentRequest
* @typedef {import('@woocommerce/type-defs/cart').CartTotalItem} CartTotalItem
*/
// @todo this can't be in the file because the block might not show up unless it's
// rendered! (which also means it won't get passed from the server until it is rendered).
// so we need to work out a loading process for when the cart or checkout hasn't been added to the
// content yet - definitely don't want to load stripe without the block in the page. So that means
// checkout will need to have some sort of editor preview for stripe.
/**
* Stripe data comes form the server passed on a global object.
*
* @return {StripeServerData}
*/
const getStripeServerData = () => {
const stripeServerData = getSetting( 'stripe_data', null );
if ( ! stripeServerData ) {
throw new Error( 'Stripe initialization data is not available' );
}
return stripeServerData;
};
/**
* Returns the public api key for the stripe payment method
*
* @throws Error
* @return {string} The public api key for the stripe payment method.
*/
const getApiKey = () => {
const apiKey = getStripeServerData().publicKey;
if ( ! apiKey ) {
throw new Error(
'There is no api key available for stripe. Make sure it is available on the wc.stripe_data.stripe.key property.'
);
}
return apiKey;
};
/**
* The total PaymentItem object used for the stripe PaymentRequest object.
*
* @param {CartTotalItem} total The total amount.
*
* @return {StripePaymentItem} The PaymentItem object used for stripe.
*/
const getTotalPaymentItem = ( total ) => {
return {
label: getStripeServerData().stripeTotalLabel,
amount: total.value,
};
};
/**
* Returns a stripe payment request object
*
* @param {Object} config A configuration object for
* getting the payment request.
* @param {Object} config.stripe The stripe api.
* @param {CartTotalItem} config.total The amount for the total
* (in subunits) provided by
* checkout/cart.
* @param {string} config.currencyCode The currency code provided
* by checkout/cart.
* @param {string} config.countryCode The country code provided by
* checkout/cart.
* @param {boolean} config.shippingRequired Whether or not shipping is
* required.
* @param {CartTotalItem[]} config.cartTotalItems Array of line items provided
* by checkout/cart.
*
* @return {StripePaymentRequest} A stripe payment request object
*/
const getPaymentRequest = ( {
stripe,
total,
currencyCode,
countryCode,
shippingRequired,
cartTotalItems,
} ) => {
const options = {
total: getTotalPaymentItem( total ),
currency: currencyCode,
country: countryCode || 'US',
requestPayerName: true,
requestPayerEmail: true,
requestPayerPhone: true,
requestShipping: shippingRequired,
displayItems: normalizeLineItems( cartTotalItems ),
};
return stripe.paymentRequest( options );
};
/**
* Utility function for updating the Stripe PaymentRequest object
*
* @param {Object} update An object containing the
* things needed for the
* update
* @param {StripePaymentRequest} update.paymentRequest A Stripe payment request
* object
* @param {CartTotalItem} update.total A total line item.
* @param {string} update.currencyCode The currency code for the
* amount provided.
* @param {CartTotalItem[]} update.cartTotalItems An array of line items
* provided by the
* cart/checkout.
*/
const updatePaymentRequest = ( {
paymentRequest,
total,
currencyCode,
cartTotalItems,
} ) => {
paymentRequest.update( {
total: getTotalPaymentItem( total ),
currency: currencyCode,
displayItems: normalizeLineItems( cartTotalItems ),
} );
};
/**
* Returns whether or not the current session can do apple pay.
*
* @param {StripePaymentRequest} paymentRequest A Stripe PaymentRequest instance.
*
* @return {Promise<boolean>} True means apple pay can be done.
*/
const canDoApplePay = ( paymentRequest ) => {
return new Promise( ( resolve ) => {
paymentRequest.canMakePayment().then( ( result ) => {
if ( result && result.applePay ) {
resolve( true );
return;
}
resolve( false );
} );
} );
};
const isNonFriendlyError = ( type ) =>
[
errorTypes.INVALID_REQUEST,
errorTypes.API_CONNECTION,
errorTypes.API_ERROR,
errorTypes.AUTHENTICATION_ERROR,
errorTypes.RATE_LIMIT_ERROR,
].includes( type );
const getErrorMessageForCode = ( code ) => {
const messages = {
[ errorCodes.INVALID_NUMBER ]: __(
'The card number is not a valid credit card number.',
'woocommerce-gateway-stripe'
),
[ errorCodes.INVALID_EXPIRY_MONTH ]: __(
"The card's expiration month is invalid.",
'woocommerce-gateway-stripe'
),
[ errorCodes.INVALID_EXPIRY_YEAR ]: __(
"The card's expiration year is invalid.",
'woocommerce-gateway-stripe'
),
[ errorCodes.INVALID_CVC ]: __(
"The card's security code is invalid.",
'woocommerce-gateway-stripe'
),
[ errorCodes.INCORRECT_NUMBER ]: __(
'The card number is incorrect.',
'woocommerce-gateway-stripe'
),
[ errorCodes.INCOMPLETE_NUMBER ]: __(
'The card number is incomplete.',
'woocommerce-gateway-stripe'
),
[ errorCodes.INCOMPLETE_CVC ]: __(
"The card's security code is incomplete.",
'woocommerce-gateway-stripe'
),
[ errorCodes.INCOMPLETE_EXPIRY ]: __(
"The card's expiration date is incomplete.",
'woocommerce-gateway-stripe'
),
[ errorCodes.EXPIRED_CARD ]: __(
'The card has expired.',
'woocommerce-gateway-stripe'
),
[ errorCodes.INCORRECT_CVC ]: __(
"The card's security code is incorrect.",
'woocommerce-gateway-stripe'
),
[ errorCodes.INCORRECT_ZIP ]: __(
"The card's zip code failed validation.",
'woocommerce-gateway-stripe'
),
[ errorCodes.INVALID_EXPIRY_YEAR_PAST ]: __(
"The card's expiration year is in the past",
'woocommerce-gateway-stripe'
),
[ errorCodes.CARD_DECLINED ]: __(
'The card was declined.',
'woocommerce-gateway-stripe'
),
[ errorCodes.MISSING ]: __(
'There is no card on a customer that is being charged.',
'woocommerce-gateway-stripe'
),
[ errorCodes.PROCESSING_ERROR ]: __(
'An error occurred while processing the card.',
'woocommerce-gateway-stripe'
),
};
return messages[ code ] || '';
};
const getErrorMessageForTypeAndCode = ( type, code = '' ) => {
switch ( type ) {
case errorTypes.INVALID_EMAIL:
return __(
'Invalid email address, please correct and try again.',
'woo-gutenberg-product-blocks'
);
case isNonFriendlyError( type ):
return __(
'Unable to process this payment, please try again or use alternative method.',
'woo-gutenberg-product-blocks'
);
case errorTypes.CARD_ERROR:
case errorTypes.VALIDATION_ERROR:
return getErrorMessageForCode( code );
}
return '';
};
export {
getStripeServerData,
getApiKey,
getTotalPaymentItem,
getPaymentRequest,
updatePaymentRequest,
canDoApplePay,
getErrorMessageForTypeAndCode,
};