Added the Payment Data Persistence API
This commit is contained in:
parent
45d57cee8d
commit
a2c2ed2a68
@ -51,7 +51,7 @@ export class PRICE_DTO {
|
|||||||
// @Max(999999999, {
|
// @Max(999999999, {
|
||||||
// message: 'Property P_PRICE must not exceed 999999999',
|
// message: 'Property P_PRICE must not exceed 999999999',
|
||||||
// })
|
// })
|
||||||
@Min(0.1, { message: 'Property P_PRICE must be greater than zero' })
|
@Min(0.01, { message: 'Property P_PRICE must be greater than zero' })
|
||||||
// @IsInt({ message: 'Property P_PRICE allows only whole numbers' })
|
// @IsInt({ message: 'Property P_PRICE allows only whole numbers' })
|
||||||
@IsNumber({}, { message: 'Property P_PRICE must be a number' })
|
@IsNumber({}, { message: 'Property P_PRICE must be a number' })
|
||||||
@Transform(({ value }) => Number(value))
|
@Transform(({ value }) => Number(value))
|
||||||
@ -59,6 +59,33 @@ export class PRICE_DTO {
|
|||||||
P_PRICE: number;
|
P_PRICE: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class PAYMENTAMOUNT_DTO {
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
// @Max(999999999, {
|
||||||
|
// message: 'Property P_PRICE must not exceed 999999999',
|
||||||
|
// })
|
||||||
|
@Min(0.01, { message: 'Property P_PAYMENTAMOUNT must be greater than zero' })
|
||||||
|
// @IsInt({ message: 'Property P_PRICE allows only whole numbers' })
|
||||||
|
@IsNumber({}, { message: 'Property P_PAYMENTAMOUNT must be a number' })
|
||||||
|
@Transform(({ value }) => Number(value))
|
||||||
|
@IsDefined({ message: 'Property P_PAYMENTAMOUNT is required' })
|
||||||
|
P_PAYMENTAMOUNT: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PAYMENTSTATUS_DTO {
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
@IsString({ message: 'Property P_STATUS must be a string' })
|
||||||
|
@IsDefined({ message: 'Property P_STATUS is required' })
|
||||||
|
P_STATUS: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PAYMENTERROR_DTO {
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
@IsString({ message: 'Property P_PAYMENTERROR must be a string' })
|
||||||
|
@IsDefined({ message: 'Property P_PAYMENTERROR is required' })
|
||||||
|
P_PAYMENTERROR: string | null = null;
|
||||||
|
}
|
||||||
|
|
||||||
export class DESCRIPTION_DTO {
|
export class DESCRIPTION_DTO {
|
||||||
@ApiProperty({ required: true })
|
@ApiProperty({ required: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
|
|||||||
@ -5,7 +5,8 @@ import {
|
|||||||
COUNTRYTABLE_DTO, CUSTCOURIERNO_DTO, DELIVERYMETHOD_DTO, DELIVERYTYPE_DTO,
|
COUNTRYTABLE_DTO, CUSTCOURIERNO_DTO, DELIVERYMETHOD_DTO, DELIVERYTYPE_DTO,
|
||||||
DESCRIPTION_DTO,
|
DESCRIPTION_DTO,
|
||||||
EXIBITIONS_FAIR_FLAG_DTO, EXTENSION_PERIOD_DTO, FORMOFSECURITY_DTO, GLTABLE_DTO, GLTABLE_ITEMNO_OPTIONAL_DTO, GOODS_COUNTRY_DTO, GOODS_PORT_DTO, HEADERID_DTO,
|
EXIBITIONS_FAIR_FLAG_DTO, EXTENSION_PERIOD_DTO, FORMOFSECURITY_DTO, GLTABLE_DTO, GLTABLE_ITEMNO_OPTIONAL_DTO, GOODS_COUNTRY_DTO, GOODS_PORT_DTO, HEADERID_DTO,
|
||||||
HORSE_FLAG_DTO, INSPROTECTION_DTO, ITEMNO_DTO, LDIPROTECTION_DTO, ORDERID_DTO, ORDERTYPE_DTO, PAYMENTMETHOD_DTO,
|
HORSE_FLAG_DTO, INSPROTECTION_DTO, ITEMNO_DTO, LDIPROTECTION_DTO, ORDERID_DTO, ORDERTYPE_DTO, PAYMENTAMOUNT_DTO, PAYMENTERROR_DTO, PAYMENTMETHOD_DTO,
|
||||||
|
PAYMENTSTATUS_DTO,
|
||||||
PRICE_DTO,
|
PRICE_DTO,
|
||||||
PRINTGL_DTO,
|
PRINTGL_DTO,
|
||||||
PROF_EQUIPMENT_FLAG_DTO, REASON_CODE_DTO, REFNO_DTO, SHIPADDRID_DTO, SHIPCONTACTID_DTO, SHIPNAME_DTO, SHIPTOTYPE_DTO, USSETS_DTO
|
PROF_EQUIPMENT_FLAG_DTO, REASON_CODE_DTO, REFNO_DTO, SHIPADDRID_DTO, SHIPCONTACTID_DTO, SHIPNAME_DTO, SHIPTOTYPE_DTO, USSETS_DTO
|
||||||
@ -72,6 +73,9 @@ export class PrintCarnetDTO extends (IntersectionType(SPID_DTO, HEADERID_DTO, PR
|
|||||||
export class PrintGLDTO extends (IntersectionType(SPID_DTO, HEADERID_DTO)) { }
|
export class PrintGLDTO extends (IntersectionType(SPID_DTO, HEADERID_DTO)) { }
|
||||||
export class CapturePaymentDTO extends (IntersectionType(ORDERID_DTO)) { }
|
export class CapturePaymentDTO extends (IntersectionType(ORDERID_DTO)) { }
|
||||||
export class InitiatePaymentDTO extends (IntersectionType(PRICE_DTO, DESCRIPTION_DTO)) { }
|
export class InitiatePaymentDTO extends (IntersectionType(PRICE_DTO, DESCRIPTION_DTO)) { }
|
||||||
|
export class GetOrderDetailsDTO extends (IntersectionType(ORDERID_DTO)) { }
|
||||||
|
export class GetPaymentHistoryDTO extends (IntersectionType(APPLICATIONNAME_DTO, USERID_DTO)) { }
|
||||||
|
export class SaveHistoryDTO extends (IntersectionType(APPLICATIONNAME_DTO, ORDERID_DTO, PAYMENTAMOUNT_DTO, PAYMENTSTATUS_DTO, USERID_DTO, PartialType(PAYMENTERROR_DTO))) { }
|
||||||
|
|
||||||
export class CreateApplicationDTO extends IntersectionType(
|
export class CreateApplicationDTO extends IntersectionType(
|
||||||
SPID_DTO, CLIENTID_DTO, LOCATIONID_DTO, USERID_DTO, APPLICATIONNAME_DTO,
|
SPID_DTO, CLIENTID_DTO, LOCATIONID_DTO, USERID_DTO, APPLICATIONNAME_DTO,
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import {
|
|||||||
AddGenerallistItemsDTO,
|
AddGenerallistItemsDTO,
|
||||||
CA_UpdateHolderDTO,
|
CA_UpdateHolderDTO,
|
||||||
CapturePaymentDTO,
|
CapturePaymentDTO,
|
||||||
CarnetProcessingCenterDTO, CarnetProcessingCenterDTO2, CopyCarnetDTO, CreateApplicationDTO, DeleteGenerallistItemsDTO, EditGenerallistItemsDTO, GetCarnetControlCenterDTO, GetExtendedSectionDTO, InitiatePaymentDTO, PrintCarnetDTO, PrintGLDTO, SaveCarnetApplicationDTO, SaveExtensionApplicationDTO, TransmitApplicationtoProcessDTO,
|
CarnetProcessingCenterDTO, CarnetProcessingCenterDTO2, CopyCarnetDTO, CreateApplicationDTO, DeleteGenerallistItemsDTO, EditGenerallistItemsDTO, GetCarnetControlCenterDTO, GetExtendedSectionDTO, GetOrderDetailsDTO, GetPaymentHistoryDTO, InitiatePaymentDTO, PrintCarnetDTO, PrintGLDTO, SaveCarnetApplicationDTO, SaveExtensionApplicationDTO, SaveHistoryDTO, TransmitApplicationtoProcessDTO,
|
||||||
UpdateExpGoodsAuthRepDTO,
|
UpdateExpGoodsAuthRepDTO,
|
||||||
UpdateShippingDetailsDTO
|
UpdateShippingDetailsDTO
|
||||||
} from 'src/dto/property.dto';
|
} from 'src/dto/property.dto';
|
||||||
@ -275,16 +275,30 @@ export class CarnetApplicationController {
|
|||||||
//[payment]
|
//[payment]
|
||||||
|
|
||||||
@Post('InitiatePayment')
|
@Post('InitiatePayment')
|
||||||
@UseGuards()
|
|
||||||
async InitiatePayment(@Body() body: InitiatePaymentDTO) {
|
async InitiatePayment(@Body() body: InitiatePaymentDTO) {
|
||||||
return this.carnetApplicationService.InitiatePayment(body);
|
return this.carnetApplicationService.InitiatePayment(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('CompletePayment')
|
@Post('CompletePayment')
|
||||||
@HttpCode(200)
|
@HttpCode(200)
|
||||||
@UseGuards()
|
|
||||||
async CapturePayment(@Body() body: CapturePaymentDTO) {
|
async CapturePayment(@Body() body: CapturePaymentDTO) {
|
||||||
return this.carnetApplicationService.CapturePayment(body);
|
return this.carnetApplicationService.CapturePayment(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Get('OrderDetails/:P_ORDERID')
|
||||||
|
async OrderDetails(@Param() body: GetOrderDetailsDTO) {
|
||||||
|
return this.carnetApplicationService.OrderDetails(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('GetPaymentHistory/:P_APPLICATIONNAME/:P_USERID')
|
||||||
|
async GetPaymentHistory(@Param() body: GetPaymentHistoryDTO) {
|
||||||
|
return this.carnetApplicationService.GetPaymentHistory(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('SaveHistory')
|
||||||
|
@HttpCode(200)
|
||||||
|
async SaveHistory(@Body() body: SaveHistoryDTO) {
|
||||||
|
return this.carnetApplicationService.SaveHistory(body);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,10 @@ import {
|
|||||||
SaveExtensionApplicationDTO,
|
SaveExtensionApplicationDTO,
|
||||||
CarnetProcessingCenterDTO2,
|
CarnetProcessingCenterDTO2,
|
||||||
CapturePaymentDTO,
|
CapturePaymentDTO,
|
||||||
InitiatePaymentDTO
|
InitiatePaymentDTO,
|
||||||
|
GetOrderDetailsDTO,
|
||||||
|
GetPaymentHistoryDTO,
|
||||||
|
SaveHistoryDTO
|
||||||
} from 'src/dto/property.dto';
|
} from 'src/dto/property.dto';
|
||||||
import { OracleService } from '../oracle.service';
|
import { OracleService } from '../oracle.service';
|
||||||
import { BadRequestException } from 'src/exceptions/badRequest.exception';
|
import { BadRequestException } from 'src/exceptions/badRequest.exception';
|
||||||
@ -1605,6 +1608,7 @@ export class CarnetApplicationService {
|
|||||||
|
|
||||||
|
|
||||||
async InitiatePayment(body: InitiatePaymentDTO) {
|
async InitiatePayment(body: InitiatePaymentDTO) {
|
||||||
|
// console.log(body);
|
||||||
|
|
||||||
const quantity = 1;
|
const quantity = 1;
|
||||||
|
|
||||||
@ -1613,7 +1617,10 @@ export class CarnetApplicationService {
|
|||||||
try {
|
try {
|
||||||
const accessToken = await this.payPalService.generateAccessToken();
|
const accessToken = await this.payPalService.generateAccessToken();
|
||||||
|
|
||||||
// return { accessToken, orderid: "1abc" }
|
// return {
|
||||||
|
// id: "6CU709471L678832M",
|
||||||
|
// href: "https://www.sandbox.paypal.com/checkoutnow?token=6CU709471L678832M"
|
||||||
|
// }
|
||||||
|
|
||||||
const response = await axios({
|
const response = await axios({
|
||||||
url: process.env.PAYPAL_BASE_URL + '/v2/checkout/orders',
|
url: process.env.PAYPAL_BASE_URL + '/v2/checkout/orders',
|
||||||
@ -1697,6 +1704,7 @@ export class CarnetApplicationService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const capture = response?.data?.purchase_units?.[0]?.payments?.captures?.[0];
|
const capture = response?.data?.purchase_units?.[0]?.payments?.captures?.[0];
|
||||||
|
// console.log(JSON.stringify(response?.data));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
@ -1723,4 +1731,157 @@ export class CarnetApplicationService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async OrderDetails(body: GetOrderDetailsDTO) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Max length of Order ID: 36 characters (UUID)
|
||||||
|
if (!body.P_ORDERID || body.P_ORDERID.length > 36) {
|
||||||
|
throw new BadRequestException("Invalid Order ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
const accessToken = await this.payPalService.generateAccessToken();
|
||||||
|
|
||||||
|
const response = await axios({
|
||||||
|
url: `${process.env.PAYPAL_BASE_URL}/v2/checkout/orders/${body.P_ORDERID}`,
|
||||||
|
method: 'get',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${accessToken}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// console.log("PayPal Order Details:", JSON.stringify(response.data));
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
message: "Order details retrieved successfully",
|
||||||
|
data: response.data,
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error: any) {
|
||||||
|
const isAxiosError = error.isAxiosError;
|
||||||
|
|
||||||
|
if (isAxiosError) {
|
||||||
|
const axiosErrorCode = error.code;
|
||||||
|
|
||||||
|
switch (axiosErrorCode) {
|
||||||
|
case 'ECONNABORTED':
|
||||||
|
case 'ETIMEDOUT':
|
||||||
|
console.error("PayPal request timed out. Please try again later.")
|
||||||
|
throw new InternalServerException("Service is currently unreachable. Please try again later.");
|
||||||
|
case 'ENOTFOUND':
|
||||||
|
case 'ECONNREFUSED':
|
||||||
|
console.error("PayPal service is currently unavailable. Please try again later.")
|
||||||
|
throw new InternalServerException("Service is currently unreachable. Please try again later.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const status = error.response?.status || 500;
|
||||||
|
const message = error.response?.data?.message || "Failed to fetch order details.";
|
||||||
|
|
||||||
|
|
||||||
|
console.error("PayPal OrderDetails Error:", {
|
||||||
|
status,
|
||||||
|
message,
|
||||||
|
details: error.response?.data,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status === 404) {
|
||||||
|
throw new NotFoundException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InternalServerException("A Error Occured while Processing your Request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetPaymentHistory(body: GetPaymentHistoryDTO) {
|
||||||
|
let connection;
|
||||||
|
try {
|
||||||
|
connection = await this.oracleDBService.getConnection();
|
||||||
|
|
||||||
|
const result = await connection.execute(
|
||||||
|
`BEGIN
|
||||||
|
Pay_GetPaymentHistory(
|
||||||
|
:P_APPLICATIONNAME, :P_USERID, :P_CURSOR
|
||||||
|
);
|
||||||
|
END;`,
|
||||||
|
{
|
||||||
|
P_APPLICATIONNAME: { val: body.P_APPLICATIONNAME, type: oracledb.DB_TYPE_NVARCHAR },
|
||||||
|
P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_NVARCHAR },
|
||||||
|
P_CURSOR: { dir: oracledb.BIND_OUT, type: oracledb.CURSOR },
|
||||||
|
// P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
|
||||||
|
},
|
||||||
|
{ outFormat: oracledb.OUT_FORMAT_OBJECT }
|
||||||
|
);
|
||||||
|
|
||||||
|
await connection.commit();
|
||||||
|
|
||||||
|
const outBinds = result.outBinds;
|
||||||
|
if (!outBinds?.P_CURSOR) {
|
||||||
|
this.logger.error('One or more expected cursors are missing from stored procedure output.');
|
||||||
|
throw new InternalServerException("Incomplete data received from the database.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const fres: any = await fetchCursor(outBinds.P_CURSOR, CarnetApplicationService.name);
|
||||||
|
|
||||||
|
if (fres.length > 0 && fres[0].ERRORMESG) {
|
||||||
|
this.logger.warn(fres[0].ERRORMESG);
|
||||||
|
throw new BadRequestException(fres[0].ERRORMESG)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fres.length > 0 ? fres[0] : {}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, CarnetApplicationService.name)
|
||||||
|
} finally {
|
||||||
|
await closeOracleDbConnection(connection, CarnetApplicationService.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async SaveHistory(body: SaveHistoryDTO) {
|
||||||
|
let connection;
|
||||||
|
try {
|
||||||
|
connection = await this.oracleDBService.getConnection();
|
||||||
|
|
||||||
|
const result = await connection.execute(
|
||||||
|
`BEGIN
|
||||||
|
Pay_SaveHistory(
|
||||||
|
:P_APPLICATIONNAME, :P_ORDERID, :P_PAYMENTAMOUNT, :P_STATUS, :P_USERID, :P_PAYMENTERROR, :P_CURSOR
|
||||||
|
);
|
||||||
|
END;`,
|
||||||
|
{
|
||||||
|
P_APPLICATIONNAME: { val: body.P_APPLICATIONNAME, type: oracledb.DB_TYPE_NVARCHAR },
|
||||||
|
P_ORDERID: { val: body.P_ORDERID, type: oracledb.DB_TYPE_NVARCHAR },
|
||||||
|
P_PAYMENTAMOUNT: { val: body.P_PAYMENTAMOUNT, type: oracledb.DB_TYPE_NUMBER },
|
||||||
|
P_STATUS: { val: body.P_STATUS, type: oracledb.DB_TYPE_NVARCHAR },
|
||||||
|
P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_NVARCHAR },
|
||||||
|
P_PAYMENTERROR: { val: body.P_PAYMENTERROR, type: oracledb.DB_TYPE_NVARCHAR },
|
||||||
|
P_CURSOR: { dir: oracledb.BIND_OUT, type: oracledb.CURSOR },
|
||||||
|
// P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
|
||||||
|
},
|
||||||
|
{ outFormat: oracledb.OUT_FORMAT_OBJECT }
|
||||||
|
);
|
||||||
|
|
||||||
|
await connection.commit();
|
||||||
|
|
||||||
|
const outBinds = result.outBinds;
|
||||||
|
if (!outBinds?.P_CURSOR) {
|
||||||
|
this.logger.error('One or more expected cursors are missing from stored procedure output.');
|
||||||
|
throw new InternalServerException("Incomplete data received from the database.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const fres: any = await fetchCursor(outBinds.P_CURSOR, CarnetApplicationService.name);
|
||||||
|
|
||||||
|
if (fres.length > 0 && fres[0].ERRORMESG) {
|
||||||
|
this.logger.warn(fres[0].ERRORMESG);
|
||||||
|
throw new BadRequestException(fres[0].ERRORMESG)
|
||||||
|
}
|
||||||
|
|
||||||
|
return { statusCode: 200, message: "Saved Successfully", ...fres[0] };
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, CarnetApplicationService.name)
|
||||||
|
} finally {
|
||||||
|
await closeOracleDbConnection(connection, CarnetApplicationService.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user