PayGreen / paygreen-php

PHP SDK for the PayGreen API.
https://www.paygreen.io/
8 stars 9 forks source link

Erreur Guzzle : URI must be a string or UriInterface #115

Closed thedigital closed 12 months ago

thedigital commented 1 year ago

Bonjour,

Je voulais utiliser le SDK que vous fournissez sauf que il y a une erreur de votre SDK quand il utilise Guzzle (version installée : "guzzlehttp/guzzle": "^6.2", "guzzlehttp/psr7": "^1.9",) :

Erreur rencontrée : URI must be a string or UriInterface 426 /var/www/web-api2/vendor/guzzlehttp/psr7/src/Utils.php

Dans la lib Guzzle, voici le contenu de la variable testée et qui devrait etre string ou UrlInterface (a priori, il recoit un object Request au lieu de request->uri)

^ GuzzleHttp\Psr7\Request {#1525
  -method: "POST"
  -requestTarget: null
  -uri: GuzzleHttp\Psr7\Uri {#1533
    -scheme: "https"
    -userInfo: ""
    -host: "sb-api.paygreen.fr"
    -port: null
    -path: "/payment/payment-orders"
    -query: ""
    -fragment: ""
  }
  -headers: array:6 [
    "Host" => array:1 [
      0 => "sb-api.paygreen.fr"
    ]
    "User-Agent" => array:1 [
      0 => "PGSDK - sdk:1.3.13 api:payment:3 php:7.3.33;"
    ]
    "Authorization" => array:1 [
      0 => "Bearer"
    ]
    "Content-Type" => array:1 [
      0 => "application/json"
    ]
    "Accept" => array:1 [
      0 => "application/json"
    ]
    "Content-Length" => array:1 [
      0 => "260"
    ]
  ]
  -headerNames: array:6 [
    "user-agent" => "User-Agent"
    "host" => "Host"
    "authorization" => "Authorization"
    "content-type" => "Content-Type"
    "accept" => "Accept"
    "content-length" => "Content-Length"
  ]
  -protocol: "1.1"
  -stream: GuzzleHttp\Psr7\Stream {#1532
    -stream: stream resource @787
      wrapper_type: "PHP"
      stream_type: "TEMP"
      mode: "w+b"
      unread_bytes: 0
      seekable: true
      uri: "php://temp"
      options: []
    }
    -size: 260
    -seekable: true
    -readable: true
    -writable: true
    -uri: "php://temp"
    -customMetadata: []
  }
}

Voici les elements PHP montrant l'utilisation du SDK PHP :

use GuzzleHttp\Client as HttpClient;
use Paygreen\Sdk\Payment\V3\Client as PaygreenClient;
use Paygreen\Sdk\Payment\V3\Environment as PaygreenEnvironment;

            $psr18Client = new HttpClient([
                'http_errors' => false,
            ]);

            $environment = new PaygreenEnvironment(
                config('services.paygreen.shop_id'),
                config('services.paygreen.secret_key'),
                App::environment('production') ? 'PRODUCTION' : 'SANDBOX'
            );

            $paygreen = new PaygreenClient($psr18Client, $environment);

            ...

            $address = new Address();
            $address->setStreetLineOne($params['billingAddress']['address']);
            $address->setCity($params['billingAddress']['city']);
            $address->setCountryCode($params['billingAddress']['country']);
            $address->setPostalCode($params['billingAddress']['zipCode']);

            $buyer = new Buyer();
            $buyer->setReference($params['buyer']['id']);
            $buyer->setEmail($params['buyer']['email']);
            $buyer->setFirstName($params['buyer']['firstName']);
            $buyer->setLastName($params['buyer']['lastName']);
            $buyer->setBillingAddress($address);

            $paymentOrder = new PaymentOrder();
            $paymentOrder->setReference($this->id);
            $paymentOrder->setBuyer($buyer);
            $paymentOrder->setAmount(round($amount * 100));
            $paymentOrder->setAutoCapture(true);
            $paymentOrder->setCurrency('eur');
            $paymentOrder->setShippingAddress($address);
            $paymentOrder->setDescription($userpro->Club);
            $paymentOrder->setShopId($userpro->conecs['shop_id']); // sub shop id

            $response = $paygreen->createPaymentOrder($paymentOrder);

