feat: implement billing, usage tracking, and administrative geocoding features in API with infrastructure updates

This commit is contained in:
Hamza-Ayed
2026-07-28 04:43:23 +03:00
parent 2f7c2066f7
commit dc9d546733
133 changed files with 3599 additions and 356 deletions
+16
View File
@@ -0,0 +1,16 @@
import { ConfigService } from '@nestjs/config';
export declare class BinanceProvider {
private configService;
private readonly logger;
private readonly apiUrl;
constructor(configService: ConfigService);
private get apiKey();
private get secretKey();
private generateSignature;
createOrder(tenantId: string, amount: number, plan: string): Promise<{
checkoutUrl: any;
orderId: string;
prepayId: any;
}>;
verifySignature(timestamp: string, nonce: string, signature: string, payloadBody: any): boolean;
}
+150
View File
@@ -0,0 +1,150 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var BinanceProvider_1;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BinanceProvider = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("@nestjs/config");
const axios_1 = __importDefault(require("axios"));
const crypto = __importStar(require("crypto"));
let BinanceProvider = BinanceProvider_1 = class BinanceProvider {
configService;
logger = new common_1.Logger(BinanceProvider_1.name);
apiUrl = 'https://bpay.binanceapi.com/binancepay/openapi/v2/order';
constructor(configService) {
this.configService = configService;
}
get apiKey() {
return this.configService.get('BINANCE_PAY_API_KEY') || '';
}
get secretKey() {
return this.configService.get('BINANCE_PAY_SECRET_KEY') || '';
}
generateSignature(timestamp, nonce, body) {
const payload = timestamp + '\n' + nonce + '\n' + JSON.stringify(body) + '\n';
return crypto
.createHmac('sha512', this.secretKey)
.update(payload)
.digest('hex')
.toUpperCase();
}
async createOrder(tenantId, amount, plan) {
this.logger.log(`Creating Binance Pay order for ${tenantId} - ${plan}`);
if (!this.apiKey || !this.secretKey) {
this.logger.error('Binance Pay API keys are not configured');
throw new common_1.InternalServerErrorException('Payment provider is not configured properly');
}
const nonce = crypto.randomBytes(16).toString('hex');
const timestamp = Date.now().toString();
const merchantTradeNo = `txn_${Date.now()}_${Math.floor(Math.random() * 10000)}`;
const body = {
env: {
terminalType: 'WEB',
},
merchantTradeNo: merchantTradeNo,
orderAmount: amount,
currency: 'USDT',
goods: {
goodsType: '01',
goodsCategory: 'Z000',
referenceGoodsId: plan,
goodsName: `${plan} Plan Subscription`,
goodsDetail: `Subscription to ${plan} plan for Maps SaaS`,
},
passThroughInfo: JSON.stringify({ tenantId, plan }),
returnUrl: `https://map-dashboard.intaleqapp.com/dashboard.html#billing`,
};
const signature = this.generateSignature(timestamp, nonce, body);
try {
const response = await axios_1.default.post(this.apiUrl, body, {
headers: {
'Content-Type': 'application/json',
'BinancePay-Timestamp': timestamp,
'BinancePay-Nonce': nonce,
'BinancePay-Certificate-SN': this.apiKey,
'BinancePay-Signature': signature,
},
});
if (response.data && response.data.status === 'SUCCESS') {
return {
checkoutUrl: response.data.data.checkoutUrl,
orderId: merchantTradeNo,
prepayId: response.data.data.prepayId,
};
}
else {
this.logger.error(`Binance API Error: ${JSON.stringify(response.data)}`);
throw new common_1.InternalServerErrorException('Failed to create Binance order');
}
}
catch (error) {
this.logger.error(`Error communicating with Binance API: ${error.message}`);
throw new common_1.InternalServerErrorException('Failed to communicate with payment provider');
}
}
verifySignature(timestamp, nonce, signature, payloadBody) {
const payload = timestamp + '\n' + nonce + '\n' + JSON.stringify(payloadBody) + '\n';
const expectedSignature = crypto
.createHmac('sha512', this.secretKey)
.update(payload)
.digest('hex')
.toUpperCase();
try {
return crypto.timingSafeEqual(Buffer.from(signature || ''), Buffer.from(expectedSignature));
}
catch (e) {
return false;
}
}
};
exports.BinanceProvider = BinanceProvider;
exports.BinanceProvider = BinanceProvider = BinanceProvider_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object])
], BinanceProvider);
//# sourceMappingURL=binance.provider.js.map
@@ -0,0 +1 @@
{"version":3,"file":"binance.provider.js","sourceRoot":"","sources":["../../../src/billing/providers/binance.provider.ts"],"names":[],"mappings":"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"}
+14
View File
@@ -0,0 +1,14 @@
import { ConfigService } from '@nestjs/config';
export declare class PayMobProvider {
private configService;
private readonly logger;
private readonly baseUrl;
constructor(configService: ConfigService);
createPaymentKey(tenantId: string, amount: number, plan: string): Promise<{
paymentKey: string;
orderId: string;
}>;
getTransactionDetails(transactionId: string): Promise<any>;
private getAuthToken;
verifyHmac(payload: any, hmac: string): boolean;
}
+179
View File
@@ -0,0 +1,179 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var PayMobProvider_1;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PayMobProvider = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("@nestjs/config");
const axios_1 = __importDefault(require("axios"));
const crypto = __importStar(require("crypto"));
let PayMobProvider = PayMobProvider_1 = class PayMobProvider {
configService;
logger = new common_1.Logger(PayMobProvider_1.name);
baseUrl = 'https://accept.paymob.com/api';
constructor(configService) {
this.configService = configService;
}
async createPaymentKey(tenantId, amount, plan) {
try {
const authToken = await this.getAuthToken();
const orderRes = await axios_1.default.post(`${this.baseUrl}/ecommerce/orders`, {
auth_token: authToken,
delivery_needed: "false",
amount_cents: amount * 50 * 100,
currency: "EGP",
items: [{
name: `${plan} Subscription`,
amount_cents: amount * 50 * 100,
description: `Intaleq Maps ${plan} Plan`
}],
shipping_data: {
first_name: "Intaleq",
last_name: "User",
email: "user@intaleq.com",
phone_number: "+201000000000",
extra_description: `${tenantId}|${plan}`
}
});
const orderId = orderRes.data.id;
const keyRes = await axios_1.default.post(`${this.baseUrl}/acceptance/payment_keys`, {
auth_token: authToken,
amount_cents: amount * 50 * 100,
expiration: 3600,
order_id: orderId,
billing_data: {
apartment: "NA",
email: "user@intaleq.com",
floor: "NA",
first_name: "Intaleq",
street: "NA",
building: "NA",
phone_number: "+201000000000",
shipping_method: "NA",
postal_code: "NA",
city: "NA",
country: "NA",
last_name: "User",
state: "NA"
},
currency: "EGP",
integration_id: this.configService.get('PAYMOB_INTEGRATION_ID') || 4556055,
lock_order_when_paid: "false"
});
return {
paymentKey: keyRes.data.token,
orderId: orderId.toString()
};
}
catch (error) {
this.logger.error(`PayMob Payment Key failed: ${error.response?.data ? JSON.stringify(error.response.data) : error.message}`);
throw new common_1.BadRequestException('Failed to initialize PayMob payment');
}
}
async getTransactionDetails(transactionId) {
try {
const authToken = await this.getAuthToken();
const res = await axios_1.default.get(`${this.baseUrl}/acceptance/transactions/${transactionId}`, {
headers: { Authorization: `Bearer ${authToken}` }
});
return res.data;
}
catch (error) {
this.logger.error(`Failed to fetch PayMob transaction ${transactionId}: ${error.message}`);
return null;
}
}
async getAuthToken() {
const authRes = await axios_1.default.post(`${this.baseUrl}/auth/tokens`, {
api_key: this.configService.get('PAYMOB_API_KEY'),
});
return authRes.data.token;
}
verifyHmac(payload, hmac) {
const secret = this.configService.get('PAYMOB_HMAC_SECRET');
if (!secret)
return false;
const { amount_cents, created_at, currency, error_occured, has_parent_transaction, id, integration_id, is_3d_secure, is_auth, is_capture, is_refunded, is_standalone_payment, is_voided, order, owner, pending, success } = payload;
const source_pan = payload.source_data?.pan || "";
const source_sub_type = payload.source_data?.sub_type || "";
const source_type = payload.source_data?.type || "";
const data = [
amount_cents,
created_at,
currency,
error_occured,
has_parent_transaction,
id,
integration_id,
is_3d_secure,
is_auth,
is_capture,
is_refunded,
is_standalone_payment,
is_voided,
order.id || order,
owner,
pending,
source_pan,
source_sub_type,
source_type,
success
].join("");
const hash = crypto
.createHmac('sha512', secret)
.update(data)
.digest('hex');
return hash === hmac;
}
};
exports.PayMobProvider = PayMobProvider;
exports.PayMobProvider = PayMobProvider = PayMobProvider_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object])
], PayMobProvider);
//# sourceMappingURL=paymob.provider.js.map
@@ -0,0 +1 @@
{"version":3,"file":"paymob.provider.js","sourceRoot":"","sources":["../../../src/billing/providers/paymob.provider.ts"],"names":[],"mappings":"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"}