web-dev-qa-db-fra.com

Problème de certificat SSL impossible d'obtenir le certificat de l'émetteur local

J'essaie de publier des données sur une API de passerelle de paiement. Cela nécessitait l'affichage de données au format XML. J'ai le code suivant:

<?php
$requestUrl = 'https://api.given.bypg'; //$block->getPaymentUrl();

$amount = 100; // $block->totalOrderAmount()*100; 

$approveUrl = $block->approveUrl();
$cancelUrl =  $block->cancelUrl();
$declineUrl = $block->declineUrl();


$merchant = 'mydomain.com'; 
//$amount = '100'; // in cents. 1$ = 100cents. 
$currency = '840'; // for dollar
$description = 'Happy customers is what we make.';
$merchantId = 'Nobel106513';
?>

<?php
echo $requestUrl;
$xml_data = '<TKKPG>
<Request>
<Operation>CreateOrder</Operation>
<Language>EN</Language>
<Order>
<OrderType>Purchase</OrderType>
<Merchant>'.$merchantId.'</Merchant>
<Amount>'.$amount.'</Amount>
<Currency>'.$currency.'</Currency>
<Description>'.$description.'</Description>
<ApproveURL>'.$approveUrl.'</ApproveURL>
<CancelURL>'.$cancelUrl.'</CancelURL>
<DeclineURL>'.$declineUrl.'</DeclineURL>
</Order>
</Request>
</TKKPG>';

$ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $requestUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60000);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);//My post data
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_CAPATH, "/etc/Apache2/ssl/m4/mydomain.com.crt");
        curl_setopt($ch, CURLOPT_CAINFO, "/etc/Apache2/ssl/m4/mydomain.com.crt");
        curl_setopt($ch, CURLOPT_CERTINFO, 1);

        $headers = [];
        array_Push($headers, 'Content-Type: text/xml;charset=UTF-8');
        //array_Push($headers, 'SoapAction: *');
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        $content = trim(curl_exec($ch));
        var_dump($content);
        var_dump(curl_getinfo($ch));
        var_dump(curl_errno($ch));
        var_dump(curl_error($ch));
        curl_close($ch);
  1. La sortie de var_dump($content); est vide ''.
  2. Sortie de var_dump(curl_getinfo($ch));.

    tableau (taille = 26) 
    'url' => chaîne ' https: //api.given.bypg '
    'content_type' => null
    'http_code' => int 0
    'header_size' => int 0
    'request_size' => int 0
    'filetime' => int -1
    'ssl_verify_result' => int 1
    'redirect_count' => int 0
    'total_time' => float 0.488533
    'namelookup_time' => float 0.028558
    'connect_time' => float 0.256858
    'pretransfer_time' => float 0
    'size_upload' => float 0
    'size_download' => float 0
    'speed_download' => float 0
    'speed_upload' => float 0
    'download_content_length' => float -1
    'upload_content_length' => float -1
    'starttransfer_time' => float 0
    'redirect_time' => float 0
    'redirect_url' => chaîne '' (longueur = 0)
    'primary_ip' => chaîne '91 .227.244.57 '(longueur = 13)
    'certinfo' =>
    tableau (taille = 0)
    vide
    'primary_port' => int 8444
    'local_ip' => chaîne '192.168.100.64' (longueur = 14)
    'local_port' => int 53456

  3. Sortie de var_dump(curl_errno($ch));: int 60

  4. Sortie de var_dump(curl_error($ch));:

    string 'Problème de certificat SSL: impossible d'obtenir le certificat de l'émetteur local' (longueur = 63) Il semble que l'API ne renvoie aucune donnée, comme le montre curl_getinfo (). S'il vous plaît aidez-moi, j'ai vu presque toutes les solutions proposées dans les communautés.

J'ai modifié mon fichier php.ini pour indiquer le chemin d'accès au certificat téléchargé depuis le site Web de curl. Mais cela n'a pas fonctionné aussi bien.

5

Les fournisseurs de mon API ont pris en charge le support et ont signalé un élément manquant dans mon approche. Pour leur passerelle, j'avais besoin de charger la clé privée, la clé publique et le mot de passe qui protège ces clés dans une requête curl. La solution est la suivante:

/*ssl crts*/
$twpg_cert_file = "/etc/Apache2/ssl/m4/mydomain.com.crt";
$twpg_key_file = "/etc/Apache2/ssl/m4/mydomain.com.key";
$twpg_key_password = '';
/*ssl crts*/
$ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $requestUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60000);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);//My post data
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSLCERT,  $twpg_cert_file);
        curl_setopt($ch, CURLOPT_SSLKEY, $twpg_key_file);
        curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $twpg_key_password);
        curl_setopt($ch, CURLOPT_CERTINFO, 1);
        $headers = [];
        array_Push($headers, 'Content-Type: text/xml;charset=UTF-8');
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        $content = trim(curl_exec($ch));
        curl_close($ch);

Maintenant, tout fonctionne comme prévu.

0

Lorsque vous vous connectez au serveur pour établir une connexion sécurisée, vous obtenez en tant que client le certificat du serveur au début de la conversation. Ce certificat et sa clé privée servent à établir la connexion sécurisée. Votre client veut s'assurer que le certificat du serveur est approuvé et qu'il n'a pas été créé par un attaquant intermédiaire. Votre client doit donc disposer du certificat de l'autorité de certification ayant signé le certificat du serveur. L'erreur ci-dessus signifie que le client a essayé de trouver l'émetteur de certificat du serveur (ou l'un des émetteurs de la chaîne) et n'a pas trouvé. L'emplacement qu'il tente de trouver se trouve dans le fichier /etc/Apache2/ssl/m4/mydomain.com.crt spécifié. Vous avez le choix entre deux options: ajouter un certificat de CA au fichier ou désactiver la vérification du certificat de serveur (non sécurisé) en définissant CURLOPT_SSL_VERIFYPEER sur false.

2
Oleg