Как стать автором
Обновить

Комментарии 8

curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, false);

Вот за это я и люблю все руководства.
Ребят, не нужно плевать на безопасность, а?
Не претендую на истину в последней инстанции, но как-то так, с проверками хоста и прочими плюшками, возможно, будет лучше:
/**
 * Yandex API wrapper.
 * - First of all you need to register new console application @link https://oauth.yandex.ru/client/new
 *   with redirect_url https://oauth.yandex.ru/verification_code
 * - Next - take <access_code>:
 *   https://oauth.yandex.ru/authorize?response_type=code&client_id=<client_id>
 * - Use $this->getTokenByCode() to obtain access_token
 */
class YandexApiBase
{
    private $client_id;
    private $client_secret;

    public $access_token;

    public function __construct($token, $id=null, $secret=null)
    {
        $this->client_id = $id;
        $this->client_secret = $secret;
        $this->access_token = $token;
    }

    /**
     * @param string $code
     * @throws YandexApiException on fail
     */
    public function getTokenByCode($code)
    {
        $data = self::rawRequest('POST', 'https://oauth.yandex.ru/token', array(
            'grant_type'=>'authorization_code',
            'code'=>$code,
            'client_id'=>$this->client_id,
            'client_secret'=>$this->client_secret,
        ));
        if (!$data)
            throw new YandexApiException("Can't take access_token by application code");
        $data = json_decode($data);
        if (isset($data['error']))
            throw new YandexApiException("Shit happens: {$data['error']}");
        if (!isset($data['access_token']))
            throw new YandexApiException("No errors, but token not send: ".CVarDumper::dumpAsString($data));
        return $data;

    }

    protected function request($method='GET', $url, $options = array())
    {
        $url .= (strpos($url, '?')===false ? '?' : '&') . http_build_query(array('oauth_token'=>$this->access_token));
        return json_decode(self::rawRequest($method, $url, $options), true);
    }

    /**
     * Send request with token
     * @param $url
     * @param array $options
     * @param string $method
     */
    protected static function rawRequest($method='GET', $url, $options = array())
    {
        //Default options for all requests
        $curlOpt = array(
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_FOLLOWLOCATION => 1,
            CURLOPT_MAXREDIRS => 3,

            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_TIMEOUT => 20,

            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_SSL_VERIFYHOST => 2,
            CURLOPT_CAPATH => dirname(__FILE__).'/cert',
            CURLOPT_CAINFO => dirname(__FILE__).'/cert/solid-cert.crt',
        );

        switch (strtoupper($method)){
            case 'DELETE':
                $curlOpt[CURLOPT_CUSTOMREQUEST] = "DELETE";
            case 'GET':
                if (!empty($options))
                    $url .= (strpos($url, '?')===false ? '?' : '&') . http_build_query($options);
            break;
            case 'PUT':
                $body = http_build_query($options);
                $fp = fopen('php://temp/maxmemory:256000', 'w');
                if (!$fp)
                    throw new YandexApiException('Could not open temp memory data');
                fwrite($fp, $body);
                fseek($fp, 0);
                $curlOpt[CURLOPT_PUT] = 1;
                $curlOpt[CURLOPT_BINARYTRANSFER] = 1;
                $curlOpt[CURLOPT_INFILE] = $fp; // file pointer
                $curlOpt[CURLOPT_INFILESIZE] = strlen($body);
            break;
            case 'POST':
                $curlOpt[CURLOPT_HTTPHEADER] = array('Content-Type: application/x-www-form-urlencoded; charset=UTF-8;');
                $curlOpt[CURLOPT_POST] = true;
                $curlOpt[CURLOPT_POSTFIELDS] = http_build_query($options);
            break;
            default:
                throw new YandexApiException("Unsupported request method '$method'");
        }

        $curl = curl_init($url);
        curl_setopt_array($curl, $curlOpt);
        $return = curl_exec($curl);
        $err_no = curl_errno($curl);
        if ($err_no === 0) {
            curl_close($curl);
            return $return;
        } else {
            $err_msg = curl_error($curl);
            curl_close($curl);
            throw new YandexApiException($err_msg, $err_no);
        }
    }

}

class YandexApiException extends Exception {}


