feat: nowpayments
This commit is contained in:
parent
5be9d276a3
commit
f3579cfcaf
|
|
@ -27,6 +27,7 @@ import { PublicController } from '@gitroom/backend/api/routes/public.controller'
|
|||
import { RootController } from '@gitroom/backend/api/routes/root.controller';
|
||||
import { TrackService } from '@gitroom/nestjs-libraries/track/track.service';
|
||||
import { ShortLinkService } from '@gitroom/nestjs-libraries/short-linking/short.link.service';
|
||||
import { Nowpayments } from '@gitroom/nestjs-libraries/crypto/nowpayments';
|
||||
|
||||
const authenticatedController = [
|
||||
UsersController,
|
||||
|
|
@ -65,6 +66,7 @@ const authenticatedController = [
|
|||
IntegrationManager,
|
||||
TrackService,
|
||||
ShortLinkService,
|
||||
Nowpayments,
|
||||
],
|
||||
get exports() {
|
||||
return [...this.imports, ...this.providers];
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { ApiTags } from '@nestjs/swagger';
|
|||
import { GetUserFromRequest } from '@gitroom/nestjs-libraries/user/user.from.request';
|
||||
import { NotificationService } from '@gitroom/nestjs-libraries/database/prisma/notifications/notification.service';
|
||||
import { Request } from 'express';
|
||||
import { Nowpayments } from '@gitroom/nestjs-libraries/crypto/nowpayments';
|
||||
|
||||
@ApiTags('Billing')
|
||||
@Controller('/billing')
|
||||
|
|
@ -15,7 +16,8 @@ export class BillingController {
|
|||
constructor(
|
||||
private _subscriptionService: SubscriptionService,
|
||||
private _stripeService: StripeService,
|
||||
private _notificationService: NotificationService
|
||||
private _notificationService: NotificationService,
|
||||
private _nowpayments: Nowpayments
|
||||
) {}
|
||||
|
||||
@Get('/check/:id')
|
||||
|
|
@ -24,10 +26,7 @@ export class BillingController {
|
|||
@Param('id') body: string
|
||||
) {
|
||||
return {
|
||||
status: await this._stripeService.checkSubscription(
|
||||
org.id,
|
||||
body
|
||||
),
|
||||
status: await this._stripeService.checkSubscription(org.id, body),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -39,7 +38,13 @@ export class BillingController {
|
|||
@Req() req: Request
|
||||
) {
|
||||
const uniqueId = req?.cookies?.track;
|
||||
return this._stripeService.subscribe(uniqueId, org.id, user.id, body, org.allowTrial);
|
||||
return this._stripeService.subscribe(
|
||||
uniqueId,
|
||||
org.id,
|
||||
user.id,
|
||||
body,
|
||||
org.allowTrial
|
||||
);
|
||||
}
|
||||
|
||||
@Get('/portal')
|
||||
|
|
@ -106,4 +111,9 @@ export class BillingController {
|
|||
body.subscription
|
||||
);
|
||||
}
|
||||
|
||||
@Get('/crypto')
|
||||
async crypto(@GetOrgFromRequest() org: Organization) {
|
||||
return this._nowpayments.createPaymentPage(org.id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { Request, Response } from 'express';
|
|||
import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
|
||||
import { getCookieUrlFromDomain } from '@gitroom/helpers/subdomain/subdomain.management';
|
||||
import { AgentGraphInsertService } from '@gitroom/nestjs-libraries/agent/agent.graph.insert.service';
|
||||
import { Nowpayments } from '@gitroom/nestjs-libraries/crypto/nowpayments';
|
||||
|
||||
@ApiTags('Public')
|
||||
@Controller('/public')
|
||||
|
|
@ -18,7 +19,8 @@ export class PublicController {
|
|||
private _agenciesService: AgenciesService,
|
||||
private _trackService: TrackService,
|
||||
private _agentGraphInsertService: AgentGraphInsertService,
|
||||
private _postsService: PostsService
|
||||
private _postsService: PostsService,
|
||||
private _nowpayments: Nowpayments
|
||||
) {}
|
||||
@Post('/agent')
|
||||
async createAgent(@Body() body: { text: string; apiKey: string }) {
|
||||
|
|
@ -120,4 +122,13 @@ export class PublicController {
|
|||
track: uniqueId,
|
||||
});
|
||||
}
|
||||
|
||||
@Post('/crypto/:path')
|
||||
async cryptoPost(
|
||||
@Body() body: any,
|
||||
@Param('path') path: string
|
||||
) {
|
||||
console.log('cryptoPost', body, path);
|
||||
return this._nowpayments.processPayment(path, body);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import { useUtmUrl } from '@gitroom/helpers/utils/utm.saver';
|
|||
import { useTolt } from '@gitroom/frontend/components/layout/tolt.script';
|
||||
import { useTrack } from '@gitroom/react/helpers/use.track';
|
||||
import { TrackEnum } from '@gitroom/nestjs-libraries/user/track.enum';
|
||||
import { PurchaseCrypto } from '@gitroom/frontend/components/billing/purchase.crypto';
|
||||
|
||||
export interface Tiers {
|
||||
month: Array<{
|
||||
|
|
@ -502,6 +503,7 @@ export const MainBillingComponent: FC<{
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
<PurchaseCrypto />
|
||||
{!!subscription?.id && (
|
||||
<div className="flex justify-center mt-[20px] gap-[10px]">
|
||||
<Button onClick={updatePayment}>Update Payment Method</Button>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
import { FC, useCallback, useState } from 'react';
|
||||
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
|
||||
import { Button } from '@gitroom/react/form/button';
|
||||
|
||||
export const PurchaseCrypto: FC = () => {
|
||||
const fetch = useFetch();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const load = useCallback(async () => {
|
||||
setLoading(true);
|
||||
const data = await (await fetch('/billing/crypto')).json();
|
||||
window.location.href = data.invoice_url;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex-1 bg-sixth items-center border border-customColor6 rounded-[4px] p-[24px] gap-[16px] flex [@media(max-width:1024px)]:items-center"
|
||||
>
|
||||
<div>Purchase a Life-time PRO account with SOL ($199)</div>
|
||||
<div>
|
||||
<Button loading={loading} onClick={load}>Purchase now</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -79,6 +79,9 @@ export const TopMenu: FC = () => {
|
|||
if (f.requireBilling && !billingEnabled) {
|
||||
return false;
|
||||
}
|
||||
if (f.name === 'Billing' && user?.isLifetime) {
|
||||
return false;
|
||||
}
|
||||
if (f.role) {
|
||||
return f.role.includes(user?.role!);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
|
||||
import { AuthService } from '@gitroom/helpers/auth/auth.service';
|
||||
import { SubscriptionService } from '@gitroom/nestjs-libraries/database/prisma/subscriptions/subscription.service';
|
||||
|
||||
export interface ProcessPayment {
|
||||
payment_id: number;
|
||||
payment_status: string;
|
||||
pay_address: string;
|
||||
price_amount: number;
|
||||
price_currency: string;
|
||||
pay_amount: number;
|
||||
actually_paid: number;
|
||||
pay_currency: string;
|
||||
order_id: string;
|
||||
order_description: string;
|
||||
purchase_id: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
outcome_amount: number;
|
||||
outcome_currency: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class Nowpayments {
|
||||
constructor(private _subscriptionService: SubscriptionService) {}
|
||||
|
||||
async processPayment(path: string, body: ProcessPayment) {
|
||||
const decrypt = AuthService.verifyJWT(path) as any;
|
||||
if (!decrypt || !decrypt.order_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
decrypt.payment_status !== 'confirmed' &&
|
||||
decrypt.payment_status !== 'finished'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [org, make] = body.order_id.split('_');
|
||||
await this._subscriptionService.lifeTime(org, make, 'PRO');
|
||||
return body;
|
||||
}
|
||||
|
||||
async createPaymentPage(orgId: string) {
|
||||
const onlyId = makeId(5);
|
||||
const make = orgId + '_' + onlyId;
|
||||
const signRequest = AuthService.signJWT({ order_id: make });
|
||||
|
||||
const { id, invoice_url } = await (
|
||||
await fetch('https://api.nowpayments.io/v1/invoice', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': process.env.NOWPAYMENTS_API_KEY!,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
price_amount: process.env.NOWPAYMENTS_AMOUNT,
|
||||
price_currency: 'USD',
|
||||
order_id: make,
|
||||
pay_currency: 'SOL',
|
||||
order_description: 'Lifetime deal account for Postiz',
|
||||
ipn_callback_url:
|
||||
process.env.NEXT_PUBLIC_BACKEND_URL +
|
||||
`/public/crypto/${signRequest}`,
|
||||
success_url: process.env.FRONTEND_URL + `/launches?check=${onlyId}`,
|
||||
cancel_url: process.env.FRONTEND_URL,
|
||||
}),
|
||||
})
|
||||
).json();
|
||||
|
||||
return {
|
||||
id,
|
||||
invoice_url,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ export class SubscriptionService {
|
|||
constructor(
|
||||
private readonly _subscriptionRepository: SubscriptionRepository,
|
||||
private readonly _integrationService: IntegrationService,
|
||||
private readonly _organizationService: OrganizationService,
|
||||
private readonly _organizationService: OrganizationService
|
||||
) {}
|
||||
|
||||
getSubscriptionByOrganizationId(organizationId: string) {
|
||||
|
|
@ -188,6 +188,19 @@ export class SubscriptionService {
|
|||
};
|
||||
}
|
||||
|
||||
async lifeTime(orgId: string, identifier: string, subscription: any) {
|
||||
return this.createOrUpdateSubscription(
|
||||
identifier,
|
||||
identifier,
|
||||
pricing[subscription].channel!,
|
||||
subscription,
|
||||
'YEARLY',
|
||||
null,
|
||||
identifier,
|
||||
orgId
|
||||
);
|
||||
}
|
||||
|
||||
async addSubscription(orgId: string, userId: string, subscription: any) {
|
||||
await this._subscriptionRepository.setCustomerId(orgId, orgId);
|
||||
return this.createOrUpdateSubscription(
|
||||
|
|
|
|||
Loading…
Reference in New Issue