ente/src/services/billingService.ts

270 lines
8.2 KiB
TypeScript
Raw Normal View History

2021-07-28 15:45:30 +00:00
import { getEndpoint, getPaymentsUrl } from 'utils/common/apiUtil';
2021-05-30 16:56:48 +00:00
import { getStripePublishableKey, getToken } from 'utils/common/key';
import { checkConnectivity, runningInBrowser } from 'utils/common/';
import { setData, LS_KEYS } from 'utils/storage/localStorage';
2021-07-18 16:10:11 +00:00
import { convertToHumanReadable } from 'utils/billingUtil';
2021-05-30 16:56:48 +00:00
import { loadStripe, Stripe } from '@stripe/stripe-js';
2021-03-09 16:23:13 +00:00
import HTTPService from './HTTPService';
2021-06-12 17:14:21 +00:00
import { logError } from 'utils/sentry';
2021-07-28 15:45:30 +00:00
import { getPaymentToken } from './userService';
2021-05-29 06:27:52 +00:00
2021-03-09 16:23:13 +00:00
const ENDPOINT = getEndpoint();
2021-04-08 06:18:28 +00:00
export enum PAYMENT_INTENT_STATUS {
SUCCESS = 'success',
REQUIRE_ACTION = 'requires_action',
REQUIRE_PAYMENT_METHOD = 'requires_payment_method',
}
2021-07-28 15:45:30 +00:00
enum PaymentActionType{
Buy='buy',
Update='update'
}
export interface Subscription {
id: number;
userID: number;
productID: string;
storage: number;
originalTransactionID: string;
expiryTime: number;
paymentProvider: string;
2021-04-21 16:45:50 +00:00
attributes: {
isCancelled: boolean;
};
}
2021-03-12 12:30:33 +00:00
export interface Plan {
2021-04-13 08:47:15 +00:00
id: string;
2021-03-12 12:30:33 +00:00
androidID: string;
iosID: string;
storage: number;
price: string;
period: string;
stripeID: string;
2021-03-12 12:30:33 +00:00
}
export interface SubscriptionUpdateResponse {
subscription: Subscription;
status: PAYMENT_INTENT_STATUS;
clientSecret: string;
}
export const FREE_PLAN = 'free';
class billingService {
private stripe: Stripe;
2021-05-29 06:27:52 +00:00
2021-03-12 22:48:44 +00:00
constructor() {
2021-05-28 12:43:04 +00:00
try {
2021-05-29 06:27:52 +00:00
const publishableKey = getStripePublishableKey();
2021-05-28 12:43:04 +00:00
const main = async () => {
2021-06-08 09:59:02 +00:00
try {
this.stripe = await loadStripe(publishableKey);
} catch (e) {
2021-06-12 17:14:21 +00:00
logError(e);
2021-06-08 09:59:02 +00:00
}
2021-05-28 12:43:04 +00:00
};
runningInBrowser() && checkConnectivity() && main();
} catch (e) {
2021-06-12 17:14:21 +00:00
logError(e);
2021-05-28 12:43:04 +00:00
}
2021-03-09 16:23:13 +00:00
}
2021-05-29 06:27:52 +00:00
public async updatePlans() {
2021-03-12 12:30:33 +00:00
try {
const response = await HTTPService.get(`${ENDPOINT}/billing/plans`);
2021-05-30 16:56:48 +00:00
const { plans } = response.data;
setData(LS_KEYS.PLANS, plans);
2021-03-12 12:30:33 +00:00
} catch (e) {
2021-06-12 17:14:21 +00:00
logError(e, 'failed to get plans');
2021-03-12 12:30:33 +00:00
}
}
2021-05-29 06:27:52 +00:00
public async syncSubscription() {
try {
const response = await HTTPService.get(
`${ENDPOINT}/billing/subscription`,
null,
{
'X-Auth-Token': getToken(),
2021-05-29 06:27:52 +00:00
},
);
2021-05-30 16:56:48 +00:00
const { subscription } = response.data;
setData(LS_KEYS.SUBSCRIPTION, subscription);
} catch (e) {
2021-06-12 17:14:21 +00:00
logError(e, 'failed to get user\'s subscription details');
}
}
2021-05-29 06:27:52 +00:00
public async buyPaidSubscription(productID) {
2021-03-09 16:23:13 +00:00
try {
2021-07-28 15:45:30 +00:00
// const response = await this.createCheckoutSession(productID);
// await this.stripe.redirectToCheckout({
// sessionId: response.data.sessionID,
// });
const paymentToken =await getPaymentToken();
await this.redirectToPayments(paymentToken, productID, PaymentActionType.Buy);
2021-03-09 16:23:13 +00:00
} catch (e) {
2021-06-12 17:14:21 +00:00
logError(e, 'unable to buy subscription');
throw e;
}
}
public async updateSubscription(productID) {
try {
2021-07-28 15:45:30 +00:00
// const response = await HTTPService.post(
// `${ENDPOINT}/billing/stripe/update-subscription`,
// {
// productID,
// },
// null,
// {
// 'X-Auth-Token': getToken(),
// },
// );
// const { result } = response.data;
// switch (result.status) {
// case PAYMENT_INTENT_STATUS.SUCCESS:
// // subscription updated successfully
// // no-op required
// break;
// case PAYMENT_INTENT_STATUS.REQUIRE_PAYMENT_METHOD:
// throw new Error(
// PAYMENT_INTENT_STATUS.REQUIRE_PAYMENT_METHOD,
// );
// case PAYMENT_INTENT_STATUS.REQUIRE_ACTION:
// {
// const { error } = await this.stripe.confirmCardPayment(
// result.clientSecret,
// );
// if (error) {
// throw error;
// }
// }
// break;
// }
const paymentToken =await getPaymentToken();
await this.redirectToPayments(paymentToken, productID, PaymentActionType.Update);
} catch (e) {
2021-07-28 15:45:30 +00:00
logError(e, 'subscription update failed');
throw e;
}
2021-07-28 15:45:30 +00:00
// try {
// await this.verifySubscription();
// } catch (e) {
// throw new Error(SUBSCRIPTION_VERIFICATION_ERROR);
// }
}
public async cancelSubscription() {
try {
2021-04-21 16:42:27 +00:00
const response = await HTTPService.post(
`${ENDPOINT}/billing/stripe/cancel-subscription`,
null,
2021-04-21 16:42:27 +00:00
null,
{
'X-Auth-Token': getToken(),
2021-05-29 06:27:52 +00:00
},
);
2021-05-30 16:56:48 +00:00
const { subscription } = response.data;
setData(LS_KEYS.SUBSCRIPTION, subscription);
} catch (e) {
2021-06-12 17:14:21 +00:00
logError(e);
throw e;
2021-03-09 16:23:13 +00:00
}
}
public async activateSubscription() {
try {
2021-04-21 16:42:27 +00:00
const response = await HTTPService.post(
`${ENDPOINT}/billing/stripe/activate-subscription`,
null,
2021-04-21 16:42:27 +00:00
null,
{
'X-Auth-Token': getToken(),
2021-05-29 06:27:52 +00:00
},
);
2021-05-30 16:56:48 +00:00
const { subscription } = response.data;
setData(LS_KEYS.SUBSCRIPTION, subscription);
} catch (e) {
2021-06-12 17:14:21 +00:00
logError(e);
throw e;
}
}
2021-03-12 22:48:44 +00:00
private async createCheckoutSession(productID) {
2021-04-21 16:42:27 +00:00
return HTTPService.get(
2021-04-13 08:47:15 +00:00
`${ENDPOINT}/billing/stripe/checkout-session`,
2021-03-13 10:04:17 +00:00
{
productID,
},
{
'X-Auth-Token': getToken(),
2021-05-29 06:27:52 +00:00
},
2021-03-13 10:04:17 +00:00
);
2021-03-09 16:23:13 +00:00
}
2021-03-10 03:25:00 +00:00
2021-04-14 08:49:48 +00:00
public async verifySubscription(
2021-05-29 06:27:52 +00:00
sessionID: string = null,
2021-04-14 08:49:48 +00:00
): Promise<Subscription> {
2021-03-10 03:25:00 +00:00
try {
2021-03-12 17:34:20 +00:00
const response = await HTTPService.post(
`${ENDPOINT}/billing/verify-subscription`,
{
2021-03-12 17:34:20 +00:00
paymentProvider: 'stripe',
2021-03-12 22:48:44 +00:00
productID: null,
2021-03-12 17:34:20 +00:00
VerificationData: sessionID,
},
null,
{
'X-Auth-Token': getToken(),
2021-05-29 06:27:52 +00:00
},
2021-03-10 03:25:00 +00:00
);
2021-05-30 16:56:48 +00:00
const { subscription } = response.data;
setData(LS_KEYS.SUBSCRIPTION, subscription);
return subscription;
2021-03-10 03:25:00 +00:00
} catch (err) {
2021-06-12 17:14:21 +00:00
logError(err, 'Error while verifying subscription');
2021-04-14 08:49:48 +00:00
throw err;
2021-03-10 03:25:00 +00:00
}
}
2021-03-12 17:34:20 +00:00
2021-07-28 15:45:30 +00:00
public async redirectToPayments(paymentToken:string, productID:string, action:string) {
try {
window.location.href =`${getPaymentsUrl()}?productID=${productID}&payment-token=${paymentToken}&action=${action}`;
} catch (e) {
logError(e, 'unable to get payments url');
throw e;
}
}
2021-03-12 17:34:20 +00:00
public async redirectToCustomerPortal() {
try {
const response = await HTTPService.get(
2021-04-08 04:56:37 +00:00
`${ENDPOINT}/billing/stripe/customer-portal`,
null,
{
'X-Auth-Token': getToken(),
2021-05-29 06:27:52 +00:00
},
);
2021-05-29 06:27:52 +00:00
window.location.href = response.data.url;
} catch (e) {
2021-06-12 17:14:21 +00:00
logError(e, 'unable to get customer portal url');
2021-04-08 05:08:15 +00:00
throw e;
}
2021-03-12 17:34:20 +00:00
}
2021-05-29 06:27:52 +00:00
public async getUsage() {
2021-03-11 16:04:52 +00:00
try {
const response = await HTTPService.get(
`${ENDPOINT}/billing/usage`,
2021-05-30 16:56:48 +00:00
{ startTime: 0, endTime: Date.now() * 1000 },
2021-03-11 16:04:52 +00:00
{
'X-Auth-Token': getToken(),
2021-05-29 06:27:52 +00:00
},
2021-03-11 16:04:52 +00:00
);
2021-07-18 16:10:11 +00:00
return convertToHumanReadable(response.data.usage);
2021-03-11 16:04:52 +00:00
} catch (e) {
2021-06-12 17:14:21 +00:00
logError(e, 'error getting usage');
2021-03-11 16:04:52 +00:00
}
}
2021-03-09 16:23:13 +00:00
}
export default new billingService();