Sistema de resposta automática a disputas do Stripe com PDFs de evidência
De Wikiprompt, a enciclopédia livre de prompts
Sistema de resposta automática a disputas do Stripe com PDFs de evidência Uma especificação completa de construção para um sistema automatizado de disputas de estorno do Stripe: envio automático via webhook, PDFs de evidência com capturas de tela do produto, um worker de sincronização por CLI e um mini painel administrativo.
Mídia relacionada
Conteúdo do PromptSalvar
🌐
Construa um sistema de resposta automática a disputas para Stripe que:
1. Coleta de evidências compartilhada (app/dispute_evidence.php)
Crie um arquivo compartilhado com funções usadas tanto pelo webhook quanto pelo trabalhador de sincronização. Isso evita duplicar a lógica de evidências.
Funções-chave:
- getDisputeUserPlan($user, $stripe) - obtém o plano de assinatura do usuário da API do Stripe (fonte da verdade, já que o campo de plano no banco de dados local é limpo no cancelamento). Recorre aos campos do banco de dados local se a chamada ao Stripe falhar. Mapeia IDs de produtos para nomes de planos e inclui preço/intervalo e status de cancelamento.
- collectDisputeEvidence($stripe, $user, $email, $charge, $photosDb) - coleta todas as evidências de texto e arquivos, retorna um array pronto para enviar ao Stripe.
- generateServiceDocPdf($stripe, $user, $email, $photos_done, $recent_photos, $total_amount_paid) - gera um PDF com informações do cliente, resumo de uso, tabela de atividade recente e até 6 imagens reais de produtos (redimensionadas para JPEG de 500px de largura / qualidade 75 para ficar abaixo do limite de upload de arquivos de 5MB do Stripe). Retorna tanto o ID do arquivo do Stripe quanto os dados PDF brutos.
Importante: obtenha total_amount_paid da API de cobranças do Stripe (soma de cobranças bem-sucedidas e não reembolsadas) em vez de confiar no banco de dados local que pode ser nulo/desatualizado.
2. Manipulador de webhook (em stripe_webhook.php)
Capture eventos charge.dispute.created. Quando uma disputa chegar:
- Obtenha os objetos de disputa, cobrança e cliente do Stripe
- Procure o usuário no banco de dados local por stripe_customer_id
- Salve a disputa em um banco de dados SQLite de disputas (campos: dispute_id, charge_id, payment_intent_id, stripe_customer_id, user_id, email, amount, currency, reason, status, epoch_created, epoch_evidence_submitted, evidence_json, stripe_response, epoch_resolved, outcome)
- Chame collectDisputeEvidence() para coletar todas as evidências (texto + uploads de arquivos)
- Envie evidências ao Stripe via $stripe->disputes->update($dispute_id, ['evidence' => $evidence])
- Envie uma notificação do Telegram de que uma nova disputa chegou e as evidências foram enviadas automaticamente
Também capture eventos charge.dispute.updated e charge.dispute.closed para rastrear resultados de disputas (ganhas/perdidas) no banco de dados e enviar notificações do Telegram com o resultado.
3. Campos de evidência enviados ao Stripe
Campos de TEXTO (escreva strings diretamente):
- product_description - descreva o que é o produto/serviço
- customer_name / customer_email_address - do objeto de cliente do Stripe
- access_activity_log - registro de uso detalhado: data de inscrição, número de itens/ações feitos, última data de atividade, plano de assinatura (do Stripe), plataforma, valor total pago (do Stripe), atividade recente com carimbos de data/hora
- uncategorized_text - o argumento "por que devemos ganhar": o cliente se inscreveu em X, usou ativamente o serviço fazendo Y coisas, valor total pago, o serviço foi entregue digitalmente/instantaneamente, o cliente nunca nos contatou para reembolso antes de disputar
- refund_policy_disclosure / cancellation_policy_disclosure - quando as políticas foram apresentadas (durante o checkout, sempre acessíveis em /legal)
- refund_refusal_explanation / cancellation_rebuttal - prova de uso e falta de contato anterior
- service_date - data da cobrança (formato Y-m-d)
Campos de UPLOAD DE ARQUIVO (carregue o arquivo no Stripe primeiro via $stripe->files->create(['purpose'=>'dispute_evidence', 'file'=>fopen($path,'r')]), depois passe o ID file_xxxxx retornado):
- receipt - puxe o PDF da fatura diretamente do Stripe ($stripe->invoices->retrieve($charge->invoice)->invoice_pdf), baixe e carregue como evidência de disputa
- service_documentation - gere um PDF contendo: seção de informações do cliente, resumo de uso do serviço, tabela de atividade recente e até 6 imagens/capturas de tela reais do produto que o cliente recebeu. Redimensione as imagens antes de incorporar (500px de largura, qualidade JPEG 75) para ficar abaixo do limite de 5MB do Stripe.
Também salve ambos os PDFs no seu armazenamento de arquivos (por exemplo, Cloudflare R2, S3) com nomes de arquivo hash para que não sejam adivinháveis, mas visíveis no painel de administração. Armazene as URLs de armazenamento no evidence_json como _receipt_r2_url e _service_doc_r2_url.
4. Trabalhador de sincronização CLI (workers/syncDisputes.php)
Um script que puxa TODAS as disputas existentes da API do Stripe (paginado com $stripe->disputes->all(['limit' => 100]) e starting_after para paginação), salva-as no banco de dados local de disputas e, para qualquer uma que ainda tenha status needs_response ou warning_needs_response e ainda não tenha tido evidências enviadas, envia automaticamente evidências usando a função compartilhada collectDisputeEvidence(). Isso é necessário porque o webhook só captura disputas futuras, não as existentes. Execute apenas via CLI (php workers/syncDisputes.php). Salva um arquivo de cache JSON com resultados de sincronização para que o painel possa mostrar a última hora de sincronização.
5. Mini painel (disputes.php com autenticação ?key=)
Uma página HTML simples protegida pelo parâmetro de consulta ?key= que mostra:
- Caixas de estatísticas: disputas totais, pendentes, ganhas, perdidas, disputadas nos últimos 30 dias (valor + contagem), disputadas nos últimos 12 meses (valor + contagem), total $ disputado
- Uma nota mostrando o comando de sincronização CLI e a última hora de sincronização do cache
- Um formulário de teste onde você insere um stripe_customer_id para pré-visualizar quais evidências seriam enviadas (sem realmente enviar)
- Uma tabela de todas as disputas: data, email, valor, motivo, status (badges coloridos), status de envio de evidências, links para a visualização de detalhes e o painel do Stripe
Visualização de detalhes (action=view&id=dispute_id): mostra todas as informações da disputa, link para o Stripe e um botão "Regenerar Evidências", links de arquivos PDF, IDs de upload de arquivos do Stripe, todos os campos de evidência de texto.
Regenerar Evidências (action=regen&id=dispute_id): regenera os PDFs de recibo e documentação de serviço e carrega para o armazenamento de arquivos, atualiza o evidence_json com novas URLs de PDF. Use fastcgi_finish_request() para enviar a resposta HTTP imediatamente (redirecionar de volta para a página de detalhes com aviso de "regenerando em segundo plano"), depois continue gerando os PDFs em segundo plano para evitar timeouts no frontend.
Adicione uma reescrita nginx para a página (por exemplo, rewrite ^/disputes/?$ /disputes.php). Certifique-se de que esteja no arquivo de configuração nginx correto (verifique para qual o symlink em sites-enabled realmente aponta).
6. Notificações do Telegram
- Nova disputa: "{site name} - Nova disputa de {email} por ${amount} ({reason}). Evidências enviadas automaticamente ao Stripe. {stripe_dashboard_link}"
- Evidência falhou: "{site name} - Nova disputa de {email} por ${amount} ({reason}). Envio de evidências FALHOU: {error}"
- Disputa ganha/perdida com o resultado e link
- Erro de permissão do banco de dados: "{site name} - ERRO DE BD DE DISPUTAS: {error} - verifique as permissões em data/disputes.db"
7. Certifique-se de que estes eventos de webhook do Stripe estejam habilitados no painel do Stripe: charge.dispute.created, charge.dispute.updated, charge.dispute.closed
8. Permissões do banco de dados
O arquivo disputes.db deve ser gravável pelo usuário do servidor web (por exemplo, www-data). Se você criá-lo via CLI como root, corrija a propriedade para corresponder aos seus outros arquivos de BD. PHP-FPM roda como um usuário diferente do root.
9. Dependências
- FPDF (setasign/fpdf) para geração de PDF, instalado via composer require setasign/fpdf
- Extensão GD para redimensionamento de imagens (geralmente já instalada)
- SDK PHP do Stripe (já instalado se você tiver webhooks do Stripe)
- SDK AWS S3 para uploads R2/S3 (já instalado se estiver usando Cloudflare R2)
Entre para ver o prompt completo
Continuar com:
Ao entrar, você concorda com nossos Termos de uso e Política de privacidade
Uso
Este prompt foi projetado para uso com coding. Copie o conteúdo acima e cole na sua ferramenta de IA preferida.
Para melhores resultados, personalize os marcadores (indicados por colchetes ou maiúsculas) com seus requisitos específicos.
Referências
- Categoria: Prompts de coding
- Fonte: https://x.com/levelsio/status/2041132289065631988
Discussão
0 comentários