TransbankDevelopers / transbank-sdk-php

Código fuente Transbank SDK para PHP
BSD 3-Clause "New" or "Revised" License
56 stars 30 forks source link

[2.0] Usar única instancia Transbank #186

Closed DarkGhostHunter closed 3 years ago

DarkGhostHunter commented 3 years ago

Problema

La mayoría de la lógica del SDK se maneja de forma estática. Esto hace extremadamente difícil testeo, y especialmente cuando usamos pruebas en paralelo para aplicaciones gigantes.

$transaction = (new Webpay(Configuration::forTestingWebpayPlusNormal()))->getNormalTransaction();

Solución

Usar una única instancia de Transbank para manejar todos los servicios: Cliente HTTP, Credenciales y Servicios. Siempre debería comenzar en integración

$transbank = Transbank::make(); // Helper

$transaction = $transbank->webpay()->create('order#123123', 100);

También se podría operar de forma manual para aquellos que ya disponen de alguna aplicación y quiere 100% control.

$transbank = new Transbank(
    new CredentialContainer(),
    new HttpClient,
    // ...
);

Alteraciones

La creación de credenciales se puede hacer directamente desde la instancia de Transbank. Usando el nombre del servicio, se puede pasar ese servicio a producción.

$transbank->webpay()->toProductionWithCredentials($key, $secret);

Breaking Changes

gdespirito commented 3 years ago

La nueva versión 2.0 usa instancia del los "API handlers" (WebpayPlus/Transaction, WebpayPlus/MallTransaction, OneClick/Transaction, etc). Es fácil de testear.

El integrador puede usar las instancias directamente $webpayTransaction = new Transaction(); Lo ideal es que esa instancia la llame como dependencia de la clase que la usa. Así puede testear todo sin problema, y pasar un Mock de la instancia si hace testing.

gdespirito commented 3 years ago

Sobre la configuración, cada "API Handler" permite pasar la configuración que desee. Existen tres formas:

Static API

WebpayPlus::configureForProduction('commerceCode', 'ApiKey'); 
(new Transaction())->create();

Static API

WebpayPlus::configureForProduction('commerceCode', 'ApiKey'); 
(new Transaction())->create();

Objeto Options

$options = Options::forProduction('comemrceCode', 'ApiKey');
(new Transaction($options))->create();

Más detalles en https://github.com/TransbankDevelopers/transbank-sdk-php/pull/182

DarkGhostHunter commented 3 years ago

Joe pino que es menos complejo ésto:

use Transbank\Sdk\Transbank;

$transaction = Transbank::make()->webpay()->setProduction($key, $secret)->create('order66', 100, ...);

que

use Transbank\Webpay\WebpayPlus;
use Transbank\Webpay\WebpayPlus\Transaction;

WebpayPlus::configureForProduction('mi-codigo-comercio', 'mi-api-key');

$response = Transaction::build()->create('buyOrder', 'sessionId', $amount, 'http://localhost/returnUrl');

Llamadas estáticas no se pueden mockear, así que si uso configureForProduction() y buid(), cago olímpicamente.

gdespirito commented 3 years ago

También se puede, pero no me gusta como opción recomendada porque para pasar de producción a integración el usuario debe modificar todas las líneas de código que haya escrito usando el SDK. Para el commit, para el status, etc.

Pero si quiere hacerlo, sería:

Transbank\Webpay\WebpayPlus\Transaction::build()->configureForProduction($key, $secret)->create();

O su primo hermano

WebpayPlus::transaction()->configureForProduction($key, $secret)->create();
gdespirito commented 3 years ago

Respondiendo a no poder mocker, si se puede:


$mockTransactionClass = MockClass::class;
WebpayPlus::$transactionClass = mockTransactionClass;

... 
Ahora WebpayPlus::transaction() devuelve una instancia de tu mock.
gdespirito commented 3 years ago

Por otro lado, todos esos métodos aceptan un HttpClient.

$mockHttpClient = new MockClass();
WebpayPlus::transaction(null, $mockHttpClient)->configureForProduction(...)->create()
Transaction::build(null, $mockHttpClient)->blahblah
DarkGhostHunter commented 3 years ago

También se puede, pero no me gusta como opción recomendada porque para pasar de producción a integración el usuario debe modificar todas las líneas de código que haya escrito usando el SDK. Para el commit, para el status, etc.

Pero si quiere hacerlo, sería:


Transbank\Webpay\WebpayPlus\Transaction::build()->configureForProduction($key, $secret)->create();

O su primo hermano


WebpayPlus::transaction()->configureForProduction($key, $secret)->create();

Es precisamente lo que hago yo en mi SDK. En la instancia madre Transbank manejo las credenciales y si está en producción o no.

$transbank->toProduction([
    'webpay' => ['555876543210','7a7b7d6cce5e...']
]);

$webpay = $transbank->webpay();
gdespirito commented 3 years ago

Para ir avanzando:

La mayoría de la lógica del SDK se maneja de forma estática. Esto hace extremadamente difícil testeo, y especialmente cuando usamos pruebas en paralelo para aplicaciones gigantes.

Como te comenté esto no es válido porque ya est´å contemplado en el SDK :) ¿entiendo entonces que podríamos cerrar este issue o hay algún otro punto acá?

DarkGhostHunter commented 3 years ago

Okay, no debería haber problema then.

gdespirito commented 3 years ago

De esto, quizás un cambio de último minuto que podría tomar es Transaction::make() e vez de Transaction::build()

DarkGhostHunter commented 3 years ago

Yo vengo del mundo donde make() es para instanciar hands-off, y new Something() para construir manualmente a mi pinta.