Mayron, eu controlo a assinatura diretamente pelo meu backoffice também. O que eu fiz foi basicamente na assinatura criar um dt_vencimento e um dt_bloqueio.
Para cartão eu crio o token com o reuse: true na API deles e armazeno essa informação.
Dito isso, eu tenho a seguinte regra:
Caso boleto, eu emito o boleto em D-3 sobre a data de vencimento. Então o cliente tem 3 dias pós emissão para pagar. E o bloqueio eu coloco em dt_vencimento + INTERVAL 7 DAY, ou seja meu sistema só irá bloquear de fato sete dias após o último vencimento.
Caso cartão eu solicito a captura do valor no dia do vencimento às 4h da manhã, caso não consiga cobrar deixo um botão para o cliente tentar mais duas vezes. Após isso ele é obrigado a cadastrar novamente o cartão de crédito.
Sobre os webhooks, sempre que obtenho um status de sucesso eu calculo a nova data de vencimento e a nova data de bloqueio no banco de dados. Apenas para boleto existe um negócio bem interessante que é o status identified que basicamente significa que foi identificado o pagamento, porém ele ainda não foi liquidado de fato em sua conta. Como existe o risco do cliente entrar no atendimento do banco dele e cancelar esse pagamento a tratativa que faço sempre é: caso o status seja identified coloca o dt_bloqueio para daqui 3 dias úteis. Porém como a Efí geralmente deposita no próximo dia útil o webhook com a identificação do pagamento já virá no próximo dia útil e a rotina para recalcular as novas datas entrará em ação.
Dessa forma ficou bacana, pois consigo criar planos com flexibilidade. Adicionar valores novos ou variáveis que foram contratados durante o mês e caso precise de fazer qualquer migração não precisaria necessariamente usar uma API de assinaturas do novo fornecedor (visto que pode levar um tempo para seguir a lógica de um possível novo fornecedor). A lógica fica toda na minha aplicação e o PSP faz apenas a parte dele que é gerir o fluxo de cobrança na forma de pagamento que eu escolher