Integração com um provedor de pagamento; Abordagem adequada e robusta de POO


8

História

Atualmente, estamos usando o chamado modelo de redirecionamento para nossos pagamentos on-line (onde você envia o pagador para um gateway de pagamento, onde ele insere seus detalhes de pagamento - o gateway o retornará a uma página de retorno de chamada com êxito / falha). Isso é fácil e direto, mas infelizmente é bastante inconveniente e às vezes confuso para nossos clientes (saindo do site, alterando os detalhes do cartão de crédito com um login adicional em outro site, etc.).

Intenção e descrição do problema

Agora, pretendemos mudar para uma abordagem integrada usando uma troca de solicitações e respostas XML. Meu problema é como lidar com todas (ou melhor, com a maioria) das coisas que podem acontecer durante o processamento - tendo em mente que normalmente a simplicidade é robusta e a complexidade é frágil.

Exemplos

  • Abortar usuário: O usuário insere os detalhes do cartão de crédito e os hits são enviados. Uma mensagem XML para o gateway do provedor é enviada e aguardando resposta. O usuário pressiona "parar" em seu navegador ou fecha a janela.
    • ignore_user_abort () no PHP pode ser uma opção - mas isso é confiável?
    • seria melhor redirecionar o usuário para uma página "aguarde", que por sua vez abre uma solicitação AJAX ou outra para o processador real que não depende da conexão?
  • O banco de dados desaparece
    • parece complicado demais, mas, por exemplo, com um servidor da web nos Estados Unidos e um banco de dados no Reino Unido, isso aconteceu e acontecerá novamente: o usuário clica em seu pedido, a solicitação de pagamento foi enviada ao provedor, mas a resposta não pode ser armazenada no base de dados. Que abordagem eu poderia usar, usando o PHP para iniciar um SQL como "Transação" que somente no final é confirmado ou revertido, dependendo das etapas individuais? Então, caso nenhum commit ou retrocesso tenha acontecido, eu poderia "bloquear" o usuário para impedir que ele pague novamente ou contabilize pagamentos indevidamente - mas como?
  • E o que mais eu preciso considerar tecnicamente? Nenhum dos exemplos de integração, por exemplo, Worldpay, Realex ou SagePay, oferece qualquer insight, e meu mecanismo de pesquisa ou meus termos de pesquisa não eram bons o suficiente para encontrar os pensamentos de outras pessoas sobre isso.

Muito obrigado por qualquer insight sobre como você abordaria isso!


1
Basta usar o Stripe. Evite dores de cabeça.
sergserg

Eu dei uma olhada no Stripe - eles estão cobrando 2,39% mais 30 centavos por transação! Isso me custaria cerca de 12 mil por ano - estou pagando 0% e 9 centavos por transação ...
ExternalUse

Por favor, leia [isto], que lhe dará algumas dicas sobre vários gateways de pagamento, incluindo XML. [1] [1]: vpasp.com/virtprog/vpasp_epsystems.htm
Badar

Olá Badar, infelizmente, isso não responde à minha pergunta. Sei como os gateways de pagamento funcionam e minha escolha para uma integração XML é corrigida. Estou procurando as melhores práticas e dicas sobre como torná-lo robusto - talvez minha pergunta não seja específica o suficiente?
ExternalUse

Respostas:


8

Como desenvolvedor que trabalha quase exclusivamente com pagamentos, talvez eu possa dar algumas dicas sobre onde estão as possíveis armadilhas. Estou trabalhando para um site com alto tráfego, ~ 40 PSPs (prestadores de serviços de pagamento ativos) e lidando com dezenas de milhares de transações por dia. E confie em mim, o sh * t sempre atingirá o ventilador e tudo o que você pode fazer é se preparar o máximo possível para lidar com a situação a partir desse ponto.

Registrar, registrar e registrar um pouco mais ...

Esta é a parte mais importante do seu processo de pagamento, verifique se você tem um registro de tudo . Faça a si mesmo as perguntas "essa informação poderia me ajudar uma vez em um milhão de transações?". Se a resposta for sim, registre-a!

Nossa configuração é que o ponto principal do log é o banco de dados. Toda transação iniciada, com falha, resolvida, redirecionada, etc. é armazenada por PSP em tabelas. Se o PSP usar uma API, todas as chamadas à API serão registradas (solicitações enviadas e respostas). Todos os retornos de chamada também são registrados em tabelas. E assim por diante..

Quando encontramos um evento ou exceção inesperada, o registramos no arquivo de log PHP com um determinado formato para torná-lo pesquisável e facilmente encontrado com base no ID da transação, ID do usuário etc.

Você ficará grato por ter todos os dados se for processado, por exemplo.

Monitoramento e alertas

