feat: send request via gateway

This commit is contained in:
Abdalhamid Alhamad
2025-07-06 16:44:23 +03:00
parent d3057beb54
commit 492e538eb8
3 changed files with 19 additions and 29 deletions

View File

@ -7,8 +7,9 @@ import { CardTransactionWebhookRequest } from '../dtos/requests';
@ApiTags('Neoleap Webhooks') @ApiTags('Neoleap Webhooks')
export class NeoLeapWebhooksController { export class NeoLeapWebhooksController {
constructor(private readonly transactionService: TransactionService) {} constructor(private readonly transactionService: TransactionService) {}
@Post('account-transaction')
async handleAccountTransactionWebhook(@Body() body: CardTransactionWebhookRequest) { @Post('card-transaction')
await this.transactionService.createCardTransaction(body); async handleCardTransactionWebhook(@Body() body: CardTransactionWebhookRequest) {
return this.transactionService.createCardTransaction(body);
} }
} }

View File

@ -30,7 +30,7 @@ export class NeoTestController {
@ApiDataResponse(CreateApplicationResponse) @ApiDataResponse(CreateApplicationResponse)
async createApplication() { async createApplication() {
const customer = await this.customerService.findCustomerById( const customer = await this.customerService.findCustomerById(
this.configService.get<string>('MOCK_CUSTOMER_ID', '0778c431-f604-4b91-af53-49c33849b5ff'), this.configService.get<string>('MOCK_CUSTOMER_ID', 'ff462af1-1e0c-4216-8865-738e5b525ac1'),
); );
const data = await this.neoleapService.createApplication(customer as Customer); const data = await this.neoleapService.createApplication(customer as Customer);
await this.cardService.createCard(customer.id, data); await this.cardService.createCard(customer.id, data);

View File

@ -2,10 +2,7 @@ import { HttpService } from '@nestjs/axios';
import { BadRequestException, Injectable, InternalServerErrorException } from '@nestjs/common'; import { BadRequestException, Injectable, InternalServerErrorException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config'; import { ConfigService } from '@nestjs/config';
import { ClassConstructor, plainToInstance } from 'class-transformer'; import { ClassConstructor, plainToInstance } from 'class-transformer';
import { readFileSync } from 'fs';
import { Agent } from 'https';
import moment from 'moment'; import moment from 'moment';
import path from 'path';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { CountriesNumericISO } from '~/common/constants'; import { CountriesNumericISO } from '~/common/constants';
import { Customer } from '~/customer/entities'; import { Customer } from '~/customer/entities';
@ -17,22 +14,22 @@ import { ICreateApplicationRequest, IInquireApplicationRequest, INeoleapHeaderRe
export class NeoLeapService { export class NeoLeapService {
private readonly baseUrl: string; private readonly baseUrl: string;
private readonly apiKey: string; private readonly apiKey: string;
private readonly useMock: boolean; private readonly useGateway: boolean;
private readonly institutionCode = '1100'; private readonly institutionCode = '1100';
useLocalCert: boolean; useLocalCert: boolean;
constructor(private readonly httpService: HttpService, private readonly configService: ConfigService) { constructor(private readonly httpService: HttpService, private readonly configService: ConfigService) {
this.baseUrl = this.configService.getOrThrow<string>('NEOLEAP_BASE_URL'); this.baseUrl = this.configService.getOrThrow<string>('GATEWAY_URL');
this.apiKey = this.configService.getOrThrow<string>('NEOLEAP_API_KEY'); this.apiKey = this.configService.getOrThrow<string>('GATEWAY_API_KEY');
this.useMock = [true, 'true'].includes(this.configService.get<boolean>('USE_MOCK', false)); this.useGateway = [true, 'true'].includes(this.configService.get<boolean>('USE_GATEWAY', false));
this.useLocalCert = this.configService.get<boolean>('USE_LOCAL_CERT', false); this.useLocalCert = this.configService.get<boolean>('USE_LOCAL_CERT', false);
} }
async createApplication(customer: Customer) { async createApplication(customer: Customer) {
const responseKey = 'CreateNewApplicationResponseDetails'; const responseKey = 'CreateNewApplicationResponseDetails';
if (customer.cards.length > 0) { // if (customer.cards.length > 0) {
throw new BadRequestException('CUSTOMER.ALREADY_HAS_CARD'); // throw new BadRequestException('CUSTOMER.ALREADY_HAS_CARD');
} // }
if (this.useMock) { if (!this.useGateway) {
return plainToInstance(CreateApplicationResponse, CREATE_APPLICATION_MOCK[responseKey], { return plainToInstance(CreateApplicationResponse, CREATE_APPLICATION_MOCK[responseKey], {
excludeExtraneousValues: true, excludeExtraneousValues: true,
}); });
@ -42,7 +39,7 @@ export class NeoLeapService {
CreateNewApplicationRequestDetails: { CreateNewApplicationRequestDetails: {
ApplicationRequestDetails: { ApplicationRequestDetails: {
InstitutionCode: this.institutionCode, InstitutionCode: this.institutionCode,
ExternalApplicationNumber: (customer.waitingNumber * 64).toString(), ExternalApplicationNumber: customer.waitingNumber.toString(),
ApplicationType: '01', ApplicationType: '01',
Product: '1101', Product: '1101',
ApplicationDate: moment().format('YYYY-MM-DD'), ApplicationDate: moment().format('YYYY-MM-DD'),
@ -105,7 +102,7 @@ export class NeoLeapService {
async inquireApplication(externalApplicationNumber: string) { async inquireApplication(externalApplicationNumber: string) {
const responseKey = 'InquireApplicationResponseDetails'; const responseKey = 'InquireApplicationResponseDetails';
if (this.useMock) { if (!this.useGateway) {
return plainToInstance(InquireApplicationResponse, INQUIRE_APPLICATION_MOCK[responseKey], { return plainToInstance(InquireApplicationResponse, INQUIRE_APPLICATION_MOCK[responseKey], {
excludeExtraneousValues: true, excludeExtraneousValues: true,
}); });
@ -152,29 +149,21 @@ export class NeoLeapService {
responseClass: ClassConstructor<R>, responseClass: ClassConstructor<R>,
): Promise<R> { ): Promise<R> {
try { try {
const response = await this.httpService.axiosRef.post(`${this.baseUrl}/${endpoint}`, payload, { const { data } = await this.httpService.axiosRef.post(`${this.baseUrl}/${endpoint}`, payload, {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
Authorization: `${this.apiKey}`, Authorization: `${this.apiKey}`,
Host: 'apigw-uat.neoleap.com.sa', Host: 'apigw-uat.neoleap.com.sa',
}, },
httpsAgent: new Agent({
rejectUnauthorized: false, // Disable SSL verification for development purposes
ca: this.useLocalCert ? readFileSync(path.join(__dirname, '../zod-certs/My_CA_Bundle.ca-bundle')) : undefined,
cert: this.useLocalCert
? readFileSync(path.join(__dirname, '../zod-certs/gw-dev_zodwallet_com.crt'))
: undefined,
key: this.useLocalCert ? readFileSync(path.join(__dirname, '../zod-certs/server.key')) : undefined,
}),
}); });
if (response.data?.ResponseHeader.ResponseCode !== '000' || !response.data[responseKey]) { if (data.data?.ResponseHeader?.ResponseCode !== '000' || !data.data[responseKey]) {
throw new BadRequestException( throw new BadRequestException(
response.data.ResponseHeader.ResponseDescription || 'Unexpected Error from Service Provider', data.data.ResponseHeader.ResponseDescription || 'Unexpected Error from Service Provider',
); );
} }
return plainToInstance(responseClass, response.data[responseKey], { return plainToInstance(responseClass, data.data[responseKey], {
excludeExtraneousValues: true, excludeExtraneousValues: true,
}); });
} catch (error: any) { } catch (error: any) {