Integración con un proveedor de pagos; Enfoque OOP adecuado y robusto


8

Historia

Actualmente estamos utilizando un llamado modelo de redireccionamiento para nuestros pagos en línea (donde envía al pagador a una pasarela de pago, donde ingresa sus detalles de pago; la pasarela lo devolverá a una página de devolución de llamada de éxito / fracaso). Eso es fácil y directo, pero desafortunadamente es bastante incómodo y en ocasiones confuso para nuestros clientes (abandonar el sitio, cambiar los detalles de su tarjeta de crédito con un inicio de sesión adicional en otro sitio, etc.).

Descripción de la intención y el problema

Ahora tenemos la intención de cambiar a un enfoque integrado utilizando un intercambio de solicitudes y respuestas XML. Mi problema es cómo atender todas (o más bien la mayoría) de las cosas que pueden suceder durante el procesamiento, teniendo en cuenta que normalmente la simplicidad es robusta mientras que la complejidad es frágil.

Ejemplos

  • Anulación del usuario: el usuario ingresa los detalles de la tarjeta de crédito y pulsa enviar. Se envía un mensaje XML a la puerta de enlace del proveedor y espera la respuesta. El usuario hace clic en "detener" en su navegador o cierra la ventana.
    • ignore_user_abort () en PHP puede ser una opción, pero ¿es confiable?
    • ¿podría ser mejor redirigir al usuario a una página de "espera", que a su vez abre una solicitud AJAX u otra solicitud al procesador real que no depende de la conexión?
  • La base de datos desaparece
    • parece demasiado complicado, pero con, por ejemplo, un servidor web en los Estados Unidos y una base de datos en el Reino Unido, ha sucedido y volverá a suceder: el usuario hace clic en su pedido, la solicitud de pago se ha enviado al proveedor pero la respuesta no se puede almacenar en el base de datos. ¿Qué enfoque podría usar, usando PHP para iniciar un SQL como "Transacción" que solo al final se compromete o revierte, dependiendo de los pasos individuales? En caso de que no se hayan cometido ni retroceder ni retroceder, podría "bloquear" al usuario para evitar que pague de nuevo o dar cuenta de forma incorrecta de los pagos, pero ¿cómo?
  • ¿Y qué más necesito considerar técnicamente? Ninguno de los ejemplos de integración de, por ejemplo, Worldpay, Realex o SagePay ofrece ninguna idea, y mi motor de búsqueda o mis términos de búsqueda no fueron lo suficientemente buenos como para encontrar los pensamientos de alguien más sobre esto.

¡Muchas gracias por cualquier idea sobre cómo abordaría esto!


1
Solo usa Stripe. Evita los dolores de cabeza.
sergserg

He echado un vistazo a Stripe: ¡están cobrando un 2,39% más 30 centavos por transacción! Eso me costará alrededor de 12 mil dólares al año - Estoy pagando 0 por ciento y 9 peniques una transacción ...
ExternalUse

Por favor, lea [esto] le dará una idea de varias pasarelas de pago, incluyendo las basadas en XML. [1] [1]: vpasp.com/virtprog/vpasp_epsystems.htm
Badar

Hola Badar, lamentablemente, eso no responde a mi pregunta. Sé cómo funcionan las pasarelas de pago, y mi elección para una integración XML es fija. Estoy buscando las mejores prácticas y consejos sobre cómo hacerlo robusto, ¿tal vez mi pregunta no es lo suficientemente específica?
ExternalUse

Respuestas:


8

Como desarrollador que trabaja casi exclusivamente con pagos, tal vez pueda darle algunos consejos sobre dónde están los posibles escollos. Estoy trabajando para un sitio con mucho tráfico, ~ 40 proveedores de servicios de pago activos (PSP) y trato con decenas de miles de transacciones por día. Y confía en mí, la mierda siempre golpeará al fanático y todo lo que puedes hacer es prepararte tanto como sea posible para lidiar con la situación desde ese punto.

