Symfony 3, paiement avec paypal, erreur 81002

a marqué ce sujet comme résolu.

Bonjour à tous,

J'utilise le bundle PayumBundle qui permet aux utilisateurs d'acheter en ligne avec paypal. Pour le moment je travaille uniquement avec la sandbox.

Sur mon site de développement en local, tout fonctionne bien. on est bien redirigé sur le site de paypal quand on clique sur le bouton "acheter maintenant", on arrive à faire le paiement jusqu'au bout. Sur mon site en ligne par contre, j'obtiens systématiquement une erreur 81002, et malgré mes recherche sur le web, je n'ai pas vraiment compris d'où pouvait venir le problème et comment le résoudre.

La version locale et celle en ligne étant synchronisées par git (i.e. la version en ligne est automatiquement pull quand je push depuis ma version locale), le code du contrôleur utilisant Payum et le config.yml sont identiques. Par contre vu que le dossier vendor n'est pas synchronisé par défaut, ça me paraissait moins problématique de ne pas partager les trucs de composer et en particuler le composer.json. A priori ce sont également les mêmes, en tout cas en ce qui concerne la partie dépendances. La seule différence significative étant donc les environnements me semble-t-il.

Voici ce que je reçois comme erreur au moment où je clique sur mon bouton "acheter maintenant" :

1
{"status":"failed","payment":{"total_amount":1490,"currency_code":"CHF","details":{"INVNUM":"5722f6d6b8476","PAYMENTREQUEST_0_CURRENCYCODE":"CHF","PAYMENTREQUEST_0_AMT":14.9,"PAYMENTREQUEST_0_DESC":"payment_dperiod0","PAYMENTREQUEST_0_PAYMENTACTION":"Sale","AUTHORIZE_TOKEN_USERACTION":"commit","RETURNURL":"http:\/\/monsite.com\/payment\/capture\/ohGauNaZrfMyNaAriyLefKhNFIfXKn8WRQtwKTICtUU","CANCELURL":"http:\/\/monsite.com\/payment\/capture\/ohGauNaZrfMyNaAriyLefKhNFIfXKn8WRQtwKTICtUU?cancelled=1","PAYMENTREQUEST_0_NOTIFYURL":"http:\/\/monsite.com\/payment\/notify\/LP_1DwyfchzB5X1Z8_oCE5NLWwGFJ5uAZhVEJfCjS0c","ACK":"Failure","L_ERRORCODE0":"81002","L_SHORTMESSAGE0":"UnspecifiedMethod","L_LONGMESSAGE0":"Method Specified is not Supported","L_SEVERITYCODE0":"Error"}}}

Voici les parties qui me paraissent intéressantes du contrôleur. Je suis très largement parti du code d'exemple donné dans la doc du bundle, pour un paiement simple utilisant paypal express checkout / paypal NVP.

