phpmagentocookiesmagento-soap-api

PHP -> SOAP -> Magento Webservice: get Cookies set by Magento


I am new to Magento Web-Service and have to expand it. The Webservice shell be able to login an customer, give me the session cookie back so that I can redirect to a file that sets the cookie again, redirects me and I can see my cart and proceed to checkout on the Magento Store.

The Problem: Magento creates a cookie (that contains the session id or whatever, ive tried to set this cookie manual and them im logged in) instead of setting a session when the customer logs in. I've tried now for several hours to get this cookie that is set by magento in my magento web-service. It seems the cookie isn't set when i call

$session = Mage::getSingleton('customer/session');
return $session->getCookie()->get('frontend');

Heres my complete Code: Magento Webservice Api:

<?php 
class Customapi_Model_Core_Api
{

public function __construct()
{
}

public function checkout($user, $cart)
{
    $ret['cookie'] = $this->login($user);

    //$coreCookie = Mage::getSingleton('core/cookie');
    //$ret['cookie'] = $_COOKIE['frontend'];
    return $ret;
}

function login($user)
{
    Mage::getSingleton('core/session', array('name'=>'frontend'));
    $session = Mage::getSingleton('customer/session');
    try
    {
        $session->loginById($user['id']);
    }
    catch (Exception $e)
    {
    }
    return $session->getCookie()->get('frontend');
}

}
?>

Heres my Api Call in Php:

<?php
$teambook_path = 'http://localhost/magento/';

$soap = new SoapClient('http://localhost/magento/api/?wsdl');
$soap->startSession();
$sessionId = $soap->login('ApiUser', 'ApiKey');

$userSession = $soap->call(
    $sessionId,
    'customapi.checkout',
    array(
        array(
            'id' => 1,
            'username' => 'Ruf_Michael@gmx.de',
            'password' => '***'
        ),
        array(
        )
    )
);

echo '<pre>';
var_dump($userSession)."\n";
if(isset($userSession['sid']))
    echo '<a href="'.$teambook_path.'session.php?sid='.$userSession['sid'].'" target="_blank">'.$userSession['sid'].'</a>'."\n";
echo '</pre>';

$soap->endSession($sessionId);
?>

Thanks for every help! MRu


Sorry i am writing an answer but the comment box denied me to write more than ... letters.

I've tried both codes you posted and all I get is an empty Array or Bool false. I wrote a static function:

private static $cookie = array();
public static function cookie($key, $value)
{
    if($key == 'frontend') {
        self::$cookie['key']   = $key;
        self::$cookie['value'] = $value;
    }
}

that is called in Mage_Core_Model_Session_Abstract_Varien::start and I got the frontend cookie value:

Customapi_Model_Core_Api::cookie($sessionName, $this->getSessionId());

in line 125.

But that didnt solve my basic Problem: The Session created in the Api call can't be restored, although it is set to the correct value.

Thanks for your help!


Solution

  • You can get an array of all your cookies with the following command:

    Mage::getModel('core/cookie')->get();
    

    The frontend cookie can be retrieved like this:

    Mage::getModel('core/cookie')->get('frontend');
    

    From your commented code I can see that you already knew that.

    As far as I know, when you log in a user, Magento doesn't just create a new session id, it uses the session id of the active connection (which is generated by PHP itself). You are logging in the user and associating him to the session that your API client just created with Magento. Thus, the code that you have commented seems to be correct for what you are trying to achieve.

    Now you should just need to get the returned session id and use it in your new request as the 'frontend' cookie.

    Edit (a second time)

    Magento has different sessions inside a single PHP session which it uses for different scopes. For instance, there is the core scope, the customer scope, etc. However, the customer scope is also specific to a given website. So, you can have a customer_website_one and a customer_website_two scope.

    If you want to log in your user, you have to tell Magento in which website that is. Take the following code as an example

    // This code goes inside your Magento API class method
    
    // These two lines get your website code for the website with id 1
    // You can obviously simply hardcode the $code variable if you prefer
    // It must obviously be the website code to which your users will be redirected in the end
    $webSites = Mage::app()->getWebsites();
    $code = $webSites[1]->getCode();
    
    $session = Mage::getSingleton("customer/session"); // This initiates the PHP session
    // The following line is the trick here. You simulate that you 
    // entered Magento through a website (instead of the API) so if you log in your user
    // his info will be stored in the customer_your_website scope
    $session->init('customer_' . $code);
    $session->loginById(4);  // Just logging in some example user
    return session_id();     // this holds your session id
    

    If I understand you correctly, you now want to let the user open a PHP script in your server that sets the Magento Cookie to what you just returned in your API method. I wrote the following example which you would access like this: example.com/set_cookie.php?session=THE_RETURNED_SESSION_ID

    <?php
    // Make sure you match the cookie path magento is setting
    setcookie('frontend', $_GET['session'], 0, '/your/magento/cookie/path');
    header('Location: http://example.com');
    ?>
    

    That should do it. Your user is now logged in (at least I got it to work in my test environment). One thing you should keep in mind is that Magento has a Session Validation Mechanism which will fail if enabled. That's because your session stores info about which browser you are using, the IP from which you are connecting, etc. These data will not match between calls through the API methods and the browser later. Here is an example output of the command print_r($session->getData()) after setting the session in the API method

    [_session_validator_data] => Array
    (
        [remote_addr] => 172.20.1.1
        [http_via] => 
        [http_x_forwarded_for] => 
        [http_user_agent] => PHP-SOAP/5.3.5
    )
    

    Make sure you turn of the validation in the Magento Admin in Settings > Configuration > General > Web > Session Validation Settings