mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 05:40:31 +00:00
fix: Stripe payment integration
This commit is contained in:
@@ -15,7 +15,6 @@ export interface StripeInvoiceCheckoutSessionPOJO {
|
||||
redirectTo: string;
|
||||
}
|
||||
|
||||
|
||||
export interface StripeWebhookEventPayload {
|
||||
event: any;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Inject, Service } from 'typedi';
|
||||
import HasTenancyService from '../Tenancy/TenancyService';
|
||||
import { GetPaymentMethodsPOJO } from './types';
|
||||
import config from '@/config';
|
||||
import { isStripePaymentConfigured } from './utils';
|
||||
|
||||
@Service()
|
||||
export class GetPaymentMethodsStateService {
|
||||
@@ -31,11 +32,13 @@ export class GetPaymentMethodsStateService {
|
||||
const stripePublishableKey = config.stripePayment.publishableKey;
|
||||
const stripeCurrencies = ['USD', 'EUR'];
|
||||
const stripeRedirectUrl = 'https://your-stripe-redirect-url.com';
|
||||
const isStripeServerConfigured = isStripePaymentConfigured();
|
||||
|
||||
const paymentMethodPOJO: GetPaymentMethodsPOJO = {
|
||||
stripe: {
|
||||
isStripeAccountCreated,
|
||||
isStripePaymentActive,
|
||||
isStripeServerConfigured,
|
||||
stripeAccountId,
|
||||
stripePaymentMethodId,
|
||||
stripePublishableKey,
|
||||
|
||||
@@ -17,6 +17,7 @@ export interface GetPaymentMethodsPOJO {
|
||||
stripe: {
|
||||
isStripeAccountCreated: boolean;
|
||||
isStripePaymentActive: boolean;
|
||||
isStripeServerConfigured: boolean;
|
||||
stripeAccountId: string | null;
|
||||
stripePaymentMethodId: number | null;
|
||||
stripePublishableKey: string | null;
|
||||
|
||||
9
packages/server/src/services/PaymentServices/utils.ts
Normal file
9
packages/server/src/services/PaymentServices/utils.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import config from '@/config';
|
||||
|
||||
export const isStripePaymentConfigured = () => {
|
||||
return (
|
||||
config.stripePayment.secretKey &&
|
||||
config.stripePayment.publishableKey &&
|
||||
config.stripePayment.webhooksSecret
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { StripePaymentService } from '@/services/StripePayment/StripePaymentService';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { CreateStripeAccountDTO } from './types';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import events from '@/subscribers/events';
|
||||
@@ -8,17 +8,17 @@ import events from '@/subscribers/events';
|
||||
@Service()
|
||||
export class CreateStripeAccountService {
|
||||
@Inject()
|
||||
private stripePaymentService: StripePaymentService;
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
private stripePaymentService: StripePaymentService;
|
||||
|
||||
@Inject()
|
||||
private eventPublisher: EventPublisher;
|
||||
|
||||
/**
|
||||
* Creates a new Stripe account.
|
||||
* @param {number} tenantId
|
||||
* @param {number} tenantI
|
||||
* @param {CreateStripeAccountDTO} stripeAccountDTO
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import { StripeIntegration2 } from '@/containers/StripePayment/StripeIntegration';
|
||||
|
||||
export default function IntegrationsPage() {
|
||||
return <StripeIntegration2 />
|
||||
}
|
||||
@@ -1,35 +1,20 @@
|
||||
// @ts-nocheck
|
||||
import React, { useEffect } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
Button,
|
||||
Classes,
|
||||
Intent,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Popover,
|
||||
Tag,
|
||||
Text,
|
||||
} from '@blueprintjs/core';
|
||||
import { AppToaster, Box, Card, Group, Stack } from '@/components';
|
||||
import { StripeLogo } from '@/icons/StripeLogo';
|
||||
import {
|
||||
PaymentMethodsBoot,
|
||||
usePaymentMethodsBoot,
|
||||
} from './PreferencesPaymentMethodsBoot';
|
||||
import { Classes, Text } from '@blueprintjs/core';
|
||||
import { Box, Stack } from '@/components';
|
||||
import { PaymentMethodsBoot } from './PreferencesPaymentMethodsBoot';
|
||||
import { StripePreSetupDialog } from './dialogs/StripePreSetupDialog/StripePreSetupDialog';
|
||||
import { DialogsName } from '@/constants/dialogs';
|
||||
import {
|
||||
useAlertActions,
|
||||
useChangePreferencesPageTitle,
|
||||
useDialogActions,
|
||||
useDrawerActions,
|
||||
} from '@/hooks/state';
|
||||
import { useCreateStripeAccountLink } from '@/hooks/query/stripe-integration';
|
||||
import { useChangePreferencesPageTitle } from '@/hooks/state';
|
||||
import { StripeIntegrationEditDrawer } from './drawers/StripeIntegrationEditDrawer';
|
||||
import { StripePaymentMethod } from './StripePaymentMethod';
|
||||
import { DialogsName } from '@/constants/dialogs';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
import { MoreIcon } from '@/icons/More';
|
||||
|
||||
/**
|
||||
* Payment methods page.
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
export default function PreferencesPaymentMethodsPage() {
|
||||
const changePageTitle = useChangePreferencesPageTitle();
|
||||
|
||||
@@ -58,141 +43,8 @@ export default function PreferencesPaymentMethodsPage() {
|
||||
);
|
||||
}
|
||||
|
||||
function StripePaymentMethod() {
|
||||
const { openDialog } = useDialogActions();
|
||||
const { openDrawer } = useDrawerActions();
|
||||
const { openAlert } = useAlertActions();
|
||||
|
||||
const { paymentMethodsState } = usePaymentMethodsBoot();
|
||||
const stripeState = paymentMethodsState?.stripe;
|
||||
|
||||
const isAccountCreated = stripeState?.isStripeAccountCreated;
|
||||
const isAccountActive = stripeState?.isStripePaymentActive;
|
||||
const stripeAccountId = stripeState?.stripeAccountId;
|
||||
const stripePaymentMethodId = stripeState?.stripePaymentMethodId;
|
||||
|
||||
const {
|
||||
mutateAsync: createStripeAccountLink,
|
||||
isLoading: isCreateStripeLinkLoading,
|
||||
} = useCreateStripeAccountLink();
|
||||
|
||||
// Handle Stripe setup button click.
|
||||
const handleSetUpBtnClick = () => {
|
||||
openDialog(DialogsName.StripeSetup);
|
||||
};
|
||||
|
||||
// Handle complete Stripe setup button click.
|
||||
const handleCompleteSetUpBtnClick = () => {
|
||||
createStripeAccountLink({ stripeAccountId })
|
||||
.then((res) => {
|
||||
const { clientSecret } = res;
|
||||
|
||||
if (clientSecret.url) {
|
||||
window.open(clientSecret.url, '_blank');
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
AppToaster.show({
|
||||
message: 'Something went wrong.',
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Handle edit button click.
|
||||
const handleEditBtnClick = () => {
|
||||
openDrawer(DRAWERS.STRIPE_PAYMENT_INTEGRATION_EDIT);
|
||||
};
|
||||
|
||||
// Handle delete connection button click.
|
||||
const handleDeleteConnectionClick = () => {
|
||||
openAlert('delete-stripe-payment-method', {
|
||||
paymentMethodId: stripePaymentMethodId,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Card style={{ margin: 0 }}>
|
||||
<Group position="apart">
|
||||
<Group>
|
||||
<StripeLogo />
|
||||
|
||||
{isAccountActive && (
|
||||
<Tag minimal intent={Intent.SUCCESS}>
|
||||
Active
|
||||
</Tag>
|
||||
)}
|
||||
</Group>
|
||||
<Group spacing={10}>
|
||||
{isAccountActive && (
|
||||
<Button small onClick={handleEditBtnClick}>
|
||||
Edit
|
||||
</Button>
|
||||
)}
|
||||
{!isAccountCreated && (
|
||||
<Button intent={Intent.PRIMARY} small onClick={handleSetUpBtnClick}>
|
||||
Set it Up
|
||||
</Button>
|
||||
)}
|
||||
{isAccountCreated && !isAccountActive && (
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
small
|
||||
onClick={handleCompleteSetUpBtnClick}
|
||||
loading={isCreateStripeLinkLoading}
|
||||
>
|
||||
Complete Stripe Set Up
|
||||
</Button>
|
||||
)}
|
||||
{isAccountCreated && (
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
intent={Intent.DANGER}
|
||||
text={'Delete Connection'}
|
||||
onClick={handleDeleteConnectionClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<Button small icon={<MoreIcon size={16} />} />
|
||||
</Popover>
|
||||
)}
|
||||
</Group>
|
||||
</Group>
|
||||
|
||||
<PaymentDescription
|
||||
className={Classes.TEXT_MUTED}
|
||||
style={{ fontSize: 13 }}
|
||||
>
|
||||
Stripe is an online payment processing platform that allows you to
|
||||
receive one-time and recurring payments securely from customers. It also
|
||||
manages all your payments and makes reconciliation a breeze. You can set
|
||||
it up in no time and get paid faster.
|
||||
</PaymentDescription>
|
||||
|
||||
<PaymentFooter>
|
||||
<Text>
|
||||
<a href={'#'}>View Stripe's Transaction Fees</a>
|
||||
</Text>
|
||||
</PaymentFooter>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
const PaymentMethodsRoot = styled(Box)`
|
||||
witdth: 100%;
|
||||
max-width: 700px;
|
||||
margin: 20px;
|
||||
`;
|
||||
|
||||
const PaymentDescription = styled(Text)`
|
||||
font-size: 13px;
|
||||
margin-top: 12px;
|
||||
`;
|
||||
|
||||
const PaymentFooter = styled(Box)`
|
||||
margin-top: 14px;
|
||||
font-size: 12px;
|
||||
`;
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
Button,
|
||||
Classes,
|
||||
Intent,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Popover,
|
||||
Tag,
|
||||
Text,
|
||||
} from '@blueprintjs/core';
|
||||
import { AppToaster, Box, Card, Group, Stack } from '@/components';
|
||||
import { StripeLogo } from '@/icons/StripeLogo';
|
||||
import { usePaymentMethodsBoot } from './PreferencesPaymentMethodsBoot';
|
||||
import { DialogsName } from '@/constants/dialogs';
|
||||
import {
|
||||
useAlertActions,
|
||||
useDialogActions,
|
||||
useDrawerActions,
|
||||
} from '@/hooks/state';
|
||||
import { useCreateStripeAccountLink } from '@/hooks/query/stripe-integration';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
import { MoreIcon } from '@/icons/More';
|
||||
import { STRIPE_PRICING_LINK } from './constants';
|
||||
|
||||
export function StripePaymentMethod() {
|
||||
const { openDialog } = useDialogActions();
|
||||
const { openDrawer } = useDrawerActions();
|
||||
const { openAlert } = useAlertActions();
|
||||
|
||||
const { paymentMethodsState } = usePaymentMethodsBoot();
|
||||
const stripeState = paymentMethodsState?.stripe;
|
||||
|
||||
const isAccountCreated = stripeState?.isStripeAccountCreated;
|
||||
const isAccountActive = stripeState?.isStripePaymentActive;
|
||||
const stripeAccountId = stripeState?.stripeAccountId;
|
||||
const stripePaymentMethodId = stripeState?.stripePaymentMethodId;
|
||||
const isStripeServerConfigured = stripeState?.isStripeServerConfigured;
|
||||
|
||||
const {
|
||||
mutateAsync: createStripeAccountLink,
|
||||
isLoading: isCreateStripeLinkLoading,
|
||||
} = useCreateStripeAccountLink();
|
||||
|
||||
// Handle Stripe setup button click.
|
||||
const handleSetUpBtnClick = () => {
|
||||
openDialog(DialogsName.StripeSetup);
|
||||
};
|
||||
|
||||
// Handle complete Stripe setup button click.
|
||||
const handleCompleteSetUpBtnClick = () => {
|
||||
createStripeAccountLink({ stripeAccountId })
|
||||
.then((res) => {
|
||||
const { clientSecret } = res;
|
||||
|
||||
if (clientSecret.url) {
|
||||
window.open(clientSecret.url, '_blank');
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
AppToaster.show({
|
||||
message: 'Something went wrong.',
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Handle edit button click.
|
||||
const handleEditBtnClick = () => {
|
||||
openDrawer(DRAWERS.STRIPE_PAYMENT_INTEGRATION_EDIT, {
|
||||
stripePaymentMethodId: stripePaymentMethodId,
|
||||
});
|
||||
};
|
||||
|
||||
// Handle delete connection button click.
|
||||
const handleDeleteConnectionClick = () => {
|
||||
openAlert('delete-stripe-payment-method', {
|
||||
paymentMethodId: stripePaymentMethodId,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Card style={{ margin: 0 }}>
|
||||
<Group position="apart">
|
||||
<Group>
|
||||
<StripeLogo />
|
||||
|
||||
{isAccountActive && (
|
||||
<Tag minimal intent={Intent.SUCCESS}>
|
||||
Active
|
||||
</Tag>
|
||||
)}
|
||||
</Group>
|
||||
<Group spacing={10}>
|
||||
{isAccountActive && (
|
||||
<Button small onClick={handleEditBtnClick}>
|
||||
Edit
|
||||
</Button>
|
||||
)}
|
||||
{!isAccountCreated && (
|
||||
<Button intent={Intent.PRIMARY} small onClick={handleSetUpBtnClick}>
|
||||
Set it Up
|
||||
</Button>
|
||||
)}
|
||||
{isAccountCreated && !isAccountActive && (
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
small
|
||||
onClick={handleCompleteSetUpBtnClick}
|
||||
loading={isCreateStripeLinkLoading}
|
||||
>
|
||||
Complete Stripe Set Up
|
||||
</Button>
|
||||
)}
|
||||
{isAccountCreated && (
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
intent={Intent.DANGER}
|
||||
text={'Delete Connection'}
|
||||
onClick={handleDeleteConnectionClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<Button small icon={<MoreIcon size={16} />} />
|
||||
</Popover>
|
||||
)}
|
||||
</Group>
|
||||
</Group>
|
||||
|
||||
<PaymentDescription
|
||||
className={Classes.TEXT_MUTED}
|
||||
style={{ fontSize: 13 }}
|
||||
>
|
||||
Stripe is an online payment processing platform that allows you to
|
||||
receive one-time and recurring payments securely from customers. It also
|
||||
manages all your payments and makes reconciliation a breeze. You can set
|
||||
it up in no time and get paid faster.
|
||||
</PaymentDescription>
|
||||
|
||||
<PaymentFooter>
|
||||
<Stack spacing={10}>
|
||||
<Text>
|
||||
<a target="_blank" rel="noreferrer" href={STRIPE_PRICING_LINK}>
|
||||
View Stripe's Transaction Fees
|
||||
</a>
|
||||
</Text>
|
||||
|
||||
{!isStripeServerConfigured && (
|
||||
<Text style={{ color: '#CD4246' }}>
|
||||
Stripe payment is not configured from the server.{' '}
|
||||
</Text>
|
||||
)}
|
||||
</Stack>
|
||||
</PaymentFooter>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
const PaymentDescription = styled(Text)`
|
||||
font-size: 13px;
|
||||
margin-top: 12px;
|
||||
`;
|
||||
|
||||
const PaymentFooter = styled(Box)`
|
||||
margin-top: 14px;
|
||||
font-size: 12px;
|
||||
`;
|
||||
@@ -5,7 +5,7 @@ import { Intent, Alert } from '@blueprintjs/core';
|
||||
import { AppToaster, FormattedMessage as T } from '@/components';
|
||||
import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect';
|
||||
import withAlertActions from '@/containers/Alert/withAlertActions';
|
||||
import { useDeletePaymentMethod } from '@/hooks/query/payment-methods';
|
||||
import { useDeletePaymentMethod } from '@/hooks/query/payment-services';
|
||||
import { compose } from '@/utils';
|
||||
|
||||
/**
|
||||
@@ -28,7 +28,6 @@ function DeleteStripeAccountAlert({
|
||||
const handleCancelOpenBill = () => {
|
||||
closeAlert(name);
|
||||
};
|
||||
|
||||
// Handle confirm bill open.
|
||||
const handleConfirmBillOpen = () => {
|
||||
deletePaymentMethod({ paymentMethodId })
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export const STRIPE_PRICING_LINK = 'https://stripe.com/pricing';
|
||||
@@ -2,6 +2,7 @@ import React, { createContext, useContext } from 'react';
|
||||
import { Spinner } from '@blueprintjs/core';
|
||||
import { useAccounts } from '@/hooks/query';
|
||||
import { useGetPaymentMethod } from '@/hooks/query/payment-services';
|
||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||
|
||||
interface StripeIntegrationEditContextType {
|
||||
accounts: any;
|
||||
@@ -20,7 +21,6 @@ export const useStripeIntegrationEditBoot = () => {
|
||||
const context = useContext<StripeIntegrationEditContextType>(
|
||||
StripeIntegrationEditContext,
|
||||
);
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useStripeIntegrationEditContext must be used within a StripeIntegrationEditProvider',
|
||||
@@ -30,9 +30,15 @@ export const useStripeIntegrationEditBoot = () => {
|
||||
};
|
||||
|
||||
export const StripeIntegrationEditBoot: React.FC = ({ children }) => {
|
||||
const {
|
||||
payload: { stripePaymentMethodId },
|
||||
} = useDrawerContext();
|
||||
|
||||
const { data: accounts, isLoading: isAccountsLoading } = useAccounts({}, {});
|
||||
const { data: paymentMethod, isLoading: isPaymentMethodLoading } =
|
||||
useGetPaymentMethod(9);
|
||||
useGetPaymentMethod(stripePaymentMethodId, {
|
||||
enabled: !!stripePaymentMethodId,
|
||||
});
|
||||
|
||||
const value = {
|
||||
// Accounts.
|
||||
|
||||
@@ -10,8 +10,9 @@ import {
|
||||
|
||||
export function StripeIntegrationEditContent() {
|
||||
return (
|
||||
<StripeIntegrationEditBoot>
|
||||
<>
|
||||
<DrawerHeaderContent title={'Edit Stripe Integration'} />
|
||||
|
||||
<StripeIntegrationEditBoot>
|
||||
<StripeIntegrationEditForm>
|
||||
<DrawerBody>
|
||||
@@ -23,6 +24,6 @@ export function StripeIntegrationEditContent() {
|
||||
</div>
|
||||
</StripeIntegrationEditForm>
|
||||
</StripeIntegrationEditBoot>
|
||||
</StripeIntegrationEditBoot>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import styled from 'styled-components';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import {
|
||||
FFormGroup,
|
||||
FEditableText,
|
||||
@@ -18,6 +20,11 @@ import { PaymentOptionsButtonPopver } from '@/containers/PaymentMethods/SelectPa
|
||||
|
||||
export function InvoiceFormFooterLeft() {
|
||||
const { paymentServices } = useInvoiceFormContext();
|
||||
const history = useHistory();
|
||||
|
||||
const handleSetupPaymentsClick = () => {
|
||||
history.push('/preferences/payment-methods');
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack spacing={20}>
|
||||
@@ -60,11 +67,22 @@ export function InvoiceFormFooterLeft() {
|
||||
<VisaIcon />
|
||||
<MastercardIcon />
|
||||
</Group>
|
||||
<PaymentOptionsButtonPopver paymentMethods={paymentServices}>
|
||||
<PaymentOptionsButton intent={Intent.PRIMARY} small minimal>
|
||||
Payment Options
|
||||
{isEmpty(paymentServices) ? (
|
||||
<PaymentOptionsButton
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleSetupPaymentsClick}
|
||||
small
|
||||
minimal
|
||||
>
|
||||
Setup payment gateways
|
||||
</PaymentOptionsButton>
|
||||
</PaymentOptionsButtonPopver>
|
||||
) : (
|
||||
<PaymentOptionsButtonPopver paymentMethods={paymentServices}>
|
||||
<PaymentOptionsButton intent={Intent.PRIMARY} small minimal>
|
||||
Payment Options
|
||||
</PaymentOptionsButton>
|
||||
</PaymentOptionsButtonPopver>
|
||||
)}
|
||||
</PaymentOptionsText>
|
||||
</PaymentOptionsFormGroup>
|
||||
</Stack>
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
useCreateStripeAccount,
|
||||
useCreateStripeAccountLink,
|
||||
} from '@/hooks/query/stripe-integration';
|
||||
|
||||
export const StripeIntegration2 = () => {
|
||||
const [accountCreatePending, setAccountCreatePending] = useState(false);
|
||||
const [accountLinkCreatePending, setAccountLinkCreatePending] =
|
||||
useState(false);
|
||||
const [error, setError] = useState(false);
|
||||
const [connectedAccountId, setConnectedAccountId] = useState<string>();
|
||||
const { mutateAsync: createStripeAccount } = useCreateStripeAccount();
|
||||
const { mutateAsync: createStripeAccountLink } = useCreateStripeAccountLink();
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="banner">
|
||||
<h2>Bigcapital Technology, Inc.</h2>
|
||||
</div>
|
||||
<div className="content">
|
||||
{!connectedAccountId && <h2>Get ready for take off</h2>}
|
||||
{!connectedAccountId && (
|
||||
<p>
|
||||
Bigcapital Technology, Inc. is the world's leading air travel
|
||||
platform: join our team of pilots to help people travel faster.
|
||||
</p>
|
||||
)}
|
||||
{connectedAccountId && (
|
||||
<h2>Add information to start accepting money</h2>
|
||||
)}
|
||||
{connectedAccountId && (
|
||||
<p>
|
||||
Matt's Mats partners with Stripe to help you receive payments and
|
||||
keep your personal bank and details secure.
|
||||
</p>
|
||||
)}
|
||||
{!accountCreatePending && !connectedAccountId && (
|
||||
<button
|
||||
onClick={async () => {
|
||||
setAccountCreatePending(true);
|
||||
setError(false);
|
||||
createStripeAccount({}).then((response) => {
|
||||
const { account_id: accountId } = response;
|
||||
setAccountCreatePending(false);
|
||||
|
||||
if (accountId) {
|
||||
setConnectedAccountId(accountId);
|
||||
}
|
||||
if (error) {
|
||||
setError(true);
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
Create an account!
|
||||
</button>
|
||||
)}
|
||||
{connectedAccountId && !accountLinkCreatePending && (
|
||||
<button
|
||||
onClick={() => {
|
||||
setAccountLinkCreatePending(true);
|
||||
setError(false);
|
||||
createStripeAccountLink({
|
||||
stripeAccountId: connectedAccountId,
|
||||
})
|
||||
.then((res) => {
|
||||
const { clientSecret } = res;
|
||||
setAccountLinkCreatePending(false);
|
||||
|
||||
if (clientSecret.url) {
|
||||
window.location.href = clientSecret.url;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
setError(true);
|
||||
});
|
||||
}}
|
||||
>
|
||||
Add information
|
||||
</button>
|
||||
)}
|
||||
{error && <p className="error">Something went wrong!</p>}
|
||||
{(connectedAccountId ||
|
||||
accountCreatePending ||
|
||||
accountLinkCreatePending) && (
|
||||
<div className="dev-callout">
|
||||
{connectedAccountId && (
|
||||
<p>
|
||||
Your connected account ID is:{' '}
|
||||
<code className="bold">{connectedAccountId}</code>
|
||||
</p>
|
||||
)}
|
||||
{accountCreatePending && <p>Creating a connected account...</p>}
|
||||
{accountLinkCreatePending && <p>Creating a new Account Link...</p>}
|
||||
</div>
|
||||
)}
|
||||
<div className="info-callout">
|
||||
<p>
|
||||
This is a sample app for Stripe-hosted Connect onboarding.{' '}
|
||||
<a
|
||||
href="https://docs.stripe.com/connect/onboarding/quickstart?connect-onboarding-surface=hosted"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
View docs
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,47 +0,0 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import {
|
||||
loadConnectAndInitialize,
|
||||
StripeConnectInstance,
|
||||
} from '@stripe/connect-js';
|
||||
import { useCreateStripeAccountSession } from '@/hooks/query/stripe-integration';
|
||||
|
||||
export const useStripeConnect = (connectedAccountId?: string) => {
|
||||
const [stripeConnectInstance, setStripeConnectInstance] =
|
||||
useState<StripeConnectInstance | null>();
|
||||
const { mutateAsync: createAccountSession } = useCreateStripeAccountSession();
|
||||
|
||||
useEffect(() => {
|
||||
if (connectedAccountId) {
|
||||
const fetchClientSecret = async (): Promise<string> => {
|
||||
try {
|
||||
const clientSecret = await createAccountSession({
|
||||
connectedAccountId,
|
||||
});
|
||||
return clientSecret?.client_secret as string;
|
||||
} catch (error) {
|
||||
// Handle errors on the client side here
|
||||
if (error instanceof Error) {
|
||||
throw new Error(`An error occurred: ${error.message}`);
|
||||
} else {
|
||||
throw new Error('An unknown error occurred');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
setStripeConnectInstance(
|
||||
loadConnectAndInitialize({
|
||||
publishableKey: 'pk_test_51PRck9BW396nDn7gxEw1uvkoGwl5BXDWnrhntQIWReiDnH2Zdm7uL0RSvzKN6SR6ELHDK99dF9UbVEumgTu8k0oN00pP0J91Lx',
|
||||
fetchClientSecret,
|
||||
appearance: {
|
||||
overlays: 'dialog',
|
||||
variables: {
|
||||
colorPrimary: '#ffffff',
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
}, [connectedAccountId, createAccountSession]);
|
||||
|
||||
return stripeConnectInstance;
|
||||
};
|
||||
@@ -7,25 +7,6 @@ import {
|
||||
import useApiRequest from '../useRequest';
|
||||
|
||||
|
||||
// # Delete payment method
|
||||
// -----------------------------------------
|
||||
interface DeletePaymentMethodValues {
|
||||
paymentMethodId: number;
|
||||
}
|
||||
export const useDeletePaymentMethod = (
|
||||
options?: UseMutationOptions<void, Error, DeletePaymentMethodValues>,
|
||||
): UseMutationResult<void, Error, DeletePaymentMethodValues> => {
|
||||
const apiRequest = useApiRequest();
|
||||
|
||||
return useMutation<void, Error, DeletePaymentMethodValues>(
|
||||
({ paymentMethodId }) => {
|
||||
return apiRequest
|
||||
.delete(`/payment-services/${paymentMethodId}`)
|
||||
.then((res) => res.data);
|
||||
},
|
||||
{ ...options },
|
||||
);
|
||||
};
|
||||
|
||||
// # Edit payment method
|
||||
// -----------------------------------------
|
||||
|
||||
@@ -12,6 +12,9 @@ import { transformToCamelCase, transfromToSnakeCase } from '@/utils';
|
||||
const PaymentServicesQueryKey = 'PaymentServices';
|
||||
const PaymentServicesStateQueryKey = 'PaymentServicesState';
|
||||
|
||||
|
||||
// # Get payment services.
|
||||
// -----------------------------------------
|
||||
export interface GetPaymentServicesResponse {}
|
||||
/**
|
||||
* Retrieves the integrated payment services.
|
||||
@@ -40,10 +43,13 @@ export const useGetPaymentServices = (
|
||||
);
|
||||
};
|
||||
|
||||
// # Get payment services state.
|
||||
// -----------------------------------------
|
||||
export interface GetPaymentServicesStateResponse {
|
||||
stripe: {
|
||||
isStripeAccountCreated: boolean;
|
||||
isStripePaymentActive: boolean;
|
||||
isStripeServerConfigured: boolean;
|
||||
stripeAccountId: string | null;
|
||||
stripePaymentMethodId: number | null;
|
||||
stripeCurrencies: string[];
|
||||
@@ -78,6 +84,8 @@ export const useGetPaymentServicesState = (
|
||||
);
|
||||
};
|
||||
|
||||
// # Update payment method
|
||||
// -----------------------------------------
|
||||
interface UpdatePaymentMethodResponse {
|
||||
id: number;
|
||||
message: string;
|
||||
@@ -125,6 +133,8 @@ export const useUpdatePaymentMethod = (): UseMutationResult<
|
||||
);
|
||||
};
|
||||
|
||||
// # Get payment method
|
||||
// -----------------------------------------
|
||||
interface GetPaymentMethodResponse {}
|
||||
/**
|
||||
* Retrieves a specific payment method.
|
||||
@@ -133,6 +143,7 @@ interface GetPaymentMethodResponse {}
|
||||
*/
|
||||
export const useGetPaymentMethod = (
|
||||
paymentMethodId: number,
|
||||
options?: UseQueryOptions<GetPaymentMethodResponse, Error>,
|
||||
): UseQueryResult<GetPaymentMethodResponse, Error> => {
|
||||
const apiRequest = useApiRequest();
|
||||
|
||||
@@ -145,5 +156,32 @@ export const useGetPaymentMethod = (
|
||||
(res) =>
|
||||
transformToCamelCase(res.data?.data) as GetPaymentMethodResponse,
|
||||
),
|
||||
options,
|
||||
);
|
||||
};
|
||||
|
||||
// # Delete payment method
|
||||
// -----------------------------------------
|
||||
interface DeletePaymentMethodValues {
|
||||
paymentMethodId: number;
|
||||
}
|
||||
export const useDeletePaymentMethod = (
|
||||
options?: UseMutationOptions<void, Error, DeletePaymentMethodValues>,
|
||||
): UseMutationResult<void, Error, DeletePaymentMethodValues> => {
|
||||
const apiRequest = useApiRequest();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<void, Error, DeletePaymentMethodValues>(
|
||||
({ paymentMethodId }) => {
|
||||
return apiRequest
|
||||
.delete(`/payment-services/${paymentMethodId}`)
|
||||
.then((res) => res.data);
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries(PaymentServicesStateQueryKey);
|
||||
},
|
||||
...options,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
@@ -83,19 +83,29 @@ export const useDialogActions = () => {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Drawer actions.
|
||||
* @returns
|
||||
*/
|
||||
export const useDrawerActions = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return {
|
||||
openDrawer: useDispatchAction(openDrawer),
|
||||
closeDrawer: useDispatchAction(closeDrawer),
|
||||
openDrawer: (name, payload?: {}) => dispatch(openDrawer(name, payload)),
|
||||
closeDrawer: (name, payload?: {}) => dispatch(closeDrawer(name, payload)),
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Alert actions.
|
||||
* @returns
|
||||
*/
|
||||
export const useAlertActions = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return {
|
||||
openAlert: (name, payload) => dispatch(openAlert(name, payload)),
|
||||
closeAlert: (name, payload) => dispatch(closeAlert(name, payload)),
|
||||
openAlert: (name, payload?: {}) => dispatch(openAlert(name, payload)),
|
||||
closeAlert: (name, payload?: {}) => dispatch(closeAlert(name, payload)),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -110,13 +110,6 @@ export const getPreferenceRoutes = () => [
|
||||
component: lazy(() => import('@/containers/Subscriptions/BillingPage')),
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: `${BASE_URL}/integrations`,
|
||||
component: lazy(
|
||||
() => import('@/containers/Preferences/Integrations/IntegrationsPage'),
|
||||
),
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: `${BASE_URL}/`,
|
||||
component: lazy(() => import('../containers/Preferences/DefaultRoute')),
|
||||
|
||||
Reference in New Issue
Block a user