mirror of
https://github.com/Sea-Haven-Industries/payments-dashboard.git
synced 2026-09-30 14:43:11 +00:00
API tokens and credentials must live in Secrets Manager per secrets-and-config.md, but the four original payment Lambdas still read 10 SecureString SSM params. Move them to three grouped secrets (slack-bot-token plaintext, boa-check-mgmt and boa-reporting as JSON), matching the pattern the expense Lambdas already use. IAM is scoped to secretsmanager:GetSecretValue per secret; the VPC Lambdas reach the public endpoint over the existing NAT path. Test/reissue scripts and the client-ssm dependency are updated/removed accordingly. Refs: #3
186 lines
5.4 KiB
JavaScript
186 lines
5.4 KiB
JavaScript
/**
|
|
* One-off script to test BoA CashPro sandbox API connectivity.
|
|
* Reads credentials from SSM Parameter Store, exchanges them for
|
|
* OAuth Bearer tokens, then makes test API calls to both Check
|
|
* Management and Reporting APIs.
|
|
*
|
|
* Prints full responses so you can capture the client ID, timestamp,
|
|
* and transactionIdentification for BoA production onboarding.
|
|
*
|
|
* Usage:
|
|
* node scripts/test-boa-sandbox.js
|
|
*/
|
|
|
|
import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager";
|
|
|
|
const secrets = new SecretsManagerClient();
|
|
const SANDBOX_BASE = "https://api-sb.bofa.com";
|
|
const AUTH_URL = `${SANDBOX_BASE}/authn/v1/client-authentication`;
|
|
|
|
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(AUTH_URL, {
|
|
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 checkMgmtClientId = checkMgmt.clientId;
|
|
const checkMgmtSecret = checkMgmt.token;
|
|
const accountInfoClientId = reporting.clientId;
|
|
const accountInfoSecret = reporting.token;
|
|
const accountNumber = checkMgmt.accountNumber;
|
|
const companyId = checkMgmt.companyId;
|
|
|
|
console.log("Credentials loaded.\n");
|
|
|
|
// --- Step 1: Get OAuth tokens for both APIs ---
|
|
console.log("=".repeat(60));
|
|
console.log("STEP 1: OAuth Token Exchange");
|
|
console.log("=".repeat(60));
|
|
|
|
console.log("\n[Check Management]");
|
|
const checkMgmtBearerToken = await getAccessToken(
|
|
"app_SeaHavenIndustries_Checkmanagement_SB",
|
|
checkMgmtClientId,
|
|
checkMgmtSecret
|
|
);
|
|
|
|
console.log("[Account Info / Reporting]");
|
|
const accountInfoBearerToken = await getAccessToken(
|
|
"app_SeaHavenIndustries_Reporting_SB",
|
|
accountInfoClientId,
|
|
accountInfoSecret
|
|
);
|
|
|
|
console.log("Both tokens acquired.\n");
|
|
|
|
// --- Step 2: Check Issue (add_Issue with a test check) ---
|
|
console.log("=".repeat(60));
|
|
console.log("TEST 1: Check Issue (add_Issue)");
|
|
console.log("=".repeat(60));
|
|
|
|
const issuePayload = {
|
|
issueList: [
|
|
{
|
|
accountNumber,
|
|
issueAction: "add_Issue",
|
|
checkNumber: "999999",
|
|
amount: "1.00",
|
|
issueDate: new Date().toISOString().split("T")[0],
|
|
payee: "Sandbox Test",
|
|
},
|
|
],
|
|
};
|
|
|
|
console.log("Request:", JSON.stringify(issuePayload, null, 2), "\n");
|
|
|
|
try {
|
|
const issueRes = await fetch(
|
|
`${SANDBOX_BASE}/cashpro/checkmanagement/v1/check-issues`,
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Authorization: `Bearer ${checkMgmtBearerToken}`,
|
|
companyId,
|
|
},
|
|
body: JSON.stringify(issuePayload),
|
|
}
|
|
);
|
|
|
|
const issueHeaders = Object.fromEntries(issueRes.headers.entries());
|
|
const issueText = await issueRes.text();
|
|
|
|
console.log("Status:", issueRes.status);
|
|
console.log("Response Headers:", JSON.stringify(issueHeaders, null, 2));
|
|
console.log("Response Body:", issueText);
|
|
} catch (err) {
|
|
console.error("Check Issue request failed:", err.message);
|
|
}
|
|
|
|
// --- Step 3: Previous Day Transaction Inquiry ---
|
|
console.log("\n" + "=".repeat(60));
|
|
console.log("TEST 2: Previous Day Transaction Inquiry");
|
|
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: "021000322",
|
|
},
|
|
],
|
|
};
|
|
|
|
console.log("Request:", JSON.stringify(inquiryPayload, null, 2), "\n");
|
|
|
|
try {
|
|
const inquiryRes = await fetch(
|
|
`${SANDBOX_BASE}/cashpro/reporting/v1/transaction-inquiries/previous-day`,
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Authorization: `Bearer ${accountInfoBearerToken}`,
|
|
},
|
|
body: JSON.stringify(inquiryPayload),
|
|
}
|
|
);
|
|
|
|
const inquiryHeaders = Object.fromEntries(inquiryRes.headers.entries());
|
|
const inquiryText = await inquiryRes.text();
|
|
|
|
console.log("Status:", inquiryRes.status);
|
|
console.log("Response Headers:", JSON.stringify(inquiryHeaders, null, 2));
|
|
console.log("Response Body:", inquiryText);
|
|
} catch (err) {
|
|
console.error("Transaction Inquiry request failed:", err.message);
|
|
}
|
|
|
|
console.log("\n" + "=".repeat(60));
|
|
console.log("Done. Look for: client ID, timestamp, transactionIdentification");
|
|
console.log("=".repeat(60));
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error("Fatal error:", err);
|
|
process.exit(1);
|
|
});
|