Registra, registra y registra un poco más ...

Esta es la parte más importante en su proceso de pago, asegúrese de tener un registro de todo . Hágase las preguntas "¿podría esta información ayudarme una vez en un millón de transacciones?". Si la respuesta es sí, ¡regístrese!

Nuestra configuración es que el punto principal del registro es la base de datos. Cada transacción iniciada, fallida, resuelta, redirigida, etc. se almacena por PSP en tablas. Si la PSP usa una API, todas las llamadas a la API se registran (tanto las solicitudes enviadas como las respuestas). Todas las devoluciones de llamada también se registran en las tablas. Etcétera..

Cuando nos encontramos con un evento inesperado o una excepción, lo registramos en el archivo de registro PHP con un cierto formato para que se pueda buscar y encontrar fácilmente en función de la identificación de la transacción, la identificación del usuario, etc.

Estará agradecido de tener todos los datos si es demandado, por ejemplo.

Monitoreo y alertas

Construya una lógica de monitoreo con algunas pruebas simples que lo alertarán por correo electrónico cuando algo salga mal. Por ejemplo, si 3 devoluciones de llamada seguidas fallan para un PSP. Todas estas pequeñas cosas que pueden hacer que trabaje para resolver problemas rápidamente en lugar de reaccionar ante ellos después de que sus clientes lo hayan advertido (lo que no siempre sucede) es muy importante.

Transacciones de bases de datos

Si tiene el lujo de configurar o cambiar la estructura de su base de datos para admitir transacciones de la base de datos, por ejemplo, use InnoDB en MySQL. Eche un vistazo a esta respuesta sobre cómo manejarlo en el código. Debes asegurarte de que cada paso de una transacción se complete o ninguno se complete, tener transacciones parcialmente completadas es solo una carga para ti y tu sistema. Por ejemplo: 1) El usuario completa la transacción, 2) El usuario es recompensado de alguna manera. Si no se cumplen los pasos 1 y 2 aquí, la transacción no debe establecerse como completa en el paso 1.

Personal técnico para contactar

Cuando tenga un problema técnico, asegúrese de tener a alguien técnico a quien contactar de inmediato. Tener un administrador de cuentas es bastante inútil, especialmente si esa persona decide mediar entre usted y su técnico.

Ejemplo del mundo en vivo que me sucedió: una PSP deja de funcionar de repente, nada en nuestro código había cambiado y dicen que tampoco han cambiado nada. Después de enviar información de depuración de ida y vuelta con ellos (a través de su administrador de cuentas), uno de sus técnicos detecta que el esquema WSDL recupera parece estar apagado. Luego se dan cuenta de que actualizaron su esquema WSDL y después de algunas depuraciones me doy cuenta de que PHP almacenó en caché el antiguo esquema WSDL. Esto podría haberse detectado antes, tal como se resolvió si hubiera tenido una persona técnica en Skype para contactarme directamente. O si simplemente admitieron haber cambiado su esquema WSDL, pero a menudo es difícil obtener una confesión de los PSP cuando algo sale mal ...

Ultimas palabras...

Prepara todo lo que puedas y asume que ALGO puede suceder :)

No estoy seguro de si este era exactamente el tipo de respuesta que buscaba, pero estoy tratando de proporcionar un ejemplo real de pagos y cómo puede evitar las mayores trampas y dificultades. Avíseme si hay algo en lo que le gustaría que elabore o si está interesado en otro tema.


+1 Olvidé mencionar lo importantes que son las transacciones distribuidas. Tener que mantener un sistema heredado que se integra con un PP y no utiliza transacciones me mostró el escenario de pesadilla de primera mano.
maple_shaft