Je ne sais pas si c'est réellement le moyen le plus simple et le meilleur pour permettre aux utilisateur de payer mon service en ligne sur mon site, car j'ai l'impression que l'acheteur doit obligatoirement avoir un compte paypal (ce qui me dérange un peu car j'ai peur que ce soit un peu bloquant) au cas où il n'en a pas, et je n'ai pas besoin de l'adresse postale (car ce que je vends est purement immatériel). Si vous pensez que je devrais utiliser une autre API, je prends volontiers vos conseils.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<?php
    /**
     * @Route("/{_locale}/activation/pay", name="paymentNew", requirements={"_locale"="%locales%"})
     */
    public function newAction(Request $request)     {
$user = $this->getUser();
if ($this->isGranted('ROLE_USER')) {
$form = $this->createForm('AppBundle\Form\PaymentForm');
$form->handleRequest($request);
if ($form->isValid()) {
//...
        $gatewayName = 'paypal_express_checkout';
        $storage = $this->get('payum')->getStorage('AppBundle\Entity\Payment');
        $payment = $storage->create();
$payment->setCurrencyCode('CHF');
$payment->setTotalAmount(floor(100*$cost));
$payment->setClientEmail($user->getEmail());
$payment->setClientId($user->getId());
$payment->setNumber(uniqid());
$payment->setDescription($this->trans("payment_d$key", array(), 'activation'));
        $storage->update($payment);
        $captureToken = $this->get('payum')->getTokenFactory()->createCaptureToken(
            $gatewayName, 
            $payment, 
            'paymentDone' 
        );
        return $this->redirect($captureToken->getTargetUrl());    
}}
}
        return $this->render('paymentNew.twig', [
            'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
//...
'form' => @$form?$form->createView() :null,
        ]);
    }

    /**
     * @Route("/{_locale}/payment/done", name="paymentDone", requirements={"_locale"="%locales%"})
     */
    public function doneAction(Request $request)     {
$this->denyAccessUnlessGranted('ROLE_USER');
        $token = $this->get('payum')->getHttpRequestVerifier()->verify($request);
        $gateway = $this->get('payum')->getGateway($token->getGatewayName());
 $this->get('payum')->getHttpRequestVerifier()->invalidate($token);
        $gateway->execute($status = new GetHumanStatus($token));
        $payment = $status->getFirstModel();
$status = strtolower($status->getValue());
$amount = $payment->getTotalAmount()/100.0;
if ($status=='captured') {
//... le paiement a réussi, on met à jour le compte utilisateur ...
        return $this->render('paymentSuccess.twig', [
            'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
        ]);
}
else {
// Le paiement a foiré, on affiche une erreur
//$this->addFlash('error', $this->trans('PaymentFailed', array(), 'activation'));
//return $this->redirectToRoute('paymentPrepare', array('_locale'=>$request->getLocale()));
echo \nl2br(\json_encode(array(
'status' => $status,
            'payment' => array(
                'total_amount' => $payment->getTotalAmount(),
                'currency_code' => $payment->getCurrencyCode(),
                'details' => $payment->getDetails(),
            ),
)));
exit();
}}

Voici la partie relative à Payum dans le config.yml :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
payum:
    security:
        token_storage:
            AppBundle\Entity\PaymentToken: { doctrine: orm }
    storages:
        AppBundle\Entity\Payment: { doctrine: orm }
    gateways:
        paypal_express_checkout:
            factory: paypal_express_checkout
            username: %payment_username%
            password: %payment_password%
            signature: %payment_signature%
            sandbox: %payment_sandbox%

ET le parameters.yml :

1
2
3
4
    payment_username: XXX-XXX_api1.XXX.com # Le nom de mon compte
    payment_password: XXX # Le mot de passe fourni par paypal sandbox
    payment_signature: XXX # La clé fournie par paypal sandbox
    payment_sandbox: true

ET le composer.json :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
{
    "name": "My application",
    "license": "proprietary",
    "type": "project",
    "autoload": {
        "psr-4": {
            "": "src/"
        },
        "classmap": [
            "app/AppKernel.php",
            "app/AppCache.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.0.*",
        "doctrine/orm": "^2.5",
        "doctrine/doctrine-bundle": "^1.6",
        "doctrine/doctrine-cache-bundle": "^1.2",
        "symfony/swiftmailer-bundle": "^2.3",
        "symfony/monolog-bundle": "^2.8",
        "sensio/distribution-bundle": "^5.0",
        "sensio/framework-extra-bundle": "^3.0.2",
        "incenteev/composer-parameter-handler": "^2.0",
        "friendsofsymfony/user-bundle": "~2.0@dev",
        "doctrine/doctrine-fixtures-bundle": "^2.3",
        "willdurand/js-translation-bundle": "^2.5",
        "payum/payum-bundle": "^2.0",
        "payum/offline": "^1.3",
        "payum/paypal-express-checkout-nvp": "^1.3",
        "captcha-com/symfony-captcha-bundle": "4.*",
        "php-http/guzzle6-adapter": "^1.0"
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0",
        "symfony/phpunit-bridge": "^2.7"
    },
    "scripts": {
        "post-install-cmd": [
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
        ],
        "post-update-cmd": [
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
        ]
    },
    "extra": {
        "symfony-app-dir": "app",
        "symfony-bin-dir": "bin",
        "symfony-var-dir": "var",
        "symfony-web-dir": "web",
        "symfony-tests-dir": "tests",
        "symfony-assets-install": "relative",
        "incenteev-parameters": {
            "file": "app/config/parameters.yml"
        }
    }
}

Comme je l'ai dit, la seule différence évidente d'après moi entre la version en local qui fonctionne et la version en ligne qui ne fonctionne pas, ce sont les environnements. A savoir :

En local: Windows 7 64 bits avec WAMP incluant PHP 5.5.12 et MySQL 5.6.17
En ligne: debian 8.0 64 bits à jour avec PHP 5.6.19 et MariaDB 10.0.23

Composer et symfony me paraissent à jour, j'ai exécuté plusieurs fois php composer.phar self-update et php composer.phar update de part et d'autre. Évidemment un vidage du cache même en virant carrément le dossier var/cache à la main ne change rien au problème.

Quelqu'un a-t-il une idée ?

Merci pour vos réponses.

+0 -0

Si vous pensez que je devrais utiliser une autre API, je prends volontiers vos conseils.

Si tu veux passer par autre chose que paypal qui est assez contraignant, il existe justement d'autres services qui proposent des API à intégrer, comme Stripe ou LemonWay . C'est quasi invisible pour le client, et ça prend les cartes bancaires (pas besoin de créer un compte !).

Je n'y ai jamais utilisé personnellement et je ne sais pas si il existe des bundle symfony (possible qu'il en existe pour Stripe je penses !) mais tu devrais y jeter un œil je penses !

