# Tutorial

This tutorial will help you implement PrestaShop Billing into your flat-fee priced module.

TIP

If you're looking for the implementation of your Stairstep plan, follow this tutorial and go to our "Implementing a Stairstep pricing model" tutorial next.

Example module

An example module already integrating the components of the PrestaShop Integration Framework is available on Github (opens new window) to help you with development.

# Implementing the module-lib-billing package in your module

module-lib-billing is an important part of the PrestaShop Billing solution, as it helps you setup some needed information in a standardized format.

  1. Edit the config\admin\services.yml file to include the following highlighted contents:































     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     

    services:
      _defaults:
        public: true
    
      ##############
      # Your Module
    
      <module_name>.module:
        class: <module_name>
        factory: ['Module', 'getInstanceByName']
        arguments:
          - '<module_name>'
    
      <module_name>.context:
        class: Context
        factory: ['Context', 'getContext']
    
      #####################
      # PrestaShop Account
    
      <module_name>.ps_accounts_installer:
        class: 'PrestaShop\PsAccountsInstaller\Installer\Installer'
        arguments:
          - '5.0'
    
      <module_name>.ps_accounts_facade:
        class: 'PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts'
        arguments:
          - '@<module_name>.ps_accounts_installer'
    
      #####################
      # PrestaShop Billing
    
      <module_name>.ps_billings_context_wrapper:
        class: 'PrestaShopCorp\Billing\Wrappers\BillingContextWrapper'
        arguments:
        - '@<module_name>.ps_accounts_facade'
        - '@<module_name>.context'
        - true # if true, enables the sandbox mode, if false or empty, disables it
    
      <module_name>.ps_billings_facade:
        class: 'PrestaShopCorp\Billing\Presenter\BillingPresenter'
        public: true
        arguments:
        - '@<module_name>.ps_billings_context_wrapper'
        - '@<module_name>.module'
    
      # Remove this if you do not need BillingService
      <module_name>.ps_billings_service:
        class: 'PrestaShopCorp\Billing\Services\BillingService'
        public: true
        arguments:
        - '@<module_name>.ps_billings_context_wrapper'
        - '@<module_name>.module'
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54

Sandbox Mode