И совсем для ленивых (кто не хочет выдирать сертификаты с сайтов Яндекса):
-----BEGIN CERTIFICATE-----
MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD
VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv
bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv
b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV
UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH
iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS
r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4
04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r
GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9
3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P
lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEPjCCA6egAwIBAgIEBycT9TANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV
UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
b2JhbCBSb290MB4XDTA3MDExNzE1MTYyMFoXDTE0MDExNzE1MTU0NlowWzESMBAG
CgmSJomT8ixkARkWAnJ1MRYwFAYKCZImiZPyLGQBGRYGeWFuZGV4MRIwEAYKCZIm
iZPyLGQBGRYCbGQxGTAXBgNVBAMTEFlhbmRleEV4dGVybmFsQ0EwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDOf3icODyZl7NcIpHKuJQ5ol5X/roVHJiG
0s2wu3vXYmyEYTFQLGM1qr/yjOAKnNtwpQMr98+quO7SWs8TvtxT+mf75lptRuD2
JawD2Vrkqq/gv92L0lyg6vfmWgovWhGftKjy6S8LPTGhsypfPEvCjBzG3IcyIlUP
S/4VIvk5hXLNFlvR9iPjMZ6Pfs1MfU+GwudBWkG4HefSTcrsJV4j/l/eORIkCc36
yWWTJrCUTTigx50qeRjiH6Aq8UxEhaNNU6GROgEQyarDT0n78Zu4v8/S6bRBhL+q
yDMTUDuXzLseDNr5i1w8g6NZ9XbvmMF4fl5SGAKKNtLFxfeDqsoXAgMBAAGjggFv
MIIBazASBgNVHRMBAf8ECDAGAQH/AgEBMFMGA1UdIARMMEowSAYJKwYBBAGxPgEA
MDswOQYIKwYBBQUHAgEWLWh0dHA6Ly93d3cucHVibGljLXRydXN0LmNvbS9DUFMv
T21uaVJvb3QuaHRtbDAOBgNVHQ8BAf8EBAMCAYYwgYkGA1UdIwSBgTB/oXmkdzB1
MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL
Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBD
eWJlclRydXN0IEdsb2JhbCBSb290ggIBpTBFBgNVHR8EPjA8MDqgOKA2hjRodHRw
Oi8vd3d3LnB1YmxpYy10cnVzdC5jb20vY2dpLWJpbi9DUkwvMjAxOC9jZHAuY3Js
MB0GA1UdDgQWBBTbQScwTxr1Wz6EVsjshZizUSwtJzANBgkqhkiG9w0BAQUFAAOB
gQAZuNLEObDlHdW3QJbokq5ANrTp9/WLLdRONjFK0tPkHq5FjeyX4GgPVvAUTuQa
ydC35nz7H+1SGZBp9F+pT9YnaNH6lKl7o8mXPOCznQYeIvGCgI4L1uv37QtBvbri
B/I8h+FY/43FMjAnk9ciR1xgbARK4bUKZaPd9MdU+/TY7w==
-----END CERTIFICATE-----
Качаем cacert.pem и скармливаем курлу через опцию CURLOPT_CAINFO.
А чем Вы сертификаты выдирали?
FireFox + блокнот =)
Заходим на страницу oauth.yandex.ru/, открываем список сертификатов, сохраняем в файлики, файлы склеиваем.
Либо поиграться с вытаскиванием через код:
    public function actionIndex($domain){
        $context = stream_context_create (array("ssl" => array("capture_peer_cert" => true)));
        $run = stream_socket_client("ssl://$domain:443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
        $cont = stream_context_get_params($run);
        if (isset($cont["options"]["ssl"]["peer_certificate"])) {
            openssl_x509_export($cont["options"]["ssl"]["peer_certificate"], $output);
            return $output;
        } else {
            return false;
        }
    }

Но так достается только OAuth сертификат, дальше копать в сторону автоматического выдергивания всех не стал. быстрее FireFox + блокнот =)
Спасибо за код. Я как-то пробовал получать сертификаты при помощи openssl в консоли, но иногда этот способ подводил или у меня руки кривые :)
У меня это происходило из бэкофиса сайта, по этой причине не видел смысла в значении «1» или «2» для CURLOPT_SSL_VERIFYHOST и true для CURLOPT_SSL_VERIFYPEER.
Но если делать это, как сервис «для всех», то согласен, что лучше подстраховаться.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории