Académique Documents
Professionnel Documents
Culture Documents
Magento 2
Briefly description about how I did the integration of both platforms.
composer.json
{
"name": "tmo/customer",
"description": "Add functions to Magento Customer Module",
"require": {
"php": "~5.5.0|~5.6.0|~7.0.0"
},
"type": "magento2-module",
"version": "1.0.7",
"license": [
"OSL-3.0",
"AFL-3.0"
],
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"Tmo\\Customer\\": ""
}
}
}
registration.php
<?php
use \Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Tmo_Customer', __DIR__);
?>
ii.
In etcfolder, module.xml:
module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Tmo_Customer" setup_version="1.0.24" />
</config>
Then execute:
ButtonSize.php
<?php
namespace Tmo\Customer\Model\Config\Source;
class ButtonSize implements \Magento\Framework\Option\ArrayInterface
{
/**
* @return array
*/
public function toOptionArray()
{
return [
['value' => 'small', 'label' => __('Small')],
['value' => 'medium', 'label' => __('Medium')],
['value' => 'large', 'label' => __('Large')]
];
}
}
system.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<system>
<section id="customer" translate="label" sortOrder="130" showInDefault="1"
showInWebsite="1" showInStore="1">
<group id="sociallogin" translate="label" sortOrder="92" showInDefault="1"
showInWebsite="1" showInStore="1">
<label>Social Login Options</label>
<field id="social_login_button_style" translate="label" type="select"
sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Size of social media login provider icons</label>
<source_model>Tmo\Customer\Model\Config\Source\ButtonSize</source_model>
</field>
<field id="social_login_enabled_wechat" translate="label comment"
type="select" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Use WeChat as Social Login</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Enables de customer to login using his existing WeChat
account.</comment>
</field>
<field id="social_login_appid_wechat" translate="label" type="text"
sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Wechat APP ID*</label>
</field>
<field id="social_login_secret_wechat" translate="label" type="text"
sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Wechat Secret*</label>
</field>
<field id="social_login_token_wechat" translate="label" type="text"
sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Token*</label>
</field>
</group>
</section>
</system>
</config>
Example of UpgradeData.php
$customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
$customerSetup->addAttribute(
\Magento\Customer\Model\Customer::ENTITY,
'social_oid',
[
'input'=>'text',
'type'=>'varchar',
'label'=>'Social OpenID',
'visible'=>false,
'required'=>false,
'system'=>false,
'position'=> 156
]
);
$customerSetup->getEavConfig()->getAttribute('customer', 'social_oid')
->setData('used_in_forms',
['customer_account_create','customer_account_edit','adminhtml_customer'])
->save();
b. Modify the module version in the file etc/module.xml, increment it. This is to tell Magento there are changes in
the module and it needs to update itself.
c. @PHP container terminal,check Magento database status, if it found changes it will show them:
bin/magento setup:db:status
The module code base doesn't match the DB schema and data.
Tmo_Customer
schema:
1.0.24 -> 1.0.25
Tmo_Customer
data:
1.0.24 -> 1.0.25
Run 'setup:upgrade' to update your DB schema and data.
bin/magento setup:upgrade
Example #1 of Provider.php
abstract class Provider
{
const BUTTON_SMALL='small';
const BUTTON_MEDIUM='medium';
const BUTTON_LARGE='large';
const BUTTON_DEFAULT=self::BUTTON_SMALL;
const XML_PATH_SOCIAL_LOGIN_BUTTON='customer/sociallogin/social_login_button_style';
public static $impl= [
Providers\Wechat::TITLE=>Providers\Wechat::TYPE,
Providers\Facebook::TITLE=>Providers\Facebook::TYPE,
Providers\Weibo::TITLE=>Providers\Weibo::TYPE,
Providers\Douban::TITLE=>Providers\Douban::TYPE
];
public static $buttonStyles=[
self::BUTTON_SMALL=>'Small',
self::BUTTON_MEDIUM=>'Medium',
self::BUTTON_LARGE=>'Large'
];
Example #2 of Provider.php
public function name()
{
return $this->m_name;
}
public function title()
{
return $this->m_title;
}
public function domain()
{
return $this->m_domain;
}
public function template()
{
return "tmo/customer/view/frontend/templates/{$this->m_name}.phtml";
}
public function isEnabled()
{
return
1===(int)$this->_scopeConfig->getValue("customer/sociallogin/social_login_enabled_{$this->m_name}
");
}
public function appID()
{
return
$this->_scopeConfig->getValue("customer/sociallogin/social_login_appid_{$this->m_name}");
}
public function secretKey()
{
return
$this->_scopeConfig->getValue("customer/sociallogin/social_login_secret_{$this->m_name}");
}
public function authorizationUrl()
{
return
$this->_scopeConfig->getValue("customer/sociallogin/social_login_general_auth_url_{$this->m_name}
");
}
Example of Wechat.php
public function login(array $data_)
{
$strOauthAccessTokenURL = $this->oauhAccessTokenUrl();
$parameters['appid'] = $this->appID();
$parameters['secret'] = $this->secretKey();
$parameters['code'] = $data_['code'];
$parameters['grant_type'] = 'authorization_code';
$parameters['state'] = $data_['state'];
if (!$contents=$this->http($strOauthAccessTokenURL,$parameters,'GET'))
return null;
$result=json_decode($contents, true);
$openid = $result["openid"];
$access_token = $result["access_token"];
$strGetUserInfo = $this->userInfoUrl();
$parameters = array();
$parameters['access_token'] = $access_token;
$parameters['openid'] = $openid;
$parameters['state'] = $data_['state'];
if (!$contents=$this->http($strGetUserInfo,$parameters,'GET'))
return null;
$result=json_decode($contents, true);
if(false===isset($result["nickname"]))
return null;
...
...
providers.phtml
<table width="100">
<tr>
<?
$providers = \Tmo\Customer\Model\Social\Login\Provider::$impl;
foreach($providers as $name=>$type)
{
$providerClass = "Tmo\Customer\Model\Social\Login\Providers\\".$name;
$provider = new $providerClass($this->getMyScopeConfig());
if($provider->isEnabled())
{?>
<td>
<ol class="<?= $provider->name().' '.$provider->buttonSize(); ?> ">
<a href="<?= $block->getUri($provider) ?>" title="<?= $provider->name() ?>">
<img src="<?= $block->getImageUrl($provider) ?>" alt="<?= $provider->name()
?>Login"/>
</a>
</ol>
</td>
<?}
}
?>
</tr>
</table>
b. Create the fileview/frontend/templates/form/login.phtml. This file completely overrides the original core file.
Copy the original content into it and add the following lines at the end before the last </form> tag:
part of login.phtml
<div class="field note"><?php echo __('Or, sign in with the Social Media Provider of your
preference:') ?></div><br>
<div class="terciary">
<?php echo $block->getChildHtml('form_social_login'); ?>
</div>
c. Create the fileview/frontend/templates/form/newcustomer.phtml. This file completely overrides the original core
file. Copy the original content into it and add the following lines at the end before the last </div> tag:
part of newcustomers.phtml
<div id="login_container"></div>
<script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
<script type="text/javascript">
var appVersion = navigator.appVersion;
var isWeChat = appVersion.indexOf("MicroMessenger");
if(isWeChat < 0 ){
var obj = new WxLogin({
id:"login_container",
appid: "wx9a4eb803e732bdec",
scope: "snsapi_login",
redirect_uri:"<?=UrlEncode('http://wechat.tmogroup.asia/getcode.php')?>",
state: "wechatqrcode",
style: "black",
href: ""
});
}
</script>
This piece of code will show the QR code to scan and log in using WeChat account, only when user is not using the
WeChat web browser.
9. Create layout. This file will tell Magento when to open which template and which block class is the owner of the
template.
a. Create fileview/frontend/layout/customer_account_login.xml. This file completely overrides the original core file.
Copy the original content into it and add the following lines:
parto of customer_account_login.xml
<block class="Magento\Customer\Block\Form\Login" name="customer_form_login"
template="Tmo_Customer::form/login.phtml">
<container name="form.additional.info" as="form_additional_info"/>
<container name="form.social.login" as="form_social_login"/>
</block>
part of customer_account_login.xml
<block class="Magento\Customer\Block\Form\Login\Info" name="customer.new"
template="Tmo_Customer::newcustomer.phtml">
<container name="form.qrcode.wechat.login" as="form_qrcode_wechat_login"/>
</block>
part of customer_account_login.xml
<referenceContainer name="form.social.login">
<block class="Tmo\Customer\Block\RenderProvider" name="form_social_login_customer"
template="Tmo_Customer::providers.phtml"/>
</referenceContainer>
Note that the blocks still define the original class but with different template.
10.
10.
Create a block to write the html code which render the social media providers.
a. Create the fileBlock/RenderProvider.php. This file will initialize all the properties required to render html to
the screen using templates, and also provide all the functionality (constructors, methods, functions, etc) to the
template files.
11.
di.xml
<config>
<type name="Magento\Customer\Controller\Account\Login">
<plugin name="controller_social_login_plugin"
type="Tmo\Customer\Controller\Account\Plugin"
sortOrder="10"
disabled="false"/>
</type>
<type name="Magento\Customer\Block\Form\Login">
<plugin name="customer_block_form_login_plugin"
type="Tmo\Customer\Block\Form\Plugin"
sortOrder="5"
disabled="false"/>
</type>
<preference for="Tmo\Customer\Model\Social\Login\Provider_wechat"
type="Tmo\Customer\Model\Social\Login\Providers\Wechat" />
<preference for="Tmo\Customer\Model\Social\Login\Provider_facebook"
type="Tmo\Customer\Model\Social\Login\Providers\Facebook" />
</config>
This file also defines something new in Magento 2: "preferences". Briefly, this preferences tells to Magento "when
you'll see this string create an instance of this type", and basically they are used in the constructors for
something also new called automatic dependency injection, I'll write about it in another article.
b. Create the fileController/Account/Plugin.php. This is finally the plugin class which implements all the previous
defined functions. The next diagram explains how this plugin works:
The plugin will intercept the core functionality of login module, it will check if there is a CODE and a PROVIDER
in the URL, if that's there plugin will get the configuration of the provider, will try to connect to the
authorization service to get the user information, will check if the user already exists, if it does will redirect
it to the dashboard but if it doesn't will register it into the database, and the redirect it to its dashboard.
Related articles
How-To: WeChat as Social Login (Part 1)
How-To: Wechat as Social Login (Part 2)