+0 -0

Salut !

J'ai édité ton message pour corriger le rendu du contenu de ton composer.json  ;)

D'après le message, la méthode n'est pas supportée. Est-ce que par hasard en local, tu as des paramètres d'environnement qui font que POST est possible, et ce serait GET en distant (ou GET en local et POST en distant) ?

Sinon, vu que c'est apparemment en PHP 5.6 que default_charset a été utilisé pour certaines fonctions pour le traitement interne des chaînes de caractères, est-ce que ce serait un souci de charset ?

+0 -0

Si tu veux passer par autre chose que paypal qui est assez contraignant, il existe justement d'autres services qui proposent des API à intégrer

A vrai dire je ne m'attendais pas à ce genre de réponse. Dans la forêt des API de paypal, je m'attendais plutôt à ce qu'on m'en pointe peut-être une autre, toujours chez paypal, qui serait peut-être plus adaptée. Mais je vais aler regarder, ces alternatives n'ont pas l'air inintéressantes !

D'après le message, la méthode n'est pas supportée. Est-ce que par hasard en local, tu as des paramètres d'environnement qui font que POST est possible, et ce serait GET en distant (ou GET en local et POST en distant) ?

Je n'ai pas la moindre idée de où il passe exactement, comment est-ce que je peux le savoir ? Il ne faut quand même pas que je resssorte tcpdump, si ?

Sinon, vu que c'est apparemment en PHP 5.6 que default_charset a été utilisé pour certaines fonctions pour le traitement interne des chaînes de caractères, est-ce que ce serait un souci de charset ?

Je n'en ai aucune idée non plus. Tout est configuré en UTF-8 en local comme sur mon serveur normalement. Je n'ai aucun problème de charset ni sur aucune page, ni dans la base, ni dans les traductions en tout cas.

Y a-t-il un moyen de tracer ce qui est envoyé aux serveurs de paypal ?

Merci.

+0 -0

Je n'ai pas la moindre idée de où il passe exactement, comment est-ce que je peux le savoir ? Il ne faut quand même pas que je resssorte tcpdump, si ?

QuentinC

J'espère que non. C'est juste que "Method not supported", ça me fait furieusement penser à la définition des statuts HTTP 501 et 505, voire 405.

Je n'en ai aucune idée non plus. Tout est configuré en UTF-8 en local comme sur mon serveur normalement. Je n'ai aucun problème de charset ni sur aucune page, ni dans la base, ni dans les traductions en tout cas.

QuentinC

C'est là que c'est vicieux, parce que si c'est la librairie utilisée par le bundle qui en interne utilise des méthodes dont le jeu de caractères a changé entre les deux versions de PHP (5.5 et 5.6), ça ne se verra pas forcément sur ton site, sinon par des erreurs incompréhensibles au premier abord… Je m'étais amusé à déboguer whatwedo/PostFinanceEPayment et CKOTech/checkout-php-library, à l'époque…

Y a-t-il un moyen de tracer ce qui est envoyé aux serveurs de paypal ?

QuentinC

… ce qui m'a mené à la seule méthode que j'aie trouvé pour déboguer le truc : mettre cURL en mode débogage, modifier temporairement le code et sortir les logs.

