Friday 25 July 2014

How do i write a nopCommerce plugin ?

Plugins are used to extend the functionality of nopCommerce. nopCommerce has several types of plugins. For example, payment methods (such as PayPal), tax providers, shipping method computation methods (such as UPS, USP, FedEx), widgets (such as 'live chat' block), and many others. nopCommerce is already distributed with many different plugins. You can also search various plugins on the nopCommerce official site to see if someone has already created a plugin that suits your needs. If not, this article will guide you through the process of creating your own plugin.

The plugin structure, required files, and locations.

  1. First thing you need to do is to create a new "Class Library" project in the solution. It's a good practice to place all plugins into \Plugins directory in the root of your solution (do not mix up with \Plugins subdirectory located in \Nop.Web directory which is used for already deployed plugins). It's a good practice to place all plugins into "Plugins" solution folder (you can find more information about solution folders here).
How to write a nopCommerce plugin

  1. A good name for a plugin project is "Nop.Plugin.{Group}.{Name}". {Group} is your plugin group (for example, "Payment"). {Name} is your plugin name (for example, "AuthorizeNet"). For example, Authorize.NET payment plugin has the following name: Nop.Plugin.Payments.AuthorizeNet.
  2. Once the plugin project is created update the project build output path. Set it to "..\..\Presentation\Nop.Web\Plugins\{Group}.{Name}\". For example, Authorize.NET payment plugin has the following output path: "..\..\Presentation\Nop.Web\Plugins\Payments.AuthorizeNet\". After it's done, appropriate plugin DLLs will be automatically copied to the \Presentation\Nop.Web\Plugins\ directory which is searched by the nopCommerce core for valid plugins.
How to write a nopCommerce plugin

    1. On the Project menu, click Properties.
    2. Click the Build tab.
    3. Click the Browse button next to the Output path box and select a new build output directory.
    You should do the steps described above to all existing configurations ("Debug" and "Release").
  1. The next step is creating a Description.txt file required for each plugin. This file contains meta information describing your plugin. Just copy this file from any other existing plugin and modify it for your needs. For example, Authorize.NET payment plugin has the following Description.txt file:
    Group: Payment methods
    FriendlyName: Credit Card
    SystemName: Payments.AuthorizeNet
    Version: 1.00
    SupportedVersions: 2.30
    Author: nopCommerce team
    DisplayOrder: 1
    FileName: Nop.Plugin.Payments.AuthorizeNet.dll
    
    Actually all fields are self-descriptive, but here are some notes. SystemName field should be unique. Version field is a version number of your plugin; you can set it to any value you like. SupportedVersions field can contain a list of supported nopCommerce versions separated by commas (ensure that the current version of nopCommerce is included in this list, otherwise, it will not be loaded). FileName field has the following format Nop.Plugin.{Group}.{Name}.dll (it is your plugin assembly filename). Ensure that "Copy to Output Directory" property of this file is set to "Copy if newer".
How to write a nopCommerce plugin


  1. You should also created a web.config file and ensure that it's copied to output. Just copy it from any existing plugin.
  2. The last required step is to create a class which implements IPlugin interface (Nop.Core.Plugins namespace). nopCommerce has BasePlugin class which already implements some IPlugin methods and allows you to avoid source code duplications. nopCommerce also provides you with some specific interfaces derived from IPlugin. For example, we have "IPaymentMethod" interface which is used for creating new payment method plugins. It contains some methods which are specific only for payment methods such as ProcessPayment() or GetAdditionalHandlingFee(). Currently nopCommerce has the following specific plugin interfaces:
    1. IExternalAuthenticationMethod. Used for creating external authentication methods such as Facebook, Twitter, OpenID, etc.
    2. IWidgetPlugin. It allows you to create widgets. Widgets are rendered on some parts of your site. For example, it can be a "Live chat" block on the left column of your site.
    3. IExchangeRateProvider. Used for getting currency exchange rate.
    4. IDiscountRequirementRule. Allows you to create new discount rules such as "Billing country of a customer should be…"
    5. IPaymentMethod. Plugins which are used for payment processing.
    6. IShippingRateComputationMethod. These plugins are used for retrieving accepted delivery methods and appropriate shipping rates. For example, UPS, UPS, FedEx, etc.
    7. ITaxProvider. Tax providers are used for getting tax rates.
    If your plugin doesn't fit any of these interfaces, then use the "IMiscPlugin" interface.
    Important note: After each project build, clean the solution before making changes. Some resources will be cached and can lead to developer insanity.