Le plantage intervient à l'appel de : $paygreen->createPaymentOrder($paymentOrder);

J'ai essayé d'utiliser la lib php-http/curl-client comme mentionné dans votre doc, et ce n'est pas mieux

j'ai testé avec $paygreen->createShop('Test', '123456789');, meme erreur Entre temps je me suis rendu compte qu'il manquait la phase d'Auth, et sans surprise $paygreen->authenticate() fait egalement la meme erreur

Je suppose que votre SDK est utilisé et testé donc je ne veux pas me lancer dans un fork avec des ajustements. C'est forcément de mon coté le problème

thedigital commented 1 year ago

En complément d'info car j'ai vu que qqun d'autre a eu ce probleme dans les issues closed

dd($environnement)

Paygreen\Sdk\Payment\V3\Environment {#1518
  -shopId: "sh_[REDACTED]"
  -secretKey: "sk_[REDACTED]"
  #bearer: null
  #environment: "SANDBOX"
  #apiName: "payment"
  #apiVersion: 3
  #applicationName: null
  #applicationVersion: null
  #cmsName: null
  #cmsVersion: null
  #testMode: false
}

et le voici le dd() de l'exception rencontrée lors de l'appel de $response = $client->authenticate(); :

  #message: "URI must be a string or UriInterface"
  #code: 0
  #file: "/var/www/web-api2/vendor/guzzlehttp/psr7/src/Utils.php"
  #line: 426
  trace: {
    /var/www/web-api2/vendor/guzzlehttp/psr7/src/Utils.php:426 {}
    /var/www/web-api2/vendor/guzzlehttp/psr7/src/functions.php:41 {}
    /var/www/web-api2/vendor/guzzlehttp/guzzle/src/Client.php:211 {}
    /var/www/web-api2/vendor/guzzlehttp/guzzle/src/Client.php:154 {}
    /var/www/web-api2/vendor/guzzlehttp/guzzle/src/Client.php:182 {}
    /var/www/web-api2/vendor/guzzlehttp/guzzle/src/Client.php:95 {}
    /var/www/web-api2/vendor/paygreen/paygreen-php/lib/PaygreenSdk/Core/Client.php:83 {}
    /var/www/web-api2/vendor/paygreen/paygreen-php/lib/PaygreenSdk/Payment/V3/Client.php:66 {}
    /var/www/web-api2/app/Providers/PaygreenServiceProvider.php:37
   ....
}
RomainPayGreen commented 1 year ago

Bonjour Guillaume,

Désolé pour la réponse tardive.

Merci de ton retour, effectivement le SDK est utilisé par plusieurs clients en intégration custom mais aussi dans tous nos modules Wordpress et Prestashop.

Est ce que tu pourrais essayer avec un client curl pour voir ? Avec un code de ce genre :

use Http\Client\Curl\Client;
$curl = new Client();
$client = new \Paygreen\Sdk\Payment\V3\Client($curl, $environment);

On a peut etre un souci avec le client guzzle ou certaines versions de client guzzle, je ferai des tests sur nos machines dès la semaine prochaine.

Bonne fin de journée,

Romain

guillaumbertin commented 1 year ago

Bonjour @thedigital,

Avez-vous pu tester l'implémentation proposé par @RomainPayGreen ?

Cordialement,

Guillaume

thedigital commented 1 year ago

Bonjour Romain et Guillaume,

Je vous confirme qu'avec la lib php-http/curl-client, ca fonctionne bien ! Merci pour votre aide

Bonne fin de journée

sebj54 commented 12 months ago

Bonjour @guillaumbertin,

Pourquoi cette issue est-elle fermée ? En rien le problème n'est réglé et il est pourtant statué dès le début du README que Guzzle est sensé fonctionner avec cette lib.

guillaumbertin commented 12 months ago

Bonjour @sebj54,

Nous avons close car le sujet nous semblait réglé et nous n'avons plus eu de retour, je vous invite à voir les derniers commentaires et nous nous sommes arrêtés là.