+0 -0

Corrigez-moi si je me trompe, mais si je comprends bien, si je veux logger les requêtes CURL effectuées

  • Soit je suis obligé d'aller modifier le code de PayumBundle pour ajouter les options de debug cf. cet article ou encore cette question stackoverflow
  • Soit je suis obligé de le faire en mode warrior avec tcpdump ou un autre sniffeur.

Et je suppose que la deuxième solution n'est même pas pratiquable, vu que la communication entre paypal et mon site est censée être en HTTPS et donc chiffrée.

Pas vraiment pratique. J'aurais espérer qu'on puisse activer un logging dans le php.ini directement, sans avoir à toucher à du code que je n'ai pas moi-même écrit.

Si je regarde mon phpinfo, je vois bien une option de configuration debug qui est réglée sur no. Mais je ne trouve pas une explication sur ce qu'elle fait dans la doc de CURL. Extrait de mon phpinfo concernant CURL sur le serveur online (attention, les tableaux ne passent pas) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
cURL support 
enabled  
cURL Information 
7.38.0  
Age 
3   
Features 
AsynchDNS 
Yes  
CharConv 
No  
Debug 
No  
GSS-Negotiate 
No  
IDN 
Yes  
IPv6 
Yes  
krb4 
No  
Largefile 
Yes  
libz 
Yes  
NTLM 
Yes  
NTLMWB 
Yes  
SPNEGO 
Yes  
SSL 
Yes  
SSPI 
No  
TLS-SRP 
Yes  
Protocols 
dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, ldaps, pop3, pop3s, rtmp, rtsp, scp, sftp, smtp, smtps, telnet, tftp  
Host 
x86_64-pc-linux-gnu  
SSL Version 
OpenSSL/1.0.1k  
ZLib Version 
1.2.8  
libSSH Version 
libssh2/1.4.3 

Je vous tiens au courant quand j'aurais réussi à logger les requêtes. Merci.

+0 -0

Bonjour,

J'ai ajouté les options de debug CURL pour voir ce qui est envoyé aux serveurs de paypal. Mais ça ne m'aide pas à comprendre davantage où est le souci.

Ci-dessous le log de debug sur le serveur, la requête qui n'aboutit pas. J'ai effacé les clés qu'on peut lire en clair.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
* Hostname was NOT found in DNS cache
*   Trying 173.0.82.83...
* Connected to api-3t.sandbox.paypal.com (173.0.82.83) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / AES256-SHA256
* Server certificate:
*    subject: C=US; ST=California; L=San Jose; O=PayPal, Inc.; OU=PayPal Production; CN=api-3t.sandbox.paypal.com
*    start date: 2016-01-14 00:00:00 GMT
*    expire date: 2018-01-14 23:59:59 GMT
*    subjectAltName: api-3t.sandbox.paypal.com matched
*    issuer: C=US; O=Symantec Corporation; OU=Symantec Trust Network; CN=Symantec Class 3 Secure Server CA - G4
*    SSL certificate verify ok.
> POST /nvp HTTP/1.1
User-Agent: GuzzleHttp/6.2.0 curl/7.38.0 PHP/5.6.19-0+deb8u1
Host: api-3t.sandbox.paypal.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 757

* upload completely sent off: 757 out of 757 bytes
< HTTP/1.1 200 OK
< Date: Mon, 09 May 2016 08:36:46 GMT
* Server Apache is not blacklisted
< Server: Apache
< Connection: close
< HTTP_X_PP_AZ_LOCATOR: sandbox.slc
< Paypal-Debug-Id: 29b7ee2ecd623
< Set-Cookie: X-PP-SILOVER=name%3DSANDBOX3.API.1%26silo_version%3D1880%26app%3Dappdispatcher_apit%26TIME%3D508309591%26HTTP_X_PP_AZ_LOCATOR%3Dsandbox.slc; Expires=Mon, 09 May 2016 09:06:46 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
< Set-Cookie: X-PP-SILOVER=; Expires=Thu, 01 Jan 1970 00:00:01 GMT
< Content-Length: 146
< Content-Type: text/plain; charset=utf-8
< 
* Closing connection 0

