Vulcan/packages/vulcan-payments/lib/components/Checkout.jsx

120 lines
3.6 KiB
React
Raw Normal View History

2017-05-31 10:25:13 +09:00
import React from 'react'
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';
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) {
const {paymentActionMutation, productKey, associatedCollection, associatedDocument, callback, properties, currentUser, flash, coupon} = this.props;
2017-05-31 10:25:13 +09:00
this.setState({ loading: true });
const args = {
2017-05-31 10:25:13 +09:00
token,
userId: currentUser._id,
productKey,
associatedCollection: associatedCollection._name,
associatedId: associatedDocument._id,
properties,
coupon,
}
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-02-14 22:21:56 +09:00
const {productKey, currentUser, button, coupon, associatedDocument} = 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
// if product has initial amount, add it to amount (for subscription products)
let amount = product.initialAmount ? product.initialAmount + product.amount : product.amount;
if (coupon && product.coupons && product.coupons[coupon]) {
amount -= product.coupons[coupon];
}
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}
amount={amount}
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
};
const WrappedCheckout = (props) => {
const { fragment, fragmentName } = props;
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;