Hola nerdklers, gracias por eso: ¡obtienes un +1 por "iniciar sesión, iniciar sesión y registrar un poco más"! Ahora estaba considerando este enfoque en "enviar": bloquear sesión de usuario. Inserte un pago en la base de datos como pendiente. Envíe la solicitud sin "autosettle" (transacción retrasada). Actualice el registro de pago como "transmitido" si tiene éxito. Enviar el comando "resolver" a PSP. Actualice el registro de pago como "completado" y desbloquee la sesión del usuario. (Bloquear significa escribir una bandera en el registro del usuario; en caso de que inicie sesión mientras hay transacciones pendientes, recibirá una página de "llame"). Me estoy quedando sin caracteres, así que lo pondré como respuesta a los comentarios.
ExternalUse

1

En mi sincera opinión, la mejor manera de administrar las transacciones a través de una pasarela de pago es a través de los servicios web. Varias pasarelas de pago diferentes ofrecen este tipo de servicios para tasas de porcentaje fijas competitivas por transacción + la comisión típica de tarjeta de crédito que la tarjeta de crédito de los clientes también tomará (por ejemplo, Cybersource ). Con casi todo en la vida, obtienes lo que pagas, no existe una transacción de 9 centavos con un procesador de pago de buena reputación que no te obligue a redirigir a los usuarios.

Tokenización y datos seguros

Almacenar los detalles de la tarjeta de crédito en su sistema solo es un problema, y ​​dependiendo de dónde viva, puede haber requisitos legales y posibles leyes penales contra la forma en que se administran estos datos. A menos que sea Amazon, no debería tener que preocuparse por toda esa complejidad técnica y legal. El procesador de pagos le quita este riesgo y complejidad al tener servicios web encriptados SSL donde los detalles de la tarjeta de crédito pueden pasarse a través de su sitio a su servidor, y desde su servidor a los servicios web del procesador de pagos para enviar un pago a través de su cuenta con el procesador. A cambio, el servicio web le devolverá un código de autorización, o un token que signifique de manera única la transacción en su sistema, y ​​le dará un número de referencia para buscar rápidamente transacciones específicas en su cuenta. Puede retener el token en su base de datos y no tiene ninguna consecuencia real para los usuarios si los tokens están comprometidos en su sistema. Además, al no almacenar los detalles de la tarjeta de crédito en su sistema, las cuentas bancarias de los usuarios están seguras incluso si su sistema se ha visto comprometido.

Retención de registros de pago

Este enfoque para integrarse con un procesador de pagos tiene el beneficio adicional de poder mantener sus propios registros de pagos y compras que están separados de los de su procesador de pagos, pero vinculados a través del token. Esto le permite ejecutar informes de ingresos a través de su sistema, las consultas analíticas y los usuarios pueden ver sus compras sin tener que consultar la información del procesador de pagos.

Cumplimiento de PCI

Cualquier procesador de pago acreditado tendrá todos sus sistemas y datos alojados en servidores e instalaciones compatibles con PCI. Para obtener más información sobre los detalles del cumplimiento de PCI, y por qué es importante, consulte este sitio .

Hay ciertos requisitos que deben cumplir, su centro de datos debe estar asegurado tanto física como técnicamente. No pueden tener WAP sin cifrar en su red, etc. Nada de esto realmente le preocupará, sin embargo, se espera que los sistemas comerciales también exijan una serie de requisitos para reclamar el cumplimiento de PCI. Algunos de estos requisitos incluyen, entre otros:

  • Usar el cifrado SSL en cualquier solicitud de pago a través de su sitio.

  • Bajo ninguna circunstancia debe haber números de tarjetas de crédito almacenados en ningún lugar de ninguno de sus sistemas, incluidos archivos de registro e incluso objetos serializados.

  • Los servidores de aplicaciones que se comunican con el procesador de pagos deben estar detrás de un firewall bien configurado que solo permita la cantidad mínima de puertos abiertos necesarios.

  • Solo el personal técnico apropiado debe tener acceso físico o remoto a estos servidores de aplicaciones en su red.

  • Otros...

