Como a obsessão por código matou meu primeiro freela
Fugindo um pouco dos posts didáticos, vim compartilhar uma história que aconteceu no início da minha carreira. Talvez seja útil pra você que está começando, ou, pra quem já passou por isso, sofrer junto com meu eu do passado.
É uma história de como um projeto tecnicamente perfeito (funcionamento e requisitos) falhou em tudo que devia entregar, custou ao cliente alguns poucos milhares de reais, e eu acabei não ganhando nada com isso.
Contexto
Estava no meu segundo ano de faculdade, e durante o primeiro já tinha aprendido sobre estruturas de dados básicas e algoritmos. Também tinha feito alguns cursos da Rocketseat, Udemy e tudo que se pensar - a fim de fugir apenas do acadêmico e procurar conhecer como se fazem aplicações do mundo real.
Nessa época, já me sentia confortável em criar meus CRUDs simples, lidar com bancos de dados relacionais e não relacionais, e fazer um frontend dinâmico com React Class Components. Claro, nenhum conhecimento era profundo nem nada do tipo, tudo superficial, mas pro objetivo dava pro gasto.
Eu tenho dois amigos que, na época, estavam numa situação similar a mim. Um deles era mais voltado pro frontend e o outro pro backend, enquanto eu estava mais como "fullstack", me arriscando nas duas áreas.
Decidimos nos unir e fundar nossa "startup", que não tinha nada formal, era só um nome para nosso grupo de projetinhos da faculdade. No entanto, fui contactado por um conhecido da minha família sobre um projeto que podia ser interessante.
O projeto
Marcamos uma reunião presencial para entender o projeto, o que nos foi passado não parecia nada de mais. Era apenas um portal em que um único administrador poderia fazer o CRUD de alguns posts e apenas usuários pagantes poderiam ver eles.
A ideia era que as atualizações feitas pelo administrador chegassem o mais rápido possível, por que o conteúdo era sempre "urgente". Sobre os usuários pagantes, deveríamos aceitar diversos tipos de pagamento, incluindo o boleto aqui do Brasil e atualizar o status de pagante dos usuários de forma automática, oferecendo um período gratuito no início e cancelando a assinatura se um novo pagamento não fosse efetuado no prazo.
Todo o objetivo era migrar um negócio digital que estava centralizado no Telegram para uma plataforma própria, pois já tinha crescido demais e administrar o canal era muito custoso.
Era muito importante para o cliente ter uma fonte única de custo, afinal estava buscando praticidade. Não deveríamos espalhar serviços do nosso backend por aí e no final receber contas de 5 lugares diferentes.
A tecnologia
Já que queríamos centralizar o custo num só lugar, escolhemos o Firebase como opção de BaaS. Isso caiu como uma roda, já que o Firestore atualiza seu conteúdo no frontend de forma reativa, cumprindo, por tabela, o requisito de atualizações rápidas de conteúdo.
Para o frontend, o construímos em React Class Components - e logo depois o migramos para os novíssimos React Hooks. O deploy do frontend era feito num CD no GitHub, que enviava a nova versão para o Firebase Hosting, mas antes criava uma branch e deploy de staging, tudo automatizado.
A parte de autenticação do usuário também vivia no Firebase, usando Firebase Auth. Podíamos autenticar pelo Google ou somente email e senha. O email de verificação de conta também era algo muito fácil de se fazer pelo Firebase.
O fluxo inicial da aplicação era muito parecido com o seguinte:
Depois do grosso da aplicação estar pronto, surgiu um novo requisito não planejado antes: o administrador poderia adicionar outros administradores em algum momento. Isso mudou nossa estrutura simples, afinal, não podemos confiar que o frontend seja seguro o suficiente para mudar as permissões de um usuário.
A saída que encontramos foi criar uma Firebase Cloud Function, que tinha a Firebase Admin SDK - em outra palavras, não precisava de um contexto de autenticação para bater nos serviços, o próprio servidor tomava conta disso.
Dessa forma, implementamos um sistema de master admin (nosso cliente) poder permissionar outros usuários ativos - ou até mesmo convidar um email não cadastrado a ser um admin. Nosso fluxo cresceu para:
Finalmente, chegou a hora de lidar de lidar com a parte da assinatura dos usuários. Queriamos fazer a funcionalidade básica funcionando antes de criar a integração com o Gateway de pagamento em si.
Nossa ideia foi a seguinte: no documento de cada usuário temos "roles" que ditam os poderes do usuário na nossa aplicação - similar a OAuth. Só tinhamos duas roles "pagante" e "não pagante", que eram atualizadas duas vezes ao dia por um cronjob que criamos no Firebase.
O cronjob tomava conta de ouvir a coleção de pagamentos e assinatura do Firestore (banco de dados) e, com base nos últimos pagamentos, atualizava a role de autenticação do usuário.
Nessa etapa, nosso fluxo cresceu para:
O gateway de pagamentos
No início, junto ao cliente, decidimos pelo PayPal, por já ser bem conhecido. Levamos algumas boas semanas tentando integrar com o sistema do PayPal de assinaturas e webhooks. Sinceramente, até hoje acho que a documentação daquilo era extremamente ruim. Não só faltavam informações, como também o ambiente de sandbox tinha erros que impediam totalmente o teste das funcionalidades que queríamos.
Nosso cliente já havia comprado o domínio dele e aberto o CNPJ - o que estava custando bastante todo mês.
Após perder muito tempo com o PayPal e não conseguir sair do lugar, resolvemos desistir da ideia e procurar um novo gateway. Descobri o Stripe, que na época tinha uma integração com o Firebase. Basicamente, linkamos a chave do nosso projeto no Stripe com o Firebase, assim, o Stripe tomava conta de atualizar a nossa coleção de pagamentos. Perfeito! Tudo com o Stripe funcionava muito bem, e nem tínhamos que criar uma nova tela para compra, já que o Stripe também tomava conta dos redirecionamentos. Era possível criar os produtos (assinaturas) a serem vendidas diretamente no portal do Stripe, toda a administração disso também era feita por lá.
Ainda assim, nosso cliente insistiu que era necessário aceitar boletos, funcionalidade que não era suportada pelo Stripe na época - não sei se já é hoje. Como o PayPal fora de questão, resolvemos optar pelo Pagar.me.
O Pagar.me foi definitivamente mais difícil que o Stripe, mas pelo menos, diferente do PayPal, sua área de testes funcionava bem, o que possibilitou testar os webhooks de forma efetiva. No entanto, a documentação tinha diversos erros na época, além da SDK para o JS não ter JSDocs nem ser feita em Typescript, o que dificultou muito o processo.
Também demos o azar de integrar com o Pagar.me bem na época em que ele estava em transição de versões, tanto da API quanto do portal de testes, o que levou a ainda mais trabalho. Isso significava que parte das nossas requisições podiam ser feitas pela SDK, mas parte devia ser feito diretamente batendo nos endpoints, o que aumentou a complexidade.
Por fim, nosso fluxo cresceu para:
Os finalmentes
Bom, os finalmentes não foram muito fáceis. Diferente da especificação inicial, o cliente insistiu que o frontend web devia ser totalmente responsivo. Isso levou a um trabalho bem árduo do nosso coitado desenvolvedor responsável pelo front.
Além disso, insistiu que uma aplicação nativa para iOS/Android era requisito. Mesmo o nosso frontend sendo responsivo e tenho suporte para PWA - que na época não era tão suportado pelo iOS.
Finalmente, ambas as plataformas mobile e web deveríam ter localização de conteúdo, pois estava recebendo clientes de fora do país. Assim, nos aventuramos por i18n.
Foi minha primeira vez lidando com React Native, mas fiquei orgulhoso que meus conhecimentos com React foram o suficiente para conseguir criar uma aplicação relativamente bonita, funcional (apenas readonly nos dados) e que satisfez o cliente. O importante era ver o conteúdo e ser redirecionado para a página web de assinatura, o que fazia com maestria.
O nosso fluxo final foi:
Desenvolvemos tudo isso conciliando com provas da faculdade e projetos, além das aulas. Como sempre, haviam cobranças do cliente relativas a prazo, mesmo com novos requisitos surgindo sempre.
No final, conseguimos entregar toda a aplicação com CD pronto para todas as Firebase Cloud Functions e Hosting no GitHub em torno de 9 meses.
A ruína do projeto
Tudo parecia extremamente bom, tudo funcionava sem nenhum problema. Nossa versão mobile já estava em análise pela Apple Store e Play Store, e o site funcionava muito bem com a versão de playground do Stripe e Pagar.me.
Chegou a hora de criar o projeto de produção de ambos os gateways de pagamento. Isso envolvia um trâmite legal com o CNPJ do nosso cliente, o que levou um tempo.
Após mais ou menos um mês, chegou a resposta - NEGADO.
Obviamente estavamos incrédulos, afinal, a empresa estava registrada e funcionando. Entramos em contato com o suporte para saber o que aconteceu:
A empresa oferece serviços que podem ser entendidos como incentivo à aposta, isso é contra nossos termos de serviço.
Esquecemos totalmente de verificar a parte legal dos gateways. Nossa plataforma tinha como objetivo o cliente postar dicas de apostas para jogos esportivos, e, na nossa cabeça inocente, nunca passou que talvez os gateways não aceitassem isso.
Nossa implementação estava muito acoplada ao Stripe e Pagar.me, na época, apenas alternativas completamente duvidosas estavam disponíveis, acho que Pix nem era uma opção ainda.
Comunicamos isso ao cliente, que obviamente não ficou feliz. O pagamento não foi realizado à nossa "startup", e, assim, ele teve prejuízo tendo que abrir e manter o CNPJ e domínio, além de falhar na promessa para os assinantes no Telegram dele.
Naquela época, aposta esportiva não era nem de perto algo tão comum como é hoje. Me pergunto o que teria acontecido caso o projeto tivesse dado certo, poderia ter gerado muito dinheiro.
Lições
Aqui vão algumas lições que tirei com o projeto:
- Tecnologia não é tudo, veja como esquecer os requisitos legais matou o projeto no final
- Seja diplomático nas negociações, adendos aos requisitos devem ser MUITO bem especificados, precificados e adicionados ao prazo do projeto
- Aprenda a dizer não
Assim, nossa plataforma web/mobile funcional pelos menos serviu para nosso aprendizado. Até hoje fico um pouco triste de não podermos ver algo que demorou tanto tempo para ser feito rodar fora do ambiente de staging.