Construa na lógica de monitoramento com alguns testes simples que o alertarão por e-mail quando algo der errado. Por exemplo, se três retornos de chamada seguidos falharem para um PSP. Todas essas pequenas coisas que podem ajudá-lo a resolver problemas rapidamente, em vez de reagir a eles depois que seus clientes o informam (o que nem sempre acontece) são muito importantes.

Transações de banco de dados

Se você tem o luxo de configurar ou alterar sua estrutura de banco de dados para suportar transações de banco de dados, por exemplo, use o InnoDB no MySQL. Dê uma olhada nesta resposta sobre como lidar com isso no código. Você deve garantir que todas as etapas de uma transação sejam concluídas ou nenhuma, concluir parcialmente transações é apenas um fardo para você e seu sistema. Por exemplo: 1) O usuário conclui a transação, 2) O usuário é recompensado de alguma forma. Se as etapas 1 e 2 não forem atendidas aqui, a transação não deve ser definida como concluída na etapa 1.

Pessoas técnicas a contatar

Quando você tiver um problema técnico, verifique com alguém técnico para entrar em contato imediatamente. Ter um gerente de contas é bastante inútil, especialmente se essa pessoa decidir mediar entre você e o técnico.

Exemplo do mundo ao vivo que aconteceu comigo: um PSP de repente para de funcionar, nada no nosso código mudou e eles dizem que também não mudaram nada. Depois de enviar informações de depuração com eles (por meio do gerente de contas), um de seus técnicos percebe que as buscas do esquema WSDL parecem desativadas. Então eles percebem que atualizaram o esquema WSDL e, após algumas depurações, percebo que o PHP armazenou em cache o antigo esquema WSDL. Isso poderia ter sido detectado mais cedo como resolvido se eu tivesse apenas uma pessoa técnica no Skype para entrar em contato diretamente. Ou se eles apenas admitiram mudar seu esquema WSDL, mas geralmente é difícil obter uma confissão dos PSPs quando algo dá errado.

Palavras finais ...

Prepare tudo o que puder e assuma que QUALQUER COISA pode acontecer :)

Não tenho certeza se esse foi exatamente o tipo de resposta que você buscava, mas estou tentando fornecer um exemplo de pagamentos no mundo real e como você pode evitar as maiores armadilhas e armadilhas. Deixe-me saber se há algo que você gostaria que eu elabore ou se estiver interessado em outro tópico.


+1 Esqueci de mencionar a importância das transações distribuídas. Ter que manter um sistema legado que se integra a um PP e não utiliza transações me mostrou o cenário do pesadelo em primeira mão.
maple_shaft

Olá nerdklers, obrigado por isso - você recebe um +1 por "log, log e log mais"! Agora eu estava considerando essa abordagem em "enviar": bloquear sessão do usuário. Insira um pagamento no banco de dados como pendente. Envie a solicitação sem "ajuste automático" (transação atrasada). Atualize o registro de pagamento como "transmitido" se for bem-sucedido. Envie o comando "resolver" para o PSP. Atualize o registro de pagamento como "concluído" e desbloqueie a sessão do usuário. (Bloquear significa escrever uma bandeira no registro do usuário; se ele fizer login enquanto as transações estiverem pendentes, ele receberá uma página "por favor, ligue".) Estou ficando sem caracteres, então vou colocar isso como resposta para comentários.
ExternalUse

1

Na minha opinião sincera, a melhor maneira de gerenciar transações por meio de um gateway de pagamento é por meio de serviços da web. Vários gateways de pagamento diferentes oferecem esses tipos de serviços para taxas percentuais fixas competitivas por transação + a comissão típica de cartão de crédito que o cartão de crédito dos clientes também receberá (por exemplo, Cybersource ). Com quase tudo na vida, você obtém o que paga, uma transação de 9 centavos / dólar não existe com um processador de pagamento respeitável que não o força a redirecionar usuários.

Tokenização e dados seguros

O armazenamento de detalhes do cartão de crédito em seu sistema está apenas causando problemas e, dependendo de onde você mora, pode haver requisitos legais e possíveis leis penais contra a forma como esses dados estão sendo gerenciados. A menos que você seja Amazon, não precisa se preocupar com toda essa complexidade técnica e jurídica. O processador de pagamento tira esse risco e a complexidade de você, tendo serviços da Web criptografados SSL, nos quais os detalhes do cartão de crédito podem ser transmitidos pelo site para o servidor e do servidor para os serviços da Web do processador de pagamentos para enviar um pagamento por meio da sua conta com o processador. Em troca, o serviço da Web devolverá um código de autorização ou um token que significa exclusivamente a transação no sistema e fornece um número de referência para pesquisar rapidamente transações específicas na sua conta. Você pode reter o token no seu banco de dados e isso não tem nenhuma consequência real para os usuários se os tokens estiverem comprometidos no seu sistema. Além disso, ao não armazenar os detalhes do cartão de crédito em seu sistema, as contas bancárias dos usuários são seguras, mesmo que seu sistema tenha sido comprometido.