Por lo general, la mayoría de los procesadores de pagos proporcionarán una herramienta en línea que puede ejecutarse en su red e identificar posibles problemas para cumplir con PCI. Aún no es NECESARIO ni REQUERIDO tener que trabajar con un procesador de pagos, pero el procesador de pagos se reserva el derecho de cobrarle tarifas adicionales si utiliza sus servicios y no cumple con los estándares de Cumplimiento de PCI.


Lo siento, pero nuevamente esto no responde ni se aplica a mi pregunta. Tenemos un procesador de pagos acreditado (en este momento) tanto en WorldPay como en Realex Payments. Tenemos auditorías permanentes sobre el cumplimiento de PCI y cumplimos con el almacenamiento interno de datos parciales de la tarjeta de crédito, sin embargo, utilizamos RealVault y FuturePay para el almacenamiento recurrente. Mi pregunta se relaciona con las mejores prácticas para lo que mencioné en mi pregunta.
ExternalUse

@ExternalUse Sentí que hice un muy buen trabajo al explicar cuáles serían las mejores prácticas para integrarme adecuadamente con su proveedor de pagos. Utilice SSL, no redirija al usuario, realice llamadas de servicio web seguras al PP desde el lado del servidor, no almacene detalles de CC, mantenga registros de pago separados con su token y considere el cumplimiento de PCI en su diseño. Si no cree que hice un buen trabajo, entonces tal vez alguien más pueda darle una respuesta más precisa que está buscando.
maple_shaft

1

Gracias a las ideas de respuestas anteriores, me gustaría proponer la solución que tengo ahora; Espero que esto pueda invitar a uno o dos comentarios del conocimiento ciclopédico presente aquí y ayudarme a mejorarlo. Solo para aclarar: aunque son cuestiones importantes, mi pregunta no estaba relacionada con la forma de elegir un proveedor de servicios de pago (PSP), los requisitos de PCI DSS o las implicaciones legales de nada, sino solo las dificultades técnicas con las que uno podría tropezar al implementar un "directo" en lugar de un modelo de "redireccionamiento" con cualquier PSP.

Prerrequisitos

El cliente se encuentra en la etapa en la que ingresa los datos de la tarjeta de crédito en su formulario. Sé lo que debe y qué cantidad y moneda quiero cobrar a la tarjeta de crédito que envíe.

Solución (?)

  1. Al enviar el formulario que contiene los detalles de la tarjeta de crédito, usaré Javascript para detener la acción predeterminada en el botón de envío (que, si JS o AJAX no estuvieran disponibles, podría ir a una página de error que le indica al usuario que obtenga una más reciente navegador...)
  2. La solicitud AJAX (repetida por un temporizador) llamaría a un script de actualización de estado, que en sí mismo activa el procesamiento real en un archivo separado; usando "ignore_user_abort () si el cliente cierra el navegador o algo
  3. entonces AJAX llama, por ejemplo, el método -> StatusUpdate () - si se llama por primera vez, comenzará el proceso y devolverá "pleasewait", en llamadas posteriores evaluaría una variable de sesión o algo para actualizar el estado
  4. Actualizaría el registro del usuario en la base de datos para establecer un indicador "lockSession" en "bloqueado": si algo sucede antes del desbloqueo, se le indicará al usuario en los inicios de sesión posteriores que se comunique con la oficina para solucionar cualquier desastre que pueda haber sucedido .
  5. inserte un registro de pago en la base de datos con un estado "preparado"
  6. Envíe la solicitud a la PSP, utilizando la identificación del pedido del registro de pago preparado. Dependiendo de la PSP, la solicitud puede enviarse como una transacción retrasada (lo que significa que no se liquidará automáticamente)
  7. actualice el registro preparado con su nuevo estado (si se rechazó, desbloquee la sesión y vuelva a la página de pago; si tiene éxito, actualice con el estado "transmitido")
  8. Si tuvo éxito, no tendríamos la referencia de autenticación y otros detalles importantes de la PSP, así que envíe una solicitud de "liquidación" a la PSP para obtener la referencia de autenticación obtenida.
  9. Si tiene éxito, actualice el registro de pago a completado (o en mi caso, muévalo y actualícelo de PendingTransactions a PaymentTransactions)
  10. Eliminar la bandera de "bloqueo" del registro del usuario