Request body:
INVNUM=57304c1c5625d&amp;PAYMENTREQUEST_0_CURRENCYCODE=CHF&amp;PAYMENTREQUEST_0_AMT=39.9&amp;PAYMENTREQUEST_0_DESC=payment_dperiod1&amp;PAYMENTREQUEST_0_PAYMENTACTION=Sale&amp;AUTHORIZE_TOKEN_USERACTION=commit&amp;RETURNURL=http%3A%2F%2Fmonsite.com%2Fpayment%2Fcapture%2FqHHCcZ0mJbc7RHqDslRYCr27T7q0545ViqIzePX30lM&amp;CANCELURL=http%3A%2F%2Fmonsite.com%2Fpayment%2Fcapture%2FqHHCcZ0mJbc7RHqDslRYCr27T7q0545ViqIzePX30lM%3Fcancelled%3D1&amp;PAYMENTREQUEST_0_NOTIFYURL=http%3A%2F%2Fmonsite.com%2Fpayment%2Fnotify%2F-AJjCAAzhh0rVgdkIFarC3njjduhTn72VXE7F4K-jQw&amp;METHOD=SetExpressCheckout&amp;VERSION=65.1&amp;PWD=...&amp;USER=...&amp;SIGNATURE=...

Response body:
ACK=Failure&L_ERRORCODE0=81002&L_SHORTMESSAGE0=Unspecified%20Method&L_LONGMESSAGE0=Method%20Specified%20is%20not%20Supported&L_SEVERITYCODE0=Error

Et pour comparaison, celui qui fonctionne en local :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
* Hostname was found in DNS cache
*   Trying 173.0.82.83...
* Connected to api-3t.sandbox.paypal.com (173.0.82.83) port 443 (#5)
* successfully set certificate verify locations:
*   CAfile: C:\wamp\bin\apache\apache2.4.9\cacert.pem
  CApath: none
* SSL connection using TLSv1.2 / AES256-SHA256
* Server certificate:
*    subject: C=US; ST=California; L=San Jose; O=PayPal, Inc.; OU=PayPal Production; CN=api-3t.sandbox.paypal.com
*    start date: 2016-01-14 00:00:00 GMT
*    expire date: 2018-01-14 23:59:59 GMT
*    subjectAltName: api-3t.sandbox.paypal.com matched
*    issuer: C=US; O=Symantec Corporation; OU=Symantec Trust Network; CN=Symantec Class 3 Secure Server CA - G4
*    SSL certificate verify ok.
> POST /nvp HTTP/1.1
User-Agent: GuzzleHttp/6.2.0 curl/7.36.0 PHP/5.5.12
Host: api-3t.sandbox.paypal.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 813

* upload completely sent off: 813 out of 813 bytes
< HTTP/1.1 200 OK
< Date: Mon, 09 May 2016 08:28:12 GMT
* Server Apache is not blacklisted
< Server: Apache
< X-PAYPAL-OPERATION-NAME: SetExpressCheckout
< X-PAYPAL-API-RC: 
< Connection: close
< HTTP_X_PP_AZ_LOCATOR: sandbox.slc
< Paypal-Debug-Id: 3861cffa767d3
< Set-Cookie: X-PP-SILOVER=name%3DSANDBOX3.API.1%26silo_version%3D1880%26app%3Dappdispatcher_apit%26TIME%3D474624087%26HTTP_X_PP_AZ_LOCATOR%3Dsandbox.slc; Expires=Mon, 09 May 2016 08:58:12 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
< Set-Cookie: X-PP-SILOVER=; Expires=Thu, 01 Jan 1970 00:00:01 GMT
< Content-Length: 137
< Content-Type: text/plain; charset=utf-8
< 
* Closing connection 5

Request body:
INVNUM=57304a1aba5af&PAYMENTREQUEST_0_CURRENCYCODE=CHF&PAYMENTREQUEST_0_AMT=39.9&PAYMENTREQUEST_0_DESC=payment_dperiod1&PAYMENTREQUEST_0_PAYMENTACTION=Sale&AUTHORIZE_TOKEN_USERACTION=commit&RETURNURL=http%3A%2F%2Flocalhost%2FSymfonyProject1%2Fweb%2Fapp_dev.php%2Fpayment%2Fcapture%2F35X7ybiolb1OlPATLZ_FqkS7Z0cQLwFsN0o8xGL25gM&CANCELURL=http%3A%2F%2Flocalhost%2FSymfonyProject1%2Fweb%2Fapp_dev.php%2Fpayment%2Fcapture%2F35X7ybiolb1OlPATLZ_FqkS7Z0cQLwFsN0o8xGL25gM%3Fcancelled%3D1&PAYMENTREQUEST_0_NOTIFYURL=http%3A%2F%2Flocalhost%2FSymfonyProject1%2Fweb%2Fapp_dev.php%2Fpayment%2Fnotify%2FrJUmsi2JD_9lQMCf-sb0r9ppRrDyBA-ZNSR4sUpqqZk&METHOD=SetExpressCheckout&VERSION=65.1&PWD=...&USER=...&SIGNATURE=...

Response body:
TOKEN=EC%2d7CU84878TE750784Y&TIMESTAMP=2016%2d05%2d09T08%3a28%3a12Z&CORRELATIONID=3861cffa767d3&ACK=Success&VERSION=65%2e1&BUILD=21799703

* Hostname was found in DNS cache
*   Trying 173.0.82.83...
* Connected to api-3t.sandbox.paypal.com (173.0.82.83) port 443 (#6)
* successfully set certificate verify locations:
*   CAfile: C:\wamp\bin\apache\apache2.4.9\cacert.pem
  CApath: none
* SSL re-using session ID
* SSL connection using TLSv1.2 / AES256-SHA256
* Server certificate:
*    subject: C=US; ST=California; L=San Jose; O=PayPal, Inc.; OU=PayPal Production; CN=api-3t.sandbox.paypal.com
*    start date: 2016-01-14 00:00:00 GMT
*    expire date: 2018-01-14 23:59:59 GMT
*    subjectAltName: api-3t.sandbox.paypal.com matched
*    issuer: C=US; O=Symantec Corporation; OU=Symantec Trust Network; CN=Symantec Class 3 Secure Server CA - G4
*    SSL certificate verify ok.
> POST /nvp HTTP/1.1
User-Agent: GuzzleHttp/6.2.0 curl/7.36.0 PHP/5.5.12
Host: api-3t.sandbox.paypal.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 199

* upload completely sent off: 199 out of 199 bytes
< HTTP/1.1 200 OK
< Date: Mon, 09 May 2016 08:28:13 GMT
* Server Apache is not blacklisted
< Server: Apache
< X-PAYPAL-OPERATION-NAME: GetExpressCheckoutDetails
< X-PAYPAL-API-RC: 
< Connection: close
< HTTP_X_PP_AZ_LOCATOR: sandbox.slc
< Paypal-Debug-Id: b5398db685e1d
< Set-Cookie: X-PP-SILOVER=name%3DSANDBOX3.API.1%26silo_version%3D1880%26app%3Dappdispatcher_apit%26TIME%3D491401303%26HTTP_X_PP_AZ_LOCATOR%3Dsandbox.slc; Expires=Mon, 09 May 2016 08:58:13 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
< Set-Cookie: X-PP-SILOVER=; Expires=Thu, 01 Jan 1970 00:00:01 GMT
< Content-Length: 1019
< Content-Type: text/plain; charset=utf-8
< 
* Closing connection 6

Request body:
TOKEN=EC-7CU84878TE750784Y&METHOD=GetExpressCheckoutDetails&VERSION=65.1&PWD=...&USER=...&SIGNATURE=...

Response body:
TOKEN=EC%2d7CU84878TE750784Y&BILLINGAGREEMENTACCEPTEDSTATUS=0&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2016%2d05%2d09T08%3a28%3a13Z&CORRELATIONID=b5398db685e1d&ACK=Success&VERSION=65%2e1&BUILD=000000&CURRENCYCODE=CHF&AMT=39%2e90&SHIPPINGAMT=0%2e00&HANDLINGAMT=0%2e00&TAXAMT=0%2e00&DESC=payment_dperiod1&NOTIFYURL=http%3a%2f%2flocalhost%2fSymfonyProject1%2fweb%2fapp_dev%2ephp%2fpayment%2fnotify%2frJUmsi2JD_9lQMCf%2dsb0r9ppRrDyBA%2dZNSR4sUpqqZk&INSURANCEAMT=0%2e00&SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_CURRENCYCODE=CHF&PAYMENTREQUEST_0_AMT=39%2e90&PAYMENTREQUEST_0_SHIPPINGAMT=0%2e00&PAYMENTREQUEST_0_HANDLINGAMT=0%2e00&PAYMENTREQUEST_0_TAXAMT=0%2e00&PAYMENTREQUEST_0_DESC=payment_dperiod1&PAYMENTREQUEST_0_NOTIFYURL=http%3a%2f%2flocalhost%2fSymfonyProject1%2fweb%2fapp_dev%2ephp%2fpayment%2fnotify%2frJUmsi2JD_9lQMCf%2dsb0r9ppRrDyBA%2dZNSR4sUpqqZk&PAYMENTREQUEST_0_INSURANCEAMT=0%2e00&PAYMENTREQUEST_0_SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUESTINFO_0_ERRORCODE=0

Je constate que sur le serveur, il n'arrive pas à récupérer de token et donc il s'arrête là. Mais je ne comprends toujours pas pourquoi ! Évidemment j'ai vérifié 36 fois les identifiants et c'est bien entendu les mêmes…

Pour référence, voici les modifications apportées qui m'ont permis de logger les requêtes CURL. On ne sait jamais, ça pourrait servir à d'autres :

1
2
3
4
5
6
7
8
9
<?php//  /vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:54
        $easy->handle = $this->handles
            ? array_pop($this->handles)
            : curl_init();
        curl_setopt_array($easy->handle, $conf);
curl_setopt($easy->handle, CURLOPT_VERBOSE, true); 
$easy->stderr = fopen('curl-log.txt', 'a');
curl_setopt($easy->handle, CURLOPT_STDERR, $easy->stderr);
        return $easy;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php//  /vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:112
        $body = $easy->response->getBody();
        if ($body->isSeekable()) {
            $body->rewind();
        }

if ($easy->stderr && $body->isSeekable()) {
$result = $body->read(65535);
            $body->rewind();
$body2 = $easy->request->getBody();
$body2->rewind();
$result2 = $body2->read(65535);
fwrite($easy->stderr, "\r\nRequest body:\r\n$result2\r\n");
fwrite($easy->stderr, "\r\nResponse body:\r\n$result\r\n");
}
        return new FulfilledPromise($easy->response);

Merci pour votre aide.

+0 -0

Petite question : est-ce que chez PayPal il ne faut pas configurer une URL d'origine pour les appels ?

Qu'est-ce que tu veux dire par là ?

Si tu penses à une vérification du genre dire à paypal que toutes les requêtes proviennent de monsite.com et de nulle part ailleurs, en tout cas je n'ai pas vu pareille configuration dans leur panel. Et comme je n'ai jamais rien configuré de ce genre, je suppose que s'il y avait, ça ne fonctionnerait pas non plus en localhost.

+0 -0

Problème trouvé et résolu, mais il faudra qu'on m'explique.

La mauvaise requête sur le serveur séparait les paramètres avec &amp; plutôt que &. Il faisait cela à cause du paramètre arg_separator.output du php.ini qui valait &amp; au lieu de &. JE l'ai remis sur & et ça fonctionne.

Par contre du coup sur un autre (vieux) site web, il génère des URL invalides, car dans un <a href="...">, le séparateur doit être &amp; et non &. C'était pour cette raison que j'avais initialement changé ce paramètre, que je l'ai conservé et perpétué à chaque changement de serveur; depuis 7 ans.

Le problème est donc résolu mais du coup j'ai une tout autre question maintenant: comment est-ce que je peux avoir un php.ini partiellement différent d'un site web à l'autre ? Sachant qu'ils tournent tous sur le même serveur, même apache, dans des virtual hosts.

+0 -0

Le problème est donc résolu mais du coup j'ai une tout autre question maintenant: comment est-ce que je peux avoir un php.ini partiellement différent d'un site web à l'autre ? Sachant qu'ils tournent tous sur le même serveur, même apache, dans des virtual hosts.

QuentinC

Alors pour ça, je pense que tu peux regarder la partie masquée de ce message. En bref, tu pourrais créer des fichiers php.ini qui seraient propres aux hébergements et lus de manière similaire à des .htaccess, pour autant que la directive que tu dois modifier soit modifiable par ce biais.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte