react-stripe-elements
Version:
React components for Stripe.js and Stripe Elements
309 lines (244 loc) • 14.7 kB
JavaScript
;
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;