feat: update dependencies and improve file handling in GBVMService
Some checks failed
GBCI / build (push) Failing after 3m57s
Some checks failed
GBCI / build (push) Failing after 3m57s
This commit is contained in:
parent
ea224b4937
commit
bc0aa7627e
13 changed files with 213 additions and 891 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -30,3 +30,4 @@ logo.svg
|
||||||
screenshot.png
|
screenshot.png
|
||||||
data.db
|
data.db
|
||||||
.wwebjs_cache
|
.wwebjs_cache
|
||||||
|
*doula*
|
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -165,6 +165,7 @@
|
||||||
"sqlite3": "5.1.7",
|
"sqlite3": "5.1.7",
|
||||||
"ssr-for-bots": "1.0.1-c",
|
"ssr-for-bots": "1.0.1-c",
|
||||||
"strict-password-generator": "1.1.2",
|
"strict-password-generator": "1.1.2",
|
||||||
|
"stripe": "^18.0.0",
|
||||||
"svg2img": "^1.0.0-beta.2",
|
"svg2img": "^1.0.0-beta.2",
|
||||||
"swagger-client": "3.29.2",
|
"swagger-client": "3.29.2",
|
||||||
"swagger-ui-dist": "5.17.14",
|
"swagger-ui-dist": "5.17.14",
|
||||||
|
@ -41856,6 +41857,19 @@
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/stripe": {
|
||||||
|
"version": "18.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/stripe/-/stripe-18.0.0.tgz",
|
||||||
|
"integrity": "sha512-3Fs33IzKUby//9kCkCa1uRpinAoTvj6rJgQ2jrBEysoxEvfsclvXdna1amyEYbA2EKkjynuB4+L/kleCCaWTpA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": ">=8.1.0",
|
||||||
|
"qs": "^6.11.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/strnum": {
|
"node_modules/strnum": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
|
||||||
|
|
|
@ -225,6 +225,7 @@
|
||||||
"sqlite3": "5.1.7",
|
"sqlite3": "5.1.7",
|
||||||
"ssr-for-bots": "1.0.1-c",
|
"ssr-for-bots": "1.0.1-c",
|
||||||
"strict-password-generator": "1.1.2",
|
"strict-password-generator": "1.1.2",
|
||||||
|
"stripe": "^18.0.0",
|
||||||
"svg2img": "^1.0.0-beta.2",
|
"svg2img": "^1.0.0-beta.2",
|
||||||
"swagger-client": "3.29.2",
|
"swagger-client": "3.29.2",
|
||||||
"swagger-ui-dist": "5.17.14",
|
"swagger-ui-dist": "5.17.14",
|
||||||
|
|
|
@ -47,7 +47,7 @@ import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
||||||
import { GBServer } from '../../../src/app.js';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
||||||
import { GBUtil } from 'src/util.js';
|
import { GBUtil } from '../../../src/util.js';
|
||||||
|
|
||||||
|
|
||||||
class AdminDialog extends IGBDialog {
|
class AdminDialog extends IGBDialog {
|
||||||
|
|
|
@ -205,7 +205,7 @@ export class GBVMService extends GBService {
|
||||||
"author": "${min.botId} owner.",
|
"author": "${min.botId} owner.",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"yaml": "2.4.2",
|
|
||||||
"encoding": "0.1.13",
|
"encoding": "0.1.13",
|
||||||
"isomorphic-fetch": "3.0.0",
|
"isomorphic-fetch": "3.0.0",
|
||||||
"punycode": "2.1.1",
|
"punycode": "2.1.1",
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// BotServer/packages/saas.gbapp/dialog/NewUserDialog.ts
|
||||||
/*****************************************************************************\
|
/*****************************************************************************\
|
||||||
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
||||||
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
|
@ -38,18 +39,45 @@ import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { GBOService } from '../service/GBOService.js';
|
import { GBOService } from '../service/GBOService.js';
|
||||||
|
|
||||||
export class NewUserDialog extends IGBDialog {
|
export class NewUserDialog extends IGBDialog {
|
||||||
|
static getPlanSelectionDialog(min: GBMinInstance) {
|
||||||
|
return {
|
||||||
|
id: '/welcome_saas_plan',
|
||||||
|
waterfall: [
|
||||||
|
async step => {
|
||||||
|
const locale = 'en-US';
|
||||||
|
await step.context.sendActivity('Please choose your plan:');
|
||||||
|
await step.context.sendActivity('1. Personal - $9.99/month (basic features)');
|
||||||
|
await step.context.sendActivity('2. Professional - $29.99/month (advanced features)');
|
||||||
|
return await step.prompt('textPrompt', 'Enter 1 or 2 to select your plan:');
|
||||||
|
},
|
||||||
|
async step => {
|
||||||
|
const planChoice = step.context.activity.text.trim();
|
||||||
|
if (planChoice === '1') {
|
||||||
|
step.activeDialog.state.options.planId = 'personal';
|
||||||
|
step.activeDialog.state.options.amount = 9.99;
|
||||||
|
} else if (planChoice === '2') {
|
||||||
|
step.activeDialog.state.options.planId = 'professional';
|
||||||
|
step.activeDialog.state.options.amount = 29.99;
|
||||||
|
} else {
|
||||||
|
await step.context.sendActivity('Invalid choice. Please select 1 or 2.');
|
||||||
|
return await step.replaceDialog('/welcome_saas_plan');
|
||||||
|
}
|
||||||
|
return await step.replaceDialog('/welcome_saas_botname', step.activeDialog.state.options);
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static getBotNameDialog(min: GBMinInstance) {
|
static getBotNameDialog(min: GBMinInstance) {
|
||||||
return {
|
return {
|
||||||
id: '/welcome_saas_botname',
|
id: '/welcome_saas_botname',
|
||||||
waterfall: [
|
waterfall: [
|
||||||
async step => {
|
async step => {
|
||||||
const locale = 'en-US';
|
const locale = 'en-US';
|
||||||
|
|
||||||
await step.prompt('textPrompt', Messages[locale].whats_botname);
|
await step.prompt('textPrompt', Messages[locale].whats_botname);
|
||||||
},
|
},
|
||||||
async step => {
|
async step => {
|
||||||
const locale = 'en-US';
|
const locale = 'en-US';
|
||||||
|
|
||||||
const extractEntity = text => {
|
const extractEntity = text => {
|
||||||
return text.match(/[_a-zA-Z][_a-zA-Z0-9]{0,16}/gi);
|
return text.match(/[_a-zA-Z][_a-zA-Z0-9]{0,16}/gi);
|
||||||
};
|
};
|
||||||
|
@ -58,17 +86,14 @@ export class NewUserDialog extends IGBDialog {
|
||||||
|
|
||||||
if (value === null || value.length != 1) {
|
if (value === null || value.length != 1) {
|
||||||
await step.context.sendActivity(Messages[locale].validation_enter_valid_botname);
|
await step.context.sendActivity(Messages[locale].validation_enter_valid_botname);
|
||||||
|
|
||||||
return await step.replaceDialog('/welcome_saas_botname', step.activeDialog.state.options);
|
return await step.replaceDialog('/welcome_saas_botname', step.activeDialog.state.options);
|
||||||
} else {
|
} else {
|
||||||
const botName = value[0];
|
const botName = value[0];
|
||||||
if (await min.deployService.botExists(botName)) {
|
if (await min.deployService.botExists(botName)) {
|
||||||
await step.context.sendActivity(`O Bot ${botName} já existe. Escolha por favor, outro nome!`);
|
await step.context.sendActivity(`The Bot ${botName} already exists. Please choose another name!`);
|
||||||
|
|
||||||
return await step.replaceDialog('/welcome_saas_botname', step.activeDialog.state.options);
|
return await step.replaceDialog('/welcome_saas_botname', step.activeDialog.state.options);
|
||||||
} else {
|
} else {
|
||||||
step.activeDialog.state.options.botName = botName;
|
step.activeDialog.state.options.botName = botName;
|
||||||
|
|
||||||
return await step.replaceDialog('/welcome_saas_bottemplate', step.activeDialog.state.options);
|
return await step.replaceDialog('/welcome_saas_bottemplate', step.activeDialog.state.options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +102,38 @@ export class NewUserDialog extends IGBDialog {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getStripePaymentDialog(min: GBMinInstance) {
|
||||||
|
return {
|
||||||
|
id: '/welcome_saas_stripe_payment',
|
||||||
|
waterfall: [
|
||||||
|
async step => {
|
||||||
|
const locale = 'en-US';
|
||||||
|
await step.context.sendActivity(`Please enter your credit card details for the ${step.activeDialog.state.options.planId} plan ($${step.activeDialog.state.options.amount}/month):`);
|
||||||
|
return await step.prompt('textPrompt', 'Card number (e.g., 4242424242424242):');
|
||||||
|
},
|
||||||
|
async step => {
|
||||||
|
step.activeDialog.state.options.ccNumber = step.context.activity.text.trim();
|
||||||
|
return await step.prompt('textPrompt', 'Expiration month (MM):');
|
||||||
|
},
|
||||||
|
async step => {
|
||||||
|
step.activeDialog.state.options.ccExpiresOnMonth = step.context.activity.text.trim();
|
||||||
|
return await step.prompt('textPrompt', 'Expiration year (YYYY):');
|
||||||
|
},
|
||||||
|
async step => {
|
||||||
|
step.activeDialog.state.options.ccExpiresOnYear = step.context.activity.text.trim();
|
||||||
|
return await step.prompt('textPrompt', 'CVC:');
|
||||||
|
},
|
||||||
|
async step => {
|
||||||
|
step.activeDialog.state.options.ccSecuritycode = step.context.activity.text.trim();
|
||||||
|
await step.context.sendActivity('Processing payment...');
|
||||||
|
await NewUserDialog.createBot(step, min, false);
|
||||||
|
return await step.replaceDialog('/ask', { isReturning: true });
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static getBotTemplateDialog(min: GBMinInstance) {
|
static getBotTemplateDialog(min: GBMinInstance) {
|
||||||
return {
|
return {
|
||||||
id: '/welcome_saas_bottemplate',
|
id: '/welcome_saas_bottemplate',
|
||||||
|
@ -176,36 +233,10 @@ export class NewUserDialog extends IGBDialog {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static getVoucherDialog(min: GBMinInstance) {
|
|
||||||
return {
|
|
||||||
id: '/welcome_saas_voucher',
|
|
||||||
waterfall: [
|
|
||||||
async step => {
|
|
||||||
const locale = 'en-US';
|
|
||||||
await step.prompt('textPrompt', Messages[locale].own_voucher);
|
|
||||||
},
|
|
||||||
async step => {
|
|
||||||
const locale = 'en-US';
|
|
||||||
|
|
||||||
if (step.result.toLowerCase() === 'gb2020') {
|
|
||||||
await NewUserDialog.createBot(step, min, true);
|
|
||||||
|
|
||||||
return await step.replaceDialog('/ask', { isReturning: true });
|
|
||||||
} else {
|
|
||||||
// return await step.replaceDialog('/welcome_saas_voucher', 'Os meios de pagamento estão neste momento desabilitados, por favor informe um voucher ou contate info@pragmatismo.com.br.');
|
|
||||||
|
|
||||||
step.activeDialog.state.options.nextDialog = 'welcome_saas_return_document';
|
|
||||||
return await step.replaceDialog('/xrm_document', step.activeDialog.state.options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async createBot(step: any, min: GBMinInstance, free: boolean) {
|
private static async createBot(step: any, min: GBMinInstance, free: boolean) {
|
||||||
const locale = 'en-US';
|
const locale = 'en-US';
|
||||||
await step.context.sendActivity(Messages[locale].ok_procceding_creation);
|
await step.context.sendActivity(Messages[locale].ok_procceding_creation);
|
||||||
const url = `https://gb.pragmatismo.com.br/${step.activeDialog.state.options.botName}`;
|
const url = `${process.env.BOT_ID}/${step.activeDialog.state.options.botName}`;
|
||||||
await step.context.sendActivity(Messages[locale].bot_created(url));
|
await step.context.sendActivity(Messages[locale].bot_created(url));
|
||||||
const service = new MainService();
|
const service = new MainService();
|
||||||
await service.createSubscription(
|
await service.createSubscription(
|
||||||
|
@ -220,49 +251,10 @@ export class NewUserDialog extends IGBDialog {
|
||||||
step.activeDialog.state.options.ccExpiresOnYear,
|
step.activeDialog.state.options.ccExpiresOnYear,
|
||||||
step.activeDialog.state.options.ccSecuritycode,
|
step.activeDialog.state.options.ccSecuritycode,
|
||||||
step.activeDialog.state.options.templateName,
|
step.activeDialog.state.options.templateName,
|
||||||
free
|
free, step.activeDialog.state.options.planId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDialogBatch(min: GBMinInstance) {
|
|
||||||
return {
|
|
||||||
id: '/welcome_saas_batch',
|
|
||||||
waterfall: [
|
|
||||||
async step => {
|
|
||||||
const locale = 'en-US';
|
|
||||||
await step.context.sendActivity(Messages[locale].welcome);
|
|
||||||
|
|
||||||
await step.prompt('textPrompt', `Please, inform bot names separeted by comma (,).`);
|
|
||||||
},
|
|
||||||
async step => {
|
|
||||||
const locale = 'en-US';
|
|
||||||
|
|
||||||
const service = new MainService();
|
|
||||||
|
|
||||||
const bots = step.context.activity.originalText.split(',');
|
|
||||||
bots.forEach(async botName => {
|
|
||||||
await service.createSubscription(
|
|
||||||
min,
|
|
||||||
botName,
|
|
||||||
'999999999',
|
|
||||||
'email@domain.com.br',
|
|
||||||
'5521999998888',
|
|
||||||
botName,
|
|
||||||
null,
|
|
||||||
'12',
|
|
||||||
'99',
|
|
||||||
'1234',
|
|
||||||
'ai-search.gbai',
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDialog(min: GBMinInstance) {
|
static getDialog(min: GBMinInstance) {
|
||||||
return {
|
return {
|
||||||
|
@ -279,28 +271,28 @@ export class NewUserDialog extends IGBDialog {
|
||||||
step.activeDialog.state.options.ccExpiresOnYear = null;
|
step.activeDialog.state.options.ccExpiresOnYear = null;
|
||||||
step.activeDialog.state.options.ccSecuritycode = null;
|
step.activeDialog.state.options.ccSecuritycode = null;
|
||||||
step.activeDialog.state.options.templateName = null;
|
step.activeDialog.state.options.templateName = null;
|
||||||
|
step.activeDialog.state.options.planId = null;
|
||||||
|
step.activeDialog.state.options.amount = null;
|
||||||
|
|
||||||
await step.context.sendActivity(Messages[locale].welcome);
|
await step.context.sendActivity(Messages[locale].welcome);
|
||||||
|
|
||||||
const mobile = step.context.activity.from.id;
|
const mobile = step.context.activity.from.id;
|
||||||
|
|
||||||
step.activeDialog.state.options.nextDialog = 'welcome_saas_botname';
|
step.activeDialog.state.options.nextDialog = 'welcome_saas_plan';
|
||||||
|
|
||||||
if (isNaN(mobile as any)) {
|
if (isNaN(mobile as any)) {
|
||||||
await step.context.sendActivity(Messages[locale].ok_get_information);
|
await step.context.sendActivity(Messages[locale].ok_get_information);
|
||||||
|
|
||||||
return await step.replaceDialog('/profile_name', step.activeDialog.state.options);
|
return await step.replaceDialog('/profile_name', step.activeDialog.state.options);
|
||||||
} else {
|
} else {
|
||||||
const name = SaaSPackage.welcomes ? SaaSPackage.welcomes[mobile] : null;
|
const name = SaaSPackage.welcomes ? SaaSPackage.welcomes[mobile] : null;
|
||||||
step.activeDialog.state.options.name = name;
|
step.activeDialog.state.options.name = name;
|
||||||
step.activeDialog.state.options.mobile = mobile;
|
step.activeDialog.state.options.mobile = mobile;
|
||||||
|
|
||||||
await step.context.sendActivity(`Olá ${name}, vamos criar o seu Bot agora.`);
|
await step.context.sendActivity(`Hello ${name}, let's create your Bot now.`);
|
||||||
|
|
||||||
return await step.replaceDialog('/profile_email', step.activeDialog.state.options);
|
return await step.replaceDialog('/profile_email', step.activeDialog.state.options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,7 +34,6 @@ import { IGBPackage, GBMinInstance, IGBCoreService, GBLog, IGBAdminService, GBDi
|
||||||
import { Sequelize } from 'sequelize-typescript'
|
import { Sequelize } from 'sequelize-typescript'
|
||||||
import { GBOnlineSubscription } from './model/MainModel.js'
|
import { GBOnlineSubscription } from './model/MainModel.js'
|
||||||
|
|
||||||
import { MSSubscriptionService } from './service/MSSubscription.js'
|
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { NewUserDialog } from './dialog/NewUserDialog.js'
|
import { NewUserDialog } from './dialog/NewUserDialog.js'
|
||||||
import { GBOService } from './service/GBOService.js'
|
import { GBOService } from './service/GBOService.js'
|
||||||
|
@ -48,12 +47,10 @@ export class SaaSPackage implements IGBPackage {
|
||||||
public getDialogs(min: GBMinInstance) {
|
public getDialogs(min: GBMinInstance) {
|
||||||
return [NewUserDialog.getDialog(min),
|
return [NewUserDialog.getDialog(min),
|
||||||
NewUserDialog.getBotNameDialog(min),
|
NewUserDialog.getBotNameDialog(min),
|
||||||
NewUserDialog.getVoucherDialog(min),
|
|
||||||
NewUserDialog.getBotTemplateDialog(min),
|
NewUserDialog.getBotTemplateDialog(min),
|
||||||
NewUserDialog.getReturnFromPayment(min),
|
NewUserDialog.getReturnFromPayment(min),
|
||||||
NewUserDialog.getReturnFromCC(min),
|
NewUserDialog.getReturnFromCC(min),
|
||||||
NewUserDialog.getReturnFromDocument(min),
|
NewUserDialog.getReturnFromDocument(min),
|
||||||
NewUserDialog.getDialogBatch(min)
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,21 +59,6 @@ export class SaaSPackage implements IGBPackage {
|
||||||
|
|
||||||
core.setEntryPointDialog('/welcome_saas');
|
core.setEntryPointDialog('/welcome_saas');
|
||||||
|
|
||||||
// Installs webhook for Microsoft intercommunication.
|
|
||||||
|
|
||||||
core.installWebHook(true, '/mslanding', async (req, res) => {
|
|
||||||
const service = new MSSubscriptionService();
|
|
||||||
await service.handleMSLanding(req, res);
|
|
||||||
});
|
|
||||||
core.installWebHook(true, '/mshook', async (req, res) => {
|
|
||||||
const service = new MSSubscriptionService();
|
|
||||||
await service.handleMSHook(req, res);
|
|
||||||
});
|
|
||||||
core.installWebHook(true, '/signup', async (req, res) => {
|
|
||||||
const service = new MSSubscriptionService();
|
|
||||||
await service.handleMSSignUp(req, res);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// BotServer/packages/saas.gbapp/model/MainModel.ts
|
||||||
/*****************************************************************************\
|
/*****************************************************************************\
|
||||||
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
||||||
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
|
@ -59,13 +60,13 @@ export class GBOnlineSubscription extends Model<GBOnlineSubscription> {
|
||||||
instanceId: number;
|
instanceId: number;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
externalSubscriptionId: string // MSFT or
|
externalSubscriptionId: string;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
saasSubscriptionStatus: string
|
saasSubscriptionStatus: string;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
isFreeTrial: boolean
|
isFreeTrial: boolean;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
planId: string;
|
planId: string;
|
||||||
|
@ -74,8 +75,14 @@ export class GBOnlineSubscription extends Model<GBOnlineSubscription> {
|
||||||
quantity: number;
|
quantity: number;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
lastCCFourDigits: number;
|
lastCCFourDigits: string;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
status: string;
|
status: string;
|
||||||
}
|
|
||||||
|
@Column({
|
||||||
|
type: DataType.DECIMAL(10, 2)
|
||||||
|
})
|
||||||
|
amount: number;
|
||||||
|
|
||||||
|
}
|
|
@ -1,579 +0,0 @@
|
||||||
/*****************************************************************************\
|
|
||||||
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
|
||||||
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
|
||||||
| ██ ███ ████ █ ██ █ ████ █████ ██████ ██ ████ █ █ █ ██ |
|
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
|
||||||
| |
|
|
||||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
|
||||||
| Licensed under the AGPL-3.0. |
|
|
||||||
| |
|
|
||||||
| According to our dual licensing model, this program can be used either |
|
|
||||||
| under the terms of the GNU Affero General Public License, version 3, |
|
|
||||||
| or under a proprietary license. |
|
|
||||||
| |
|
|
||||||
| The texts of the GNU Affero General Public License with an additional |
|
|
||||||
| permission and of our proprietary license can be found at and |
|
|
||||||
| in the LICENSE file you have received along with this program. |
|
|
||||||
| |
|
|
||||||
| This program is distributed in the hope that it will be useful, |
|
|
||||||
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
|
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
||||||
| GNU Affero General Public License for more details. |
|
|
||||||
| |
|
|
||||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
|
||||||
| our trademarks remain entirely with us. |
|
|
||||||
| |
|
|
||||||
\*****************************************************************************/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
import fs from 'fs/promises';
|
|
||||||
import { HttpMethods, HttpOperationResponse, ServiceClient, WebResource } from '@azure/ms-rest-js';
|
|
||||||
import { GBLog } from 'botlib';
|
|
||||||
import urlJoin from 'url-join';
|
|
||||||
// tslint:disable-next-line: no-require-imports
|
|
||||||
const Juno = require('juno-payment-node');
|
|
||||||
var FormData = require('form-data');
|
|
||||||
export class JunoSubscription {
|
|
||||||
/**
|
|
||||||
* The host this service will call REST API through VPN.
|
|
||||||
*/
|
|
||||||
public host: string = process.env.SAAS_JUNO_HOST;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a HTTP request object to make REST calls.
|
|
||||||
*/
|
|
||||||
private async getAuthorizationToken(): Promise<string> {
|
|
||||||
GBLog.info( `JunoAPI: Getting Auth Token from API...`);
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
|
|
||||||
const req: WebResource = new WebResource();
|
|
||||||
req.method = 'POST';
|
|
||||||
req.url = JunoSubscription.getAuthUrl();
|
|
||||||
req.body = 'grant_type=client_credentials';
|
|
||||||
req.headers.set('Content-Type', 'application/x-www-form-urlencoded');
|
|
||||||
req.headers.set(
|
|
||||||
'Authorization',
|
|
||||||
'Basic ' +
|
|
||||||
new Buffer(JunoSubscription.getClientId() + ':' + JunoSubscription.getClientSecret()).toString('base64')
|
|
||||||
);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
|
|
||||||
GBLog.info( `JunoAPI: Response from Authorization API ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody.access_token;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a HTTP request object to make REST calls.
|
|
||||||
*/
|
|
||||||
private async setupWebhook(): Promise<string> {
|
|
||||||
GBLog.info( `JunoAPI: Setting Webhook...`);
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
|
|
||||||
const host = process.env.BOT_URL;
|
|
||||||
const url = `${host}/store.gbapp/payment_notification`;
|
|
||||||
|
|
||||||
const body = {
|
|
||||||
url: '',
|
|
||||||
eventTypes: ['PAYMENT_NOTIFICATION']
|
|
||||||
};
|
|
||||||
|
|
||||||
const req: WebResource = new WebResource();
|
|
||||||
req.method = 'POST';
|
|
||||||
req.url = urlJoin(JunoSubscription.getResourceUrl(), 'notifications', 'webhooks');
|
|
||||||
|
|
||||||
req.body = body;
|
|
||||||
req.headers.set('Content-Type', 'application/x-www-form-urlencoded');
|
|
||||||
req.headers.set(
|
|
||||||
'Authorization',
|
|
||||||
'Basic ' +
|
|
||||||
new Buffer(JunoSubscription.getClientId() + ':' + JunoSubscription.getClientSecret()).toString('base64')
|
|
||||||
);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
|
|
||||||
GBLog.info( `JunoAPI: Response from Authorization API ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody.access_token;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a HTTP request object to make REST calls.
|
|
||||||
*/
|
|
||||||
private static createRequestObject(
|
|
||||||
token: string,
|
|
||||||
url: string,
|
|
||||||
verb: HttpMethods,
|
|
||||||
body: string,
|
|
||||||
headers: any,
|
|
||||||
externalAccountToken = undefined
|
|
||||||
): WebResource {
|
|
||||||
const req: WebResource = new WebResource();
|
|
||||||
req.method = verb;
|
|
||||||
req.url = url;
|
|
||||||
|
|
||||||
req.headers.set('Content-Type', 'application/json;charset=UTF-8');
|
|
||||||
req.headers.set('Authorization', `Bearer ${token}`);
|
|
||||||
req.headers.set('X-Api-Version', 2);
|
|
||||||
req.headers.set(
|
|
||||||
'X-Resource-Token',
|
|
||||||
externalAccountToken ? externalAccountToken : JunoSubscription.getJunoPrivateKey()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (headers !== undefined) {
|
|
||||||
// tslint:disable-next-line: typedef
|
|
||||||
headers.forEach(e => {
|
|
||||||
req.headers.set(e.name, e.value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
req.body = body;
|
|
||||||
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async PayByBoleto(
|
|
||||||
name: string,
|
|
||||||
document: string,
|
|
||||||
email: string,
|
|
||||||
phone: string,
|
|
||||||
amount: number
|
|
||||||
): Promise<string> {
|
|
||||||
let charge = await this.createCharge(name, document, email, phone, amount, 'BOLETO');
|
|
||||||
|
|
||||||
return charge;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async PayByCC(
|
|
||||||
name: string,
|
|
||||||
document: string,
|
|
||||||
email: string,
|
|
||||||
phone: string,
|
|
||||||
ccNumber: string,
|
|
||||||
ccExpiresOnMonth: string,
|
|
||||||
ccExpiresOnYear: string,
|
|
||||||
ccCode: string,
|
|
||||||
amount: number
|
|
||||||
): Promise<string> {
|
|
||||||
let externalSubscriptionId = '1';
|
|
||||||
|
|
||||||
let charge = await this.createCharge(name, document, email, phone, amount, 'CREDIT_CARD');
|
|
||||||
|
|
||||||
let ccHash = await this.getCardHash(ccNumber, name, ccCode, ccExpiresOnMonth, ccExpiresOnYear);
|
|
||||||
let ccId = await this.getCreditCardId(ccHash);
|
|
||||||
let final = await this.makePayment(ccId, ccHash, charge.Id, email);
|
|
||||||
|
|
||||||
return externalSubscriptionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* Get active users available to the workflow process.
|
|
||||||
*/
|
|
||||||
public async createDigitalAccount(
|
|
||||||
name,
|
|
||||||
document,
|
|
||||||
email,
|
|
||||||
birthDate,
|
|
||||||
phone,
|
|
||||||
businessArea,
|
|
||||||
linesOfBusiness,
|
|
||||||
number: string,
|
|
||||||
digit: string,
|
|
||||||
bank: string
|
|
||||||
) {
|
|
||||||
GBLog.info( `JunoAPI: Calling createDigitalAccount API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), 'digital-accounts');
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'POST', '', undefined);
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
|
|
||||||
let json = {
|
|
||||||
type: 'PAYMENT',
|
|
||||||
name: name,
|
|
||||||
document: document,
|
|
||||||
email: email,
|
|
||||||
birthDate: birthDate,
|
|
||||||
phone: phone
|
|
||||||
};
|
|
||||||
|
|
||||||
GBLog.info( `JunoAPI: Response from createDigitalAccount ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async createCharge(name, document, email, phone, amount, paymentType) {
|
|
||||||
GBLog.info( `JunoAPI: Calling createCharge API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), 'charges');
|
|
||||||
|
|
||||||
let json = {
|
|
||||||
charge: {
|
|
||||||
description: 'string',
|
|
||||||
amount: amount,
|
|
||||||
paymentTypes: [paymentType]
|
|
||||||
},
|
|
||||||
billing: {
|
|
||||||
name: name,
|
|
||||||
document: document,
|
|
||||||
email: email,
|
|
||||||
phone: phone,
|
|
||||||
notify: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'POST', JSON.stringify(json), undefined);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from createCharge ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody._embedded.charges[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public async createPlan(name, amount) {
|
|
||||||
GBLog.info( `JunoAPI: Calling createPlan API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), '/plans');
|
|
||||||
|
|
||||||
let json = {
|
|
||||||
name: name,
|
|
||||||
amount: amount
|
|
||||||
};
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'POST', JSON.stringify(json), undefined);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from createPlan ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async createSubscription(
|
|
||||||
dueDay,
|
|
||||||
planId,
|
|
||||||
description,
|
|
||||||
email,
|
|
||||||
creditCardId,
|
|
||||||
creditCardHash,
|
|
||||||
street,
|
|
||||||
number,
|
|
||||||
city,
|
|
||||||
state,
|
|
||||||
postCode,
|
|
||||||
partnerAccountToken
|
|
||||||
) {
|
|
||||||
GBLog.info( `JunoAPI: Calling createSubscription API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), '/subscriptions');
|
|
||||||
|
|
||||||
let json = {
|
|
||||||
dueDay: dueDay,
|
|
||||||
planId: planId,
|
|
||||||
chargeDescription: description,
|
|
||||||
creditCardDetails: {
|
|
||||||
creditCardId: creditCardId,
|
|
||||||
creditCardHash: creditCardHash
|
|
||||||
},
|
|
||||||
billing: {
|
|
||||||
email: email,
|
|
||||||
address: {
|
|
||||||
street: street,
|
|
||||||
number: number,
|
|
||||||
city: city,
|
|
||||||
state: state,
|
|
||||||
postCode: postCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (partnerAccountToken) {
|
|
||||||
json['split'] = [
|
|
||||||
{
|
|
||||||
recipientToken: this.getAuthorizationToken(),
|
|
||||||
percentage: 90,
|
|
||||||
amountRemainder: true,
|
|
||||||
chargeFee: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
recipientToken: partnerAccountToken,
|
|
||||||
percentage: 10,
|
|
||||||
amountRemainder: false,
|
|
||||||
chargeFee: true
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'POST', JSON.stringify(json), undefined);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from createSubscription ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getBusinessAreas() {
|
|
||||||
GBLog.info( `JunoAPI: Calling getBusinessAreas API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), '/data/business-areas');
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'GET', undefined, undefined);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from getBusiness ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody._embedded.businessAreas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getBanks() {
|
|
||||||
GBLog.info( `JunoAPI: Calling getBanks API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), '/data/banks');
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'GET', undefined, undefined);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from getBanks ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody._embedded.banks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getCompanyTypes() {
|
|
||||||
GBLog.info( `JunoAPI: Calling getCompanyTypes API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), '/data/company-types');
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'GET', undefined, undefined);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from getCompanyTypes ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody._embedded.banks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getAccountPublicKey(externalAccountToken) {
|
|
||||||
GBLog.info( `JunoAPI: Calling getAccountPublicKey API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), '/credentials/public-key');
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'GET', undefined, undefined, externalAccountToken);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from getAccountPublicKey ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.bodyAsText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async listAccountDocuments(externalAccountToken: string) {
|
|
||||||
GBLog.info( `JunoAPI: Calling listAccountDocuments API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), '/documents');
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'GET', undefined, undefined, externalAccountToken);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from listAccountDocuments ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody._embedded.documents;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getAccountDocumentProperties(externalAccountToken: string, id: string) {
|
|
||||||
GBLog.info( `JunoAPI: Calling getAccountDocumentProperties API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), `/documents/${id}`);
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'GET', undefined, undefined, externalAccountToken);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from getAccountDocumentProperties ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async sendAccountDocument(externalAccountToken: string, id: string, file: string) {
|
|
||||||
GBLog.info( `JunoAPI: Calling sendAccountDocument API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), `/documents/${id}/files`);
|
|
||||||
var form = new FormData();
|
|
||||||
form.append('file', await fs.readFile(file));
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(
|
|
||||||
token,
|
|
||||||
url,
|
|
||||||
'POST',
|
|
||||||
form.getBuffer(),
|
|
||||||
form.getHeaders(),
|
|
||||||
externalAccountToken
|
|
||||||
);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from sendAccountDocument ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getAccountBalance(externalAccountToken) {
|
|
||||||
GBLog.info( `JunoAPI: Calling getAccountBalance API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), '/balance');
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'GET', undefined, undefined, externalAccountToken);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from getAccountBalance ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getAccount(externalAccountToken: string, id: string): Promise<string> {
|
|
||||||
GBLog.info( `JunoAPI: Calling Get Digital Accounts API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), '/digital-accounts');
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'GET', undefined, undefined, externalAccountToken);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from Get Digital Accounts ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getCreditCardId(ccHash: string): Promise<string> {
|
|
||||||
GBLog.info( `JunoAPI: Calling tokenizeCreditCard API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), '/credit-cards/tokenization');
|
|
||||||
|
|
||||||
let json = {
|
|
||||||
creditCardHash: ccHash
|
|
||||||
};
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'POST', JSON.stringify(json), undefined);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from tokenizeCreditCard ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody.creditCardId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async makePayment(ccId, ccHash, chargeId, email): Promise<string> {
|
|
||||||
GBLog.info( `JunoAPI: Calling makePayment API...`);
|
|
||||||
|
|
||||||
let token = await this.getAuthorizationToken();
|
|
||||||
const httpClient = new ServiceClient();
|
|
||||||
const url = urlJoin(JunoSubscription.getResourceUrl(), '/payments');
|
|
||||||
|
|
||||||
let json = {
|
|
||||||
chargeId: chargeId,
|
|
||||||
billing: {
|
|
||||||
email: email
|
|
||||||
// address: {
|
|
||||||
// street: street,
|
|
||||||
// number: number,
|
|
||||||
// complement: complement,
|
|
||||||
// neighborhood: neighborhood,
|
|
||||||
// city: city,
|
|
||||||
// state: state,
|
|
||||||
// postCode: postCode
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
creditCardDetails: {
|
|
||||||
creditCardId: ccId,
|
|
||||||
creditCardHash: ccHash
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const req = JunoSubscription.createRequestObject(token, url, 'POST', JSON.stringify(json), undefined);
|
|
||||||
|
|
||||||
const res = await httpClient.sendRequest(req);
|
|
||||||
GBLog.info( `JunoAPI: Response from makePayment ${res.bodyAsText}`);
|
|
||||||
|
|
||||||
return res.parsedBody._embedded.charges[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static isProd() {
|
|
||||||
return process.env.SAAS_JUNO_IS_PROD === 'true';
|
|
||||||
}
|
|
||||||
|
|
||||||
private static getClientId() {
|
|
||||||
return JunoSubscription.isProd() ? process.env.SAAS_JUNO_PROD_CLIENT_ID : process.env.SAAS_JUNO_SANDBOX_CLIENT_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static getClientSecret() {
|
|
||||||
return JunoSubscription.isProd()
|
|
||||||
? process.env.SAAS_JUNO_PROD_CLIENT_SECRET
|
|
||||||
: process.env.SAAS_JUNO_SANDBOX_CLIENT_SECRET;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static getJunoPublicKey() {
|
|
||||||
return JunoSubscription.isProd() ? process.env.SAAS_JUNO_PROD_PUBLIC_KEY : process.env.SAAS_JUNO_SANDBOX_PUBLIC_KEY;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static getJunoPrivateKey() {
|
|
||||||
return JunoSubscription.isProd()
|
|
||||||
? process.env.SAAS_JUNO_PROD_PRIVATE_KEY
|
|
||||||
: process.env.SAAS_JUNO_SANDBOX_PRIVATE_KEY;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static getResourceUrl() {
|
|
||||||
return JunoSubscription.isProd() ? process.env.SAAS_JUNO_PROD_RESOURCE : process.env.SAAS_JUNO_SANDBOX_RESOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static getAuthUrl() {
|
|
||||||
return JunoSubscription.isProd() ? process.env.SAAS_JUNO_PROD_AUTH : process.env.SAAS_JUNO_SANDBOX_AUTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getCardHash(
|
|
||||||
ccNumber: string,
|
|
||||||
name: string,
|
|
||||||
ccCode: string,
|
|
||||||
ccExpiresOnMonth: string,
|
|
||||||
ccExpiresOnYear: string
|
|
||||||
): Promise<string> {
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
let tokenJuno = JunoSubscription.getJunoPublicKey();
|
|
||||||
|
|
||||||
let cardData = {
|
|
||||||
cardNumber: ccNumber,
|
|
||||||
holderName: name,
|
|
||||||
securityCode: ccCode,
|
|
||||||
expirationMonth: ccExpiresOnMonth,
|
|
||||||
expirationYear: ccExpiresOnYear
|
|
||||||
};
|
|
||||||
|
|
||||||
let checkout = new Juno.DirectCheckout(tokenJuno, JunoSubscription.isProd());
|
|
||||||
|
|
||||||
checkout.getCardHash(cardData, resolve, reject);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,135 +0,0 @@
|
||||||
/*****************************************************************************\
|
|
||||||
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
|
||||||
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
|
||||||
| ██ ███ ████ █ ██ █ ████ █████ ██████ ██ ████ █ █ █ ██ |
|
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
|
||||||
| |
|
|
||||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
|
||||||
| Licensed under the AGPL-3.0. |
|
|
||||||
| |
|
|
||||||
| According to our dual licensing model, this program can be used either |
|
|
||||||
| under the terms of the GNU Affero General Public License, version 3, |
|
|
||||||
| or under a proprietary license. |
|
|
||||||
| |
|
|
||||||
| The texts of the GNU Affero General Public License with an additional |
|
|
||||||
| permission and of our proprietary license can be found at and |
|
|
||||||
| in the LICENSE file you have received along with this program. |
|
|
||||||
| |
|
|
||||||
| This program is distributed in the hope that it will be useful, |
|
|
||||||
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
|
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
||||||
| GNU Affero General Public License for more details. |
|
|
||||||
| |
|
|
||||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
|
||||||
| our trademarks remain entirely with us. |
|
|
||||||
| |
|
|
||||||
\*****************************************************************************/
|
|
||||||
|
|
||||||
"use strict"
|
|
||||||
|
|
||||||
import { MainService } from "./MainService.js";
|
|
||||||
|
|
||||||
export class MSSubscriptionService {
|
|
||||||
|
|
||||||
public async handleMSHook(req: any, res: any) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public async handleMSSignUp(req: any, res: any) {
|
|
||||||
let token = req.params.token;
|
|
||||||
let url = `https://marketplaceapi.microsoft.com/api/saas/subscriptions/resolve?api-version=2018-08-31`;
|
|
||||||
let options = {
|
|
||||||
uri: url,
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'x-ms-marketplace-token': token
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let result = null; // TODO: await fetch({});
|
|
||||||
let data = JSON.parse(result);
|
|
||||||
|
|
||||||
const additionalData = {
|
|
||||||
"id": "<guid>", // purchased SaaS subscription ID
|
|
||||||
"subscriptionName": "Contoso Cloud Solution", // SaaS subscription name
|
|
||||||
"offerId": "offer1", // purchased offer ID
|
|
||||||
"planId": "silver", // purchased offer's plan ID
|
|
||||||
"quantity": "20", // number of purchased seats, might be empty if the plan is not per seat
|
|
||||||
"subscription": { // full SaaS subscription details, see Get Subscription APIs response body for full description
|
|
||||||
"id": "<guid>",
|
|
||||||
"publisherId": "contoso",
|
|
||||||
"offerId": "offer1",
|
|
||||||
"name": "Contoso Cloud Solution",
|
|
||||||
"saasSubscriptionStatus": " PendingFulfillmentStart ",
|
|
||||||
"beneficiary": {
|
|
||||||
"emailId": "test@test.com",
|
|
||||||
"objectId": "<guid>",
|
|
||||||
"tenantId": "<guid>",
|
|
||||||
"pid": "<ID of the user>"
|
|
||||||
},
|
|
||||||
"purchaser": {
|
|
||||||
"emailId": "test@test.com",
|
|
||||||
"objectId": "<guid>",
|
|
||||||
"tenantId": "<guid>",
|
|
||||||
"pid": "<ID of the user>"
|
|
||||||
},
|
|
||||||
"planId": "silver",
|
|
||||||
"term": {
|
|
||||||
"termUnit": "P1M",
|
|
||||||
"startDate": "2019 - 05 - 31",
|
|
||||||
"endDate": "2019-06-29",
|
|
||||||
},
|
|
||||||
"isTest": true,
|
|
||||||
"isFreeTrial": false,
|
|
||||||
"allowedCustomerOperations": [
|
|
||||||
"Delete",
|
|
||||||
"Update",
|
|
||||||
"Read"
|
|
||||||
],
|
|
||||||
"sandboxType": "None",
|
|
||||||
"sessionMode": "None"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const service = new MainService();
|
|
||||||
service.createSubscriptionMSFT("email", "plan", "offer",
|
|
||||||
Number.parseInt(additionalData.quantity), additionalData);
|
|
||||||
|
|
||||||
url = `https://marketplaceapi.microsoft.com/api/saas/subscriptions/${data.id}?api-version=2018-08-31`;
|
|
||||||
options = {
|
|
||||||
uri: url,
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'x-ms-marketplace-token': token
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
result = null; // TODO: fetch.
|
|
||||||
data = JSON.parse(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async handleMSLanding(req: any, res: any) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Unsubscribe() {
|
|
||||||
|
|
||||||
}
|
|
||||||
public async Suspend() {
|
|
||||||
|
|
||||||
}
|
|
||||||
public async Reinstateou() {
|
|
||||||
|
|
||||||
}
|
|
||||||
public async ChangePlan() {
|
|
||||||
|
|
||||||
}
|
|
||||||
public async ChangeQuantity() {
|
|
||||||
|
|
||||||
}
|
|
||||||
public async Transfer() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -36,9 +36,48 @@ import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import urlJoin from 'url-join';
|
import urlJoin from 'url-join';
|
||||||
import { GBOService } from './GBOService.js';
|
import { GBOService } from './GBOService.js';
|
||||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
||||||
|
import Stripe from 'stripe';
|
||||||
|
|
||||||
export class MainService {
|
export class MainService {
|
||||||
async createSubscriptionMSFT(email: string, plan: string, offer: string, quantity: number, additionalData: any) { }
|
private stripe: Stripe;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
async createStripeCustomer(name: string, email: string, paymentMethodId: string) {
|
||||||
|
const customer = await this.stripe.customers.create({
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
payment_method: paymentMethodId,
|
||||||
|
invoice_settings: {
|
||||||
|
default_payment_method: paymentMethodId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createStripeSubscription(customerId: string, priceId: string) {
|
||||||
|
const subscription = await this.stripe.subscriptions.create({
|
||||||
|
customer: customerId,
|
||||||
|
items: [{ price: priceId }],
|
||||||
|
expand: ['latest_invoice.payment_intent']
|
||||||
|
});
|
||||||
|
return subscription;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createPaymentMethod(cardNumber: string, expMonth: number, expYear: number, cvc: string) {
|
||||||
|
const paymentMethod = await this.stripe.paymentMethods.create({
|
||||||
|
type: 'card',
|
||||||
|
card: {
|
||||||
|
number: cardNumber,
|
||||||
|
exp_month: expMonth,
|
||||||
|
exp_year: expYear,
|
||||||
|
cvc: cvc
|
||||||
|
}
|
||||||
|
}, {});
|
||||||
|
return paymentMethod;
|
||||||
|
}
|
||||||
|
|
||||||
async createSubscription(
|
async createSubscription(
|
||||||
min: GBMinInstance,
|
min: GBMinInstance,
|
||||||
|
@ -48,90 +87,94 @@ export class MainService {
|
||||||
mobile: string,
|
mobile: string,
|
||||||
botName: string,
|
botName: string,
|
||||||
ccNumber: string,
|
ccNumber: string,
|
||||||
ccExpiresOnMonth: string,
|
ccExpiresOnMonth: number,
|
||||||
ccExpiresOnYear: string,
|
ccExpiresOnYear: number,
|
||||||
ccCode: string,
|
ccCode: string,
|
||||||
templateName: string,
|
templateName: string,
|
||||||
free: boolean
|
free: boolean, planId: string,
|
||||||
)
|
) {
|
||||||
{
|
let externalSubscriptionId = null;
|
||||||
// Syncs internal subscription management.
|
|
||||||
|
if (!free) {
|
||||||
|
try {
|
||||||
|
// Create Stripe payment method
|
||||||
|
const paymentMethod = await this.createPaymentMethod(
|
||||||
|
ccNumber,
|
||||||
|
ccExpiresOnMonth,
|
||||||
|
ccExpiresOnYear,
|
||||||
|
ccCode
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create Stripe customer
|
||||||
|
const customer = await this.createStripeCustomer(
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
paymentMethod.id
|
||||||
|
);
|
||||||
|
|
||||||
|
// Determine price ID based on plan
|
||||||
|
const priceId = planId === 'professional'
|
||||||
|
? process.env.STRIPE_PROFESSIONAL_PRICE_ID
|
||||||
|
: process.env.STRIPE_PERSONAL_PRICE_ID;
|
||||||
|
|
||||||
|
// Create subscription
|
||||||
|
const subscription = await this.createStripeSubscription(
|
||||||
|
customer.id,
|
||||||
|
priceId
|
||||||
|
);
|
||||||
|
|
||||||
|
externalSubscriptionId = subscription.id;
|
||||||
|
} catch (error) {
|
||||||
|
GBLog.error(`Stripe payment failed: ${error.message}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Syncs internal subscription management
|
||||||
|
const status = free ? 'FreeTrial' : 'Active';
|
||||||
|
GBLog.info(`Creating subscription for ${name} (${email}, ${mobile}) with status: ${status}`);
|
||||||
|
|
||||||
const status = 'Started';
|
|
||||||
const planId = 'default';
|
|
||||||
const quantity = 1;
|
const quantity = 1;
|
||||||
const amount = 0.52;
|
const amount = 1;
|
||||||
const language = 'en';
|
|
||||||
|
|
||||||
const subscription = await GBOnlineSubscription.create(<GBOnlineSubscription>{
|
const subscription = await GBOnlineSubscription.create({
|
||||||
instanceId: min.instance.instanceId,
|
instanceId: min.instance.instanceId,
|
||||||
isFreeTrial: free,
|
isFreeTrial: free,
|
||||||
planId: planId,
|
planId: planId,
|
||||||
quantity: quantity,
|
quantity: quantity,
|
||||||
status: status,
|
status: status,
|
||||||
// TODO: lastCCFourDigits: ccNumber...
|
amount: amount,
|
||||||
|
lastCCFourDigits: ccNumber ? ccNumber.slice(-4) : null
|
||||||
});
|
});
|
||||||
|
|
||||||
let externalSubscriptionId = null;
|
// Creates a bot
|
||||||
let service = min.gbappServices['junoSubscription'];
|
GBLog.info('Deploying a blank bot to storage...');
|
||||||
|
|
||||||
if (!free) {
|
|
||||||
// if (ccNumber !== undefined) {
|
|
||||||
// // Performs billing management.
|
|
||||||
|
|
||||||
// externalSubscriptionId = await service.PayByCC(
|
|
||||||
// name,
|
|
||||||
// document,
|
|
||||||
// email,
|
|
||||||
// mobile,
|
|
||||||
// ccNumber,
|
|
||||||
// ccExpiresOnMonth,
|
|
||||||
// ccExpiresOnYear,
|
|
||||||
// ccCode,
|
|
||||||
// amount
|
|
||||||
// );
|
|
||||||
// } else {
|
|
||||||
// externalSubscriptionId = await service.PayByBoleto(name, document, email, mobile);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a bot.
|
|
||||||
|
|
||||||
GBLog.info( 'Deploying a blank bot to storage...');
|
|
||||||
|
|
||||||
const instance = await min.deployService.deployBlankBot(botName, mobile, email);
|
const instance = await min.deployService.deployBlankBot(botName, mobile, email);
|
||||||
|
|
||||||
GBLog.info( 'Creating subscription...');
|
GBLog.info('Creating subscription...');
|
||||||
subscription.instanceId = instance.instanceId;
|
subscription.instanceId = instance.instanceId;
|
||||||
subscription.externalSubscriptionId = externalSubscriptionId;
|
subscription.externalSubscriptionId = externalSubscriptionId;
|
||||||
await subscription.save();
|
await subscription.save();
|
||||||
|
|
||||||
let token =
|
let token =
|
||||||
GBConfigService.get('GB_MODE') === 'legacy'?
|
GBConfigService.get('GB_MODE') === 'legacy' ?
|
||||||
await (min.adminService.acquireElevatedToken as any)(min.instance.instanceId, true) :
|
await (min.adminService.acquireElevatedToken as any)(min.instance.instanceId, true) :
|
||||||
null;
|
null;
|
||||||
|
|
||||||
let siteId = process.env.STORAGE_SITE_ID;
|
let siteId = process.env.STORAGE_SITE_ID;
|
||||||
let libraryId = process.env.STORAGE_LIBRARY;
|
let libraryId = process.env.STORAGE_LIBRARY;
|
||||||
let gboService = new GBOService();
|
let gboService = new GBOService();
|
||||||
|
|
||||||
let sleep = ms => {
|
let sleep = ms => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
setTimeout(resolve, ms);
|
setTimeout(resolve, ms);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GBLog.info('Creating .gbai folder ...');
|
||||||
GBLog.info( 'Creating .gbai folder ...');
|
|
||||||
let item = await gboService.createRootFolder(token, `${botName}.gbai`, siteId, libraryId);
|
let item = await gboService.createRootFolder(token, `${botName}.gbai`, siteId, libraryId);
|
||||||
|
|
||||||
|
GBLog.info('Copying Templates...');
|
||||||
GBLog.info( 'Copying Templates...');
|
|
||||||
// await gboService.copyTemplates(min, item, 'shared.gbai', 'gbkb', botName);
|
|
||||||
// await gboService.copyTemplates(min, item, 'shared.gbai', 'gbot', botName);
|
|
||||||
// await gboService.copyTemplates(min, item, 'shared.gbai', 'gbtheme', botName);
|
|
||||||
// await gboService.copyTemplates(min, item, 'shared.gbai', 'gbdialog', botName);
|
|
||||||
// await gboService.copyTemplates(min, item, 'shared.gbai', 'gbdata', botName);
|
|
||||||
await gboService.copyTemplates(min, item, templateName, 'gbkb', botName);
|
await gboService.copyTemplates(min, item, templateName, 'gbkb', botName);
|
||||||
await gboService.copyTemplates(min, item, templateName, 'gbot', botName);
|
await gboService.copyTemplates(min, item, templateName, 'gbot', botName);
|
||||||
await gboService.copyTemplates(min, item, templateName, 'gbtheme', botName);
|
await gboService.copyTemplates(min, item, templateName, 'gbtheme', botName);
|
||||||
|
@ -140,16 +183,16 @@ export class MainService {
|
||||||
await gboService.copyTemplates(min, item, templateName, 'gbdrive', botName);
|
await gboService.copyTemplates(min, item, templateName, 'gbdrive', botName);
|
||||||
|
|
||||||
await sleep(10000);
|
await sleep(10000);
|
||||||
GBLog.info( 'Configuring .gbot...');
|
GBLog.info('Configuring .gbot...');
|
||||||
await min.core['setConfig'] (min, instance.botId, "Can Publish", mobile + ";");
|
await min.core['setConfig'](min, instance.botId, "Can Publish", mobile + ";");
|
||||||
await min.core['setConfig'](min, instance.botId, "Admin Notify E-mail", email);
|
await min.core['setConfig'](min, instance.botId, "Admin Notify E-mail", email);
|
||||||
await min.core['setConfig'](min, instance.botId, 'WebDav Username', instance.botId);
|
await min.core['setConfig'](min, instance.botId, 'WebDav Username', instance.botId);
|
||||||
await min.core['setConfig'](min, instance.botId, 'WebDav Secret', instance.adminPass);
|
await min.core['setConfig'](min, instance.botId, 'WebDav Secret', instance.adminPass);
|
||||||
|
|
||||||
GBLog.info( 'Bot creation done.');
|
GBLog.info('Bot creation done.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public async otherTasks(min, botName, webUrl, instance, language){
|
public async otherTasks(min, botName, webUrl, instance, language) {
|
||||||
let message = `Seu bot ${botName} está disponível no endereço:
|
let message = `Seu bot ${botName} está disponível no endereço:
|
||||||
<br/><a href="${urlJoin(process.env.BOT_URL, botName)}">${urlJoin(process.env.BOT_URL, botName)}</a>.
|
<br/><a href="${urlJoin(process.env.BOT_URL, botName)}">${urlJoin(process.env.BOT_URL, botName)}</a>.
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -170,7 +213,7 @@ export class MainService {
|
||||||
<br/>
|
<br/>
|
||||||
<br/>Atenciosamente,
|
<br/>Atenciosamente,
|
||||||
<br/>General Bots Online.
|
<br/>General Bots Online.
|
||||||
<br/><a href="https://gb.pragmatismo.com.br">https://gb.pragmatismo.com.br</a>
|
<br/><a href=""></a>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>E-mail remetido por Pragmatismo.
|
<br/>E-mail remetido por Pragmatismo.
|
||||||
<br/>`;
|
<br/>`;
|
||||||
|
@ -180,17 +223,16 @@ export class MainService {
|
||||||
message,
|
message,
|
||||||
language
|
language
|
||||||
);
|
);
|
||||||
|
|
||||||
GBLog.info( 'Generating MS Teams manifest....');
|
GBLog.info('Generating MS Teams manifest....');
|
||||||
|
|
||||||
const appManifest = await min.deployService.getBotManifest(min.instance);
|
const appManifest = await min.deployService.getBotManifest(min.instance);
|
||||||
|
|
||||||
// GBLog.info( 'Sending e-mails....');
|
// GBLog.info( 'Sending e-mails....');
|
||||||
// const emailToken = process.env.SAAS_SENDGRID_API_KEY;
|
// const emailToken = process.env.SAAS_SENDGRID_API_KEY;
|
||||||
// gboService.sendEmail(
|
// gboService.sendEmail(
|
||||||
// emailToken,
|
// emailToken,
|
||||||
// email,
|
// email,
|
||||||
// 'operations@pragmatismo.com.br',
|
|
||||||
// `${botName}`,
|
// `${botName}`,
|
||||||
// message,
|
// message,
|
||||||
// message,
|
// message,
|
||||||
|
|
|
@ -32,7 +32,7 @@ export class GBUtil {
|
||||||
|
|
||||||
|
|
||||||
// When creating/updating a user (hashing before saving to DB)
|
// When creating/updating a user (hashing before saving to DB)
|
||||||
public async static hashPassword(password) {
|
public static async hashPassword(password) {
|
||||||
try {
|
try {
|
||||||
const hash = await bcrypt.hash(password, saltRounds);
|
const hash = await bcrypt.hash(password, saltRounds);
|
||||||
return hash;
|
return hash;
|
||||||
|
@ -43,7 +43,7 @@ export class GBUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
// When comparing passwords (like during login)
|
// When comparing passwords (like during login)
|
||||||
public async static comparePassword(inputPassword, hashedPassword) {
|
public static async comparePassword(inputPassword, hashedPassword) {
|
||||||
try {
|
try {
|
||||||
return await bcrypt.compare(inputPassword, hashedPassword);
|
return await bcrypt.compare(inputPassword, hashedPassword);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -367,7 +367,7 @@ export class GBUtil {
|
||||||
const localName = path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.png`);
|
const localName = path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.png`);
|
||||||
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
|
|
||||||
await fs.writeFile(localName, buffer, { encoding: null });
|
await fs.writeFile(localName, new Uint8Array(buffer), { encoding: null });
|
||||||
|
|
||||||
generatedFiles.push({ localName: localName, url: url, data: buffer });
|
generatedFiles.push({ localName: localName, url: url, data: buffer });
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ module.exports = (async () => {
|
||||||
// Imports npm packages for this .gbdialog conversational application.
|
// Imports npm packages for this .gbdialog conversational application.
|
||||||
|
|
||||||
require('isomorphic-fetch');
|
require('isomorphic-fetch');
|
||||||
const YAML = require('yaml');
|
|
||||||
const http = require('node:http');
|
const http = require('node:http');
|
||||||
const retry = require('async-retry');
|
const retry = require('async-retry');
|
||||||
const createRpcClient = require('@push-rpc/core').createRpcClient;
|
const createRpcClient = require('@push-rpc/core').createRpcClient;
|
||||||
|
@ -185,9 +184,7 @@ module.exports = (async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const TOYAML = json => {
|
const TOYAML = json => {
|
||||||
const doc = new YAML.Document();
|
return json;
|
||||||
doc.contents = json;
|
|
||||||
return doc.toString();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Line of Business logic.
|
// Line of Business logic.
|
||||||
|
|
Loading…
Add table
Reference in a new issue