2018-03-03 11:21:55 +09:00
|
|
|
import React from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
2017-05-31 10:25:13 +09:00
|
|
|
import StripeCheckout from 'react-stripe-checkout';
|
2018-01-25 15:03:03 -06:00
|
|
|
import { Components, registerComponent, getSetting, withCurrentUser, withMessages } from 'meteor/vulcan:core';
|
2017-05-31 10:25:13 +09:00
|
|
|
import Users from 'meteor/vulcan:users';
|
2017-06-01 11:42:30 +09:00
|
|
|
import { intlShape } from 'meteor/vulcan:i18n';
|
2017-05-31 10:25:13 +09:00
|
|
|
import classNames from 'classnames';
|
2017-10-18 20:05:51 +09:00
|
|
|
import withPaymentAction from '../containers/withPaymentAction.js';
|
2017-05-31 10:25:13 +09:00
|
|
|
import { Products } from '../modules/products.js';
|
|
|
|
|
|
|
|
const stripeSettings = getSetting('stripe');
|
|
|
|
|
|
|
|
class Checkout extends React.Component {
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
this.onToken = this.onToken.bind(this);
|
|
|
|
this.state = {
|
|
|
|
loading: false,
|
|
|
|
mounted: false
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
onToken(token) {
|
|
|
|
|
2017-10-18 20:05:51 +09:00
|
|
|
const {paymentActionMutation, productKey, associatedCollection, associatedDocument, callback, properties, currentUser, flash, coupon} = this.props;
|
2017-05-31 10:25:13 +09:00
|
|
|
|
|
|
|
this.setState({ loading: true });
|
|
|
|
|
2017-07-23 16:29:21 +09:00
|
|
|
const args = {
|
2017-05-31 10:25:13 +09:00
|
|
|
token,
|
|
|
|
userId: currentUser._id,
|
|
|
|
productKey,
|
|
|
|
associatedCollection: associatedCollection._name,
|
|
|
|
associatedId: associatedDocument._id,
|
2017-07-23 16:29:21 +09:00
|
|
|
properties,
|
|
|
|
coupon,
|
|
|
|
}
|
|
|
|
|
2017-10-18 20:05:51 +09:00
|
|
|
paymentActionMutation(args).then(response => {
|
2017-05-31 10:25:13 +09:00
|
|
|
|
|
|
|
// not needed because we just unmount the whole component:
|
|
|
|
this.setState({ loading: false });
|
|
|
|
|
|
|
|
if (callback) {
|
|
|
|
callback(response);
|
|
|
|
}else{
|
|
|
|
flash(this.context.intl.formatMessage({id: 'payments.payment_succeeded'}), 'success');
|
|
|
|
}
|
|
|
|
|
|
|
|
}).catch(error => {
|
2018-01-25 15:03:03 -06:00
|
|
|
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
console.log(error);
|
2017-05-31 10:25:13 +09:00
|
|
|
flash(this.context.intl.formatMessage({id: 'payments.error'}), 'error');
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
|
2018-03-03 11:21:55 +09:00
|
|
|
const { productKey, currentUser, button, coupon, associatedDocument, customAmount } = this.props;
|
2017-05-31 10:25:13 +09:00
|
|
|
|
|
|
|
const sampleProduct = {
|
|
|
|
amount: 10000,
|
|
|
|
name: 'My Cool Product',
|
|
|
|
description: 'This product is awesome.',
|
|
|
|
currency: 'USD',
|
|
|
|
}
|
|
|
|
|
|
|
|
// get the product from Products (either object or function applied to doc)
|
|
|
|
// or default to sample product
|
|
|
|
const definedProduct = Products[productKey];
|
2018-02-14 22:21:56 +09:00
|
|
|
const product = typeof definedProduct === 'function' ? definedProduct(associatedDocument) : definedProduct || sampleProduct;
|
2017-05-31 10:25:13 +09:00
|
|
|
|
2018-03-03 11:21:55 +09:00
|
|
|
// if product has initial amount, use it (for subscription products)
|
|
|
|
let checkoutAmount = customAmount || ( product.initialAmount ? product.initialAmount + product.amount : product.amount );
|
2017-07-23 16:29:21 +09:00
|
|
|
|
|
|
|
if (coupon && product.coupons && product.coupons[coupon]) {
|
2018-03-03 11:21:55 +09:00
|
|
|
checkoutAmount -= product.coupons[coupon];
|
2017-07-23 16:29:21 +09:00
|
|
|
}
|
|
|
|
|
2017-05-31 10:25:13 +09:00
|
|
|
return (
|
|
|
|
<div className={classNames('stripe-checkout', {'checkout-loading': this.state.loading})}>
|
|
|
|
<StripeCheckout
|
|
|
|
token={this.onToken}
|
2018-02-05 10:19:44 -06:00
|
|
|
stripeKey={Meteor.isDevelopment || stripeSettings.alwaysUseTest ? stripeSettings.publishableKeyTest : stripeSettings.publishableKey}
|
2017-05-31 10:25:13 +09:00
|
|
|
ComponentClass="div"
|
|
|
|
name={product.name}
|
|
|
|
description={product.description}
|
2018-03-03 11:21:55 +09:00
|
|
|
amount={checkoutAmount}
|
2017-05-31 10:25:13 +09:00
|
|
|
currency={product.currency}
|
|
|
|
email={Users.getEmail(currentUser)}
|
|
|
|
allowRememberMe
|
|
|
|
>
|
|
|
|
{button ? button :
|
|
|
|
<button className="btn btn-primary">
|
|
|
|
Buy
|
|
|
|
</button>
|
|
|
|
}
|
|
|
|
</StripeCheckout>
|
|
|
|
{this.state.loading ? <Components.Loading /> : null}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Checkout.contextTypes = {
|
|
|
|
intl: intlShape
|
|
|
|
};
|
|
|
|
|
2018-03-03 11:21:55 +09:00
|
|
|
Checkout.propTypes = {
|
|
|
|
productKey: PropTypes.string,
|
|
|
|
currentUser: PropTypes.object,
|
|
|
|
button: PropTypes.func,
|
|
|
|
coupon: PropTypes.string,
|
|
|
|
associatedDocument: PropTypes.object,
|
|
|
|
customAmount: PropTypes.number,
|
|
|
|
};
|
|
|
|
|
2017-05-31 10:25:13 +09:00
|
|
|
const WrappedCheckout = (props) => {
|
|
|
|
const { fragment, fragmentName } = props;
|
2017-10-18 20:05:51 +09:00
|
|
|
const WrappedCheckout = withPaymentAction({fragment, fragmentName})(Checkout);
|
2017-05-31 10:25:13 +09:00
|
|
|
return <WrappedCheckout {...props}/>;
|
|
|
|
}
|
|
|
|
|
|
|
|
registerComponent('Checkout', WrappedCheckout, withCurrentUser, withMessages);
|
|
|
|
|
|
|
|
export default WrappedCheckout;
|