initial commit
This commit is contained in:
@ -0,0 +1,28 @@
|
||||
export const errorTypes = {
|
||||
INVALID_EMAIL: 'email_invalid',
|
||||
INVALID_REQUEST: 'invalid_request_error',
|
||||
API_CONNECTION: 'api_connection_error',
|
||||
API_ERROR: 'api_error',
|
||||
AUTHENTICATION_ERROR: 'authentication_error',
|
||||
RATE_LIMIT_ERROR: 'rate_limit_error',
|
||||
CARD_ERROR: 'card_error',
|
||||
VALIDATION_ERROR: 'validation_error',
|
||||
};
|
||||
|
||||
export const errorCodes = {
|
||||
INVALID_NUMBER: 'invalid_number',
|
||||
INVALID_EXPIRY_MONTH: 'invalid_expiry_month',
|
||||
INVALID_EXPIRY_YEAR: 'invalid_expiry_year',
|
||||
INVALID_CVC: 'invalid_cvc',
|
||||
INCORRECT_NUMBER: 'incorrect_number',
|
||||
INCOMPLETE_NUMBER: 'incomplete_number',
|
||||
INCOMPLETE_CVC: 'incomplete_cvc',
|
||||
INCOMPLETE_EXPIRY: 'incomplete_expiry',
|
||||
EXPIRED_CARD: 'expired_card',
|
||||
INCORRECT_CVC: 'incorrect_cvc',
|
||||
INCORRECT_ZIP: 'incorrect_zip',
|
||||
INVALID_EXPIRY_YEAR_PAST: 'invalid_expiry_year_past',
|
||||
CARD_DECLINED: 'card_declined',
|
||||
MISSING: 'missing',
|
||||
PROCESSING_ERROR: 'processing_error',
|
||||
};
|
@ -0,0 +1,3 @@
|
||||
export * from './normalize';
|
||||
export * from './utils';
|
||||
export * from './load-stripe';
|
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { loadStripe } from '@stripe/stripe-js';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getApiKey } from './utils';
|
||||
|
||||
const stripePromise = () =>
|
||||
new Promise( ( resolve ) => {
|
||||
try {
|
||||
resolve( loadStripe( getApiKey() ) );
|
||||
} catch ( error ) {
|
||||
// In order to avoid showing console error publicly to users,
|
||||
// we resolve instead of rejecting when there is an error.
|
||||
resolve( { error } );
|
||||
}
|
||||
} );
|
||||
|
||||
export { stripePromise as loadStripe };
|
@ -0,0 +1,176 @@
|
||||
/**
|
||||
* @typedef {import('./type-defs').StripePaymentItem} StripePaymentItem
|
||||
* @typedef {import('./type-defs').StripeShippingOption} StripeShippingOption
|
||||
* @typedef {import('./type-defs').StripeShippingAddress} StripeShippingAddress
|
||||
* @typedef {import('./type-defs').StripePaymentResponse} StripePaymentResponse
|
||||
* @typedef {import('@woocommerce/type-defs/registered-payment-method-props').PreparedCartTotalItem} CartTotalItem
|
||||
* @typedef {import('@woocommerce/type-defs/cart').CartShippingOption} CartShippingOption
|
||||
* @typedef {import('@woocommerce/type-defs/shipping').ShippingAddress} CartShippingAddress
|
||||
* @typedef {import('@woocommerce/type-defs/billing').BillingData} CartBillingAddress
|
||||
*/
|
||||
|
||||
/**
|
||||
* Normalizes incoming cart total items for use as a displayItems with the
|
||||
* Stripe api.
|
||||
*
|
||||
* @param {CartTotalItem[]} cartTotalItems CartTotalItems to normalize
|
||||
* @param {boolean} pending Whether to mark items as pending or
|
||||
* not
|
||||
*
|
||||
* @return {StripePaymentItem[]} An array of PaymentItems
|
||||
*/
|
||||
const normalizeLineItems = ( cartTotalItems, pending = false ) => {
|
||||
return cartTotalItems
|
||||
.map( ( cartTotalItem ) => {
|
||||
return cartTotalItem.value
|
||||
? {
|
||||
amount: cartTotalItem.value,
|
||||
label: cartTotalItem.label,
|
||||
pending,
|
||||
}
|
||||
: false;
|
||||
} )
|
||||
.filter( Boolean );
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalizes incoming cart shipping option items for use as shipping options
|
||||
* with the Stripe api.
|
||||
*
|
||||
* @param {CartShippingOption[]} shippingOptions An array of CartShippingOption items.
|
||||
*
|
||||
* @return {StripeShippingOption[]} An array of Stripe shipping option items.
|
||||
*/
|
||||
const normalizeShippingOptions = ( shippingOptions ) => {
|
||||
const rates = shippingOptions[ 0 ].shipping_rates;
|
||||
return rates.map( ( rate ) => {
|
||||
return {
|
||||
id: rate.rate_id,
|
||||
label: rate.name,
|
||||
detail: rate.description,
|
||||
amount: parseInt( rate.price, 10 ),
|
||||
};
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize shipping address information from stripe's address object to
|
||||
* the cart shipping address object shape.
|
||||
*
|
||||
* @param {StripeShippingAddress} shippingAddress Stripe's shipping address item
|
||||
*
|
||||
* @return {CartShippingAddress} The shipping address in the shape expected by
|
||||
* the cart.
|
||||
*/
|
||||
const normalizeShippingAddressForCheckout = ( shippingAddress ) => {
|
||||
const address = {
|
||||
first_name: shippingAddress.recipient
|
||||
.split( ' ' )
|
||||
.slice( 0, 1 )
|
||||
.join( ' ' ),
|
||||
last_name: shippingAddress.recipient
|
||||
.split( ' ' )
|
||||
.slice( 1 )
|
||||
.join( ' ' ),
|
||||
company: '',
|
||||
address_1:
|
||||
typeof shippingAddress.addressLine[ 0 ] === 'undefined'
|
||||
? ''
|
||||
: shippingAddress.addressLine[ 0 ],
|
||||
address_2:
|
||||
typeof shippingAddress.addressLine[ 1 ] === 'undefined'
|
||||
? ''
|
||||
: shippingAddress.addressLine[ 1 ],
|
||||
city: shippingAddress.city,
|
||||
state: shippingAddress.region,
|
||||
country: shippingAddress.country,
|
||||
postcode: shippingAddress.postalCode.replace( ' ', '' ),
|
||||
};
|
||||
return address;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalizes shipping option shape selection from Stripe's shipping option
|
||||
* object to the expected shape for cart shipping option selections.
|
||||
*
|
||||
* @param {StripeShippingOption} shippingOption The customer's selected shipping
|
||||
* option.
|
||||
*
|
||||
* @return {string[]} An array of ids (in this case will just be one)
|
||||
*/
|
||||
const normalizeShippingOptionSelectionsForCheckout = ( shippingOption ) => {
|
||||
return shippingOption.id;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the billing data extracted from the stripe payment response to the
|
||||
* CartBillingData shape.
|
||||
*
|
||||
* @param {StripePaymentResponse} paymentResponse Stripe's payment response
|
||||
* object.
|
||||
*
|
||||
* @return {CartBillingAddress} The cart billing data
|
||||
*/
|
||||
const getBillingData = ( paymentResponse ) => {
|
||||
const source = paymentResponse.source;
|
||||
const name = source && source.owner.name;
|
||||
const billing = source && source.owner.address;
|
||||
const payerEmail = paymentResponse.payerEmail || '';
|
||||
const payerPhone = paymentResponse.payerPhone || '';
|
||||
return {
|
||||
first_name: name ? name.split( ' ' ).slice( 0, 1 ).join( ' ' ) : '',
|
||||
last_name: name ? name.split( ' ' ).slice( 1 ).join( ' ' ) : '',
|
||||
email: ( source && source.owner.email ) || payerEmail,
|
||||
phone:
|
||||
( source && source.owner.phone ) ||
|
||||
payerPhone.replace( '/[() -]/g', '' ),
|
||||
country: ( billing && billing.country ) || '',
|
||||
address_1: ( billing && billing.line1 ) || '',
|
||||
address_2: ( billing && billing.line2 ) || '',
|
||||
city: ( billing && billing.city ) || '',
|
||||
state: ( billing && billing.state ) || '',
|
||||
postcode: ( billing && billing.postal_code ) || '',
|
||||
company: '',
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* This returns extra payment method data to add to the payment method update
|
||||
* request made by the checkout processor.
|
||||
*
|
||||
* @param {StripePaymentResponse} paymentResponse A stripe payment response
|
||||
* object.
|
||||
* @param {string} paymentRequestType The payment request type
|
||||
* used for payment.
|
||||
*
|
||||
* @return {Object} An object with the extra payment data.
|
||||
*/
|
||||
const getPaymentMethodData = ( paymentResponse, paymentRequestType ) => {
|
||||
return {
|
||||
payment_method: 'stripe',
|
||||
stripe_source: paymentResponse.source
|
||||
? paymentResponse.source.id
|
||||
: null,
|
||||
payment_request_type: paymentRequestType,
|
||||
};
|
||||
};
|
||||
|
||||
const getShippingData = ( paymentResponse ) => {
|
||||
return paymentResponse.shippingAddress
|
||||
? {
|
||||
address: normalizeShippingAddressForCheckout(
|
||||
paymentResponse.shippingAddress
|
||||
),
|
||||
}
|
||||
: null;
|
||||
};
|
||||
|
||||
export {
|
||||
normalizeLineItems,
|
||||
normalizeShippingOptions,
|
||||
normalizeShippingAddressForCheckout,
|
||||
normalizeShippingOptionSelectionsForCheckout,
|
||||
getBillingData,
|
||||
getPaymentMethodData,
|
||||
getShippingData,
|
||||
};
|
@ -0,0 +1,324 @@
|
||||
/**
|
||||
* Stripe PaymentItem object
|
||||
*
|
||||
* @typedef {Object} StripePaymentItem
|
||||
*
|
||||
* @property {string} label The label for the payment item.
|
||||
* @property {number} amount The amount for the payment item (in subunits)
|
||||
* @property {boolean} [pending] Whether or not the amount is pending update on
|
||||
* recalculation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stripe ShippingOption object
|
||||
*
|
||||
* @typedef {Object} StripeShippingOption
|
||||
*
|
||||
* @property {string} id A unique ID for the shipping option.
|
||||
* @property {string} label A short label for the shipping option.
|
||||
* @property {string} detail A longer description for the shipping option.
|
||||
* @property {number} amount The amount to show for the shipping option
|
||||
* (in subunits)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} StripeShippingAddress
|
||||
*
|
||||
* @property {string} country Two letter country code, capitalized
|
||||
* (ISO3166 alpha-2).
|
||||
* @property {Array} addressLine An array of address line items.
|
||||
* @property {string} region The most coarse subdivision of a
|
||||
* country. (state etc)
|
||||
* @property {string} city The name of a city, town, village etc.
|
||||
* @property {string} postalCode The postal or ZIP code.
|
||||
* @property {string} recipient The name of the recipient.
|
||||
* @property {string} phone The phone number of the recipient.
|
||||
* @property {string} [sortingCode] The sorting code as used in France.
|
||||
* Not present on Apple platforms.
|
||||
* @property {string} [dependentLocality] A logical subdivision of a city.
|
||||
* Not present on Apple platforms.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} StripeBillingDetails
|
||||
*
|
||||
* @property {Object} address The billing address
|
||||
* @property {string} address.city The billing address city
|
||||
* @property {string} address.country The billing address country
|
||||
* @property {string} address.line1 The first line for the address
|
||||
* @property {string} address.line2 The second line fro the address
|
||||
* @property {string} address.postal_code The postal/zip code
|
||||
* @property {string} address.state The state
|
||||
* @property {string} email The billing email
|
||||
* @property {string} name The billing name
|
||||
* @property {string} phone The billing phone
|
||||
* @property {Object} [verified_address] The verified address of the owner.
|
||||
* @property {string} [verified_email] Provided by the payment provider.
|
||||
* @property {string} [verified_phone] Provided by the payment provider.
|
||||
* @property {string} [verified_name] Provided by the payment provider.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} StripeBillingCard
|
||||
*
|
||||
* @property {string} brand The card brand
|
||||
* @property {Object} checks Various security checks
|
||||
* @property {string} checks.address_line1_check If an address line1 was
|
||||
* provided, results of the
|
||||
* check.
|
||||
* @property {string} checks.address_postal_code_check If a postal code was
|
||||
* provided, results of the
|
||||
* check.
|
||||
* @property {string} checks.cvc_check If CVC provided, results
|
||||
* of the check.
|
||||
* @property {string} country Two-letter ISO code for
|
||||
* the country on the card.
|
||||
* @property {number} exp_month Two-digit number for
|
||||
* card expiry month.
|
||||
* @property {number} exp_year Two-digit number for
|
||||
* card expiry year.
|
||||
* @property {string} fingerprint Uniquely identifies this
|
||||
* particular card number
|
||||
* @property {string} funding The card funding type
|
||||
* @property {Object} generated_from Details of the original
|
||||
* PaymentMethod that
|
||||
* created this object.
|
||||
* @property {string} last4 The last 4 digits of the
|
||||
* card
|
||||
* @property {Object} three_d_secure_usage Contains details on how
|
||||
* this card may be used for
|
||||
* 3d secure
|
||||
* @property {Object} wallet If this card is part of a
|
||||
* card wallet, this
|
||||
* contains the details of
|
||||
* the card wallet.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} StripePaymentMethod
|
||||
*
|
||||
* @property {string} id Unique identifier for the
|
||||
* object
|
||||
* @property {StripeBillingDetails} billing_details The billing details for the
|
||||
* payment method
|
||||
* @property {StripeBillingCard} card Details on the card used to
|
||||
* pay
|
||||
* @property {string} customer The ID of the customer to
|
||||
* which this payment method
|
||||
* is saved.
|
||||
* @property {Object} metadata Set of key-value pairs that
|
||||
* can be attached to the
|
||||
* object.
|
||||
* @property {string} type Type of payment method
|
||||
* @property {string} object The type of object. Always
|
||||
* 'payment_method'. Can use
|
||||
* to validate!
|
||||
* @property {Object} card_present If this is a card present
|
||||
* payment method, contains
|
||||
* details about that card
|
||||
* @property {number} created The timestamp for when the
|
||||
* card was created.
|
||||
* @property {Object} fpx If this is an fpx payment
|
||||
* method, contains details
|
||||
* about it.
|
||||
* @property {Object} ideal If this is an ideal payment
|
||||
* method, contains details
|
||||
* about it.
|
||||
* @property {boolean} livemode True if the object exists
|
||||
* in live mode or if in test
|
||||
* mode.
|
||||
* @property {Object} sepa_debit If this is a sepa_debit
|
||||
* payment method, contains
|
||||
* details about it.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} StripeSource
|
||||
*
|
||||
* @property {string} id Unique identifier for
|
||||
* object
|
||||
* @property {number} amount A positive number in
|
||||
* the smallest currency
|
||||
* unit.
|
||||
* @property {string} currency The three-letter ISO
|
||||
* code for the currency
|
||||
* @property {string} customer The ID of the customer
|
||||
* to which this source
|
||||
* is attached.
|
||||
* @property {Object} metadata Arbitrary key-value
|
||||
* pairs that can be
|
||||
* attached.
|
||||
* @property {StripeBillingDetails} owner Information about the
|
||||
* owner of the payment
|
||||
* made.
|
||||
* @property {Object} [redirect] Information related to
|
||||
* the redirect flow
|
||||
* (present if the source
|
||||
* is authenticated by
|
||||
* redirect)
|
||||
* @property {string} statement_descriptor Extra information
|
||||
* about a source (will
|
||||
* appear on customer's
|
||||
* statement)
|
||||
* @property {string} status The status of the
|
||||
* source.
|
||||
* @property {string} type The type of the source
|
||||
* (it is a payment
|
||||
* method type)
|
||||
* @property {string} object Value is "source" can
|
||||
* be used to validate.
|
||||
* @property {string} client_secret The client secret of
|
||||
* the source. Used for
|
||||
* client-side retrieval
|
||||
* using a publishable
|
||||
* key.
|
||||
* @property {Object} [code_verification] Information related to
|
||||
* the code verification
|
||||
* flow.
|
||||
* @property {number} created When the source object
|
||||
* was instantiated
|
||||
* (timestamp).
|
||||
* @property {string} flow The authentication
|
||||
* flow of the source.
|
||||
* @property {boolean} livemode If true then payment
|
||||
* is made in live mode
|
||||
* otherwise test mode.
|
||||
* @property {Object} [receiver] Information related to
|
||||
* the receiver flow.
|
||||
* @property {Object} source_order Information about the
|
||||
* items and shipping
|
||||
* associated with the
|
||||
* source.
|
||||
* @property {string} usage Whether source should
|
||||
* be reusable or not.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} StripePaymentResponse
|
||||
*
|
||||
* @property {Object} token A stripe token object
|
||||
* @property {StripePaymentMethod} paymentMethod The stripe payment method
|
||||
* object
|
||||
* @property {?StripeSource} source Present if this was the
|
||||
* result of a source event
|
||||
* listener
|
||||
* @property {Function} complete Call this when the token
|
||||
* data has been processed.
|
||||
* @property {string} [payerName] The customer's name.
|
||||
* @property {string} [payerEmail] The customer's email.
|
||||
* @property {string} [payerPhone] The customer's phone.
|
||||
* @property {StripeShippingAddress} [shippingAddress] The final shipping
|
||||
* address the customer
|
||||
* indicated
|
||||
* @property {StripeShippingOption} [shippingOption] The final shipping
|
||||
* option the customer
|
||||
* selected.
|
||||
* @property {string} methodName The unique name of the
|
||||
* payment handler the
|
||||
* customer chose to
|
||||
* authorize payment
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} StripePaymentRequestOptions The configuration of stripe
|
||||
* payment request options to
|
||||
* pass in.
|
||||
*
|
||||
* @property {string} country Two-letter (ISO)
|
||||
* country code.
|
||||
* @property {string} currency Three letter currency
|
||||
* code.
|
||||
* @property {StripePaymentItem} total Shown to the customer.
|
||||
* @property {StripePaymentItem[]} displayItems Line items shown to the
|
||||
* customer.
|
||||
* @property {boolean} requestPayerName Whether or not to
|
||||
* collect the payer's
|
||||
* name.
|
||||
* @property {boolean} requestPayerEmail Whether or not to
|
||||
* collect the payer's
|
||||
* email.
|
||||
* @property {boolean} requestPayerPhone Whether or not to
|
||||
* collect the payer's
|
||||
* phone.
|
||||
* @property {boolean} requestShipping Whether to collect
|
||||
* shipping address.
|
||||
* @property {StripeShippingOption[]} shippingOptions Available shipping
|
||||
* options.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} StripePaymentRequest Stripe payment request object.
|
||||
*
|
||||
* @property {function():Promise} canMakePayment Returns a promise that resolves
|
||||
* with an object detailing if a
|
||||
* browser payment API is
|
||||
* available.
|
||||
* @property {function()} show Shows the browser's payment
|
||||
* interface (called automatically
|
||||
* if payment request button in
|
||||
* use)
|
||||
* @property {function()} update Used to update a PaymentRequest
|
||||
* object.
|
||||
* @property {function()} on For registering callbacks on
|
||||
* payment request events.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Stripe Stripe api object.
|
||||
* @property {any} api Various api properties
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} CreditCardIcon
|
||||
*
|
||||
* @property {string} url Url to icon.
|
||||
* @property {string} alt Alt text for icon.
|
||||
*/
|
||||
|
||||
/* eslint-disable jsdoc/valid-types */
|
||||
// [k:string]:CreditCardIcon triggers the above rule even though VSCode interprets it fine.
|
||||
/**
|
||||
* @typedef {Object} StripeServerData
|
||||
*
|
||||
* @property {string} stripeTotalLabel The string used for payment
|
||||
* descriptor.
|
||||
* @property {string} publicKey The public api key for stripe
|
||||
* requests.
|
||||
* @property {boolean} allowPrepaidCard True means that prepaid cards
|
||||
* can be used for payment.
|
||||
* @property {Object} button Contains button styles
|
||||
* @property {string} button.type The type of button.
|
||||
* @property {string} button.theme The theme for the button.
|
||||
* @property {string} button.height The height (in pixels) for
|
||||
* the button.
|
||||
* @property {string} button.locale The locale to use for stripe
|
||||
* elements.
|
||||
* @property {boolean} inline_cc_form Whether stripe cc should use
|
||||
* inline cc
|
||||
* form or separate inputs.
|
||||
* @property {{[k:string]:CreditCardIcon}} icons Contains supported cc icons.
|
||||
* @property {boolean} showSavedCards Used to indicate whether saved cards
|
||||
* can be used.
|
||||
* @property {boolean} showSaveOption Used to indicate whether the option to
|
||||
* save card can be displayed.
|
||||
* @property {boolean} allowPaymentRequest True if merchant has enabled payment
|
||||
* request (Chrome/Apple Pay).
|
||||
* @property {Object} supports List of features supported by the payment gateway
|
||||
*/
|
||||
/* eslint-enable jsdoc/valid-types */
|
||||
|
||||
/**
|
||||
* @typedef {Object} StripeElementOptions
|
||||
*
|
||||
* @property {Object} options The configuration object for stripe
|
||||
* elements.
|
||||
* @property {function(boolean)} onActive A callback for setting whether an
|
||||
* element is active or not. "Active"
|
||||
* means it's not empty.
|
||||
* @property {string} error Any error message from the stripe
|
||||
* element.
|
||||
* @property {function(string)} setError A callback for setting an error
|
||||
* message.
|
||||
*/
|
||||
|
||||
export {};
|
@ -0,0 +1,279 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { getSetting } from '@woocommerce/settings';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { normalizeLineItems } from './normalize';
|
||||
import { errorTypes, errorCodes } from './constants';
|
||||
|
||||
/**
|
||||
* @typedef {import('./type-defs').StripeServerData} StripeServerData
|
||||
* @typedef {import('./type-defs').StripePaymentItem} StripePaymentItem
|
||||
* @typedef {import('./type-defs').StripePaymentRequest} StripePaymentRequest
|
||||
* @typedef {import('@woocommerce/type-defs/registered-payment-method-props').PreparedCartTotalItem} CartTotalItem
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stripe data comes form the server passed on a global object.
|
||||
*
|
||||
* @return {StripeServerData} Stripe server data.
|
||||
*/
|
||||
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 ||
|
||||
__( 'Total', 'woocommerce' ),
|
||||
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<Object>} True means apple pay can be done.
|
||||
*/
|
||||
const canDoPaymentRequest = ( paymentRequest ) => {
|
||||
return new Promise( ( resolve ) => {
|
||||
paymentRequest.canMakePayment().then( ( result ) => {
|
||||
if ( result ) {
|
||||
const paymentRequestType = result.applePay
|
||||
? 'apple_pay'
|
||||
: 'payment_request_api';
|
||||
resolve( { canPay: true, requestType: paymentRequestType } );
|
||||
return;
|
||||
}
|
||||
resolve( { canPay: 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 expiration month is invalid.',
|
||||
'woocommerce-gateway-stripe'
|
||||
),
|
||||
[ errorCodes.INVALID_EXPIRY_YEAR ]: __(
|
||||
'The card expiration year is invalid.',
|
||||
'woocommerce-gateway-stripe'
|
||||
),
|
||||
[ errorCodes.INVALID_CVC ]: __(
|
||||
'The card 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 security code is incomplete.',
|
||||
'woocommerce-gateway-stripe'
|
||||
),
|
||||
[ errorCodes.INCOMPLETE_EXPIRY ]: __(
|
||||
'The card expiration date is incomplete.',
|
||||
'woocommerce-gateway-stripe'
|
||||
),
|
||||
[ errorCodes.EXPIRED_CARD ]: __(
|
||||
'The card has expired.',
|
||||
'woocommerce-gateway-stripe'
|
||||
),
|
||||
[ errorCodes.INCORRECT_CVC ]: __(
|
||||
'The card security code is incorrect.',
|
||||
'woocommerce-gateway-stripe'
|
||||
),
|
||||
[ errorCodes.INCORRECT_ZIP ]: __(
|
||||
'The card zip code failed validation.',
|
||||
'woocommerce-gateway-stripe'
|
||||
),
|
||||
[ errorCodes.INVALID_EXPIRY_YEAR_PAST ]: __(
|
||||
'The card 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 ] || null;
|
||||
};
|
||||
|
||||
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:
|
||||
return getErrorMessageForCode( code );
|
||||
case errorTypes.VALIDATION_ERROR:
|
||||
return ''; // These are shown inline.
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* pluckAddress takes a full address object and returns relevant fields for calculating
|
||||
* shipping, so we can track when one of them change to update rates.
|
||||
*
|
||||
* @param {Object} address An object containing all address information
|
||||
* @param {string} address.country
|
||||
* @param {string} address.state
|
||||
* @param {string} address.city
|
||||
* @param {string} address.postcode
|
||||
*
|
||||
* @return {Object} pluckedAddress An object containing shipping address that are needed to fetch an address.
|
||||
*/
|
||||
const pluckAddress = ( { country, state, city, postcode } ) => ( {
|
||||
country,
|
||||
state,
|
||||
city,
|
||||
postcode: postcode.replace( ' ', '' ).toUpperCase(),
|
||||
} );
|
||||
|
||||
export {
|
||||
getStripeServerData,
|
||||
getApiKey,
|
||||
getTotalPaymentItem,
|
||||
getPaymentRequest,
|
||||
updatePaymentRequest,
|
||||
canDoPaymentRequest,
|
||||
getErrorMessageForTypeAndCode,
|
||||
pluckAddress,
|
||||
};
|
Reference in New Issue
Block a user