Add Mellat e-payment, videos/instructions CMS, and legacy domain lookup.
Store gateway credentials per business, initiate/verify Mellat at checkout, and resolve old CMS ids from domains in the migrate modal. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
513673a7da
commit
d5e502cf77
@@ -1,11 +1,13 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AuthModule } from '../auth/auth.module';
|
||||
import { BusinessSettingsModule } from '../business-settings/business-settings.module';
|
||||
import { OrdersModule } from '../orders/orders.module';
|
||||
import { PaymentsModule } from '../payments/payments.module';
|
||||
import { CartController } from './cart.controller';
|
||||
import { CartService } from './cart.service';
|
||||
|
||||
@Module({
|
||||
imports: [AuthModule, OrdersModule],
|
||||
imports: [AuthModule, OrdersModule, PaymentsModule, BusinessSettingsModule],
|
||||
controllers: [CartController],
|
||||
providers: [CartService],
|
||||
})
|
||||
|
||||
@@ -15,6 +15,11 @@ import {
|
||||
UpdateCartItemDto,
|
||||
} from './dto/cart.dto';
|
||||
import { OrdersService } from '../orders/orders.service';
|
||||
import { PaymentsService } from '../payments/payments.service';
|
||||
import { TransactionType } from '@prisma/client';
|
||||
import { BusinessSettingsService } from '../business-settings/business-settings.service';
|
||||
import type { PaymentGatewayId } from '../business-settings/business-settings.types';
|
||||
import { listPublicPaymentGateways } from '../business-settings/business-settings.util';
|
||||
|
||||
const cartVariantInclude = {
|
||||
storeItem: {
|
||||
@@ -52,6 +57,8 @@ export class CartService {
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly permissions: PermissionsService,
|
||||
private readonly orders: OrdersService,
|
||||
private readonly payments: PaymentsService,
|
||||
private readonly businessSettings: BusinessSettingsService,
|
||||
) {}
|
||||
|
||||
async getCart(businessIdRaw: string, actor: AuthUser) {
|
||||
@@ -193,6 +200,30 @@ export class CartService {
|
||||
dto.shippingAddress,
|
||||
);
|
||||
|
||||
const isEPayment = dto.payment.type === TransactionType.e_payment_gate;
|
||||
let gatewayType: PaymentGatewayId | undefined;
|
||||
|
||||
if (isEPayment) {
|
||||
if (!dto.returnUrl?.trim()) {
|
||||
throw new BadRequestException(
|
||||
'returnUrl is required for e-payment checkout',
|
||||
);
|
||||
}
|
||||
|
||||
const settings =
|
||||
await this.businessSettings.getNormalizedSettings(businessId);
|
||||
const publicMethods = listPublicPaymentGateways(settings.store.ePayment);
|
||||
if (!publicMethods.enabled) {
|
||||
throw new BadRequestException(
|
||||
'Online payment is not enabled for this store',
|
||||
);
|
||||
}
|
||||
gatewayType = this.payments.resolveGatewayType(
|
||||
dto.payment.gatewayType,
|
||||
publicMethods,
|
||||
);
|
||||
}
|
||||
|
||||
const order = await this.orders.createFromCart({
|
||||
businessId,
|
||||
userId: actor.id,
|
||||
@@ -207,13 +238,38 @@ export class CartService {
|
||||
payment: {
|
||||
type: dto.payment.type,
|
||||
posType: dto.payment.posType,
|
||||
gatewayType: dto.payment.gatewayType,
|
||||
gatewayType: isEPayment ? gatewayType : dto.payment.gatewayType,
|
||||
transferAccount: dto.payment.transferAccount,
|
||||
transferRefNumber: dto.payment.transferRefNumber,
|
||||
notes: dto.payment.notes?.trim() || null,
|
||||
},
|
||||
});
|
||||
|
||||
if (isEPayment && gatewayType) {
|
||||
const payment = await this.payments.initiateForCheckout({
|
||||
businessId,
|
||||
order: {
|
||||
id: order.id,
|
||||
total: order.total,
|
||||
transactions: order.transactions,
|
||||
},
|
||||
gatewayType,
|
||||
returnUrl: dto.returnUrl!.trim(),
|
||||
});
|
||||
|
||||
await this.prisma.cartItem.deleteMany({ where: { cartId: cart.id } });
|
||||
|
||||
return {
|
||||
message: 'Redirect customer to payment gateway',
|
||||
order,
|
||||
payment: {
|
||||
gatewayType: payment.gatewayType,
|
||||
transactionId: payment.transactionId,
|
||||
redirect: payment.redirect,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
await this.prisma.cartItem.deleteMany({ where: { cartId: cart.id } });
|
||||
|
||||
return {
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
IsInt,
|
||||
IsOptional,
|
||||
IsString,
|
||||
IsUrl,
|
||||
MaxLength,
|
||||
Min,
|
||||
MinLength,
|
||||
@@ -67,6 +68,14 @@ export class CheckoutCartDto {
|
||||
@IsString()
|
||||
customerNotes?: string;
|
||||
|
||||
/**
|
||||
* Absolute URL the bank callback redirects the shopper to after payment.
|
||||
* Required when payment.type is e_payment_gate.
|
||||
*/
|
||||
@IsOptional()
|
||||
@IsUrl({ require_protocol: true, require_tld: false })
|
||||
returnUrl?: string;
|
||||
|
||||
@ValidateNested()
|
||||
@Type(() => CreateTransactionPaymentDto)
|
||||
payment!: CreateTransactionPaymentDto;
|
||||
|
||||
Reference in New Issue
Block a user