Otras Consideraciones

Por favor, comprenda lo anterior como una invitación a compartir sus conocimientos e ideas, ¡hasta ahora son solo ideas!

Inicio sesión

Estoy muy de acuerdo con los nerdklers en el registro: actualmente estoy considerando usar alguna forma de registro basado en archivos para cada etapa del proceso anterior (y mantener registros durante unos días, incluso si están completos y verificados), quién sabe. ..)

Transacciones de bases de datos

No estoy seguro de estar de acuerdo con el uso de transacciones de bases de datos. Estamos utilizando MS SQL, y con la configuración predeterminada, cualquier transacción se revertiría en caso de pérdida de conexión. Y al configurar la transacción para que no se confirme automáticamente o se deshaga automáticamente, uno podría terminar con algunas transacciones de base de datos abiertas y algunas implicaciones en el bloqueo de registros / tablas, etc. Creo que preferiré varias actualizaciones en el proceso; en caso de que alguno de ellos falle (y, en consecuencia, el proceso se termine), el usuario aún no podría volver a enviar una transacción posiblemente completada (pero aún no registrada) hasta que se haya resuelto manualmente.

AJAX, político

No estoy completamente seguro de si aún necesitamos considerar navegadores que no admitan AJAX. Supongo que de todos modos es un tema "político". Creo que podríamos permitirnos tomar libertades en nuestro negocio, otros posiblemente no.

AJAX, técnico

Todavía no estoy tan seguro de mi enfoque al llamar a un método "StatusUpdate" de forma asincrónica, que en la primera llamada intentará desencadenar el proceso real. Pero haré de esta una pregunta separada si no encuentro buenos ejemplos, que creo que bien podría encontrar. De todos modos, si conoce una práctica recomendada, hágamelo saber (y a otros) en su comentario.

Pensamientos finales

Sería bueno si tuviera una idea remotamente acercando el término "final" - esto si trabajo en progreso para mí y estoy muy agradecido por cualquier comentario y sugerencias sobre cómo esto podría mejorarse.


Su solución parece sólida, pero cuestiono la necesidad de ese nivel de esfuerzo cuando en realidad una transacción distribuida con bloqueo optimista de registros en las filas necesarias puede lograr lo mismo. No estoy seguro acerca de MSSQL, pero estoy seguro de que es capaz de hacerlo si puedo hacer esto en InnoDB MySQL. No estoy seguro de seguir su argumento contra el uso de transacciones.
maple_shaft

Estoy (¿equivocado?) Preocupado por lo que sucede si el script termina mientras se procesa, o si la base de datos desaparece (por cualquier motivo). ¿Qué pasa con la transacción iniciada? ¿Está comprometido, revertido o dejado abierto? Y esa pregunta puede responderse con a, b o c dependiendo de la configuración y la base de datos, supongo. Estaba considerando compartir mi desarrollo como un conjunto de clases de código abierto si funcionara como quisiera, después de todo, obtengo conocimiento de la comunidad, por lo que debería volver a ello.
ExternalUse

Diría que estás pensando demasiado en esto un poco. Mientras mantengas un registro de lo que está sucediendo, aprenderás a medida que avanzas ... Solo quiero comentar esto: "(y mantener registros durante unos días, incluso si están completos y verificados, quién sabe ...) ", y di no, no, no :) Mantenga los registros para siempre, divídalos por día, trx_120917.logpor ejemplo. Los registros son muy pequeños y el espacio en disco es muy barato. De todos modos, ¡buena suerte con tu proyecto!
Niklas Modess
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.