update : bycryptjs
Build and Deploy / build_and_deploy (push) Has been cancelled

This commit is contained in:
2026-06-14 08:49:13 +03:30
parent d7bf6e4791
commit 78d8795155
16 changed files with 64 additions and 274 deletions
+4 -3
View File
@@ -30,9 +30,10 @@ class PaymentGateway implements IPaymentGateway {
public async verifyPayment(gatewayType: GatewayProvider, data: VerifyPaymentData): Promise<any> {
const gateway = this.getGateway(gatewayType);
const verifyData = gatewayType === GatewayProvider.SEP
? { refNum: data.refNum, amount: data.amount }
: { authority: data.authority, amount: data.amount };
const verifyData =
gatewayType === GatewayProvider.SEP
? { refNum: data.refNum, amount: data.amount }
: { authority: data.authority, amount: data.amount };
return await gateway.verifyPayment(verifyData);
}
+21 -22
View File
@@ -12,19 +12,19 @@ interface SepRequestPaymentResponse {
}
interface SepVerifyPaymentResponse {
TransactionDetail: {
"RRN": string,
"RefNum": string,
"MaskedPan": string,
"HashedPan": string,
"TerminalNumber": number,
"OrginalAmount": number,
"AffectiveAmount": number,
"StraceDate": string,
"StraceNo": string,
},
"ResultCode": number,
"ResultDescription": string,
"Success": boolean
RRN: string;
RefNum: string;
MaskedPan: string;
HashedPan: string;
TerminalNumber: number;
OrginalAmount: number;
AffectiveAmount: number;
StraceDate: string;
StraceNo: string;
};
ResultCode: number;
ResultDescription: string;
Success: boolean;
}
@injectable()
@@ -47,7 +47,7 @@ class SepGateway implements IGateway {
const purchaseData = {
Action: "Token",
TerminalId: this.terminalNumber,
Amount: amount * 10,//ریال
Amount: amount * 10, //ریال
RedirectUrl: `${this.callBackURL}${callBackPath}`,
ResNum: Date.now().toString(),
CellNumber: _mobile,
@@ -71,8 +71,6 @@ class SepGateway implements IGateway {
}
}
async verifyPayment(data: { authority?: string; refNum?: string; amount: number }) {
if (!this.gatewayApiUrl || !this.terminalNumber) {
throw new InternalError(["SEP gateway is not configured"]);
@@ -80,13 +78,14 @@ class SepGateway implements IGateway {
try {
const verifyData = { RefNum: data.refNum, TerminalNumber: this.terminalNumber };
const response = await axios.post<SepVerifyPaymentResponse>(`${this.gatewayApiUrl}/verifyTxnRandomSessionkey/ipg/VerifyTransaction`,
const response = await axios.post<SepVerifyPaymentResponse>(
`${this.gatewayApiUrl}/verifyTxnRandomSessionkey/ipg/VerifyTransaction`,
verifyData,
{ headers: this.requestHeader }
{ headers: this.requestHeader },
);
const sepResponse = response.data;
console.log('sepResponse verify response *', sepResponse)
console.log("sepResponse verify response *", sepResponse);
// Normalize SEP response to match expected format
// SEP considers ResultCode = 0 and Success = true as successful
const isSuccess = sepResponse.ResultCode === 0 && sepResponse.Success === true;
@@ -95,18 +94,18 @@ class SepGateway implements IGateway {
let amountValid = true;
if (sepResponse.TransactionDetail && sepResponse.TransactionDetail.OrginalAmount) {
// According to SEP docs, OrginalAmount should match the expected amount
amountValid = sepResponse.TransactionDetail.OrginalAmount === data.amount*10;
amountValid = sepResponse.TransactionDetail.OrginalAmount === data.amount * 10;
if (!amountValid) {
this.logger.warn(`SEP amount mismatch: expected ${data.amount}, got ${sepResponse.TransactionDetail.OrginalAmount}`);
}
}
return {
code: (isSuccess && amountValid) ? 100 : sepResponse.ResultCode, // Use 100 for success to match expected format
code: isSuccess && amountValid ? 100 : sepResponse.ResultCode, // Use 100 for success to match expected format
message: sepResponse.ResultDescription,
ref_id: data.refNum, // SEP uses refNum as transaction identifier
success: isSuccess && amountValid,
raw_response: sepResponse // Keep original response for debugging
raw_response: sepResponse, // Keep original response for debugging
};
} catch (error) {
this.logger.error("error in SEP payment verification", error);
+1 -1
View File
@@ -40,5 +40,5 @@ export interface NewPaymentData {
export interface VerifyPaymentData {
amount: number;
authority?: string;
refNum?:string
refNum?: string;
}
+1 -1
View File
@@ -1,4 +1,4 @@
import { compare, hash } from "bcrypt";
import { compare, hash } from "bcryptjs";
import { inject, injectable } from "inversify";
import { LoginPassDTO } from "./DTO/loginPassword.dto";
+1 -1
View File
@@ -1,4 +1,4 @@
import { hash } from "bcrypt";
import { hash } from "bcryptjs";
import { CallbackError, Schema, model } from "mongoose";
import { IAdmin } from "./Abstraction/IAdmin";
+1 -1
View File
@@ -58,7 +58,7 @@ class OrderService {
const province = userAddress.province as unknown as IProvince;
console.log("city", city);
console.log("province", province);
if(!city?.name || !province?.name ){
if (!city?.name || !province?.name) {
throw new BadRequestError(AddressMessage.INVALID_ADDRESS);
}
const shipmentAddress: IShipmentAddress = {
+1 -1
View File
@@ -115,7 +115,7 @@ class PaymentController extends BaseController {
@response() res: Response,
@requestBody() dto: VerifyOnlinePaymentDTO,
) {
const verifyCallbackData = {
const verifyCallbackData = {
status: dto.State,
refNum: dto.RefNum,
authority: dto.Token,
@@ -165,7 +165,6 @@ class PaymentService {
const session = await startSession();
session.startTransaction();
try {
// For SEP gateway, check if refNum has already been used as transaction_id
if (gateway === GatewayProvider.SEP && refNum) {
const existingPayment = await this.cartPaymentRepo.model.findOne({ transaction_id: refNum }).session(session);
@@ -185,17 +184,14 @@ class PaymentService {
// Handle unsuccessful payment status
if (status !== "OK") {
return this.buildPaymentResponse(status ?? 'Nok', PaymentMessage.PaymentNotSuccessful, paymentData._id.toString(), order._id);
return this.buildPaymentResponse(status ?? "Nok", PaymentMessage.PaymentNotSuccessful, paymentData._id.toString(), order._id);
}
// Verify payment through gateway
const verifyData =
gateway === GatewayProvider.SEP
? { refNum, amount: paymentData.totalPrice }
: { authority, amount: paymentData.totalPrice };
gateway === GatewayProvider.SEP ? { refNum, amount: paymentData.totalPrice } : { authority, amount: paymentData.totalPrice };
const data = await this.paymentGateway.verifyPayment(gateway, verifyData);
if (data.code === 100 || data.code === 101) {
await this.handleSellerNotify(order._id, user, session);
// For SEP gateway, save refNum as transaction_id; for Zarinpal, save ref_id
@@ -397,8 +393,17 @@ class PaymentService {
}
//##################################################################
//##################################################################
private async updatePaymentStatusAndReference(paymentId: string, transactionId: string | null, status: PaymentStatus, session: ClientSession) {
return await this.cartPaymentRepo.model.findByIdAndUpdate(paymentId, { paymentStatus: status, transaction_id: transactionId }, { session });
private async updatePaymentStatusAndReference(
paymentId: string,
transactionId: string | null,
status: PaymentStatus,
session: ClientSession,
) {
return await this.cartPaymentRepo.model.findByIdAndUpdate(
paymentId,
{ paymentStatus: status, transaction_id: transactionId },
{ session },
);
}
}
@@ -130,7 +130,6 @@ export class ProductVariantRepository extends BaseRepository<IProductVariant> {
},
},
{
$addFields: {
product_id: "$product._id",
@@ -22,7 +22,7 @@ export interface IProductVariant {
dimensions: IDimensions;
sellerSpecialCode: string;
themeValue: Types.ObjectId;
deleted: boolean
deleted: boolean;
}
export interface IPrice {
@@ -1105,7 +1105,7 @@ class ProductService {
async softDeleteProductVariant(variantId: string) {
await this.productVariantRepo.model.findOneAndUpdate({ _id: variantId }, { deleted: true });
return { message: 'Deleted successfully' }
return { message: "Deleted successfully" };
}
//################################################################