Use Space HTTPS URL for Snippe webhooks
Browse files- src/routes/devices.routes.js +2 -3
- src/routes/payouts.routes.js +2 -3
- src/routes/portal.routes.js +2 -3
- src/utils/webhookUrl.js +16 -0
src/routes/devices.routes.js
CHANGED
|
@@ -16,6 +16,7 @@ const {
|
|
| 16 |
makePaymentAssetUrl,
|
| 17 |
resolvePaymentAssetPath,
|
| 18 |
} = require("../utils/portalPaymentStorage");
|
|
|
|
| 19 |
|
| 20 |
const ALLOWED_PORTAL_PAYMENT_MODES = new Set(["online_only", "direct_only", "both"]);
|
| 21 |
const PAYMENT_IMAGE_MIME_EXTENSIONS = {
|
|
@@ -837,14 +838,12 @@ router.post("/:id/renew", async (req, res) => {
|
|
| 837 |
);
|
| 838 |
|
| 839 |
// Initiate Snippe payment to tenant's phone
|
| 840 |
-
const host = (process.env.PORTAL_HOST || '').replace(/^https?:\/\//, '');
|
| 841 |
-
const webhookBase = `${process.env.PORTAL_SCHEME || "http"}://${host}`;
|
| 842 |
try {
|
| 843 |
await snippe.createPayment({
|
| 844 |
reference,
|
| 845 |
amount: parseFloat(device.monthly_fee),
|
| 846 |
phone: device.client_phone,
|
| 847 |
-
webhookUrl:
|
| 848 |
metadata: { reference, type: "device_renewal", device_id: String(device.id) },
|
| 849 |
});
|
| 850 |
} catch (payErr) {
|
|
|
|
| 16 |
makePaymentAssetUrl,
|
| 17 |
resolvePaymentAssetPath,
|
| 18 |
} = require("../utils/portalPaymentStorage");
|
| 19 |
+
const { snippeWebhookUrl } = require("../utils/webhookUrl");
|
| 20 |
|
| 21 |
const ALLOWED_PORTAL_PAYMENT_MODES = new Set(["online_only", "direct_only", "both"]);
|
| 22 |
const PAYMENT_IMAGE_MIME_EXTENSIONS = {
|
|
|
|
| 838 |
);
|
| 839 |
|
| 840 |
// Initiate Snippe payment to tenant's phone
|
|
|
|
|
|
|
| 841 |
try {
|
| 842 |
await snippe.createPayment({
|
| 843 |
reference,
|
| 844 |
amount: parseFloat(device.monthly_fee),
|
| 845 |
phone: device.client_phone,
|
| 846 |
+
webhookUrl: snippeWebhookUrl(),
|
| 847 |
metadata: { reference, type: "device_renewal", device_id: String(device.id) },
|
| 848 |
});
|
| 849 |
} catch (payErr) {
|
src/routes/payouts.routes.js
CHANGED
|
@@ -2,6 +2,7 @@ const router = require('express').Router();
|
|
| 2 |
const db = require('../config/db');
|
| 3 |
const snippe = require('../services/snippe');
|
| 4 |
const { requireAuth } = require('../middleware/auth');
|
|
|
|
| 5 |
|
| 6 |
router.use(requireAuth);
|
| 7 |
|
|
@@ -66,8 +67,6 @@ router.post('/', async (req, res) => {
|
|
| 66 |
);
|
| 67 |
|
| 68 |
const payoutId = result.insertId;
|
| 69 |
-
const host = (process.env.PORTAL_HOST || '').replace(/^https?:\/\//, '');
|
| 70 |
-
const webhookBase = `${process.env.PORTAL_SCHEME || 'http'}://${host}`;
|
| 71 |
|
| 72 |
// Call Snippe disbursement
|
| 73 |
try {
|
|
@@ -77,7 +76,7 @@ router.post('/', async (req, res) => {
|
|
| 77 |
phone,
|
| 78 |
recipientName: client.contact_name,
|
| 79 |
narration: 'WiFi platform payout',
|
| 80 |
-
webhookUrl:
|
| 81 |
});
|
| 82 |
|
| 83 |
// Save disbursement reference
|
|
|
|
| 2 |
const db = require('../config/db');
|
| 3 |
const snippe = require('../services/snippe');
|
| 4 |
const { requireAuth } = require('../middleware/auth');
|
| 5 |
+
const { snippeWebhookUrl } = require('../utils/webhookUrl');
|
| 6 |
|
| 7 |
router.use(requireAuth);
|
| 8 |
|
|
|
|
| 67 |
);
|
| 68 |
|
| 69 |
const payoutId = result.insertId;
|
|
|
|
|
|
|
| 70 |
|
| 71 |
// Call Snippe disbursement
|
| 72 |
try {
|
|
|
|
| 76 |
phone,
|
| 77 |
recipientName: client.contact_name,
|
| 78 |
narration: 'WiFi platform payout',
|
| 79 |
+
webhookUrl: snippeWebhookUrl(),
|
| 80 |
});
|
| 81 |
|
| 82 |
// Save disbursement reference
|
src/routes/portal.routes.js
CHANGED
|
@@ -10,6 +10,7 @@ const { v4: uuidv4 } = require('uuid');
|
|
| 10 |
const { purchaseLimiter, portalAuthLimiter } = require('../middleware/rateLimiter');
|
| 11 |
const { alertAdmin } = require('../utils/adminAlert');
|
| 12 |
const { makePaymentAssetUrl } = require('../utils/portalPaymentStorage');
|
|
|
|
| 13 |
const { decryptSecret } = require('../utils/paymentSecrets');
|
| 14 |
|
| 15 |
const normalizeMac = mac => String(mac || '').toUpperCase().replace(/[:\-]/g, '');
|
|
@@ -519,14 +520,12 @@ router.post('/:siteId/purchase', purchaseLimiter, async (req, res) => {
|
|
| 519 |
]
|
| 520 |
);
|
| 521 |
|
| 522 |
-
const host = (process.env.PORTAL_HOST || '').replace(/^https?:\/\//, '');
|
| 523 |
-
const webhookBase = `${process.env.PORTAL_SCHEME || 'http'}://${host}`;
|
| 524 |
try {
|
| 525 |
await snippe.createPayment({
|
| 526 |
reference,
|
| 527 |
amount: parseFloat(plan.price),
|
| 528 |
phone,
|
| 529 |
-
webhookUrl:
|
| 530 |
apiKey: paymentAccount.apiKey,
|
| 531 |
metadata: {
|
| 532 |
reference: reference,
|
|
|
|
| 10 |
const { purchaseLimiter, portalAuthLimiter } = require('../middleware/rateLimiter');
|
| 11 |
const { alertAdmin } = require('../utils/adminAlert');
|
| 12 |
const { makePaymentAssetUrl } = require('../utils/portalPaymentStorage');
|
| 13 |
+
const { snippeWebhookUrl } = require('../utils/webhookUrl');
|
| 14 |
const { decryptSecret } = require('../utils/paymentSecrets');
|
| 15 |
|
| 16 |
const normalizeMac = mac => String(mac || '').toUpperCase().replace(/[:\-]/g, '');
|
|
|
|
| 520 |
]
|
| 521 |
);
|
| 522 |
|
|
|
|
|
|
|
| 523 |
try {
|
| 524 |
await snippe.createPayment({
|
| 525 |
reference,
|
| 526 |
amount: parseFloat(plan.price),
|
| 527 |
phone,
|
| 528 |
+
webhookUrl: snippeWebhookUrl(),
|
| 529 |
apiKey: paymentAccount.apiKey,
|
| 530 |
metadata: {
|
| 531 |
reference: reference,
|
src/utils/webhookUrl.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
function publicHost() {
|
| 2 |
+
return String(process.env.WEBHOOK_HOST || process.env.SPACE_HOST || process.env.PORTAL_HOST || '')
|
| 3 |
+
.replace(/^https?:\/\//, '')
|
| 4 |
+
.replace(/\/+$/, '');
|
| 5 |
+
}
|
| 6 |
+
|
| 7 |
+
function snippeWebhookUrl(path = '/api/webhooks/snippe') {
|
| 8 |
+
const host = publicHost();
|
| 9 |
+
if (!host) {
|
| 10 |
+
throw new Error('WEBHOOK_HOST, SPACE_HOST, or PORTAL_HOST is required for Snippe webhooks');
|
| 11 |
+
}
|
| 12 |
+
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
|
| 13 |
+
return `https://${host}${normalizedPath}`;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
module.exports = { snippeWebhookUrl };
|