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
|
||||
data.db
|
||||
.wwebjs_cache
|
||||
*doula*
|
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -165,6 +165,7 @@
|
|||
"sqlite3": "5.1.7",
|
||||
"ssr-for-bots": "1.0.1-c",
|
||||
"strict-password-generator": "1.1.2",
|
||||
"stripe": "^18.0.0",
|
||||
"svg2img": "^1.0.0-beta.2",
|
||||
"swagger-client": "3.29.2",
|
||||
"swagger-ui-dist": "5.17.14",
|
||||
|
@ -41856,6 +41857,19 @@
|
|||
"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": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
|
||||
|
|
|
@ -225,6 +225,7 @@
|
|||
"sqlite3": "5.1.7",
|
||||
"ssr-for-bots": "1.0.1-c",
|
||||
"strict-password-generator": "1.1.2",
|
||||
"stripe": "^18.0.0",
|
||||
"svg2img": "^1.0.0-beta.2",
|
||||
"swagger-client": "3.29.2",
|
||||
"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 { GBServer } from '../../../src/app.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 {
|
||||
|
|
|
@ -205,7 +205,7 @@ export class GBVMService extends GBService {
|
|||
"author": "${min.botId} owner.",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"yaml": "2.4.2",
|
||||
|
||||
"encoding": "0.1.13",
|
||||
"isomorphic-fetch": "3.0.0",
|
||||
"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';
|
||||
|
||||
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) {
|
||||
return {
|
||||
id: '/welcome_saas_botname',
|
||||
waterfall: [
|
||||
async step => {
|
||||
const locale = 'en-US';
|
||||
|
||||
await step.prompt('textPrompt', Messages[locale].whats_botname);
|
||||
},
|
||||
async step => {
|
||||
const locale = 'en-US';
|
||||
|
||||
const extractEntity = text => {
|
||||
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) {
|
||||
await step.context.sendActivity(Messages[locale].validation_enter_valid_botname);
|
||||
|
||||
return await step.replaceDialog('/welcome_saas_botname', step.activeDialog.state.options);
|
||||
} else {
|
||||
const botName = value[0];
|
||||
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);
|
||||
} else {
|
||||
step.activeDialog.state.options.botName = botName;
|
||||
|
||||
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) {
|
||||
return {
|
||||
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) {
|
||||
const locale = 'en-US';
|
||||
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));
|
||||
const service = new MainService();
|
||||
await service.createSubscription(
|
||||
|
@ -220,49 +251,10 @@ export class NewUserDialog extends IGBDialog {
|
|||
step.activeDialog.state.options.ccExpiresOnYear,
|
||||
step.activeDialog.state.options.ccSecuritycode,
|
||||
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) {
|
||||
return {
|
||||
|
@ -279,28 +271,28 @@ export class NewUserDialog extends IGBDialog {
|
|||
step.activeDialog.state.options.ccExpiresOnYear = null;
|
||||
step.activeDialog.state.options.ccSecuritycode = 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);
|
||||
|
||||
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)) {
|
||||
await step.context.sendActivity(Messages[locale].ok_get_information);
|
||||
|
||||
return await step.replaceDialog('/profile_name', step.activeDialog.state.options);
|
||||
} else {
|
||||
const name = SaaSPackage.welcomes ? SaaSPackage.welcomes[mobile] : null;
|
||||
step.activeDialog.state.options.name = name;
|
||||
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);
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,7 +34,6 @@ import { IGBPackage, GBMinInstance, IGBCoreService, GBLog, IGBAdminService, GBDi
|
|||
import { Sequelize } from 'sequelize-typescript'
|
||||
import { GBOnlineSubscription } from './model/MainModel.js'
|
||||
|
||||
import { MSSubscriptionService } from './service/MSSubscription.js'
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import { NewUserDialog } from './dialog/NewUserDialog.js'
|
||||
import { GBOService } from './service/GBOService.js'
|
||||
|
@ -48,12 +47,10 @@ export class SaaSPackage implements IGBPackage {
|
|||
public getDialogs(min: GBMinInstance) {
|
||||
return [NewUserDialog.getDialog(min),
|
||||
NewUserDialog.getBotNameDialog(min),
|
||||
NewUserDialog.getVoucherDialog(min),
|
||||
NewUserDialog.getBotTemplateDialog(min),
|
||||
NewUserDialog.getReturnFromPayment(min),
|
||||
NewUserDialog.getReturnFromCC(min),
|
||||
NewUserDialog.getReturnFromDocument(min),
|
||||
NewUserDialog.getDialogBatch(min)
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -62,21 +59,6 @@ export class SaaSPackage implements IGBPackage {
|
|||
|
||||
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;
|
||||
|
||||
@Column
|
||||
externalSubscriptionId: string // MSFT or
|
||||
externalSubscriptionId: string;
|
||||
|
||||
@Column
|
||||
saasSubscriptionStatus: string
|
||||
saasSubscriptionStatus: string;
|
||||
|
||||
@Column
|
||||
isFreeTrial: boolean
|
||||
isFreeTrial: boolean;
|
||||
|
||||
@Column
|
||||
planId: string;
|
||||
|
@ -74,8 +75,14 @@ export class GBOnlineSubscription extends Model<GBOnlineSubscription> {
|
|||
quantity: number;
|
||||
|
||||
@Column
|
||||
lastCCFourDigits: number;
|
||||
lastCCFourDigits: string;
|
||||
|
||||
@Column
|
||||
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 { GBOService } from './GBOService.js';
|
||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
||||
import Stripe from 'stripe';
|
||||
|
||||
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(
|
||||
min: GBMinInstance,
|
||||
|
@ -48,90 +87,94 @@ export class MainService {
|
|||
mobile: string,
|
||||
botName: string,
|
||||
ccNumber: string,
|
||||
ccExpiresOnMonth: string,
|
||||
ccExpiresOnYear: string,
|
||||
ccExpiresOnMonth: number,
|
||||
ccExpiresOnYear: number,
|
||||
ccCode: string,
|
||||
templateName: string,
|
||||
free: boolean
|
||||
)
|
||||
{
|
||||
// Syncs internal subscription management.
|
||||
free: boolean, planId: string,
|
||||
) {
|
||||
let externalSubscriptionId = null;
|
||||
|
||||
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 amount = 0.52;
|
||||
const language = 'en';
|
||||
const amount = 1;
|
||||
|
||||
const subscription = await GBOnlineSubscription.create(<GBOnlineSubscription>{
|
||||
const subscription = await GBOnlineSubscription.create({
|
||||
instanceId: min.instance.instanceId,
|
||||
isFreeTrial: free,
|
||||
planId: planId,
|
||||
quantity: quantity,
|
||||
status: status,
|
||||
// TODO: lastCCFourDigits: ccNumber...
|
||||
amount: amount,
|
||||
lastCCFourDigits: ccNumber ? ccNumber.slice(-4) : null
|
||||
});
|
||||
|
||||
let externalSubscriptionId = null;
|
||||
let service = min.gbappServices['junoSubscription'];
|
||||
|
||||
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...');
|
||||
|
||||
// Creates a bot
|
||||
GBLog.info('Deploying a blank bot to storage...');
|
||||
const instance = await min.deployService.deployBlankBot(botName, mobile, email);
|
||||
|
||||
GBLog.info( 'Creating subscription...');
|
||||
GBLog.info('Creating subscription...');
|
||||
subscription.instanceId = instance.instanceId;
|
||||
subscription.externalSubscriptionId = externalSubscriptionId;
|
||||
await subscription.save();
|
||||
|
||||
let token =
|
||||
GBConfigService.get('GB_MODE') === 'legacy'?
|
||||
await (min.adminService.acquireElevatedToken as any)(min.instance.instanceId, true) :
|
||||
null;
|
||||
let token =
|
||||
GBConfigService.get('GB_MODE') === 'legacy' ?
|
||||
await (min.adminService.acquireElevatedToken as any)(min.instance.instanceId, true) :
|
||||
null;
|
||||
|
||||
let siteId = process.env.STORAGE_SITE_ID;
|
||||
let libraryId = process.env.STORAGE_LIBRARY;
|
||||
let gboService = new GBOService();
|
||||
|
||||
|
||||
let sleep = ms => {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
GBLog.info( 'Creating .gbai folder ...');
|
||||
GBLog.info('Creating .gbai folder ...');
|
||||
let item = await gboService.createRootFolder(token, `${botName}.gbai`, siteId, libraryId);
|
||||
|
||||
|
||||
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);
|
||||
GBLog.info('Copying Templates...');
|
||||
await gboService.copyTemplates(min, item, templateName, 'gbkb', botName);
|
||||
await gboService.copyTemplates(min, item, templateName, 'gbot', 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 sleep(10000);
|
||||
GBLog.info( 'Configuring .gbot...');
|
||||
await min.core['setConfig'] (min, instance.botId, "Can Publish", mobile + ";");
|
||||
GBLog.info('Configuring .gbot...');
|
||||
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, 'WebDav Username', instance.botId);
|
||||
await min.core['setConfig'](min, instance.botId, 'WebDav Secret', instance.adminPass);
|
||||
await min.core['setConfig'](min, instance.botId, 'WebDav Username', instance.botId);
|
||||
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:
|
||||
<br/><a href="${urlJoin(process.env.BOT_URL, botName)}">${urlJoin(process.env.BOT_URL, botName)}</a>.
|
||||
<br/>
|
||||
|
@ -170,7 +213,7 @@ export class MainService {
|
|||
<br/>
|
||||
<br/>Atenciosamente,
|
||||
<br/>General Bots Online.
|
||||
<br/><a href="https://gb.pragmatismo.com.br">https://gb.pragmatismo.com.br</a>
|
||||
<br/><a href=""></a>
|
||||
<br/>
|
||||
<br/>E-mail remetido por Pragmatismo.
|
||||
<br/>`;
|
||||
|
@ -180,17 +223,16 @@ export class MainService {
|
|||
message,
|
||||
language
|
||||
);
|
||||
|
||||
GBLog.info( 'Generating MS Teams manifest....');
|
||||
|
||||
|
||||
GBLog.info('Generating MS Teams manifest....');
|
||||
|
||||
const appManifest = await min.deployService.getBotManifest(min.instance);
|
||||
|
||||
|
||||
// GBLog.info( 'Sending e-mails....');
|
||||
// const emailToken = process.env.SAAS_SENDGRID_API_KEY;
|
||||
// gboService.sendEmail(
|
||||
// emailToken,
|
||||
// email,
|
||||
// 'operations@pragmatismo.com.br',
|
||||
// `${botName}`,
|
||||
// message,
|
||||
// message,
|
||||
|
|
|
@ -32,7 +32,7 @@ export class GBUtil {
|
|||
|
||||
|
||||
// When creating/updating a user (hashing before saving to DB)
|
||||
public async static hashPassword(password) {
|
||||
public static async hashPassword(password) {
|
||||
try {
|
||||
const hash = await bcrypt.hash(password, saltRounds);
|
||||
return hash;
|
||||
|
@ -43,7 +43,7 @@ export class GBUtil {
|
|||
}
|
||||
|
||||
// When comparing passwords (like during login)
|
||||
public async static comparePassword(inputPassword, hashedPassword) {
|
||||
public static async comparePassword(inputPassword, hashedPassword) {
|
||||
try {
|
||||
return await bcrypt.compare(inputPassword, hashedPassword);
|
||||
} catch (err) {
|
||||
|
@ -367,7 +367,7 @@ export class GBUtil {
|
|||
const localName = path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.png`);
|
||||
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 });
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ module.exports = (async () => {
|
|||
// Imports npm packages for this .gbdialog conversational application.
|
||||
|
||||
require('isomorphic-fetch');
|
||||
const YAML = require('yaml');
|
||||
const http = require('node:http');
|
||||
const retry = require('async-retry');
|
||||
const createRpcClient = require('@push-rpc/core').createRpcClient;
|
||||
|
@ -185,9 +184,7 @@ module.exports = (async () => {
|
|||
};
|
||||
|
||||
const TOYAML = json => {
|
||||
const doc = new YAML.Document();
|
||||
doc.contents = json;
|
||||
return doc.toString();
|
||||
return json;
|
||||
};
|
||||
|
||||
// Line of Business logic.
|
||||
|
|
Loading…
Add table
Reference in a new issue