Compare commits
3 Commits
dfc10b52fb
...
f922db16cf
| Author | SHA1 | Date |
|---|---|---|
|
|
f922db16cf | |
|
|
75b38bfa0d | |
|
|
b26494d147 |
|
|
@ -5,6 +5,7 @@ import crypto from "crypto";
|
||||||
import db from "../db";
|
import db from "../db";
|
||||||
import { get, set } from "lodash";
|
import { get, set } from "lodash";
|
||||||
import { hashToken } from "../middleware/auth";
|
import { hashToken } from "../middleware/auth";
|
||||||
|
import generateSignatureService from "../lib/bank/mandiri/generateSignatureService";
|
||||||
|
|
||||||
const KEY_PATH =
|
const KEY_PATH =
|
||||||
process.env.PRIVATE_KEY_PATH || path.join(__dirname, "../../secrets/key.pem");
|
process.env.PRIVATE_KEY_PATH || path.join(__dirname, "../../secrets/key.pem");
|
||||||
|
|
@ -112,7 +113,6 @@ export async function createSignature({
|
||||||
pattern: string;
|
pattern: string;
|
||||||
passphrase?: string;
|
passphrase?: string;
|
||||||
}) {
|
}) {
|
||||||
console.log(data);
|
|
||||||
if (data?.accesstoken) {
|
if (data?.accesstoken) {
|
||||||
const session = await db.sessions.findFirst({
|
const session = await db.sessions.findFirst({
|
||||||
where: { token_hash: hashToken(data.accesstoken) },
|
where: { token_hash: hashToken(data.accesstoken) },
|
||||||
|
|
@ -310,3 +310,32 @@ export async function verifySignature(req: Request, res: Response) {
|
||||||
return res.status(500).json({ error: err.message || "internal error" });
|
return res.status(500).json({ error: err.message || "internal error" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export async function generateSignatureBank(req: Request, res: Response) {
|
||||||
|
try {
|
||||||
|
const data = req.body || {};
|
||||||
|
const clientId = get(data, "client_id") || get(data, "clientId");
|
||||||
|
const user = await db.users.findFirst({
|
||||||
|
where: { clientbank_id: clientId },
|
||||||
|
include: { database: true, parameters: true, tenants: true, banks: true },
|
||||||
|
});
|
||||||
|
const signatureService = await generateSignatureService({
|
||||||
|
data: {
|
||||||
|
isGenerateNewToken: true,
|
||||||
|
client_secret: get(data, "client_secret") || "",
|
||||||
|
endpointurl: get(data, "endpointurl") || "",
|
||||||
|
body: get(data, "requestBody", {}),
|
||||||
|
},
|
||||||
|
user: user as any,
|
||||||
|
});
|
||||||
|
return res.json({
|
||||||
|
...signatureService,
|
||||||
|
algorithm: "RSA-SHA256",
|
||||||
|
client_secret: get(data, "client_secret") || "",
|
||||||
|
endpointurl: get(data, "endpointurl") || "",
|
||||||
|
body: get(data, "requestBody", {}),
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error("generateSignature error", err);
|
||||||
|
return res.status(500).json({ error: err.message || "internal error" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,9 @@ import path from "path";
|
||||||
import { hashToken } from "../middleware/auth";
|
import { hashToken } from "../middleware/auth";
|
||||||
import db from "../db";
|
import db from "../db";
|
||||||
import { formatTimestamp } from "../lib/formatTimestamp";
|
import { formatTimestamp } from "../lib/formatTimestamp";
|
||||||
|
import callGate from "../lib/gate";
|
||||||
|
import { getParameter } from "../lib/getParameter";
|
||||||
|
import { get } from "lodash";
|
||||||
|
|
||||||
function loadCertForUser(user: any): string | null {
|
function loadCertForUser(user: any): string | null {
|
||||||
// try deriving .cer from private_key_file
|
// try deriving .cer from private_key_file
|
||||||
|
|
@ -179,3 +182,56 @@ export async function b2bAccessToken(req: Request, res: Response) {
|
||||||
.json({ responseCode: "5000000", responseMessage: "internal error" });
|
.json({ responseCode: "5000000", responseMessage: "internal error" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function signatureBank(req: Request, res: Response) {
|
||||||
|
try {
|
||||||
|
const clientKey = (req.headers["x-token-key"] ||
|
||||||
|
req.headers["X-TOKEN-KEY"] ||
|
||||||
|
req.headers["x-token-key" as any]) as string;
|
||||||
|
const data = req.body || {};
|
||||||
|
const requiredHeader = ["X-TOKEN-KEY"];
|
||||||
|
const requiredBody = ["endpointurl", "requestBody"];
|
||||||
|
for (const h of requiredHeader) {
|
||||||
|
if (!req.headers[h.toLowerCase()]) {
|
||||||
|
return res.status(400).json({ error: `missing header ${h}` });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const b of requiredBody) {
|
||||||
|
if (!data[b]) {
|
||||||
|
return res.status(400).json({ error: `missing body ${b}` });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const user = await db.users.findFirst({
|
||||||
|
where: { token_access: clientKey },
|
||||||
|
include: {
|
||||||
|
parameters: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!user) {
|
||||||
|
return res.status(401).json({
|
||||||
|
responseCode: "4017300",
|
||||||
|
responseMessage: "Unauthorized. Client ID not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const signature = await callGate({
|
||||||
|
client: "mandiri",
|
||||||
|
action: "generateSignatureService",
|
||||||
|
data: {
|
||||||
|
isGenerateNewToken: true,
|
||||||
|
client_secret: getParameter(user, "client_secret") || "",
|
||||||
|
endpointurl: get(data, "endpointurl", ""),
|
||||||
|
body: get(data, "requestBody", {}),
|
||||||
|
},
|
||||||
|
user,
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
...signature,
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error("b2bAccessToken error", err);
|
||||||
|
return res
|
||||||
|
.status(500)
|
||||||
|
.json({ responseCode: "5000000", responseMessage: "internal error" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import callGateFromReq from "../lib/gateClient";
|
|
||||||
import getTokenAuth from "../lib/getTokenAuth";
|
import getTokenAuth from "../lib/getTokenAuth";
|
||||||
import { getUserFromToken } from "../middleware/auth";
|
import { getUserFromToken } from "../middleware/auth";
|
||||||
import { dbQueryClient } from "../lib/dbQueryClient";
|
import { dbQueryClient } from "../lib/dbQueryClient";
|
||||||
|
|
@ -29,11 +28,26 @@ export async function inquiry(req: Request, res: Response) {
|
||||||
return res.status(400).json({ error: `missing body field ${f}` });
|
return res.status(400).json({ error: `missing body field ${f}` });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const parameters = await db.parameters.findFirst({
|
||||||
const result = await callGateFromReq(req, {
|
where: {
|
||||||
|
param_key: "partnerServiceId",
|
||||||
|
param_value: get(body, "partnerServiceId"),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const user = await db.users.findFirst({
|
||||||
|
where: { user_id: parameters?.user_id },
|
||||||
|
include: {
|
||||||
|
database: true,
|
||||||
|
banks: true,
|
||||||
|
parameters: true,
|
||||||
|
tenants: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const result = await callGate({
|
||||||
client: "mandiri",
|
client: "mandiri",
|
||||||
action: "getInvoiceVirtualAccount",
|
action: "getInvoiceVirtualAccount",
|
||||||
data: { ...body },
|
data: { ...body },
|
||||||
|
user: user,
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
|
|
@ -46,7 +60,9 @@ export async function inquiry(req: Request, res: Response) {
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("transfer inquiry error:", err);
|
console.error("transfer inquiry error:", err);
|
||||||
return res.status(500).json({ error: "internal_error" });
|
return res
|
||||||
|
.status(500)
|
||||||
|
.json({ error: "internal_error", message: get(err, "message") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { get } from "lodash";
|
||||||
|
import { db } from "../../../db";
|
||||||
|
import axios from "axios";
|
||||||
|
import { formatTimestamp } from "../../formatTimestamp";
|
||||||
|
import generateSignatureService from "./generateSignatureService";
|
||||||
|
import { getParameter } from "../../getParameter";
|
||||||
|
export default async function ({ data }: { data: any }) {
|
||||||
|
const endpointurl = "/api/v1.0/transfer-va/payment";
|
||||||
|
const user = await db.users.findFirst({
|
||||||
|
where: {
|
||||||
|
clientbank_id: data.clientbank_id,
|
||||||
|
},
|
||||||
|
include: { banks: true, database: true, parameters: true },
|
||||||
|
});
|
||||||
|
if (!user) throw new Error("User not found");
|
||||||
|
const timestamp = formatTimestamp();
|
||||||
|
const signatureService = await generateSignatureService({
|
||||||
|
data: {
|
||||||
|
accessToken: data.accessToken,
|
||||||
|
timestamp,
|
||||||
|
isGenerateNewToken: true,
|
||||||
|
client_secret: getParameter(user, "client_secret") || "",
|
||||||
|
endpointurl,
|
||||||
|
body: get(data, "requestBody", {}),
|
||||||
|
},
|
||||||
|
user,
|
||||||
|
});
|
||||||
|
data.accessToken = signatureService.accessToken;
|
||||||
|
data.timestamp = signatureService.timestamp;
|
||||||
|
data.signature = signatureService.signature;
|
||||||
|
const clientId = data.clientbank_id;
|
||||||
|
const headers: Record<string, string> = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
"X-PARTNER-ID": clientId,
|
||||||
|
"X-TIMESTAMP": data.timestamp,
|
||||||
|
"X-SIGNATURE": data.signature,
|
||||||
|
Authorization: `Bearer ${data.accessToken}`,
|
||||||
|
"X-EXTERNAL-ID": data.external_id,
|
||||||
|
"CHANNEL-ID": data.channel_id,
|
||||||
|
};
|
||||||
|
const mandiriUrl = String(get(user, "endpoint") || process.env.PAYMENT_URL);
|
||||||
|
|
||||||
|
const resp = await axios.post(
|
||||||
|
mandiriUrl + endpointurl,
|
||||||
|
{ ...get(data, "requestBody", {}) },
|
||||||
|
{
|
||||||
|
headers,
|
||||||
|
timeout: 15000,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...resp.data,
|
||||||
|
timestamp: data.timestamp,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { get } from "lodash";
|
||||||
|
import { db } from "../../../db";
|
||||||
|
import axios from "axios";
|
||||||
|
import { formatTimestamp } from "../../formatTimestamp";
|
||||||
|
import generateSignatureService from "./generateSignatureService";
|
||||||
|
import { getParameter } from "../../getParameter";
|
||||||
|
export default async function ({ data }: { data: any }) {
|
||||||
|
const endpointurl = "/api/v1.0/transfer-va/status";
|
||||||
|
const user = await db.users.findFirst({
|
||||||
|
where: {
|
||||||
|
clientbank_id: data.clientbank_id,
|
||||||
|
},
|
||||||
|
include: { banks: true, database: true, parameters: true },
|
||||||
|
});
|
||||||
|
if (!user) throw new Error("User not found");
|
||||||
|
const timestamp = formatTimestamp();
|
||||||
|
const signatureService = await generateSignatureService({
|
||||||
|
data: {
|
||||||
|
accessToken: data.accessToken,
|
||||||
|
timestamp,
|
||||||
|
isGenerateNewToken: true,
|
||||||
|
client_secret: getParameter(user, "client_secret") || "",
|
||||||
|
endpointurl,
|
||||||
|
body: get(data, "requestBody", {}),
|
||||||
|
},
|
||||||
|
user,
|
||||||
|
});
|
||||||
|
data.accessToken = signatureService.accessToken;
|
||||||
|
data.timestamp = signatureService.timestamp;
|
||||||
|
data.signature = signatureService.signature;
|
||||||
|
const clientId = data.clientbank_id;
|
||||||
|
const headers: Record<string, string> = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
"X-PARTNER-ID": clientId,
|
||||||
|
"X-TIMESTAMP": data.timestamp,
|
||||||
|
"X-SIGNATURE": data.signature,
|
||||||
|
Authorization: `Bearer ${data.accessToken}`,
|
||||||
|
"X-EXTERNAL-ID": data.external_id,
|
||||||
|
"CHANNEL-ID": data.channel_id,
|
||||||
|
};
|
||||||
|
const mandiriUrl = String(get(user, "endpoint") || process.env.PAYMENT_URL);
|
||||||
|
|
||||||
|
const resp = await axios.post(
|
||||||
|
mandiriUrl + endpointurl,
|
||||||
|
{ ...get(data, "requestBody", {}) },
|
||||||
|
{
|
||||||
|
headers,
|
||||||
|
timeout: 15000,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...resp.data,
|
||||||
|
timestamp: data.timestamp,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -12,7 +12,9 @@ export default async function ({ data }: { data: any }) {
|
||||||
});
|
});
|
||||||
if (!user) throw new Error("User not found");
|
if (!user) throw new Error("User not found");
|
||||||
const clientId = data.clientbank_id;
|
const clientId = data.clientbank_id;
|
||||||
const timestamp = formatTimestamp();
|
const timestamp = get(data, "isNewTimestamp", true)
|
||||||
|
? formatTimestamp()
|
||||||
|
: get(data, "timestamp", formatTimestamp());
|
||||||
const headers: Record<string, any> = {
|
const headers: Record<string, any> = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
|
|
@ -21,10 +23,7 @@ export default async function ({ data }: { data: any }) {
|
||||||
Private_Key: getParameter(user, "private_key") || "",
|
Private_Key: getParameter(user, "private_key") || "",
|
||||||
};
|
};
|
||||||
const mandiriUrl = String(get(user, "endpoint") || process.env.PAYMENT_URL);
|
const mandiriUrl = String(get(user, "endpoint") || process.env.PAYMENT_URL);
|
||||||
console.log({
|
|
||||||
headers,
|
|
||||||
url: `${mandiriUrl}/api/v1.0/utilities/signature-auth`,
|
|
||||||
});
|
|
||||||
const resp = await axios.post(
|
const resp = await axios.post(
|
||||||
`${mandiriUrl}/api/v1.0/utilities/signature-auth`,
|
`${mandiriUrl}/api/v1.0/utilities/signature-auth`,
|
||||||
{},
|
{},
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,13 @@ export default async function ({
|
||||||
const isGenerateNewToken = get(data, "isGenerateNewToken", false);
|
const isGenerateNewToken = get(data, "isGenerateNewToken", false);
|
||||||
let timestamp = data.timestamp;
|
let timestamp = data.timestamp;
|
||||||
let accessToken = data.accessToken;
|
let accessToken = data.accessToken;
|
||||||
|
let isNewTimestamp = get(data, "isNewTimestamp", true);
|
||||||
if (isGenerateNewToken) {
|
if (isGenerateNewToken) {
|
||||||
const signatureAuth = await generateSignatureAuth({
|
const signatureAuth = await generateSignatureAuth({
|
||||||
data: {
|
data: {
|
||||||
clientbank_id: user.clientbank_id,
|
clientbank_id: user.clientbank_id,
|
||||||
|
timestamp: timestamp,
|
||||||
|
isNewTimestamp,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
timestamp = signatureAuth.timestamp;
|
timestamp = signatureAuth.timestamp;
|
||||||
|
|
@ -40,11 +43,6 @@ export default async function ({
|
||||||
AccessToken: accessToken,
|
AccessToken: accessToken,
|
||||||
};
|
};
|
||||||
const mandiriUrl = String(get(user, "endpoint") || process.env.PAYMENT_URL);
|
const mandiriUrl = String(get(user, "endpoint") || process.env.PAYMENT_URL);
|
||||||
console.log({
|
|
||||||
url: `${mandiriUrl}/api/v1.0/utilities/signature-service`,
|
|
||||||
headers,
|
|
||||||
body: { ...get(data, "body", {}) },
|
|
||||||
});
|
|
||||||
const resp = await axios.post(
|
const resp = await axios.post(
|
||||||
`${mandiriUrl}/api/v1.0/utilities/signature-service`,
|
`${mandiriUrl}/api/v1.0/utilities/signature-service`,
|
||||||
{ ...get(data, "body", {}) },
|
{ ...get(data, "body", {}) },
|
||||||
|
|
@ -53,5 +51,5 @@ export default async function ({
|
||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return { ...resp.data, timestamp, accessToken };
|
return { ...resp.data, timestamp, accessToken, headers };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ export default async function ({
|
||||||
session: any;
|
session: any;
|
||||||
data: any;
|
data: any;
|
||||||
}) {
|
}) {
|
||||||
console.log(user);
|
|
||||||
// sample implementation — adapt to real bank payload and API calls
|
// sample implementation — adapt to real bank payload and API calls
|
||||||
const { invoiceId } = data || {};
|
const { invoiceId } = data || {};
|
||||||
if (!user.database) throw new Error("User database information is missing");
|
if (!user.database) throw new Error("User database information is missing");
|
||||||
|
|
@ -30,6 +29,7 @@ export default async function ({
|
||||||
virtualAccountNo: invoiceId,
|
virtualAccountNo: invoiceId,
|
||||||
dbName: get(user, "database.name", ""),
|
dbName: get(user, "database.name", ""),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!c_bpartner) {
|
if (!c_bpartner) {
|
||||||
throw new Error("C_BPartner_ID not found for the given Virtual Account No");
|
throw new Error("C_BPartner_ID not found for the given Virtual Account No");
|
||||||
}
|
}
|
||||||
|
|
@ -43,6 +43,16 @@ export default async function ({
|
||||||
is_pay: "N",
|
is_pay: "N",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
// console.log({
|
||||||
|
// _sum: {
|
||||||
|
// grandtotal: true,
|
||||||
|
// },
|
||||||
|
// where: {
|
||||||
|
// c_bpartner_id: c_bpartner.c_bpartner_id,
|
||||||
|
// db_id: user.database.db_id,
|
||||||
|
// is_pay: "N",
|
||||||
|
// },
|
||||||
|
// });
|
||||||
if (lo.get(grandtotal, "_sum.grandtotal") === null) {
|
if (lo.get(grandtotal, "_sum.grandtotal") === null) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"No outstanding amount found for the given Virtual Account No"
|
"No outstanding amount found for the given Virtual Account No"
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,7 @@ export default async function ({
|
||||||
.replace("{accesstoken}", get(data, "accesstoken"))
|
.replace("{accesstoken}", get(data, "accesstoken"))
|
||||||
.replace("{requestbody}", hashBody)
|
.replace("{requestbody}", hashBody)
|
||||||
.replace("{timestamp}", get(data, "timestamp"));
|
.replace("{timestamp}", get(data, "timestamp"));
|
||||||
console.log(stringToSign);
|
|
||||||
const pathPublicKey = user.public_key_file;
|
const pathPublicKey = user.public_key_file;
|
||||||
console.log(user);
|
|
||||||
if (!pathPublicKey) {
|
if (!pathPublicKey) {
|
||||||
throw new Error("No public key file associated with the user");
|
throw new Error("No public key file associated with the user");
|
||||||
}
|
}
|
||||||
|
|
@ -63,11 +61,7 @@ export default async function ({
|
||||||
throw new Error("Public key file not found");
|
throw new Error("Public key file not found");
|
||||||
}
|
}
|
||||||
const cerPem = readCertAsPEM(fullPath);
|
const cerPem = readCertAsPEM(fullPath);
|
||||||
console.log({
|
|
||||||
stringToVerify: stringToSign,
|
|
||||||
signatureBase64: get(data, "signature"),
|
|
||||||
certPem: cerPem,
|
|
||||||
});
|
|
||||||
const result = verifyRsaSignature({
|
const result = verifyRsaSignature({
|
||||||
stringToVerify: stringToSign,
|
stringToVerify: stringToSign,
|
||||||
signatureBase64: get(data, "signature"),
|
signatureBase64: get(data, "signature"),
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response, NextFunction } from "express";
|
||||||
import { authMiddleware, hashToken } from "./auth";
|
|
||||||
import { db } from "../db";
|
import { db } from "../db";
|
||||||
import callGateFromReq from "../lib/gateClient";
|
|
||||||
import { get } from "lodash";
|
import { get } from "lodash";
|
||||||
|
import generateSignatureService from "../lib/bank/mandiri/generateSignatureService";
|
||||||
|
import { getParameter } from "../lib/getParameter";
|
||||||
|
|
||||||
export async function vaMiddleware(
|
export async function vaMiddleware(
|
||||||
req: Request,
|
req: Request,
|
||||||
|
|
@ -20,85 +20,53 @@ export async function vaMiddleware(
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return res.status(401).json({ error: "missing token" });
|
return res.status(401).json({ error: "missing token" });
|
||||||
}
|
}
|
||||||
const session = await db.sessions.findFirst({
|
const data = req.body || {};
|
||||||
where: { token_hash: hashToken(token), is_revoked: false },
|
if (!get(data, "partnerServiceId")) {
|
||||||
include: { users: true },
|
return res.status(400).json({
|
||||||
|
responseCode: "2002400",
|
||||||
|
responseMessage: `Invalid Mandatory Field partnerServiceId`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const parameters = await db.parameters.findFirst({
|
||||||
|
where: {
|
||||||
|
param_key: "partnerServiceId",
|
||||||
|
param_value: get(data, "partnerServiceId"),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
if (!session) {
|
if (!parameters) {
|
||||||
return res.status(401).json({ error: "invalid token" });
|
return res.status(404).json({
|
||||||
}
|
responseCode: "4042412",
|
||||||
if (!timestamp || !signature) {
|
responseMessage: `Invalid partnerServiceId`,
|
||||||
return res.status(400).json({ error: "missing required headers" });
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const result = await callGateFromReq(req, {
|
|
||||||
client: "mandiri",
|
|
||||||
action: "verifySignature",
|
|
||||||
data: {
|
|
||||||
timestamp,
|
|
||||||
signature,
|
|
||||||
httpmethod: req.method === "POST" ? "POST" : "GET",
|
|
||||||
endpointurl: req.originalUrl,
|
|
||||||
accesstoken: token,
|
|
||||||
requestbody: req.body,
|
|
||||||
typeVerify: "transaction",
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
console.log({ result });
|
|
||||||
if (!result) {
|
|
||||||
return res.status(401).json({
|
|
||||||
responseCode: "4012400",
|
|
||||||
responseMessage: `Unauthorized`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
const message: any = get(err, "message", "internal_error");
|
|
||||||
if (
|
|
||||||
message === "Invalid access token" ||
|
|
||||||
message === "Access token expired"
|
|
||||||
) {
|
|
||||||
return res.status(401).json({
|
|
||||||
responseCode: "4012400",
|
|
||||||
responseMessage: `Unauthorized ${message}`,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error("vaMiddleware error", err);
|
|
||||||
return res.status(500).json({
|
|
||||||
responseCode: "5002401",
|
|
||||||
responseMessage: `Internal Server Error ${message}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Prefer RSA verification if the user record contains a public cert
|
const users = await db.users.findFirst({
|
||||||
const user = session.users;
|
where: { user_id: parameters.user_id },
|
||||||
// some projects store certs in different user columns; access via any to avoid TS errors
|
include: { database: true, banks: true, parameters: true, tenants: true },
|
||||||
const uAny = user as any;
|
});
|
||||||
const certPem = (uAny &&
|
const signatureService = await generateSignatureService({
|
||||||
(uAny.public_cert ||
|
data: {
|
||||||
uAny.cert_pem ||
|
accessToken: token,
|
||||||
uAny.certificate ||
|
timestamp: timestamp,
|
||||||
uAny.publicCert)) as string | undefined;
|
isNewTimestamp: false,
|
||||||
const clientId = (uAny &&
|
isGenerateNewToken: false,
|
||||||
(uAny.client_id ||
|
client_secret: getParameter(users, "client_secret") || "",
|
||||||
uAny.clientbank_id ||
|
endpointurl: req.originalUrl,
|
||||||
uAny.clientKey ||
|
body: data,
|
||||||
uAny.clientkey)) as string | undefined;
|
},
|
||||||
|
user: users as any,
|
||||||
let ok = false;
|
});
|
||||||
|
const signatureServiceResult = signatureService.signature;
|
||||||
if (authHeader) {
|
if (signatureServiceResult !== signature) {
|
||||||
const token = authHeader.slice("Bearer ".length).trim();
|
return res.status(401).json({
|
||||||
const tokenHash = hashToken(token);
|
responseCode: "4012400",
|
||||||
const session = await db.sessions.findFirst({
|
responseMessage: `Unauthorized. Invalid signature`,
|
||||||
where: { token_hash: tokenHash, is_revoked: false },
|
|
||||||
});
|
});
|
||||||
// If we have an auth header, we're good
|
|
||||||
return authMiddleware(req as any, res, next as any);
|
|
||||||
} else {
|
|
||||||
return res.status(401).json({ error: "missing token" });
|
|
||||||
}
|
}
|
||||||
|
next();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("vaMiddleware error", err);
|
console.error("vaMiddleware error", err);
|
||||||
return res.status(500).json({ error: "internal_error" });
|
return res
|
||||||
|
.status(500)
|
||||||
|
.json({ error: "internal_error", message: get(err, "message") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,10 @@ export const setRoutes = () => {
|
||||||
router.post("/generate-signature", (req, res) =>
|
router.post("/generate-signature", (req, res) =>
|
||||||
signController.generateSignature(req, res)
|
signController.generateSignature(req, res)
|
||||||
);
|
);
|
||||||
|
// Signature generation for testing (uses PRIVATE_KEY_PATH file)
|
||||||
|
router.post("/generate-signature-bank", (req, res) =>
|
||||||
|
signController.generateSignature(req, res)
|
||||||
|
);
|
||||||
// Verify signature using public cert (default: public/mandiri/midsuit.cer)
|
// Verify signature using public cert (default: public/mandiri/midsuit.cer)
|
||||||
router.post("/verify-signature", (req, res) =>
|
router.post("/verify-signature", (req, res) =>
|
||||||
signController.verifySignature(req, res)
|
signController.verifySignature(req, res)
|
||||||
|
|
@ -110,6 +114,9 @@ export const setRoutes = () => {
|
||||||
versionRouter.post("/access-token/b2b", (req, res) =>
|
versionRouter.post("/access-token/b2b", (req, res) =>
|
||||||
tokenController.b2bAccessToken(req, res)
|
tokenController.b2bAccessToken(req, res)
|
||||||
);
|
);
|
||||||
|
versionRouter.post("/utilities/signature-service", (req, res) =>
|
||||||
|
tokenController.signatureBank(req, res)
|
||||||
|
);
|
||||||
router.use("/:version", versionRouter);
|
router.use("/:version", versionRouter);
|
||||||
|
|
||||||
// Sync endpoints group
|
// Sync endpoints group
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue