Skip to content

Commit a2d2537

Browse files
committed
Debugging payment gateway bug
1 parent ef8482e commit a2d2537

File tree

5 files changed

+39
-14
lines changed

5 files changed

+39
-14
lines changed

src/modules/giving/controllers/CustomerController.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export class CustomerController extends GivingCrudController {
2323
@httpGet("/:id/subscriptions")
2424
public async getSubscriptions(@requestParam("id") id: string, req: express.Request<{}, {}, null>, res: express.Response): Promise<any> {
2525
return this.actionWrapper(req, res, async (au) => {
26-
const gateway = await GatewayService.getGatewayForChurch(au.churchId, {}, this.repos.gateway).catch(() => null);
26+
// Subscriptions are Stripe-only currently
27+
const gateway = await GatewayService.getGatewayForChurch(au.churchId, { provider: "stripe" }, this.repos.gateway).catch(() => null);
2728
let permission = false;
2829
if (gateway) {
2930
if (au.checkAccess(Permissions.donations.viewSummary)) {

src/modules/giving/controllers/PaymentMethodController.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ export class PaymentMethodController extends GivingCrudController {
113113
@httpGet("/personid/:id")
114114
public async getPersonPaymentMethods(@requestParam("id") id: string, req: express.Request<{}, {}, null>, res: express.Response): Promise<any> {
115115
return this.actionWrapper(req, res, async (au) => {
116-
const gateway = await GatewayService.getGatewayForChurch(au.churchId, {}, this.repos.gateway).catch(() => null);
116+
// Default to Stripe for payment method operations (vault requires Stripe or PayPal)
117+
const gateway = await GatewayService.getGatewayForChurch(au.churchId, { provider: "stripe" }, this.repos.gateway).catch(() => null);
117118
const permission = gateway && (au.checkAccess(Permissions.donations.view) || id === au.personId);
118119
if (!permission) return this.json({}, 401);
119120

@@ -228,9 +229,10 @@ export class PaymentMethodController extends GivingCrudController {
228229
@httpPost("/addcard")
229230
public async addCard(req: express.Request<any>, res: express.Response): Promise<any> {
230231
return this.actionWrapper(req, res, async (au) => {
231-
const { id, personId, customerId, email, name, churchId } = req.body;
232+
const { id, personId, customerId, email, name, churchId, provider } = req.body;
232233
const cId = au?.churchId || churchId;
233-
const gateway = await GatewayService.getGatewayForChurch(cId, {}, this.repos.gateway).catch(() => null);
234+
// Default to Stripe for card operations, but allow frontend to specify provider
235+
const gateway = await GatewayService.getGatewayForChurch(cId, { provider: provider || "stripe" }, this.repos.gateway).catch(() => null);
234236

235237
if (!gateway) {
236238
return this.json({ error: "Payment gateway not configured" }, 400);
@@ -328,8 +330,8 @@ export class PaymentMethodController extends GivingCrudController {
328330
@httpPost("/updatecard")
329331
public async updateCard(req: express.Request<any>, res: express.Response): Promise<any> {
330332
return this.actionWrapper(req, res, async (au) => {
331-
const { personId, paymentMethodId, cardData } = req.body;
332-
const gateway = await GatewayService.getGatewayForChurch(au.churchId, {}, this.repos.gateway).catch(() => null);
333+
const { personId, paymentMethodId, cardData, provider } = req.body;
334+
const gateway = await GatewayService.getGatewayForChurch(au.churchId, { provider: provider || "stripe" }, this.repos.gateway).catch(() => null);
333335
const permission = gateway && (au.checkAccess(Permissions.donations.edit) || personId === au.personId);
334336
if (!permission) return this.json({ error: "Insufficient permissions" }, 401);
335337
try {
@@ -356,7 +358,8 @@ export class PaymentMethodController extends GivingCrudController {
356358
return this.actionWrapper(req, res, async (au) => {
357359
const { personId, customerId, email, name, churchId } = req.body;
358360
const cId = au?.churchId || churchId;
359-
const gateway = await GatewayService.getGatewayForChurch(cId, {}, this.repos.gateway).catch(() => null);
361+
// ACH SetupIntent is Stripe-only
362+
const gateway = await GatewayService.getGatewayForChurch(cId, { provider: "stripe" }, this.repos.gateway).catch(() => null);
360363

361364
if (!gateway) {
362365
return this.json({ error: "Payment gateway not configured" }, 400);
@@ -472,7 +475,8 @@ export class PaymentMethodController extends GivingCrudController {
472475
public async addBankAccount(req: express.Request<any>, res: express.Response): Promise<any> {
473476
return this.actionWrapper(req, res, async (au) => {
474477
const { id, personId, customerId, email, name } = req.body;
475-
const gateway = await GatewayService.getGatewayForChurch(au.churchId, {}, this.repos.gateway).catch(() => null);
478+
// Bank accounts are Stripe-only
479+
const gateway = await GatewayService.getGatewayForChurch(au.churchId, { provider: "stripe" }, this.repos.gateway).catch(() => null);
476480
const permission = gateway && (au.checkAccess(Permissions.donations.edit) || personId === au.personId);
477481
if (!permission) return this.json({ error: "Insufficient permissions" }, 401);
478482

@@ -516,7 +520,8 @@ export class PaymentMethodController extends GivingCrudController {
516520
public async updateBank(req: express.Request<any>, res: express.Response): Promise<any> {
517521
return this.actionWrapper(req, res, async (au) => {
518522
const { paymentMethodId, personId, bankData, customerId } = req.body;
519-
const gateway = await GatewayService.getGatewayForChurch(au.churchId, {}, this.repos.gateway).catch(() => null);
523+
// Bank operations are Stripe-only
524+
const gateway = await GatewayService.getGatewayForChurch(au.churchId, { provider: "stripe" }, this.repos.gateway).catch(() => null);
520525
const permission = gateway && (au.checkAccess(Permissions.donations.edit) || personId === au.personId);
521526
if (!permission) return this.json({}, 401);
522527
try {
@@ -531,7 +536,8 @@ export class PaymentMethodController extends GivingCrudController {
531536
public async verifyBank(req: express.Request<any>, res: express.Response): Promise<any> {
532537
return this.actionWrapper(req, res, async (au) => {
533538
const { paymentMethodId, customerId, amountData } = req.body;
534-
const gateway = await GatewayService.getGatewayForChurch(au.churchId, {}, this.repos.gateway).catch(() => null);
539+
// Bank verification is Stripe-only
540+
const gateway = await GatewayService.getGatewayForChurch(au.churchId, { provider: "stripe" }, this.repos.gateway).catch(() => null);
535541
const permission =
536542
gateway &&
537543
(au.checkAccess(Permissions.donations.edit) || (await this.repos.customer.convertToModel(au.churchId, await this.repos.customer.load(au.churchId, customerId)).personId) === au.personId);
@@ -549,7 +555,9 @@ export class PaymentMethodController extends GivingCrudController {
549555
@httpDelete("/:id/:customerid")
550556
public async deletePaymentMethod(@requestParam("id") id: string, @requestParam("customerid") customerId: string, req: express.Request<{}, {}, null>, res: express.Response): Promise<any> {
551557
return this.actionWrapper(req, res, async (au) => {
552-
const gateway = await GatewayService.getGatewayForChurch(au.churchId, {}, this.repos.gateway).catch(() => null);
558+
// Determine provider from payment method ID prefix (pm_ and ba_ are Stripe)
559+
const isStripe = id.startsWith("pm_") || id.startsWith("ba_");
560+
const gateway = await GatewayService.getGatewayForChurch(au.churchId, { provider: isStripe ? "stripe" : "paypal" }, this.repos.gateway).catch(() => null);
553561
const permission =
554562
gateway &&
555563
(au.checkAccess(Permissions.donations.edit) || (await this.repos.customer.convertToModel(au.churchId, await this.repos.customer.load(au.churchId, customerId)).personId) === au.personId);

src/modules/giving/controllers/SubscriptionController.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ export class SubscriptionController extends GivingCrudController {
3232
public async save(req: express.Request<{}, {}, any[]>, res: express.Response): Promise<any> {
3333
return this.actionWrapper(req, res, async (au) => {
3434
const promises: Promise<any>[] = [];
35-
const gateway = await GatewayService.getGatewayForChurch(au.churchId, {}, this.repos.gateway).catch(() => null);
35+
// Subscriptions are Stripe-only currently
36+
const gateway = await GatewayService.getGatewayForChurch(au.churchId, { provider: "stripe" }, this.repos.gateway).catch(() => null);
3637

3738
if (!gateway) return this.json({ error: "No gateway configured" }, 400);
3839

@@ -62,7 +63,8 @@ export class SubscriptionController extends GivingCrudController {
6263
const permission = au.checkAccess(Permissions.donations.edit) || (subscription as any)?.personId === au.personId;
6364
if (!permission) return this.json(null, 401);
6465

65-
const gateway = await GatewayService.getGatewayForChurch(au.churchId, {}, this.repos.gateway).catch(() => null);
66+
// Subscriptions are Stripe-only currently
67+
const gateway = await GatewayService.getGatewayForChurch(au.churchId, { provider: "stripe" }, this.repos.gateway).catch(() => null);
6668
if (!gateway) return this.json({ error: "No gateway configured" }, 400);
6769

6870
const capabilities = GatewayService.getProviderCapabilities(gateway);

src/shared/helpers/GatewayService.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,22 @@ export class GatewayService {
4646
}
4747
};
4848

49+
const privateKey = decryptIfPresent(gateway.privateKey);
50+
51+
if (!privateKey && gateway.provider?.toLowerCase() === "stripe") {
52+
console.error("Gateway privateKey is missing or failed to decrypt", {
53+
provider: gateway.provider,
54+
gatewayId: gateway.id,
55+
churchId: gateway.churchId,
56+
hasPrivateKey: !!gateway.privateKey
57+
});
58+
}
59+
4960
return {
5061
gatewayId: gateway.id,
5162
churchId: gateway.churchId,
5263
publicKey: gateway.publicKey,
53-
privateKey: decryptIfPresent(gateway.privateKey),
64+
privateKey,
5465
webhookKey: decryptIfPresent(gateway.webhookKey),
5566
productId: gateway.productId,
5667
settings: gateway.settings ?? null,

src/shared/helpers/StripeHelper.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,9 @@ export class StripeHelper {
379379
}
380380

381381
private static getStripeObj = (secretKey: string) => {
382+
if (!secretKey) {
383+
throw new Error("Stripe API key is not configured. Please check your gateway settings.");
384+
}
382385
return new Stripe(secretKey, { apiVersion: "2025-02-24.acacia" });
383386
};
384387
}

0 commit comments

Comments
 (0)