diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index 6bbb0cbd..914980b7 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -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(` + + +
+General Bots: Your transaction was completed successfully.
+ + + `); + + } 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 { diff --git a/packages/saas.gbapp/dialog/NewUserDialog.ts b/packages/saas.gbapp/dialog/NewUserDialog.ts index 3bd97ed9..4eb10dc2 100644 --- a/packages/saas.gbapp/dialog/NewUserDialog.ts +++ b/packages/saas.gbapp/dialog/NewUserDialog.ts @@ -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'); } } } diff --git a/packages/saas.gbapp/service/MainService.ts b/packages/saas.gbapp/service/MainService.ts index 05c6cfd5..8bb403ab 100644 --- a/packages/saas.gbapp/service/MainService.ts +++ b/packages/saas.gbapp/service/MainService.ts @@ -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.'); } }