UNPKG

react-stripe-elements

Version:

React components for Stripe.js and Stripe Elements

309 lines (244 loc) 14.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _Elements = require('./Elements'); var _Provider = require('./Provider'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // react-redux does a bunch of stuff with pure components / checking if it needs to re-render. // not sure if we need to do the same. var inject = function inject(WrappedComponent) { var _class, _temp; var componentOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var _componentOptions$wit = componentOptions.withRef, withRef = _componentOptions$wit === undefined ? false : _componentOptions$wit; return _temp = _class = function (_React$Component) { _inherits(_class, _React$Component); function _class(props, context) { _classCallCheck(this, _class); if (!context || !context.getRegisteredElements) { throw new Error('It looks like you are trying to inject Stripe context outside of an Elements context.\nPlease be sure the component that calls createSource or createToken is within an <Elements> component.'); } var _this = _possibleConstructorReturn(this, _React$Component.call(this, props, context)); _this.parseElementOrData = function (elementOrOptions) { return elementOrOptions && (typeof elementOrOptions === 'undefined' ? 'undefined' : _typeof(elementOrOptions)) === 'object' && elementOrOptions._frame && _typeof(elementOrOptions._frame) === 'object' && elementOrOptions._frame.id && typeof elementOrOptions._frame.id === 'string' && typeof elementOrOptions._componentName === 'string' ? { type: 'element', element: elementOrOptions } : { type: 'data', data: elementOrOptions }; }; _this.findElement = function (filterBy, specifiedType) { var allElements = _this.context.getRegisteredElements(); var filteredElements = allElements.filter(function (e) { return e[filterBy]; }); var matchingElements = specifiedType === 'auto' ? filteredElements : filteredElements.filter(function (e) { return e[filterBy] === specifiedType; }); if (matchingElements.length === 1) { return matchingElements[0].element; } else if (matchingElements.length > 1) { throw new Error('You did not specify the type of Source, Token, or PaymentMethod to create.\n We could not infer which Element you want to use for this operation.'); } else { return null; } }; _this.requireElement = function (filterBy, specifiedType) { var element = _this.findElement(filterBy, specifiedType); if (element) { return element; } else { throw new Error('You did not specify the type of Source, Token, or PaymentMethod to create.\n We could not infer which Element you want to use for this operation.'); } }; _this.wrappedCreateToken = function (stripe) { return function () { var tokenTypeOrOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (tokenTypeOrOptions && (typeof tokenTypeOrOptions === 'undefined' ? 'undefined' : _typeof(tokenTypeOrOptions)) === 'object') { // First argument is options; infer the Element and tokenize var opts = tokenTypeOrOptions; var tokenType = opts.type, rest = _objectWithoutProperties(opts, ['type']); var specifiedType = typeof tokenType === 'string' ? tokenType : 'auto'; // Since only options were passed in, a corresponding Element must exist // for the tokenization to succeed -- thus we call requireElement. var element = _this.requireElement('impliedTokenType', specifiedType); return stripe.createToken(element, rest); } else if (typeof tokenTypeOrOptions === 'string') { // First argument is token type; tokenize with token type and options var _tokenType = tokenTypeOrOptions; return stripe.createToken(_tokenType, options); } else { // If a bad value was passed in for options, throw an error. throw new Error('Invalid options passed to createToken. Expected an object, got ' + (typeof tokenTypeOrOptions === 'undefined' ? 'undefined' : _typeof(tokenTypeOrOptions)) + '.'); } }; }; _this.wrappedCreateSource = function (stripe) { return function () { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (options && (typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') { if (typeof options.type !== 'string') { throw new Error('Invalid Source type passed to createSource. Expected string, got ' + _typeof(options.type) + '.'); } var element = _this.findElement('impliedSourceType', options.type); if (element) { // If an Element exists for the source type, use that to create the // corresponding source. // // NOTE: this prevents users from independently creating sources of // type `foo` if an Element that can create `foo` sources exists in // the current <Elements /> context. return stripe.createSource(element, options); } else { // If no Element exists for the source type, directly create a source. return stripe.createSource(options); } } else { // If a bad value was passed in for options, throw an error. throw new Error('Invalid options passed to createSource. Expected an object, got ' + (typeof options === 'undefined' ? 'undefined' : _typeof(options)) + '.'); } }; }; _this.wrappedCreatePaymentMethod = function (stripe) { return function (paymentMethodType, elementOrData, maybeData) { if (paymentMethodType && (typeof paymentMethodType === 'undefined' ? 'undefined' : _typeof(paymentMethodType)) === 'object') { return stripe.createPaymentMethod(paymentMethodType); } if (!paymentMethodType || typeof paymentMethodType !== 'string') { throw new Error('Invalid PaymentMethod type passed to createPaymentMethod. Expected a string, got ' + (typeof paymentMethodType === 'undefined' ? 'undefined' : _typeof(paymentMethodType)) + '.'); } var elementOrDataResult = _this.parseElementOrData(elementOrData); // Second argument is Element; use passed in Element if (elementOrDataResult.type === 'element') { var _element = elementOrDataResult.element; if (maybeData) { return stripe.createPaymentMethod(paymentMethodType, _element, maybeData); } else { return stripe.createPaymentMethod(paymentMethodType, _element); } } // Second argument is data or undefined; infer the Element var data = elementOrDataResult.data; var element = _this.findElement('impliedPaymentMethodType', paymentMethodType); if (element) { return data ? stripe.createPaymentMethod(paymentMethodType, element, data) : stripe.createPaymentMethod(paymentMethodType, element); } if (data && (typeof data === 'undefined' ? 'undefined' : _typeof(data)) === 'object') { return stripe.createPaymentMethod(paymentMethodType, data); } else if (!data) { throw new Error('Could not find an Element that can be used to create a PaymentMethod of type: ' + paymentMethodType + '.'); } else { // If a bad value was passed in for data, throw an error. throw new Error('Invalid data passed to createPaymentMethod. Expected an object, got ' + (typeof data === 'undefined' ? 'undefined' : _typeof(data)) + '.'); } }; }; _this.wrappedHandleCardX = function (stripe, method) { return function (clientSecret, elementOrData, maybeData) { if (!clientSecret || typeof clientSecret !== 'string') { // If a bad value was passed in for clientSecret, throw an error. throw new Error('Invalid PaymentIntent client secret passed to handleCardPayment. Expected string, got ' + (typeof clientSecret === 'undefined' ? 'undefined' : _typeof(clientSecret)) + '.'); } var elementOrDataResult = _this.parseElementOrData(elementOrData); // Second argument is Element; handle with element if (elementOrDataResult.type === 'element') { var _element2 = elementOrDataResult.element; if (maybeData) { return stripe[method](clientSecret, _element2, maybeData); } else { return stripe[method](clientSecret, _element2); } } // Second argument is data or undefined; see if we can find a mounted Element // that can create card PaymentMethods var data = elementOrDataResult.data; var element = _this.findElement('impliedPaymentMethodType', 'card'); if (element) { // If an Element exists that can create card PaymentMethods use it. Otherwise // assume that we must be calling with data only. // // NOTE: this prevents users from using handleCard* with an existing // Source or PaymentMethod if an Element that can create card PaymentMethods // exists in the current <Elements /> context. if (data) { return stripe[method](clientSecret, element, data); } else { return stripe[method](clientSecret, element); } } else if (data) { // if no element exists call handleCard* directly (with data) return stripe[method](clientSecret, data); } else { // if no element exists call handleCard* directly (with only the clientSecret) return stripe[method](clientSecret); } }; }; if (_this.context.tag === 'sync') { _this.state = { stripe: _this.stripeProps(_this.context.stripe) }; } else { _this.state = { stripe: null }; } return _this; } _class.prototype.componentDidMount = function componentDidMount() { var _this2 = this; if (this.context.tag === 'async') { this.context.addStripeLoadListener(function (stripe) { _this2.setState({ stripe: _this2.stripeProps(stripe) }); }); } else { // when 'sync', it's already set in the constructor. } }; _class.prototype.getWrappedInstance = function getWrappedInstance() { if (!withRef) { throw new Error('To access the wrapped instance, the `{withRef: true}` option must be set when calling `injectStripe()`'); } return this.wrappedInstance; }; _class.prototype.stripeProps = function stripeProps(stripe) { return _extends({}, stripe, { // These are the only functions that take elements. createToken: this.wrappedCreateToken(stripe), createSource: this.wrappedCreateSource(stripe), createPaymentMethod: this.wrappedCreatePaymentMethod(stripe), handleCardPayment: this.wrappedHandleCardX(stripe, 'handleCardPayment'), handleCardSetup: this.wrappedHandleCardX(stripe, 'handleCardSetup') }); }; // Finds an Element by the specified type, if one exists. // Throws if multiple Elements match. // Require that exactly one Element is found for the specified type. // Throws if no Element is found. // Wraps createToken in order to infer the Element that is being tokenized. // Wraps createSource in order to infer the Element that is being used for // source creation. // Wraps createPaymentMethod in order to infer the Element that is being // used for PaymentMethod creation. _class.prototype.render = function render() { var _this3 = this; return _react2.default.createElement(WrappedComponent, _extends({}, this.props, { stripe: this.state.stripe, elements: this.context.elements, ref: withRef ? function (c) { _this3.wrappedInstance = c; } : null })); }; return _class; }(_react2.default.Component), _class.contextTypes = _extends({}, _Provider.providerContextTypes, _Elements.injectContextTypes), _class.displayName = 'InjectStripe(' + (WrappedComponent.displayName || WrappedComponent.name || 'Component') + ')', _temp; }; exports.default = inject;