多店多域一次结账,单个客户登录到所有商店?

Multi store multi domain one checkout, single customer login into all stores?

我是 运行 Opencart v2.3.0.2 在多个域(不是子域)上的多商店,想在主站点上结帐,该站点包含所有商店的所有产品。

由于很难在多个域上共享会话,因此认为最好在结帐过程之前强制用户登录(所有商店的登录凭据都相同,并且购物车项目是共享的)。但是,默认情况下,用户必须分别登录每个商店 - 如何创建单一登录 into/for 所有商店 ?登录后,我可以将它们发送到主站点进行结帐。

如果您认为有更好的单点结账方式,欢迎提出。

如果您只需在所有商店中登录您的用户就足够了(并且您不会使用相同的会话 ID),您可以

1) 为所有商店实施登录 link 锁定

2) 成功登录到您的一家商店后作为回应将他发回所有其他商店登录 links

3) 执行每个登录 link by ajax.

因此您将登录一个,但会自动登录所有商店

注意: 最好是您的登录表单本身也由 ajax 填写,这样用户只需输入凭据,如果成功,会看到更长的时间 ajax加载期间你将一一执行rest login links

您想要的是单点登录。有很多方法可以做到这一点,一种更安全的方法是使用 JSON Web Token(如 https://github.com/lcobucci/jwt)。简而言之,这些是带符号的 JSON 字符串,因此您可以使用异步加密的强大功能! ;)

Opencart 2 设置了两个 HTTPOnly cookie PHPSESSIDdefault 来识别客户。因此,我决定 share/sync 他们在商店里。

1.获取 Javascript

的商店列表

也许不是最好的,但在/catalog/controller/common/header.php我分配了一个变量:

$this->load->language('setting/store');
$this->load->model('setting/store');
$this->load->model('setting/setting');

$data['multi_stores'] = array();

$data['multi_stores'][] = array(
    'store_id'      => 0,
    'name'          => 'Main Site',
    'url'           => 'https://mysite.co.uk/',
    'is_current'    => stripos('https://mysite.co.uk/', $_SERVER['SERVER_NAME']) !== false
);

$results = $this->model_setting_store->getStores();
foreach ($results as $result) {
    $data['multi_stores'][] = array(
        'store_id'      => $result['store_id'],
        'name'          => $result['name'],
        'url'           => $result['url'],
        'is_current'    => stripos($result['url'], $_SERVER['SERVER_NAME']) !== false
    );
}

2。比在我使用的模板中:

<script type="text/javascript">
var multiStores = <?php echo json_encode($multi_stores); ?>;
</script>

3。创建了两个 PHP 脚本来设置和获取 cookie:

  • 请注意,要设置 PHP HTTPOnly cookie,第 7 个参数必须是 true
  • 另外请注意,要获取 HTTPOnly cookie,我们必须从服务器请求它,它无法通过 Javascript 访问(这首先是它的目的)。

getCookies.php:

$cookies = array(
    'PHPSESSID' => $_COOKIE['PHPSESSID'],
    'default' => $_COOKIE['default'],
    'currency' => $_COOKIE['currency'],
    'language' => $_COOKIE['language']
);

header('Content-Type: application/json');
echo json_encode( $cookies );

setCookies.php:

$response = array(
    'status' => 'ok'
);

/* Format: [cookie name] => [expire days] */
$cookies_to_sync = array(
    'PHPSESSID' => '',
    'default' => '',
    'currency' => 30,
    'language'=> 30
);

/* If no expire was set, than set session HTTPOnly cookie (last, 7th parameter 'true') */
foreach( $cookies_to_sync as $cname=>$cexpire ) {
    if( $_POST[$cname] ) {
        if( $cexpire ) {
            /* 86400 seconds per day */
            setcookie($cname, $_POST[$cname], time() + (86400 * $cexpire), '/', null, null, false);
        } else {
            setcookie($cname, $_POST[$cname], null, '/', null, null, true);
        };
    };
};

/* Browser requests a JSON, cross-origin enabled, with OPTIONS enabled to set cookies */
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Max-Age: 1000');
header('Content-Type: application/json');
echo json_encode( $response );

4. Javascript部分: - 请注意,为了 send/set cookies cross-domain,我们在 PHP header 和 jQuery 中设置了 OPTIONS我们添加 $.ajax xhrFields 选项 withCredentials: true。考虑到这一点,我创建了同步网站 cookie 的方法:

this.syncWebsites = function() {
    if( typeof multiStores!='undefined' ) {
        that.stores = multiStores;
        that.synced = that.readCookie('synced');
        if( !that.synced ) {
            /* First get cookies */
            $.getJSON( "catalog/view/theme/mytheme/javascript/getCookies.php", function( data ) {
                /* Send to other sites */
                $.each(that.stores, function(i, store) {
                    if( !store.is_current ) {
                        /* Send to other sites, MUST use xhrFields->withCredentials: true, to set cookies */
                        $.ajax({
                            url: store.url.replace('http://', '//') + "catalog/view/theme/mytheme/javascript/setCookies.php",
                            xhrFields: {
                                withCredentials: true
                            },
                            type: "post",
                            crossDomain: true,
                            data: data,
                            dataType: "json",
                            success:function(result){
                                that.echo(JSON.stringify(result));
                            },
                            error:function(xhr, status, error){
                                that.echo(status);
                            }
                        });
                    };
                });
                that.createCookie('synced', 'Yes', '');
            });
        };
    };
};

请注意:我创建了 synced cookie,因此此请求仅在 session 期间发生一次。

最终结果: 我们在所有网站上同步了所有 Opencart 2 客户。

安全考虑: 所有网站都使用 SSL 加密。窃取信息的危险与访问所有这些网站的危险相同。