Handling requests. Controllers, models and views.

Now you can see the plugin by going to Admin area > Configuration > Plugins. But as you guessed our plugin does nothing. It does not even have a user interface for its configuration. Let's create a page to configure the plugin. What we need to do now is create a controller, a model, and a view.
  1. MVC controllers are responsible for responding to requests made against an ASP.NET MVC website. Each browser request is mapped to a particular controller.
  2. A view contains the HTML markup and content that is sent to the browser. A view is the equivalent of a page when working with an ASP.NET MVC application.
  3. An MVC model contains all of your application logic that is not contained in a view or a controller.
You can find more information about the MVC pattern here.
So let's start:
  1. Create the model. Add a Models folder in the new plugin, and then add a new model class which fits your need.
  2. Create the view. Add a Views folder in the new plugin, then add a {Name} folder (where {Name} is your plugin name), and finally add a cshtml file named Configure.cshtml. Important note: for versions 2.00-3.30 the view should be marked as an embedded resource. And starting version 3.40 views should be copied to output.
  3. Create the controller. Add a Controllers folder in the new plugin, and then add a new controller class. A good practice is to name plugin controllers {Group}{Name}Controller.cs. For example, PaymentAuthorizeNetController. Create an appropriate action method for configuration. Let's name it "Configure". Prepare a model class and pass it to the following view. For versions 2.00-3.30 you should pass embedded view path - "Nop.Plugin.{Group}.{Name}.Views. {Group}{Name}.Configure". And starting version 3.40 you should pass physical view path - "~/Plugins/{Group}.{Name}/Views/{Group}{Name}/Configure.cshtml". For example, open Authorize.NET payment plugin and look at its implementation of PaymentAuthorizeNetController.
Tip 1: The easiest way to complete the steps described above is opening any other plugin and copying these files into your plugin project. Then just rename appropriate classes and directories.
Tip 2: If you want to limit access to a certain action method of the controller to administrators (store owners), then just mark it with [AdminAuthorize] attribute.
Tip 3: Going forward make sure "Copy local" properties of all third-party assembly references are set to "False" (do not copy). This will reduce the deployed package size.
For example, the project structure of Authorize.NET plugin looks like the image below

How to write a nopCommerce plugin

Routes.

Now we need to register appropriate plugin routes. ASP.NET routing is responsible for mapping incoming browser requests to particular MVC controller actions. You can find more information about routing here. So follow the next steps:
  1. Some of the specific plugin interfaces (described above) and the "IMiscPlugin" interface have the following method: "GetConfigurationRoute". It should return a route to a controller action which is used for plugin configuration. Implement the "GetConfigurationRoute" method of your plugin interface. This method informs nopCommerce about what route is used for plugin configuration. If your plugin doesn't have a configuration page, then "GetConfigurationRoute" should return null. For example see the code below:
    public void GetConfigurationRoute(out string actionName, 
                out string controllerName, 
                out RouteValueDictionary routeValues)
            {
                actionName = "Configure";
                controllerName = "PaymentAuthorizeNet";
                routeValues = new RouteValueDictionary()
                {
                    { "Namespaces", "Nop.Plugin.Payments.AuthorizeNet.Controllers" }, 
                    { "area", null }
                };
            }
    
  2. (optional) If you need to add some custom route, then create RouteProvider.cs file. It informs the nopCommerce system about plugin routes. For example, the following RouteProvider class adds a new route which can be accessed by opening your web browser and navigating to http://www.yourStore.com/Plugins/PaymentPayPalStandard/PDTHandler URL (used by PayPal plugin):
    public partial class RouteProvider : IRouteProvider
        {
            public void RegisterRoutes(RouteCollection routes)
            {
    
    
                 routes.MapRoute("Plugin.Payments.PayPalStandard.PDTHandler",
                     "Plugins/PaymentPayPalStandard/PDTHandler",
                     new { controller = "PaymentPayPalStandard", action = "PDTHandler" },
                     new[] { "Nop.Plugin.Payments.PayPalStandard.Controllers"  }
                );
    
            }
            public int Priority
            {
                get
                {
                    return 0;
                }
            }
        }
    
