Z User commited on
Commit
351fd2b
·
1 Parent(s): cb3d98c

fix: remove duplicate searchGmailForPayment function (syntax error)

Browse files
Files changed (1) hide show
  1. supabase/functions/payment/index.ts +0 -119
supabase/functions/payment/index.ts CHANGED
@@ -461,125 +461,6 @@ async function markEmailAsRead(msgId: string): Promise<void> {
461
  await logoutImap(conn, encoder, decoder, tag);
462
  }
463
 
464
- // No match found within 10 minutes — mark as expired
465
- await updateOrderStatus(orderId, 'expired', null);
466
- console.log(`⏰ Order ${orderId} expired — no matching payment found`);
467
- }
468
-
469
- // ---------------------------------------------------------------------------
470
- // Gmail IMAP search — connects to Gmail, searches for PalmPay emails
471
- // ---------------------------------------------------------------------------
472
- async function searchGmailForPayment(expectedAmount: number): Promise<{ messageId: string; senderName: string; amount: number } | null> {
473
- // Connect to Gmail IMAP using Deno's TCP socket + TLS
474
- // We use a raw IMAP implementation since Deno doesn't have a built-in IMAP library
475
-
476
- const IMAP_HOST = 'imap.gmail.com';
477
- const IMAP_PORT = 993;
478
-
479
- // Connect via TLS
480
- const conn = await Deno.connectTls({ hostname: IMAP_HOST, port: IMAP_PORT });
481
- const decoder = new TextDecoder();
482
- const encoder = new TextEncoder();
483
-
484
- // Read until we see the server greeting
485
- await readUntil(conn, decoder, '\r\n');
486
-
487
- // Login
488
- const tag = `A${Date.now()}`;
489
- await writeLine(conn, encoder, `${tag} LOGIN ${GMAIL_EMAIL} ${GMAIL_APP_PASSWORD}\r\n`);
490
- const loginResp = await readUntil(conn, decoder, `${tag} OK`);
491
- if (loginResp.includes('BAD') || loginResp.includes('NO')) {
492
- conn.close();
493
- throw new Error('Gmail login failed');
494
- }
495
-
496
- // Select the "PalmPay" label/folder (or INBOX if no label)
497
- const folderTag = `${tag}1`;
498
- await writeLine(conn, encoder, `${folderTag} SELECT INBOX\r\n`);
499
- await readUntil(conn, decoder, `${folderTag} OK`);
500
-
501
- // Search for unread emails from PalmPay (last 24 hours)
502
- const searchTag = `${tag}2`;
503
- const sinceDate = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString().split('T')[0].replace(/-/g, '-');
504
- await writeLine(conn, encoder, `${searchTag} SEARCH UNSEEN FROM "palmpay" SINCE ${sinceDate}\r\n`);
505
- const searchResp = await readUntil(conn, decoder, `${searchTag} OK`);
506
-
507
- // Parse search results — format: * SEARCH 1 2 3 4
508
- const searchMatch = searchResp.match(/\* SEARCH (.+)/);
509
- if (!searchMatch) {
510
- // No unread PalmPay emails
511
- await logoutImap(conn, encoder, decoder, tag);
512
- return null;
513
- }
514
-
515
- const messageIds = searchMatch[1].trim().split(/\s+/);
516
-
517
- // Check each email for matching amount
518
- for (const msgId of messageIds) {
519
- const fetchTag = `${tag}3`;
520
- await writeLine(conn, encoder, `${fetchTag} FETCH ${msgId} (BODY.PEEK[HEADER.FIELDS (FROM SUBJECT)] BODY.PEEK[TEXT])\r\n`);
521
- const fetchResp = await readUntil(conn, decoder, `${fetchTag} OK`);
522
-
523
- // Parse the email for amount
524
- const amount = parseAmountFromEmail(fetchResp);
525
- const senderName = parseSenderFromEmail(fetchResp);
526
-
527
- if (amount !== null && Math.abs(amount - expectedAmount) < 0.01) {
528
- // Amount matches! Check that this email hasn't been used for another order
529
- const usedCheck = await fetch(
530
- `${SUPABASE_URL}/rest/v1/payment_orders?matched_email_id=not.is.null&select=matched_email_id`,
531
- { headers: adminHeaders }
532
- );
533
- const usedEmails = await usedCheck.json();
534
- const usedIds = new Set((usedEmails || []).map((o: Record<string, unknown>) => o.matched_email_id));
535
-
536
- // Generate a unique email ID (folder + message number)
537
- const emailUid = `INBOX:${msgId}`;
538
-
539
- if (!usedIds.has(emailUid)) {
540
- // Mark the email as read (SEEN)
541
- const seenTag = `${tag}4`;
542
- await writeLine(conn, encoder, `${seenTag} STORE ${msgId} +FLAGS (\Seen)\r\n`);
543
- await readUntil(conn, decoder, `${seenTag} OK`);
544
-
545
- await logoutImap(conn, encoder, decoder, tag);
546
- return { messageId: emailUid, senderName, amount };
547
- }
548
- }
549
- }
550
-
551
- await logoutImap(conn, encoder, decoder, tag);
552
- return null;
553
- }
554
-
555
- // Parse amount from PalmPay email body
556
- function parseAmountFromEmail(emailText: string): number | null {
557
- // PalmPay emails typically contain: "Amount: ₦5,000.23" or "You received ₦5,000.23"
558
- const patterns = [
559
- /Amount:\s*₦?\s*([\d,]+\.?\d*)/i,
560
- /received\s*₦?\s*([\d,]+\.?\d*)/i,
561
- /₦\s*([\d,]+\.?\d*)/i,
562
- /NGN\s*([\d,]+\.?\d*)/i,
563
- ];
564
-
565
- for (const pattern of patterns) {
566
- const match = emailText.match(pattern);
567
- if (match) {
568
- const amount = parseFloat(match[1].replace(/,/g, ''));
569
- if (!isNaN(amount) && amount > 0) return Math.round(amount * 100) / 100;
570
- }
571
- }
572
- return null;
573
- }
574
-
575
- // Parse sender name from email
576
- function parseSenderFromEmail(emailText: string): string {
577
- const fromMatch = emailText.match(/From:\s*(.+)/i);
578
- if (fromMatch) return fromMatch[1].trim().split('<')[0].trim().replace(/"/g, '');
579
- return 'Unknown';
580
- }
581
-
582
- // IMAP helper: read until we find a specific string
583
  async function readUntil(conn: Deno.TlsConn, decoder: TextDecoder, until: string): Promise<string> {
584
  let buf = '';
585
  const chunk = new Uint8Array(4096);
 
461
  await logoutImap(conn, encoder, decoder, tag);
462
  }
463
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
464
  async function readUntil(conn: Deno.TlsConn, decoder: TextDecoder, until: string): Promise<string> {
465
  let buf = '';
466
  const chunk = new Uint8Array(4096);