mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 07:10:33 +00:00
feat: clean up the stripe payment integration
This commit is contained in:
3064
packages/server/newrelic_agent.log
Normal file
3064
packages/server/newrelic_agent.log
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,55 +0,0 @@
|
|||||||
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';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export class CreateStripeAccountService {
|
|
||||||
@Inject()
|
|
||||||
private stripePaymentService: StripePaymentService;
|
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private tenancy: HasTenancyService;
|
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private eventPublisher: EventPublisher;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Stripe account.
|
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {CreateStripeAccountDTO} stripeAccountDTO
|
|
||||||
* @returns {Promise<string>}
|
|
||||||
*/
|
|
||||||
async createStripeAccount(
|
|
||||||
tenantId: number,
|
|
||||||
stripeAccountDTO?: CreateStripeAccountDTO
|
|
||||||
): Promise<string> {
|
|
||||||
const { PaymentIntegration } = this.tenancy.models(tenantId);
|
|
||||||
const stripeAccount = await this.stripePaymentService.createAccount();
|
|
||||||
const stripeAccountId = stripeAccount.id;
|
|
||||||
|
|
||||||
const parsedStripeAccountDTO = {
|
|
||||||
...stripeAccountDTO,
|
|
||||||
name: 'Stripe',
|
|
||||||
};
|
|
||||||
// Stores the details of the Stripe account.
|
|
||||||
await PaymentIntegration.query().insert({
|
|
||||||
name: parsedStripeAccountDTO.name,
|
|
||||||
accountId: stripeAccountId,
|
|
||||||
enable: false,
|
|
||||||
service: 'Stripe',
|
|
||||||
});
|
|
||||||
// Triggers `onStripeIntegrationAccountCreated` event.
|
|
||||||
await this.eventPublisher.emitAsync(
|
|
||||||
events.stripeIntegration.onAccountCreated,
|
|
||||||
{
|
|
||||||
tenantId,
|
|
||||||
stripeAccountDTO,
|
|
||||||
stripeAccountId,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return stripeAccountId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import { Service, Inject } from 'typedi';
|
|
||||||
import { CreateStripeAccountService } from './CreateStripeAccountService';
|
|
||||||
import { CreateStripeAccountDTO } from './types';
|
|
||||||
@Service()
|
|
||||||
export class StripeIntegrationApplication {
|
|
||||||
@Inject()
|
|
||||||
private createStripeAccountService: CreateStripeAccountService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Stripe account for the tenant.
|
|
||||||
* @param {TenantContext} tenantContext - The tenant context.
|
|
||||||
* @param {string} label - The label for the Stripe account.
|
|
||||||
* @returns {Promise<string>} The ID of the created Stripe account.
|
|
||||||
*/
|
|
||||||
public async createStripeAccount(
|
|
||||||
tenantId: number,
|
|
||||||
stripeAccountDTO?: CreateStripeAccountDTO
|
|
||||||
): Promise<string> {
|
|
||||||
return this.createStripeAccountService.createStripeAccount(
|
|
||||||
tenantId,
|
|
||||||
stripeAccountDTO
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/**
|
|
||||||
* @param { import("knex").Knex } knex
|
|
||||||
* @returns { Promise<void> }
|
|
||||||
*/
|
|
||||||
exports.up = function (knex) {
|
|
||||||
return knex.schema.table('sales_invoices', (table) => {
|
|
||||||
table.string('stripe_plink_id').nullable();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param { import("knex").Knex } knex
|
|
||||||
* @returns { Promise<void> }
|
|
||||||
*/
|
|
||||||
exports.down = function (knex) {
|
|
||||||
return knex.schema.table('sales_invoices', (table) => {
|
|
||||||
table.dropColumn('stripe_plink_id');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -117,9 +117,7 @@ import { DisconnectPlaidItemOnAccountDeleted } from '@/services/Banking/BankAcco
|
|||||||
import { LoopsEventsSubscriber } from '@/services/Loops/LoopsEventsSubscriber';
|
import { LoopsEventsSubscriber } from '@/services/Loops/LoopsEventsSubscriber';
|
||||||
import { DeleteUncategorizedTransactionsOnAccountDeleting } from '@/services/Banking/BankAccounts/events/DeleteUncategorizedTransactionsOnAccountDeleting';
|
import { DeleteUncategorizedTransactionsOnAccountDeleting } from '@/services/Banking/BankAccounts/events/DeleteUncategorizedTransactionsOnAccountDeleting';
|
||||||
import { SeedInitialDemoAccountDataOnOrgBuild } from '@/services/OneClickDemo/events/SeedInitialDemoAccountData';
|
import { SeedInitialDemoAccountDataOnOrgBuild } from '@/services/OneClickDemo/events/SeedInitialDemoAccountData';
|
||||||
import { TriggerInvalidateCacheOnSubscriptionChange } from '@/services/Subscription/events/TriggerInvalidateCacheOnSubscriptionChange';
|
|
||||||
import { EventsTrackerListeners } from '@/services/EventsTracker/events/events';
|
import { EventsTrackerListeners } from '@/services/EventsTracker/events/events';
|
||||||
import { CreatePaymentLinkOnInvoiceCreated } from '@/services/StripePayment/events/CreatePaymentLinkOnInvoiceCreated';
|
|
||||||
import { InvoicePaymentIntegrationSubscriber } from '@/services/Sales/Invoices/subscribers/InvoicePaymentIntegrationSubscriber';
|
import { InvoicePaymentIntegrationSubscriber } from '@/services/Sales/Invoices/subscribers/InvoicePaymentIntegrationSubscriber';
|
||||||
import { StripeWebhooksSubscriber } from '@/services/StripePayment/events/StripeWebhooksSubscriber';
|
import { StripeWebhooksSubscriber } from '@/services/StripePayment/events/StripeWebhooksSubscriber';
|
||||||
|
|
||||||
@@ -255,7 +253,6 @@ export const susbcribers = () => {
|
|||||||
// Subscription
|
// Subscription
|
||||||
SubscribeFreeOnSignupCommunity,
|
SubscribeFreeOnSignupCommunity,
|
||||||
SendVerfiyMailOnSignUp,
|
SendVerfiyMailOnSignUp,
|
||||||
TriggerInvalidateCacheOnSubscriptionChange,
|
|
||||||
|
|
||||||
// Attachments
|
// Attachments
|
||||||
AttachmentsOnSaleInvoiceCreated,
|
AttachmentsOnSaleInvoiceCreated,
|
||||||
@@ -295,7 +292,6 @@ export const susbcribers = () => {
|
|||||||
SeedInitialDemoAccountDataOnOrgBuild,
|
SeedInitialDemoAccountDataOnOrgBuild,
|
||||||
|
|
||||||
// Stripe Payment
|
// Stripe Payment
|
||||||
CreatePaymentLinkOnInvoiceCreated,
|
|
||||||
InvoicePaymentIntegrationSubscriber,
|
InvoicePaymentIntegrationSubscriber,
|
||||||
StripeWebhooksSubscriber,
|
StripeWebhooksSubscriber,
|
||||||
|
|
||||||
|
|||||||
@@ -47,8 +47,11 @@ export class CreateInvoiceCheckoutSession {
|
|||||||
const stripeAccountId = stripePaymentMethod?.paymentIntegration?.accountId;
|
const stripeAccountId = stripePaymentMethod?.paymentIntegration?.accountId;
|
||||||
const paymentIntegrationId = stripePaymentMethod?.paymentIntegration?.id;
|
const paymentIntegrationId = stripePaymentMethod?.paymentIntegration?.id;
|
||||||
|
|
||||||
const session = await this.createCheckoutSession(invoice, stripeAccountId);
|
// Creates checkout session for the given invoice.
|
||||||
|
const session = await this.createCheckoutSession(invoice, stripeAccountId, {
|
||||||
|
tenantId,
|
||||||
|
paymentLinkId: paymentLink.id,
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
sessionId: session.id,
|
sessionId: session.id,
|
||||||
publishableKey: config.stripePayment.publishableKey,
|
publishableKey: config.stripePayment.publishableKey,
|
||||||
@@ -64,7 +67,8 @@ export class CreateInvoiceCheckoutSession {
|
|||||||
*/
|
*/
|
||||||
private createCheckoutSession(
|
private createCheckoutSession(
|
||||||
invoice: ISaleInvoice,
|
invoice: ISaleInvoice,
|
||||||
stripeAccountId: string
|
stripeAccountId: string,
|
||||||
|
metadata?: Record<string, any>
|
||||||
) {
|
) {
|
||||||
return this.stripePaymentService.stripe.checkout.sessions.create(
|
return this.stripePaymentService.stripe.checkout.sessions.create(
|
||||||
{
|
{
|
||||||
@@ -84,11 +88,13 @@ export class CreateInvoiceCheckoutSession {
|
|||||||
mode: 'payment',
|
mode: 'payment',
|
||||||
success_url: `${origin}/success`,
|
success_url: `${origin}/success`,
|
||||||
cancel_url: `${origin}/cancel`,
|
cancel_url: `${origin}/cancel`,
|
||||||
|
metadata: {
|
||||||
|
saleInvoiceId: invoice.id,
|
||||||
|
resource: 'SaleInvoice',
|
||||||
|
...metadata,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{ stripeAccount: stripeAccountId }
|
||||||
stripeAccount: stripeAccountId,
|
|
||||||
// stripeAccount: 'acct_1Q0nE7ESY7RfeebE',
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
|
import { StripePaymentService } from '@/services/StripePayment/StripePaymentService';
|
||||||
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import { snakeCase } from 'lodash';
|
import { CreateStripeAccountDTO } from './types';
|
||||||
import { StripePaymentService } from './StripePaymentService';
|
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||||
import HasTenancyService from '../Tenancy/TenancyService';
|
import events from '@/subscribers/events';
|
||||||
|
|
||||||
interface CreateStripeAccountDTO {
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class CreateStripeAccountService {
|
export class CreateStripeAccountService {
|
||||||
@@ -15,29 +13,43 @@ export class CreateStripeAccountService {
|
|||||||
@Inject()
|
@Inject()
|
||||||
private tenancy: HasTenancyService;
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
private eventPublisher: EventPublisher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Stripe account for Bigcapital.
|
* Creates a new Stripe account.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
* @param {number} createStripeAccountDTO
|
* @param {CreateStripeAccountDTO} stripeAccountDTO
|
||||||
|
* @returns {Promise<string>}
|
||||||
*/
|
*/
|
||||||
async createAccount(
|
async createStripeAccount(
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
createStripeAccountDTO: CreateStripeAccountDTO
|
stripeAccountDTO?: CreateStripeAccountDTO
|
||||||
) {
|
): Promise<string> {
|
||||||
const { PaymentIntegration } = this.tenancy.models(tenantId);
|
const { PaymentIntegration } = this.tenancy.models(tenantId);
|
||||||
|
const stripeAccount = await this.stripePaymentService.createAccount();
|
||||||
|
const stripeAccountId = stripeAccount.id;
|
||||||
|
|
||||||
// Creates a new Stripe account.
|
const parsedStripeAccountDTO = {
|
||||||
const account = await this.stripePaymentService.createAccount();
|
...stripeAccountDTO,
|
||||||
|
name: 'Stripe',
|
||||||
const slug = snakeCase(createStripeAccountDTO.name);
|
};
|
||||||
|
// Stores the details of the Stripe account.
|
||||||
// Store the Stripe account on tenant store.
|
|
||||||
await PaymentIntegration.query().insert({
|
await PaymentIntegration.query().insert({
|
||||||
service: 'stripe',
|
name: parsedStripeAccountDTO.name,
|
||||||
name: createStripeAccountDTO.name,
|
accountId: stripeAccountId,
|
||||||
slug,
|
enable: false,
|
||||||
enable: true,
|
service: 'Stripe',
|
||||||
accountId: account.id,
|
|
||||||
});
|
});
|
||||||
|
// Triggers `onStripeIntegrationAccountCreated` event.
|
||||||
|
await this.eventPublisher.emitAsync(
|
||||||
|
events.stripeIntegration.onAccountCreated,
|
||||||
|
{
|
||||||
|
tenantId,
|
||||||
|
stripeAccountDTO,
|
||||||
|
stripeAccountId,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return stripeAccountId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
import { Knex } from 'knex';
|
|
||||||
import { Inject, Service } from 'typedi';
|
|
||||||
import HasTenancyService from '../Tenancy/TenancyService';
|
|
||||||
import { StripePaymentService } from './StripePaymentService';
|
|
||||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
|
||||||
import events from '@/subscribers/events';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export class DeleteStripePaymentLinkInvoice {
|
|
||||||
@Inject()
|
|
||||||
private tenancy: HasTenancyService;
|
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private stripePayment: StripePaymentService;
|
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private eventPublisher: EventPublisher;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the Stripe payment link associates to the given sale invoice.
|
|
||||||
* @param {number} tenantId -
|
|
||||||
* @param {number} invoiceId -
|
|
||||||
* @param {Knex.Transaction} knex -
|
|
||||||
*/
|
|
||||||
async deleteInvoicePaymentLink(
|
|
||||||
tenantId: number,
|
|
||||||
invoiceId: number,
|
|
||||||
trx?: Knex.Transaction
|
|
||||||
): Promise<void> {
|
|
||||||
const { SaleInvoice } = this.tenancy.models(tenantId);
|
|
||||||
|
|
||||||
const invoice = await SaleInvoice.query(trx)
|
|
||||||
.findById(invoiceId)
|
|
||||||
.withGraphFetched('paymentMethods.paymentIntegration')
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
// It will be only one Stripe payment method associated to the invoice.
|
|
||||||
const stripePaymentMethod = invoice.paymentMethods?.find(
|
|
||||||
(method) => method.paymentIntegration?.service === 'Stripe'
|
|
||||||
);
|
|
||||||
const stripeAccountId = stripePaymentMethod?.paymentIntegration?.accountId;
|
|
||||||
const paymentIntegrationId = stripePaymentMethod?.paymentIntegration?.id;
|
|
||||||
|
|
||||||
if (invoice.stripePlinkId && stripeAccountId) {
|
|
||||||
const stripeAcocunt = { stripeAccount: stripeAccountId };
|
|
||||||
const stripePlinkId = invoice.stripePlinkId;
|
|
||||||
|
|
||||||
await this.stripePayment.stripe.paymentLinks.update(
|
|
||||||
stripePlinkId,
|
|
||||||
{ active: false },
|
|
||||||
stripeAcocunt
|
|
||||||
);
|
|
||||||
// Triggers `onStripePaymentLinkInactivated` event.
|
|
||||||
await this.eventPublisher.emitAsync(
|
|
||||||
events.stripeIntegration.onPaymentLinkInactivated,
|
|
||||||
{
|
|
||||||
tenantId,
|
|
||||||
saleInvoiceId: invoiceId,
|
|
||||||
paymentIntegrationId,
|
|
||||||
stripePlinkId,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
|
||||||
import { ISaleInvoice } from '@/interfaces';
|
|
||||||
import { StripePaymentService } from './StripePaymentService';
|
|
||||||
import HasTenancyService from '../Tenancy/TenancyService';
|
|
||||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
|
||||||
import { StripePaymentLinkCreatedEventPayload } from '@/interfaces/StripePayment';
|
|
||||||
import { STRIPE_PAYMENT_LINK_REDIRECT } from './constants';
|
|
||||||
import events from '@/subscribers/events';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export class SaleInvoiceStripePaymentLink {
|
|
||||||
@Inject()
|
|
||||||
private stripePayment: StripePaymentService;
|
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private tenancy: HasTenancyService;
|
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private eventPublisher: EventPublisher;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a Stripe payment link for the given sale invoice.
|
|
||||||
* @param {number} tenantId - Tenant id.
|
|
||||||
* @param {number} stripeIntegrationId - Stripe integration id.
|
|
||||||
* @param {ISaleInvoice} saleInvoice - Sale invoice id.
|
|
||||||
* @returns {Promise<string>}
|
|
||||||
*/
|
|
||||||
async createPaymentLink(
|
|
||||||
tenantId: number,
|
|
||||||
stripeIntegrationId: number,
|
|
||||||
invoiceId: number
|
|
||||||
) {
|
|
||||||
const { SaleInvoice, PaymentIntegration } = this.tenancy.models(tenantId);
|
|
||||||
|
|
||||||
const stripeIntegration = await PaymentIntegration.query()
|
|
||||||
.findById(stripeIntegrationId)
|
|
||||||
.throwIfNotFound();
|
|
||||||
const stripeAccountId = stripeIntegration.accountId;
|
|
||||||
|
|
||||||
const invoice = await SaleInvoice.query()
|
|
||||||
.findById(invoiceId)
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
// Creates Stripe price.
|
|
||||||
const price = await this.createStripePrice(invoice, stripeAccountId);
|
|
||||||
|
|
||||||
// Creates Stripe payment link.
|
|
||||||
const paymentLink = await this.createStripePaymentLink(
|
|
||||||
price.id,
|
|
||||||
invoice,
|
|
||||||
stripeAccountId,
|
|
||||||
{ tenantId }
|
|
||||||
);
|
|
||||||
// Associate the payment link id to the invoice.
|
|
||||||
await this.updateInvoiceWithPaymentLink(
|
|
||||||
tenantId,
|
|
||||||
invoiceId,
|
|
||||||
paymentLink.id
|
|
||||||
);
|
|
||||||
// Triggers `onStripePaymentLinkCreated` event.
|
|
||||||
await this.eventPublisher.emitAsync(
|
|
||||||
events.stripeIntegration.onPaymentLinkCreated,
|
|
||||||
{
|
|
||||||
tenantId,
|
|
||||||
stripeIntegrationId,
|
|
||||||
saleInvoiceId: invoiceId,
|
|
||||||
paymentLinkId: paymentLink.id,
|
|
||||||
} as StripePaymentLinkCreatedEventPayload
|
|
||||||
);
|
|
||||||
return paymentLink.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a Stripe price for the invoice.
|
|
||||||
* @param {ISaleInvoice} invoice - Sale invoice.
|
|
||||||
* @param {string} stripeAccountId - Stripe account id.
|
|
||||||
* @returns {Promise<Stripe.Price>}
|
|
||||||
*/
|
|
||||||
private async createStripePrice(
|
|
||||||
invoice: ISaleInvoice,
|
|
||||||
stripeAccountId: string
|
|
||||||
) {
|
|
||||||
return this.stripePayment.stripe.prices.create(
|
|
||||||
{
|
|
||||||
unit_amount: invoice.total * 100,
|
|
||||||
currency: 'usd',
|
|
||||||
product_data: {
|
|
||||||
name: invoice.invoiceNo,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ stripeAccount: stripeAccountId }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a Stripe payment link.
|
|
||||||
* @param {string} priceId - Stripe price id.
|
|
||||||
* @param {ISaleInvoice} invoice - Sale invoice.
|
|
||||||
* @param {number} tenantId - Tenant id.
|
|
||||||
* @param {string} stripeAccountId - Stripe account id.
|
|
||||||
* @returns {Promise<Stripe.PaymentLink>}
|
|
||||||
*/
|
|
||||||
private async createStripePaymentLink(
|
|
||||||
priceId: string,
|
|
||||||
invoice: ISaleInvoice,
|
|
||||||
stripeAccountId: string,
|
|
||||||
metadata: Record<string, any> = {}
|
|
||||||
) {
|
|
||||||
const paymentLinkInfo = {
|
|
||||||
line_items: [{ price: priceId, quantity: 1 }],
|
|
||||||
after_completion: {
|
|
||||||
type: 'redirect',
|
|
||||||
redirect: {
|
|
||||||
url: STRIPE_PAYMENT_LINK_REDIRECT,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
metadata: {
|
|
||||||
saleInvoiceId: invoice.id,
|
|
||||||
resource: 'SaleInvoice',
|
|
||||||
...metadata,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return this.stripePayment.stripe.paymentLinks.create(paymentLinkInfo, {
|
|
||||||
stripeAccount: stripeAccountId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the sale invoice with the Stripe payment link id.
|
|
||||||
* @param {number} tenantId - Tenant id.
|
|
||||||
* @param {number} invoiceId - Sale invoice id.
|
|
||||||
* @param {string} paymentLinkId - Stripe payment link id.
|
|
||||||
*/
|
|
||||||
private async updateInvoiceWithPaymentLink(
|
|
||||||
tenantId: number,
|
|
||||||
invoiceId: number,
|
|
||||||
paymentLinkId: string
|
|
||||||
) {
|
|
||||||
const { SaleInvoice } = this.tenancy.models(tenantId);
|
|
||||||
|
|
||||||
await SaleInvoice.query().findById(invoiceId).patch({
|
|
||||||
stripePlinkId: paymentLinkId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,13 @@
|
|||||||
import { Knex } from 'knex';
|
|
||||||
import { Inject } from 'typedi';
|
import { Inject } from 'typedi';
|
||||||
import { CreateStripeAccountService } from '@/api/controllers/StripeIntegration/CreateStripeAccountService';
|
|
||||||
import { CreateStripeAccountDTO } from '@/api/controllers/StripeIntegration/types';
|
|
||||||
import { SaleInvoiceStripePaymentLink } from './SaleInvoiceStripePaymentLink';
|
|
||||||
import { DeleteStripePaymentLinkInvoice } from './DeleteStripePaymentLinkInvoice';
|
|
||||||
import { CreateInvoiceCheckoutSession } from './CreateInvoiceCheckoutSession';
|
import { CreateInvoiceCheckoutSession } from './CreateInvoiceCheckoutSession';
|
||||||
import { StripeInvoiceCheckoutSessionPOJO } from '@/interfaces/StripePayment';
|
import { StripeInvoiceCheckoutSessionPOJO } from '@/interfaces/StripePayment';
|
||||||
|
import { CreateStripeAccountService } from './CreateStripeAccountService';
|
||||||
|
import { CreateStripeAccountDTO } from './types';
|
||||||
|
|
||||||
export class StripePaymentApplication {
|
export class StripePaymentApplication {
|
||||||
@Inject()
|
@Inject()
|
||||||
private createStripeAccountService: CreateStripeAccountService;
|
private createStripeAccountService: CreateStripeAccountService;
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private saleInvoiceStripePaymentLinkService: SaleInvoiceStripePaymentLink;
|
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private deleteStripePaymentLinkInvoice: DeleteStripePaymentLinkInvoice;
|
|
||||||
|
|
||||||
@Inject()
|
@Inject()
|
||||||
private createSaleInvoiceCheckoutSessionService: CreateInvoiceCheckoutSession;
|
private createSaleInvoiceCheckoutSessionService: CreateInvoiceCheckoutSession;
|
||||||
|
|
||||||
@@ -35,25 +26,6 @@ export class StripePaymentApplication {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a Stripe payment link for the given sale invoice.
|
|
||||||
* @param {number} tenantId - Tenant id.
|
|
||||||
* @param {number} stripeIntegrationId - Stripe integration id.
|
|
||||||
* @param {ISaleInvoice} saleInvoice - Sale invoice id.
|
|
||||||
* @returns {Promise<string>}
|
|
||||||
*/
|
|
||||||
public createSaleInvoicePaymentLink(
|
|
||||||
tenantId: number,
|
|
||||||
stripeIntegrationId: number,
|
|
||||||
invoiceId: number
|
|
||||||
) {
|
|
||||||
return this.saleInvoiceStripePaymentLinkService.createPaymentLink(
|
|
||||||
tenantId,
|
|
||||||
stripeIntegrationId,
|
|
||||||
invoiceId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the Stripe checkout session from the given sale invoice.
|
* Creates the Stripe checkout session from the given sale invoice.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
@@ -69,22 +41,4 @@ export class StripePaymentApplication {
|
|||||||
paymentLinkId
|
paymentLinkId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the Stripe payment link associated with the given sale invoice.
|
|
||||||
* @param {number} tenantId - Tenant id.
|
|
||||||
* @param {number} invoiceId - Sale invoice id.
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
public deleteInvoicePaymentLink(
|
|
||||||
tenantId: number,
|
|
||||||
invoiceId: number,
|
|
||||||
trx?: Knex.Transaction
|
|
||||||
): Promise<void> {
|
|
||||||
return this.deleteStripePaymentLinkInvoice.deleteInvoicePaymentLink(
|
|
||||||
tenantId,
|
|
||||||
invoiceId,
|
|
||||||
trx
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export class StripePaymentService {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.stripe = new stripe(config.stripePayment.secretKey, {
|
this.stripe = new stripe(config.stripePayment.secretKey, {
|
||||||
apiVersion: '2023-10-16',
|
apiVersion: '2024-06-20',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
|
||||||
import { EventSubscriber } from '@/lib/EventPublisher/EventPublisher';
|
|
||||||
import {
|
|
||||||
PaymentIntegrationTransactionLinkDeleteEventPayload,
|
|
||||||
PaymentIntegrationTransactionLinkEventPayload,
|
|
||||||
} from '@/interfaces';
|
|
||||||
import { SaleInvoiceStripePaymentLink } from '../SaleInvoiceStripePaymentLink';
|
|
||||||
import { runAfterTransaction } from '@/services/UnitOfWork/TransactionsHooks';
|
|
||||||
import events from '@/subscribers/events';
|
|
||||||
import { DeleteStripePaymentLinkInvoice } from '../DeleteStripePaymentLinkInvoice';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export class CreatePaymentLinkOnInvoiceCreated extends EventSubscriber {
|
|
||||||
@Inject()
|
|
||||||
private invoiceStripePaymentLink: SaleInvoiceStripePaymentLink;
|
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private deleteStripePaymentLinkInvoice: DeleteStripePaymentLinkInvoice;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor method.
|
|
||||||
*/
|
|
||||||
public attach(bus) {
|
|
||||||
bus.subscribe(
|
|
||||||
events.paymentIntegrationLink.onPaymentIntegrationLink,
|
|
||||||
this.handleCreatePaymentLinkOnIntegrationLink
|
|
||||||
);
|
|
||||||
bus.subscribe(
|
|
||||||
events.paymentIntegrationLink.onPaymentIntegrationDeleteLink,
|
|
||||||
this.handleDeletePaymentLinkOnIntegrationLinkDelete
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the Plaid item transactions
|
|
||||||
* @param {IPlaidItemCreatedEventPayload} payload - Event payload.
|
|
||||||
*/
|
|
||||||
private handleCreatePaymentLinkOnIntegrationLink = async ({
|
|
||||||
tenantId,
|
|
||||||
paymentIntegrationId,
|
|
||||||
referenceId,
|
|
||||||
referenceType,
|
|
||||||
trx,
|
|
||||||
}: PaymentIntegrationTransactionLinkEventPayload) => {
|
|
||||||
// Can't continue if the link request is not coming from the invoice transaction.
|
|
||||||
if ('SaleInvoice' !== referenceType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runAfterTransaction(trx, async () => {
|
|
||||||
await this.invoiceStripePaymentLink.createPaymentLink(
|
|
||||||
tenantId,
|
|
||||||
paymentIntegrationId,
|
|
||||||
referenceId
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the Stripe payment link once the associated invoice deleted.
|
|
||||||
* @param {ISaleInvoiceDeletedPayload}
|
|
||||||
*/
|
|
||||||
private handleDeletePaymentLinkOnIntegrationLinkDelete = async ({
|
|
||||||
oldSaleInvoiceId,
|
|
||||||
tenantId,
|
|
||||||
trx,
|
|
||||||
}: PaymentIntegrationTransactionLinkDeleteEventPayload) => {
|
|
||||||
await this.deleteStripePaymentLinkInvoice.deleteInvoicePaymentLink(
|
|
||||||
tenantId,
|
|
||||||
oldSaleInvoiceId,
|
|
||||||
trx
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
.companyLogoWrap {
|
.companyLogoWrap {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
width :50px;
|
width :50px;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import React, { createContext, useContext, ReactNode } from 'react';
|
import React, { createContext, useContext, ReactNode } from 'react';
|
||||||
import {
|
import {
|
||||||
GetSharableLinkMetaResponse,
|
GetInvoicePaymentLinkResponse,
|
||||||
useGetSharableLinkMeta,
|
useGetInvoicePaymentLink,
|
||||||
} from '@/hooks/query/payment-link';
|
} from '@/hooks/query/payment-link';
|
||||||
import { Spinner } from '@blueprintjs/core';
|
import { Spinner } from '@blueprintjs/core';
|
||||||
|
|
||||||
interface PaymentPortalContextType {
|
interface PaymentPortalContextType {
|
||||||
linkId: string;
|
linkId: string;
|
||||||
sharableLinkMeta: GetSharableLinkMetaResponse | undefined;
|
sharableLinkMeta: GetInvoicePaymentLinkResponse | undefined;
|
||||||
isSharableLinkMetaLoading: boolean;
|
isSharableLinkMetaLoading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ export const PaymentPortalBoot: React.FC<PaymentPortalBootProps> = ({
|
|||||||
children,
|
children,
|
||||||
}) => {
|
}) => {
|
||||||
const { data: sharableLinkMeta, isLoading: isSharableLinkMetaLoading } =
|
const { data: sharableLinkMeta, isLoading: isSharableLinkMetaLoading } =
|
||||||
useGetSharableLinkMeta(linkId);
|
useGetInvoicePaymentLink(linkId);
|
||||||
|
|
||||||
const value = {
|
const value = {
|
||||||
linkId,
|
linkId,
|
||||||
|
|||||||
@@ -10,17 +10,17 @@ import {
|
|||||||
import useApiRequest from '../useRequest';
|
import useApiRequest from '../useRequest';
|
||||||
import { transformToCamelCase, transfromToSnakeCase } from '@/utils';
|
import { transformToCamelCase, transfromToSnakeCase } from '@/utils';
|
||||||
|
|
||||||
|
// Create Payment Link
|
||||||
|
// ------------------------------------
|
||||||
interface CreatePaymentLinkValues {
|
interface CreatePaymentLinkValues {
|
||||||
publicity: string;
|
publicity: string;
|
||||||
transactionType: string;
|
transactionType: string;
|
||||||
transactionId: number | string;
|
transactionId: number | string;
|
||||||
expiryDate: string;
|
expiryDate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CreatePaymentLinkResponse {
|
interface CreatePaymentLinkResponse {
|
||||||
link: string;
|
link: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new payment link.
|
* Creates a new payment link.
|
||||||
* @param {UseMutationOptions<CreatePaymentLinkResponse, Error, CreatePaymentLinkValues>} options
|
* @param {UseMutationOptions<CreatePaymentLinkResponse, Error, CreatePaymentLinkValues>} options
|
||||||
@@ -50,7 +50,10 @@ export function useCreatePaymentLink(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetSharableLinkMetaResponse {
|
|
||||||
|
// Get Invoice Payment Link
|
||||||
|
// -----------------------------------------
|
||||||
|
export interface GetInvoicePaymentLinkResponse {
|
||||||
dueAmount: number;
|
dueAmount: number;
|
||||||
dueAmountFormatted: string;
|
dueAmountFormatted: string;
|
||||||
dueDate: string;
|
dueDate: string;
|
||||||
@@ -80,20 +83,19 @@ export interface GetSharableLinkMetaResponse {
|
|||||||
totalFormatted: string;
|
totalFormatted: string;
|
||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the sharable link metadata for a given link ID.
|
* Fetches the sharable invoice link metadata for a given link ID.
|
||||||
* @param {string} linkId - The ID of the link to fetch metadata for.
|
* @param {string} linkId - The ID of the link to fetch metadata for.
|
||||||
* @param {UseQueryOptions<GetSharableLinkMetaResponse, Error>} options - Optional query options.
|
* @param {UseQueryOptions<GetInvoicePaymentLinkResponse, Error>} options - Optional query options.
|
||||||
* @returns {UseQueryResult<GetSharableLinkMetaResponse, Error>} The query result.
|
* @returns {UseQueryResult<GetInvoicePaymentLinkResponse, Error>} The query result.
|
||||||
*/
|
*/
|
||||||
export function useGetSharableLinkMeta(
|
export function useGetInvoicePaymentLink(
|
||||||
linkId: string,
|
linkId: string,
|
||||||
options?: UseQueryOptions<GetSharableLinkMetaResponse, Error>,
|
options?: UseQueryOptions<GetInvoicePaymentLinkResponse, Error>,
|
||||||
): UseQueryResult<GetSharableLinkMetaResponse, Error> {
|
): UseQueryResult<GetInvoicePaymentLinkResponse, Error> {
|
||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
return useQuery<GetSharableLinkMetaResponse, Error>(
|
return useQuery<GetInvoicePaymentLinkResponse, Error>(
|
||||||
['sharable-link-meta', linkId],
|
['sharable-link-meta', linkId],
|
||||||
() =>
|
() =>
|
||||||
apiRequest
|
apiRequest
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ import { transformToCamelCase } from '@/utils';
|
|||||||
|
|
||||||
const PaymentServicesQueryKey = 'PaymentServices';
|
const PaymentServicesQueryKey = 'PaymentServices';
|
||||||
|
|
||||||
export interface GetPaymentServicesResponse {
|
export interface GetPaymentServicesResponse {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the integrated payment services.
|
||||||
|
* @param {UseQueryOptions<GetPaymentServicesResponse, Error>} options
|
||||||
|
* @returns {UseQueryResult<GetPaymentServicesResponse, Error>}
|
||||||
|
*/
|
||||||
export const useGetPaymentServices = (
|
export const useGetPaymentServices = (
|
||||||
options?: UseQueryOptions<GetPaymentServicesResponse, Error>,
|
options?: UseQueryOptions<GetPaymentServicesResponse, Error>,
|
||||||
): UseQueryResult<GetPaymentServicesResponse, Error> => {
|
): UseQueryResult<GetPaymentServicesResponse, Error> => {
|
||||||
|
|||||||
@@ -14,6 +14,11 @@ interface AccountSessionResponse {
|
|||||||
client_secret: string;
|
client_secret: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a new Stripe checkout session for the provided link ID.
|
||||||
|
* @param {CreateCheckoutSessionValues} values - The values required to create a checkout session.
|
||||||
|
* @returns {Promise<CreateCheckoutSessionResponse>} The response containing the checkout session details.
|
||||||
|
*/
|
||||||
export const useCreateStripeAccountSession = (
|
export const useCreateStripeAccountSession = (
|
||||||
options?: UseMutationOptions<
|
options?: UseMutationOptions<
|
||||||
AccountSessionResponse,
|
AccountSessionResponse,
|
||||||
|
|||||||
Reference in New Issue
Block a user