During your development, you should set the sandbox mode to true (as shown in the code above), which allows you to use a test card. You can use 4111 1111 1111 1111 as a test card, or see the official Chargebee documentation (opens new window).

  1. Make sure you replace every occurrence of <module_name> with the actual name of your module.

  2. Edit the composer.json file to include the PrestaShop Billing library:



















     










    {
      "name": "prestashop/<module_name>",
      "description": "",
      "config": {
        "preferred-install": "dist",
        "optimize-autoloader": true,
        "prepend-autoloader": false,
        "platform": {
            "php": "7.1"
        }
      },
      "require-dev": {
        "prestashop/php-dev-tools": "^4.2.1"
      },
      "require": {
        "php": ">=5.6",
        "prestashop/prestashop-accounts-installer": "^1.0",
        "prestashop/module-lib-service-container": "^1.4",
        "prestashopcorp/module-lib-billing": "^3.0.0"
      },
      "autoload": {
        "classmap": [
          "<module_name>.php"
        ]
      },
      "author": "PrestaShop",
      "license": "MIT"
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
  3. Run the composer install --no-dev -o command to implement the new dependency.

# Inject the PrestaShop Billing Context

You need to inject the psBillingContext into the window.psBillingContext global variable to initialize PrestaShop Billing related components.

  1. Add the following highlighted contents to the <module_name>.php file:










































     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     






        public function getContent()
        {
            /**
             * If values have been submitted in the form, process.
             */
            if (((bool)Tools::isSubmit('submit<module_name>Module')) == true) {
                $this->postProcess();
            }
    
            $this->context->smarty->assign('module_dir', $this->_path);
    
            /*********************
            * PrestaShop Account *
            * *******************/
    
            $accountsService = null;
    
            try {
                $accountsFacade = $this->getService('<module_name>.ps_accounts_facade');
                $accountsService = $accountsFacade->getPsAccountsService();
            } catch (\PrestaShop\PsAccountsInstaller\Installer\Exception\InstallerException $e) {
                $accountsInstaller = $this->getService('<module_name>.ps_accounts_installer');
                $accountsInstaller->install();
                $accountsFacade = $this->getService('<module_name>.ps_accounts_facade');
                $accountsService = $accountsFacade->getPsAccountsService();
            }
    
            try {
                Media::addJsDef([
                    'contextPsAccounts' => $accountsFacade->getPsAccountsPresenter()
                        ->present($this->name),
                ]);
    
                // Retrieve the PrestaShop Account CDN
                $this->context->smarty->assign('urlAccountsCdn', $accountsService->getAccountsCdn());
    
            } catch (Exception $e) {
                $this->context->controller->errors[] = $e->getMessage();
                return '';
            }
    
            /**********************
             * PrestaShop Billing *
             * *******************/
    
            // Load the context for PrestaShop Billing
            $billingFacade = $this->getService('<module_name>.ps_billings_facade');
            $partnerLogo = $this->getLocalPath() . 'views/img/partnerLogo.png';
    
            // PrestaShop Billing
            Media::addJsDef($billingFacade->present([
              'logo' => $partnerLogo,
              'tosLink' => 'https://yoururl/',
              'privacyLink' => 'https://yoururl/',
              // This field is deprecated but a valid email must be provided to ensure backward compatibility
              'emailSupport' => '[email protected]'
            ]));
    
            $this->context->smarty->assign('urlBilling', "https://unpkg.com/@prestashopcorp/billing-cdc/dist/bundle.js");
    
            $output = $this->context->smarty->fetch($this->local_path.'views/templates/admin/configure.tpl');
            return $output;
        }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
  2. The presenter will serve some context informations. Set the following parameters:

    Attribute Type Description
    logo string Set your logo as a file (at the root of the module folder) or a URL
    tosLink string Link to your terms & services (required)
    privacyLink string Link to your privacy page (required)
    emailSupport string Email to your support (required)

# Edit the Template File

  1. Access the template file allowing you to render the configuration page for your module in the back office (located by default at views/templates/admin/configure.tpl).

  2. In the template file, add the following highlighted contents at the beginning:


     
     

    <prestashop-accounts></prestashop-accounts>
    <div id="ps-billing"></div>
    <div id="ps-modal"></div>
    
    1
    2
    3

    TIP

    The ps-billing and ps-modal divs are simple containers for our frontend components to inject themselves into your code. You can how they are used on the line 13 in the snippet below.

  3. In the template file, add the following highlighted contents at the end:


     










     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     



    <script src="{$urlAccountsCdn|escape:'htmlall':'UTF-8'}" rel=preload></script>
    <script src="{$urlBilling|escape:'htmlall':'UTF-8'}" rel=preload></script>
    
    <script>
        /*********************
        * PrestaShop Account *
        * *******************/
        window?.psaccountsVue?.init();
    
        // Check if Account is associated before displaying Billing component
        if(window.psaccountsVue.isOnboardingCompleted() == true)
        {
        	  /*********************
    	        * PrestaShop Billing *
    	        * *******************/
    	        window.psBilling.initialize(window.psBillingContext.context, '#ps-billing', '#ps-modal', (type, data) => {
    	    	      // Event hook listener
    	    	      switch (type) {
                    // Hook triggered when the subscription is created
    	    	          case window.psBilling.EVENT_HOOK_TYPE.SUBSCRIPTION_CREATED:
    	    	              console.log('subscription created', data);
    	    	              break;
                    // Hook when the subscription is updated
    	    	          case window.psBilling.EVENT_HOOK_TYPE.SUBSCRIPTION_UPDATED:
    	    	              console.log('subscription updated', data);
    		    	          break;
                    // Hook triggered when the subscription is cancelled
    	    	          case window.psBilling.EVENT_HOOK_TYPE.SUBSCRIPTION_CANCELLED:
    	        	          console.log('subscription cancelled', data);
    	        	          break;
    	    	      }
    	        });
        }
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34

    TIP

    In the snippet above, you can see three "hooks". They are events that you can 'hook' into to implement some custom logic on your side. They are not linked to the webhook services we offer, which are the source of truth of your exchanges with PrestaShop Billing.

    WARNING

    In case of a CSP (Content Security Policy) error in console for merchants installing your Built for PrestaShop module, or even your own developments, please refer to our dedicated section in the FAQ

# Test Your Module

To test if PrestaShop Billing is loading successfully into your module:

  1. Zip your module folder.

  2. In the back office of your PrestaShop store, go to Modules > Module Catalog.

  3. Click the Upload a module button and select your archive.

  4. Click Configure in the pop-up window that displays.

    ➡️ Your module configuration page should contain the PrestaShop Billing plan selection pane under the PrestaShop Account one:

# Responding to our webhooks

TIP

For more details on our webhook system, you can see our reference and concept sections.

The last step to start using PrestaShop Billing is to have in your systems some way to process the events we send via webhook during the subscription lifecycle.

In order to have everything running correctly, you must:

  • Create a POST endpoint and communicate it to us: we will send our events regularly to this URL.
  • Communicate us a basic token for us to add to every request we send to the aforementionned URL. This step and whitelisting our URL ensures that your integration with Billing is as secure as possible.
    • It takes the form of an additional Authorization header added to our webhook event requests:
    {
      headers: {
        Authorization: Basic <token>
      }
    }
    
    1
    2
    3
    4
    5
    • The IP address of the webhook system is 34.77.109.237. You can protect your API by filtering calls which are not triggered from this IP address.
  • Have a way to process these events on your side.
  • Configure the webhook in PrestaShop Billing. This is done manually for now.

WARNING

Note that if your endpoint does not return a 2xx HTTP status, our webhooks will be retried at exponential time intervals until a 2xx HTTP response is received.

# Next Steps