feat(GBMinService, MainService): integrate Stripe payment success handling and update dialog flow
All checks were successful
GBCI / build (push) Successful in 1m18s

This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-04-24 01:18:30 -03:00
parent e3ac4f58b3
commit ec8b0d44df
3 changed files with 62 additions and 7 deletions

View file

@ -105,6 +105,7 @@ import { GBConversationalService } from './GBConversationalService.js';
import { GBDeployer } from './GBDeployer.js';
import { GBLogEx } from './GBLogEx.js';
import { GBSSR } from './GBSSR.js';
import Stripe from 'stripe';
/**
* Minimal service layer for a bot and encapsulation of BOT Framework calls.
@ -459,7 +460,61 @@ export class GBMinService {
this.createCheckHealthAddress(GBServer.globals.server, min, min.instance);
GBServer.globals.server
.all(`/${min.instance.botId}/paymentSuccess`, async (req, res) => {
try {
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
GBLogEx.info(min, `Payment success webhook received for bot ${min.instance.botId}`);
const sessionId = req.query.session_id;
if (!sessionId) {
GBLogEx.info(min, 'No session_id parameter found in payment success callback');
return res.status(400).json({ success: false, error: 'Missing session_id parameter' });
}
const session = await stripe.checkout.sessions.retrieve(sessionId);
if (session.payment_status === 'paid') {
GBLogEx.info(min, `Payment confirmed for session ${sessionId}`);
// Only for successful payment - send HTML to close window
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Payment Successful</title>
<script>
// Close the window after a short delay
setTimeout(() => {
window.close();
}, 1000);
</script>
</head>
<body style="text-align: center; padding: 40px; font-family: Arial;">
<h1 style="color: #4CAF50;">Payment Successful!</h1>
<p>General Bots: Your transaction was completed successfully.</p>
</body>
</html>
`);
} else {
GBLogEx.info(min, `Payment not completed for session ${sessionId}`);
res.status(402).json({
success: false,
error: 'Payment not completed',
sessionId: sessionId
});
}
} catch (error) {
GBLogEx.error(min, `Error processing payment success: ${error.message}`);
res.status(500).json({
success: false,
error: error.message
});
}
})
.bind(min);
// Setups official handler for WhatsApp.
GBServer.globals.server
@ -742,9 +797,9 @@ export class GBMinService {
if (GBConfigService.get('GB_MODE') !== 'legacy') {
const url =
process.env.BOT_URL ||
`http://localhost:${GBConfigService.get('PORT')}`;
process.env.BOT_URL && !process.env.BOT_URL.includes('ngrok')
? process.env.BOT_URL
: `http://localhost:${GBConfigService.get('PORT')}`;
config['domain'] = urlJoin(url, 'directline', botId);
} else {

View file

@ -136,7 +136,7 @@ export class NewUserDialog extends IGBDialog {
return await step.replaceDialog('/ask', { isReturning: true });
} catch (error) {
await step.context.sendActivity(`Error: ${error.message}`);
return await step.replaceDialog('/welcome_saas_plan');
return await step.replaceDialog('/welcome_saas');
}
}
}

View file

@ -51,7 +51,7 @@ export class MainService {
price: priceId,
quantity: 1,
}],
success_url: urlJoin(process.env.BOT_URL, min.botId, 'paymentSuccess?session_id={CHECKOUT_SESSION_ID}'),
mode: 'subscription',
metadata: {
subscriptionId: subscription.subscriptionId.toString(),
@ -103,7 +103,7 @@ export class MainService {
return await this.createBotResources(min, subscription, templateName);
}
if (session.payment_status === 'unpaid' || session.status === 'expired') {
if (session.status === 'expired') {
throw new Error('Payment failed or session expired. Please try again.');
}
}