Retenção de registros de pagamento

Essa abordagem para integrar-se a um processador de pagamento tem o benefício adicional de poder manter seus próprios registros de pagamento e compra que são separados dos do seu processador de pagamento, ainda que vinculados pelo token. Isso permite que você execute relatórios de receita por meio do sistema, consultas analíticas e usuários podem visualizar suas compras sem precisar consultar o processador de pagamento para obter informações.

Conformidade com PCI

Qualquer processador de pagamento respeitável terá todos os seus sistemas e dados hospedados em servidores e instalações compatíveis com PCI. Para obter mais informações sobre os detalhes da própria conformidade com o PCI e por que é importante, consulte este site .

Existem certos requisitos aos quais eles devem cumprir, seu data center deve ser protegido tanto fisicamente quanto tecnicamente. Eles não podem ter WAPs não criptografados em sua rede, etc ... Nada disso realmente interessa a você, no entanto, existem vários requisitos esperados dos sistemas comerciais para que eles também reivindiquem a conformidade com PCI. Alguns desses requisitos incluem, mas não estão limitados a:

  • Usando criptografia SSL em qualquer solicitação de pagamento através do seu site.

  • Sob nenhuma circunstância deve haver números de cartão de crédito armazenados em qualquer lugar do sistema, incluindo arquivos de log e até objetos serializados.

  • Os servidores de aplicativos que se comunicam com o processador de pagamento devem estar atrás de um firewall bem configurado que permita apenas o número mínimo de portas abertas necessárias.

  • Somente o pessoal técnico apropriado deve ter acesso físico ou remoto a esses servidores de aplicativos na sua rede.

  • Outras...

Normalmente, a maioria dos processadores de pagamento fornece uma ferramenta on-line que pode ser executada em sua rede e identificar possíveis problemas ao se tornar compatível com PCI. Ainda não é uma coisa NECESSÁRIA ou NECESSÁRIA ter que trabalhar com um processador de pagamento, mas o processador de pagamento se reserva o direito de cobrar taxas adicionais se você utilizar seus serviços e não atender aos padrões de conformidade com PCI.


Desculpe, mas novamente isso não responde ou se aplica à minha pergunta. Temos um processador de pagamentos respeitável (no momento) no WorldPay e no Realex Payments. Temos auditorias permanentes na conformidade com o PCI e são compatíveis com o armazenamento interno de dados parciais do cartão de crédito, no entanto, usamos o RealVault e o FuturePay para armazenamento recorrente. Minha pergunta estava relacionada às melhores práticas para o que mencionei na minha pergunta.
ExternalUse

@ExternalUse Eu senti que fiz um bom trabalho ao explicar quais seriam as melhores práticas para a integração adequada com seu provedor de pagamentos. Use SSL, não redirecione o usuário, faça chamadas seguras de serviço da Web para o PP do lado do servidor, não armazene detalhes de CC, mantenha registros de pagamento separados com seu token e considere a conformidade com PCI em seu design. Se você não acha que eu fiz um bom trabalho, talvez alguém possa dar uma resposta mais precisa que você está procurando.
Maple_shaft

1

Graças às idéias das respostas anteriores, gostaria de propor a solução que tenho agora; Espero que isso possa convidar um ou dois comentários do conhecimento ciclópico aqui apresentado e me ajudar a melhorá-lo. Apenas para esclarecimento: Embora questões importantes, minha pergunta não fosse sobre como escolher um PSP (provedor de serviços de pagamento), os requisitos do PCI DSS ou implicações legais de qualquer coisa, mas apenas as armadilhas técnicas que se pode encontrar ao implementar um "direto" em vez de um modelo de "redirecionamento" com qualquer PSP.

Pré-requisitos

O cliente está no estágio em que ele insere os detalhes do cartão de crédito em seu formulário. Sei o que ele deve e que quantia e moeda quero cobrar no cartão de crédito que ele envia.