Cependant vous semblez avoir un problème avec la solution proposée, je vous invite à le décrire ici.

Cordialement.

sebj54 commented 12 months ago

Merci pour la réponse rapide.

Effectivement, je rencontre le même problème qu'énoncé par l'OP. Le problème est que ça ne fonctionne pas avec Guzzle, et notamment Guzzle 6.

Il y a plein de raisons de ne pas vouloir utiliser php-http/curl-client :


Sinon, concernant le problème en lui-même, j'ai investigué. Le problème est causé par cette ligne :

https://github.com/PayGreen/paygreen-php/blob/cea9ab062f2a690ffda39bd77c2fd9ca52fe167d/lib/PaygreenSdk/Core/Client.php#L83

La méthode sendRequest du client n'existe pas chez Guzzle. Du coup c'est la méthode magique __call qui est appelée et cette méthode n'est pas prévue pour être appelée en lui passant un objet implémentant RequestInterface. À la place, il faudrait appeler $this->client->send($request).

Voici un correctif qui ne nécessite pas d'appel à instanceof (et donc ajouter les deux libs http à paygreen-php) :

if (method_exists($this->client, 'send')) {
    $response = $this->client->send($request);
} else if (method_exists($this->client, 'sendRequest')) {
    $response = $this->client->sendRequest($request);
} else {
    throw new \Exception('The client class ('.get_class($this->client).') does not have a "send" or "sendRequest" method.');
}

Je peux faire une PR pour proposer ce correctif si besoin. Toutefois, je pense qu'il serait judicieux d'implémenter, d'une manière ou d'une autre, des tests pour les deux clients qui sont sensés être supportés.

guillaumbertin commented 12 months ago

Bonjour,

Merci pour la clareté du message, c'est assez peu courant pour être souligné.

Notre readme semble laisser une interprétation.

Sur le point "La version PHP minimale de cette lib est PHP 7.1. Or, vous annoncez être compatible PHP 5.6 (Guzzle 6 supporte PHP > 5.5)".

Nous annoncons être compatible php 5.6 et PSR-18.

La PSR-18 est la PSR qui ajoute l'interface ClientInterface et notamment la méthode sendRequest.

Or, avec la dernière version 6 de guzzle, il n'y a pas la PSR-18. Et avec la version 7 de guzzle, la version minimum de PHP est 7.2.5.

Le correctif que vous proposez fait fonctionner la version 6, mais cela supprime notre pré-requis PSR-18.

sebj54 commented 12 months ago

Merci pour la clareté du message, c'est assez peu courant pour être souligné.

🙏

Très bonne remarque concernant PSR-18, j'ai omis ce point lors de ma tentative d'implémentation.

Dans ce cas, nul besoin de modifier le code de Core\Client, c'est plutôt le README qui nécessiterait quelques précisions, notamment les versions supportées.

J'ai trouvé finalement une parade pour supporter Guzzle 6 avec PSR-18 grâce à https://github.com/mjelamanov/psr18-guzzle. Néanmoins, la librairie supplémentaire nécessite PHP 7.0 donc le support de PHP 5.6 est rendu plus complexe car il nécessiterait une implémentation maison du client HTTP.

$httpClient = new \Mjelamanov\GuzzlePsr18\Client(new \GuzzleHttp\Client);
$client = new \Paygreen\Sdk\Payment\V3\Client($httpClient, $environment);

La requête est bien envoyée avec cette configuration, mais malheureusement je ne peux pas aller plus loin car je rencontre une 403 (mais je ne pense pas que ce soit lié au package mais à notre compte PayGreen).

guillaumbertin commented 12 months ago

En effet, nous allons éditer le readme pour afficher le détail des versions selon le client http choisi.

Concernant la 403, c'est surement un problème de clé, je vous invite à générer des clés sur votre back-office Paygreen.

Si ce n'est pas le problème, vous pouvez passer par ce canal: https://paygreen.atlassian.net/servicedesk/customer/portal/9/group/25/create/114

Cordialement.

sebj54 commented 12 months ago

Effectivement, il s'agissait d'un problème de compte sandbox qui n'était pas en mode marketplace (c'est maintenant résolu). Merci pour votre disponibilité !