/** * 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 { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager"; const secrets = new SecretsManagerClient(); const BASE_URL = "https://api.bofa.com"; async function getSecretJson(secretId) { const { SecretString } = await secrets.send( new GetSecretValueCommand({ SecretId: secretId }) ); return JSON.parse(SecretString); } 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 Secrets Manager...\n"); const checkMgmt = await getSecretJson("payments-dashboard/boa-check-mgmt"); const reporting = await getSecretJson("payments-dashboard/boa-reporting"); const checkMgmtAppId = checkMgmt.appId; const checkMgmtClientId = checkMgmt.clientId; const checkMgmtSecret = checkMgmt.token; const reportingAppId = reporting.appId; const reportingClientId = reporting.clientId; const reportingSecret = reporting.token; const accountNumber = reporting.accountNumber; const bankId = reporting.bankId; 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); });