Solução (?)

  1. Ao enviar o formulário que contém os detalhes do cartão de crédito, usarei o Javascript para interromper a ação padrão no botão enviar (que, se JS ou AJAX não estivesse disponível, poderia ir para uma página de erro informando ao usuário para obter informações mais recentes navegador...)
  2. A solicitação (repetida por um timer) AJAX chamaria um script de atualização de status, que por si só aciona o processamento real em um arquivo separado; usando "ignore_user_abort () caso o cliente feche o navegador ou algo
  3. para que o AJAX chame, por exemplo, o método -> StatusUpdate () - se chamado pela primeira vez, ele iniciará o processo e retornará "pleasewait"; nas chamadas subsequentes, avaliará uma variável de sessão ou algo para atualizar o status
  4. Eu atualizaria o registro do usuário no banco de dados para definir um sinalizador "lockSession" como "bloqueado" - se algo acontecesse antes do desbloqueio, o usuário seria informado nos logins subsequentes para entrar em contato com o escritório para resolver qualquer confusão que possa ter acontecido. .
  5. insira um registro de pagamento no banco de dados com o status "preparado"
  6. Envie a solicitação ao PSP, usando o ID do pedido do registro de pagamento preparado. Dependendo do PSP, a solicitação pode ser enviada como uma transação atrasada (o que significa que não será resolvida automaticamente)
  7. atualize o registro preparado com seu novo status (se recusado, desbloqueie a sessão e volte para a página de pagamento; se for bem-sucedido, atualize com o status "transmitido")
  8. Se fosse bem-sucedido, não teríamos a referência de autenticação e outros detalhes importantes do PSP - envie uma solicitação de "acordo" ao PSP para obter a referência de autenticação obtida.
  9. Se for bem-sucedido, atualize o registro de pagamento para concluído (ou, no meu caso, mova e atualize-o de PendingTransactions para PaymentTransactions)
  10. Remova o sinalizador "lock" do registro do usuário

Outras considerações

Por favor, entenda o exposto como um convite para compartilhar seus conhecimentos e idéias - eles são apenas idéias até agora!

Exploração madeireira

Eu concordo muito com os nerdklers no log - atualmente, estou pensando em usar alguma forma de log baseado em arquivo para todas as etapas do processo acima (e manter os logs por alguns dias, mesmo que completos e verificados - quem sabe. ..)

Transações de banco de dados

Não tenho certeza se concordo em usar transações de banco de dados. Estamos usando o MS SQL e, com as configurações padrão, qualquer transação seria revertida com a perda de conexão. E ao definir a transação para não confirmar ou reverter automaticamente, pode-se acabar com algumas transações de banco de dados abertas e algumas implicações no bloqueio de registros / tabelas, etc. Acho que vou preferir várias atualizações no processo; se alguma dessas falhas (e o processo conseqüentemente for encerrado), o usuário ainda será impedido de reenviar uma transação possivelmente concluída (mas ainda não registrada) até que seja resolvida manualmente.

AJAX, político

Não tenho certeza se ainda precisamos considerar navegadores que não suportam AJAX. Eu acho que é um tópico "político" de qualquer maneira. Acho que poderíamos ter liberdade em nossos negócios, outros possivelmente não.

AJAX, técnico

Ainda não tenho tanta certeza da minha abordagem ao chamar um método "StatusUpdate" de forma assíncrona, que, na primeira chamada, tentamos acionar o processo real. Mas farei disso uma pergunta separada, se não encontrar bons exemplos - que acho que posso encontrar. De qualquer forma, se você conhece uma prática recomendada, informe-me (e outros) em seu comentário.

Pensamentos finais

Seria bom se eu pensasse em abordar remotamente o termo "final" - isso se trabalhar em andamento para mim e estou muito agradecido por qualquer feedback e dicas adicionais sobre como isso pode ser melhorado.


Sua solução parece sólida, mas questiono a necessidade desse nível de esforço quando, na realidade, uma transação distribuída com bloqueio otimista de registros nas linhas necessárias pode alcançar a mesma coisa. Não tenho certeza sobre o MSSQL, mas tenho certeza de que é capaz disso se eu puder fazer isso no InnoDB MySQL. Não tenho certeza se sigo seu argumento contra o uso de transações.
maple_shaft

Estou (erroneamente?) Preocupado com o que acontece se o script terminar durante o processamento ou se o banco de dados desaparecerá (por qualquer motivo). O que acontece com a transação iniciada? É confirmado, revertido ou deixado em aberto? E essa pergunta pode ser respondida com a, b ou c, dependendo da configuração e do banco de dados, eu acho. Eu estava pensando em compartilhar meu desenvolvimento como um conjunto de classes de código-fonte aberto, caso funcione como eu quero - depois de tudo, obtenho conhecimento da comunidade, por isso deveria voltar a ele.
ExternalUse

Eu diria que você está pensando demais sobre isso. Contanto que você mantenha um registro do que está acontecendo, você aprenderá. Só quero comentar o seguinte: "(e manter registros por alguns dias, mesmo que completos e verificados - quem sabe ...) "e diga não, não, não :) Mantenha os logs para sempre, divida-os por dia, por exemplo, trx_120917.logpor exemplo. Os logs são muito pequenos e o espaço em disco é muito barato. De qualquer forma, boa sorte com o seu projeto!
Niklas Modess
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.