import { Injectable } from '@nestjs/common' import { isNil } from 'lodash' import { Api } from '../../typings/global' import { HttpService } from '../http' import { CardType } from '../../models' import { Person, Addon } from './models' import { ForeignIntegrationStatus, SignInOptions, SingleAccessToken } from './types' import { SmartfitHelper } from './helpers' const MOCK_PERSON = Person.build({ id: 3796067, email: 'vinicius@n2bbrasil.com', name: 'Marcus Vinicius Marin', phone: '11-9453484229', full_phone: '+55 11 945348422', status: 'active', turnstile_status: 'active', membership_due_date: '10', payment_method: 'Cartão de Crédito', birthdate: '1982-05-11', remaining_guests: 0, limit_guests: 0, purchase_confirmed_at: '2017-10-31T20:47:13.000-02:00', plan: 'Smart', black_benefits: false, location_acronym: 'SPCCRR3', location_country: 'Brazil', photo_url: null, last_email_message_deliver_at: null, gender: 'Masculino', welsher: false, main_purchase_expired_at: null, main_purchase_frozen: false, address: { complement: '', number: '16', region: 'Vila Carro', street: 'Avenida Norberto Mayer', zip: '03425040', zone: null, city: 'São Paulo', state: 'São Paulo', }, smartphone_configs: [], password_recovery_url: 'http://www.smartfit.com.br/passwords/new?auth_token=fSHTG6MYGuZRUuUpKd', can_purchase_addon: true, card_number: '8956', addons_installments: [], auth_token: 'fSHTG6MYGuZRUuUpKd', }) @Injectable() export class SmartfitApi { protected headers = { 'Cache-Control': 'no-cache', Authorization: `Token token=${this.authorizationToken}`, 'Content-Type': 'application/json', } constructor(protected readonly httpService: HttpService) {} protected get authorizationToken(): string { return process.env.SMARTFIT_API_AUTHORIZATION_TOKEN } protected get clientToken(): string { return process.env.SMARTFIT_API_CLIENT_TOKEN } protected get endpoint(): string { return process.env.SMARTFIT_API_ENDPOINT } protected get privatedEndpoint(): Api { return globalThis.secret.smartfit.privated } protected url(path: string, restricted = false): string { let basePath = this.endpoint if (restricted) basePath = this.privatedEndpoint.endpoint return `${basePath}${path}` } async getByLogin(login: string): Promise { return this.getSession(login, { field: 'client_token', value: this.clientToken }) } async signIn({ login, password }: SignInOptions): Promise { return this.getSession(login, { field: 'password', value: password }) } async findAddons(access: SingleAccessToken): Promise> { const addons = await this.httpService.get(this.url(`people/${access.token}/addons`), { headers: this.headers, errorMessage: 'Erro ao tentar buscar addons do aluno na SmartFit.', name: this.constructor.name, timeout: 10000, }) return addons.map((addon: any) => Addon.build(addon.purchase_addon)) } async addAddon(access: SingleAccessToken, addonCode: string, location_acronym?: string): Promise { try { const body = { single_access_token: access.token, code: addonCode, origin: 'equipment', ...(isNil(location_acronym) ? {} : { location_acronym }), } const result = await this.httpService.post(this.url(`people/addons`), body, { headers: this.headers, errorMessage: `Erro ao tentar adicionar addon ${addonCode} ao aluno na SmartFit.`, name: this.constructor.name, timeout: 10000, }) if (location_acronym === 'DIGITAL') console.log('Assinatura via unidade DIGITAL') return result } catch (error) { if (location_acronym === 'DIGITAL') throw error console.error(error.message) console.log('Tentando via unidade DIGITAL') return this.addAddon(access, addonCode, 'DIGITAL') } } async removeAddon(access: SingleAccessToken, addonCode: string): Promise { return this.httpService.delete(this.url(`people/${access.token}/addons/${addonCode}`), { headers: this.headers, errorMessage: `Erro ao tentar remover addon ${addonCode} do aluno na SmartFit.`, name: this.constructor.name, timeout: 10000, }) } async getPersonByToken(access: SingleAccessToken): Promise { if (process.env.STAGE !== 'prod' && access.token === 'fSHTG6MYGuZRUuUpKd') return MOCK_PERSON const person = await this.httpService.get(this.url(`person_session/${access.token}`), { headers: this.headers, errorMessage: 'Erro ao tentar buscar os dados do aluno na SmartFit.', name: this.constructor.name, timeout: 10000, }) return Person.build({ ...person, auth_token: access.token }) } async getPersonByLogin(login: string): Promise { if (process.env.STAGE !== 'prod' && login === '22223702805') return MOCK_PERSON try { const token = await this.getByLogin(login) return token?.token ? this.getPersonByToken(token) : null } catch (error) { if (error.statusCode === 422) return undefined throw error } } async getWalletToken(walletToken: string): Promise<{ token: string; kind: CardType; source?: string }> { try { const { token, kind, source } = await this.httpService.get(this.url(`wallet_tokens/${walletToken}`, true), { headers: { ...this.headers, Authorization: `Token token=${this.privatedEndpoint.token.authorization}` }, errorMessage: 'Erro ao tentar buscar o token do cartão do aluno na SmartFit.', name: this.constructor.name, timeout: 10000, }) return { token, source, kind: kind === 'credit_card' ? 'credit' : 'debit' } } catch (error) { if (process.env.STAGE !== 'prod') return { token: 'mock', kind: 'credit' } throw error } } async createIntegration( id: string, document: string, email: string, status?: ForeignIntegrationStatus, update = false, ): Promise { return this.httpService[update ? 'patch' : 'post']( this.url('person/foreign_integrations', true), update ? { id, status } : { id, document, email, status }, { headers: { ...this.headers, Authorization: `Token token=${this.privatedEndpoint.token.authorization}` }, errorMessage: 'Erro ao realizar uma integração de status do aluno na SmartFit.', name: this.constructor.name, timeout: 6000, }, ) } private async getSession( login: string, authentication: { field: string; value: string }, ): Promise { if (process.env.STAGE !== 'prod' && login === '22223702805') return { token: 'fSHTG6MYGuZRUuUpKd' } try { const body = { login: new SmartfitHelper().cleanUpLogin(login), authentication_field: authentication.field, authentication_value: authentication.value, } const token = await this.httpService.post<{ auth_token: string }>(this.url('person_session'), body, { headers: this.headers, name: this.constructor.name, timeout: 10000, }) return { token: token.auth_token } } catch (error) { if (error.message === 'invalid_login') return null error.message = `Erro ao tentar realizar o login de ${login} na SmartFit.` throw error } } }