Once you have installed your plugin and added the configuration method you will find a link to configure your plugin under Admin > Configuration > Plugins.

Handling "Install" and "Uninstall" methods.

This step is optional. Some plugins can require additional logic during plugin installation. For example, a plugin can insert new locale resources. So open your IPlugin implementation (in most case it'll be derived from BasePlugin class) and override the following methods:
  1. Install. This method will be invoked during plugin installation. You can initialize any settings here, insert new locale resources, or create some new database tables (if required).
  2. Uninstall. This method will be invoked during plugin uninstallation.
Important note: If you override one of these methods, do not hide its base implementation. For example, overridden "Install" method should include the following method call: base.Install(). The "Install" method of Authorize.NET plugin looks like the code below
public override void Install()
        {
            var settings = new AuthorizeNetPaymentSettings()
            {
                UseSandbox = true,
                TransactMode = TransactMode.Authorize,
                TransactionKey = "123",
                LoginId = "456"
            };
            _settingService.SaveSetting(settings);

            base.Install();
        }
Tip: The list of installed plugins is located in \App_Data\InstalledPlugins.txt. The list is created during installation.

Upgrading nopCommerce may break plugins

Some plugins may become outdated and no longer work with the newer version of nopCommerce. If you have issues after upgrading to the newer version, delete the plugin and visit the official nopCommerce website to see if a newer version is available. Many plugin authors will upgrade their plugins to accommodate the newer version, however, some will not and their plugin will become obsolete with the improvements in nopCommerce. But in most cases, you can simply open an appropriate Description.txt file and update SupportedVersions field.

Conclusion

Hopefully this will get you started with nopCommerce and prepare you to build more elaborate plugins.

Sunday 20 July 2014

Login with facebook using PHP ( Demo and Download )

Login with facebook : You can use facebook login in your websites to allow users to login using their facebook account.you don’t need an extra registration and user management for your sites.you can also manage users in your facebook application page. This article explains how to integrate “Facebook login” to your websites using Facebook PHP SDK with an example and demo.

Login with facebook

This article contains 3 main files and 2 facebook SDK files in src folder.
» src
- – -base_facebook.php
- – -facebook.php
» fbconfig.php
» index.php
» logout.php

Creating facebook App for your site

Step 1 » Goto https://developers.facebook.com/apps/ and Create a new app .
Login with facebook app creation

Type your app name and press continue.
Step 2 » After completing captcha verification . you can see your App ID and App secret .
Login with facebook app ID and secret
Step 3 » Now complete the other basic details .
» Find App Domains: under Basic Info and Enter your domain details like demos.zombi.com.
» Find Site URL: under Website with Facebook Login and type your site url like http://demos.zombi.com/.
Login with facebook app creation

fbconfig.php file overview

Step 4 » Download the Demo package here Login with facebook .
Step 5 » Now open fbconfig.php file and enter your app ID and secrets .

$facebook = new Facebook(array(
'appId' => '642945345353456456', // Facebook App ID
'secret' => '856379884d66aeefdfgdgdgtesdgdrgr', // Facebook App Secret
'cookie' => true,
));


Step 6 » And change logout URL path ( Enter Full path ) .
$logoutUrl = $facebook->getLogoutUrl(array(
'next' => 'http://demos.krizna.com/logout.php', // Logout URL full path
));

Step 7 » Enter the permission details, Here i need permission to view the user email registered with their facebook account. Here is the list of permissionshttps://developers.facebook.com/docs/reference/login/#permissions and scope names you can call in this sections.
$loginUrl = $facebook->getLoginUrl(array(
'scope' => 'email', // Permissions to request from the user
));

Step 8 » Finally full code of fbconfig.php file. See the commented lines for more details


<?php
require 'src/facebook.php';  // Include facebook SDK file
$facebook = new Facebook(array(
  'appId'  => '642945345353456456',   // Facebook App ID
  'secret' => '856379884d66aeefdfgdgdgtesdgdrgr',  // Facebook App Secret
  'cookie' => true,    
));
$user = $facebook->getUser();
if ($user) {
  try {
    $user_profile = $facebook->api('/me');
          $fbid = $user_profile['id'];           // To Get Facebook ID
        $fbuname = $user_profile['username'];  // To Get Facebook Username
        $fbfullname = $user_profile['name'];    // To Get Facebook full name
  } catch (FacebookApiException $e) {
    error_log($e);
   $user = null;
  }
}
if ($user) {
  $logoutUrl = $facebook->getLogoutUrl(array(
         'next' => 'http://demos.krizna.com/1353/logout.php',  // Logout URL full path
        ));
} else {
$loginUrl = $facebook->getLoginUrl(array(
        'scope'        => 'email', // Permissions to request from the user
        ));
}
?>

logout.php file overview


Logout.php file is used only to destroy facebook session and return back to your home page .
Step 9 » If you want you can enter your home page in the code.

<?php
require 'fbconfig.php';   // Include fbconfig.php file
$facebook->destroySession();  // to destroy facebook sesssion
header("Location: " ."./");        // you can enter home page here ( Eg : header("Location: " ."http://demo.krizna.com");
?>

index.php file overview


Step 10 » You can change this file as per your need . Split this file into 2 parts before login and after login.
<?php
require 'fbconfig.php';   // Include fbconfig.php file
?>
<!doctype html>
<html xmlns:fb="http://www.facebook.com/2008/fbml">
  <head>
    <title>Login with facebook</title>
   --- --- ---
  css stuff
   --- --- ----
</head>
  <body>
  <?php if ($user): ?>      
              -- --- - - - -- -
           Display content After user login
             -- -- - --- ---- -- -  
    <?php else: ?>    
              -- --- - - - -- -
           Display content before login
             -- -- - --- ---- -- -  
    <?php endif ?>
  </body>
</html>

Finally full code of index.php file .

<?php
require 'fbconfig.php';   // Include fbconfig.php file
?>
<!doctype html>
<html xmlns:fb="http://www.facebook.com/2008/fbml">
  <head>
    <title>Login with Facebook</title>
<link href="http://www.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap-combined.min.css" rel="stylesheet">
</head>
  <body>
  <?php if ($user): ?>      <!--  After user login  -->
<div class="container">
<div class="hero-unit">
  <h1>Hello <?php echo $fbuname; ?></h1>
  <p>Welcome to "facebook login" tutorial</p>
  </div>
<div class="span4">
<ul class="nav nav-list">
<li class="nav-header">Image</li>
    <li><img src="https://graph.facebook.com/<?php echo $user; ?>/picture"></li>
<li class="nav-header">Facebook ID</li>
<li><?php echo  $fbid; ?></li>
<li class="nav-header">Facebook Username</li>
<li><?php echo $fbuname; ?></li>
<li class="nav-header">Facebook fullname</li>
<li><?php echo $fbfullname; ?></li>
<div><a href="<?php echo $logoutUrl; ?>">Logout</a></div>
</ul></div></div>
    <?php else: ?>     <!-- Before login -->
<div class="container">
<h1>>Login with Facebook</h1>
           Not Connected
<div>
      <a href="<?php echo $loginUrl; ?>">Login with Facebook</a></div>
      </div>
    <?php endif ?>
  </body>
</html>