payments-dashboard/scripts/test-boa-prod.js

131 lines
3.9 KiB
JavaScript
Raw Normal View History

/**
* Dry-run test for BoA CashPro production API connectivity.
* 1. Authenticates with both Check Management and Reporting credentials
* 2. Calls Previous Day Transaction Inquiry (read-only)
* 3. Does NOT issue or cancel any checks
*
* Usage:
* node scripts/test-boa-prod.js
*/
import { SSMClient, GetParameterCommand } from "@aws-sdk/client-ssm";
const ssm = new SSMClient();
const BASE_URL = "https://api.bofa.com";
async function getSSMParam(name) {
const { Parameter } = await ssm.send(
new GetParameterCommand({ Name: name, WithDecryption: true })
);
return Parameter.Value;
}
async function getAccessToken(applicationID, clientId, clientSecret) {
console.log(` Requesting token for ${applicationID}...`);
const res = await fetch(`${BASE_URL}/authn/v1/client-authentication`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
applicationID,
authn: { client_id: clientId, client_secret: clientSecret },
}),
});
const text = await res.text();
console.log(` Auth response (${res.status}):`, text, "\n");
if (!res.ok) {
throw new Error(`Auth failed for ${applicationID}: ${res.status} - ${text}`);
}
const data = JSON.parse(text);
return data.access_token;
}
async function main() {
console.log("Loading credentials from SSM...\n");
const [
checkMgmtAppId,
checkMgmtClientId,
checkMgmtSecret,
reportingAppId,
reportingClientId,
reportingSecret,
accountNumber,
bankId,
] = await Promise.all([
getSSMParam("/payments-dashboard/boa-check-mgmt-app-id"),
getSSMParam("/payments-dashboard/boa-check-mgmt-client-id"),
getSSMParam("/payments-dashboard/boa-check-mgmt-token"),
getSSMParam("/payments-dashboard/boa-reporting-app-id"),
getSSMParam("/payments-dashboard/boa-account-info-client-id"),
getSSMParam("/payments-dashboard/boa-account-info-token"),
getSSMParam("/payments-dashboard/boa-account-number"),
getSSMParam("/payments-dashboard/boa-bank-id"),
]);
console.log("Credentials loaded.\n");
// --- Step 1: OAuth for Check Management ---
console.log("=".repeat(60));
console.log("STEP 1: OAuth — Check Management");
console.log("=".repeat(60));
console.log();
const checkMgmtToken = await getAccessToken(checkMgmtAppId, checkMgmtClientId, checkMgmtSecret);
console.log(" ✓ Check Management token acquired\n");
// --- Step 2: OAuth for Reporting ---
console.log("=".repeat(60));
console.log("STEP 2: OAuth — Reporting");
console.log("=".repeat(60));
console.log();
const reportingToken = await getAccessToken(reportingAppId, reportingClientId, reportingSecret);
console.log(" ✓ Reporting token acquired\n");
// --- Step 3: Previous Day Transaction Inquiry (read-only) ---
console.log("=".repeat(60));
console.log("STEP 3: Previous Day Transaction Inquiry (read-only)");
console.log("=".repeat(60));
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
const dateStr = yesterday.toISOString().split("T")[0];
const inquiryPayload = {
fromDate: dateStr,
toDate: dateStr,
accounts: [{ accountNumber, bankId }],
};
console.log("Request:", JSON.stringify(inquiryPayload, null, 2), "\n");
const inquiryRes = await fetch(
`${BASE_URL}/cashpro/reporting/v1/transaction-inquiries/previous-day`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${reportingToken}`,
},
body: JSON.stringify(inquiryPayload),
}
);
const inquiryText = await inquiryRes.text();
console.log("Status:", inquiryRes.status);
console.log("Response:", inquiryText);
console.log("\n" + "=".repeat(60));
console.log("Dry run complete. No checks were issued or cancelled.");
console.log("=".repeat(60));
}
main().catch((err) => {
console.error("Fatal error:", err);
process.exit(1);
});