4elements, web design and consultancy

  1. Integrate Bitcoin Payment Gateway Into OpenCart: Part 1

    In this series, we are going to look at building a Bitcoin payment system into our installation of OpenCart. Before we get started, I recommend that you practice the basic OpenCart module development if you are not familiar with how to build your own modules.

    Once done, you should have enough knowledge to continue with developing more advanced modules. In this series, that's exactly what we aim to do.

    Getting Started

    Before we begin building the extension, set up OpenCart on your local machine. Next, download the BitPay API Library from the article attachment and place it in your store root as shown in the following screenshot:

    BitPay API Library

    To configure and set up up our Bitcoin Payment Module, we need an admin interface. To do this, we'll follow the MVC pattern for implementing our admin panel.

    1. Create the Admin Controller

    1. Navigate to admin/controller/payment
    2. Create a PHP file and name it bitpay.php
    3. Open the file in your favorite IDE and create a class following the OpenCart class naming convention, for example: class ControllerPaymentBitpay extends Controller {}
    4. Inside the controller class, define the default index function. 
    5. Then, inside this function, start writing the code as featured below.

    1.1 Loading Language & Models

    $this->language->load('payment/bitpay');
    $this->load->model('localisation/order_status'); // loading the model to get system Order Statuses

    1.2 Setting Up Page Title

    To set the Page Title of the document we use the following code:

    $this->document->setTitle($this->language->get('text_title')); // Setting the document heading title

    1.3. Parsing Controllers Elements to View

    /* Assigning and parsing the from values  */
    
    $this->data['heading_title']           = $this->language->get('text_title');
    $this->data['text_enabled']            = $this->language->get('text_enabled'); // gets default language text
    $this->data['text_disabled']           = $this->language->get('text_disabled'); // gets default language text
    $this->data['text_high']               = $this->language->get('text_high');
    $this->data['text_medium']             = $this->language->get('text_medium');
    $this->data['text_low']                = $this->language->get('text_low');
    $this->data['api_key']           = $this->language->get('text_api_key');
    $this->data['confirmed_status']  = $this->language->get('text_confirmed_status');
    $this->data['invalid_status']    = $this->language->get('text_invalid_status');
    $this->data['transaction_speed'] = $this->language->get('text_transaction_speed');
    $this->data['test_mode']         = $this->language->get('text_test_mode');
    $this->data['status']            = $this->language->get('text_status');
    $this->data['sort_order']        = $this->language->get('text_sort_order');
    $this->data['button_save']             = $this->language->get('button_save'); // gets default language text
    $this->data['button_cancel']           = $this->language->get('button_cancel'); // gets default language text
    $this->data['tab_general']             = $this->language->get('tab_general'); // gets default language text
    
    /* End Text Assignation */
    

    1.4. Routing Save & Cancel Buttons

    The following code is used to assign Action / Save & Cancel URLs triggers:

    $this->data['action'] = HTTPS_SERVER . 'index.php?route=payment/'.$this->payment_module_name.'&token=' . $this->session->data['token'];
    $this->data['cancel'] = HTTPS_SERVER . 'index.php?route=extension/payment&token=' . $this->session->data['token']; 

    1.5. Getting Available Order Statuses

    The following code gets all the order statuses from the Localisation-Model (which is pre-coded into OpenCart) and parses it for the view:

    $this->data['order_statuses'] = $this->model_localisation_order_status->getOrderStatuses(); 

    1.6. Fetching Data From the Database

    Our saving process will come in the model section. However the following code is responsible for fetching this module data (if any) and parsing it for view.

    /* Fetching the Field Values saved in Database*/ 
    $this->data['bitpay_api_key'] = $this->config->get('bitpay_api_key');
    
    $this->data['bitpay_confirmed_status_id'] = $this->config->get('bitpay_confirmed_status_id'); 
    
    $this->data['bitpay_invalid_status_id'] = $this->config->get('bitpay_invalid_status_id'); 
    
    $this->data['bitpay_transaction_speed'] = $this->config->get('bitpay_transaction_speed'); 
    
    $this->data['bitpay_test_mode'] = $this->config->get('bitpay_test_mode'); 
    
    $this->data['bitpay_status'] = $this->config->get('bitpay_status');
    
    $this->data['bitpay_sort_order'] = $this->config->get('bitpay_sort_order');
    /* Database fields fetching ends */
    

    1.6 Rendering the View Template

    The following code adds children to our view template and renders it for the user view.

    $this->template = 'payment/bitpay.tpl'; // Template Assigning
    $this->children = array(
    'common/header',    
    'common/footer'    
    ); // Provide the list of template childeren
    
    $this->response->setOutput($this->render(TRUE), $this->config->get('config_compression')); // Rendering the Template Output

    2. Creating Admin View

    1. Navigate to admin/view/template/payment
    2. Create a file and name it bitpay.tpl
    3. You can place your own HTML. In my case, I've done that using the following steps.

    2.1. Adding Header Child

    To load the header that we passed as a child at 1.6:

    <?php echo $header; ?> 

    2.2 Warning Block

    Warning Block is a div section which will display user warnings if any:

    <?php if ($error_warning) {  ?> <div class="warning"><?php echo $error_warning; ?></div><?php } ?>

    2.3 The Complete Template

    The complete HTML will look something like below:

    <div id="content">
      
    <?php 
    /* Warning Block*/
    if ($error_warning) {  ?>
    <div class="warning"><?php echo $error_warning; ?></div>
    <?php }
    /* Warning Block Ends */
     ?>
    <div class="box">
      <div class="left"></div>
      <div class="right"></div>
        <div class="heading">
          <h1><?php echo $heading_title; ?></h1>
          <div class="buttons"><a onclick="$('#form').submit();" class="button"><span><?php echo $button_save; ?></span></a><a onclick="location = '<?php echo $cancel; ?>';" class="button"><span><?php echo $button_cancel; ?></span></a></div>
        </div>
      <div class="content">
        <form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form">
          <table class="form">
            <tr>
              <td><span class="required">*</span> <?php echo $api_key; ?></td>
              <td><input type="text" name="bitpay_api_key" value="<?php echo $bitpay_api_key; ?>" style="width:300px;" />
                <?php 
                // API Key Error case block
                if ($error_api_key) { ?>
                <span class="error"><?php echo $error_api_key; ?></span>
                <?php }
                // Error Case Block Ends
                 ?></td>
            </tr>
             <tr>
                <td><?php echo $confirmed_status; ?></td>
                <td><select name="bitpay_confirmed_status_id">
                    <?php foreach ($order_statuses as $order_status) { ?>
                    <?php if ($order_status['order_status_id'] == $bitpay_confirmed_status_id) { ?>
                    <option value="<?php echo $order_status['order_status_id']; ?>" selected="selected"><?php echo $order_status['name']; ?></option>
                    <?php } else { ?>
                    <option value="<?php echo $order_status['order_status_id']; ?>"><?php echo $order_status['name']; ?></option>
                    <?php } ?>
                    <?php } ?>
                  </select></td>
              </tr>
              <tr>
                <td><?php echo $invalid_status; ?></td>
                <td><select name="bitpay_invalid_status_id">
                    <?php foreach ($order_statuses as $order_status) { ?>
                    <?php if ($order_status['order_status_id'] == $bitpay_invalid_status_id) { ?>
                    <option value="<?php echo $order_status['order_status_id']; ?>" selected="selected"><?php echo $order_status['name']; ?></option>
                    <?php } else { ?>
                    <option value="<?php echo $order_status['order_status_id']; ?>"><?php echo $order_status['name']; ?></option>
                    <?php } ?>
                    <?php } ?>
                  </select></td>
              </tr>
              <tr>
                <td><?php echo $transaction_speed; ?></td>
                <td><select name="bitpay_transaction_speed">
                    <?php if ($bitpay_transaction_speed == 'high') { ?>
                    <option value="high" selected="selected"><?php echo $text_high; ?></option>
                    <?php } else { ?>
                    <option value="high"><?php echo $text_high; ?></option>
                    <?php } ?>
                    <?php if ($bitpay_transaction_speed == 'medium') { ?>
                    <option value="medium" selected="selected"><?php echo $text_medium; ?></option>
                    <?php } else { ?>
                    <option value="medium"><?php echo $text_medium; ?></option>
                    <?php } ?>
                    <?php if ($bitpay_transaction_speed == 'low') { ?>
                    <option value="low" selected="selected"><?php echo $text_low; ?></option>
                    <?php } else { ?>
                    <option value="low"><?php echo $text_low; ?></option>
                    <?php } ?>
                  </select></td>
              </tr>
              <tr>
                <td><?php echo $test_mode; ?></td>
                <td><select name="bitpay_test_mode"> 
                    <?php if ($bitpay_test_mode) { ?>
                    <option value="1" selected="selected"><?php echo $text_enabled; ?></option>
                    <option value="0"><?php echo $text_disabled; ?></option>
                    <?php } else { ?>
                    <option value="1"><?php echo $text_enabled; ?></option>
                    <option value="0" selected="selected"><?php echo $text_disabled; ?></option>
                    <?php } ?>
                  </select></td>
              </tr>
            <tr>
              <td><?php echo $status; ?></td>
              <td><select name="bitpay_status"> 
                  <?php if ($bitpay_status) { ?>
                  <option value="1" selected="selected"><?php echo $text_enabled; ?></option>
                  <option value="0"><?php echo $text_disabled; ?></option>
                  <?php } else { ?>
                  <option value="1"><?php echo $text_enabled; ?></option>
                  <option value="0" selected="selected"><?php echo $text_disabled; ?></option>
                  <?php } ?>
                </select></td>
            </tr>
            <tr>
              <td><?php echo $sort_order; ?></td>
              <td><input type="text" name="bitpay_sort_order" value="<?php echo $bitpay_sort_order; ?>" size="1" /></td>
            </tr>
          </table>
        </form>
      </div>
    </div>
    </div>
    <?php echo $footer; //loading the footer ?>

    At this point, we are done with the layout of the module. Now its time to save the Module Data into the database. So we will be putting a little code inside the controller for this purpose.

    Saving the Data

    Inside your controller's default function, place some serialization code as shown below:

    if (($this->request->server['REQUEST_METHOD'] == 'POST') && ($this->validate())) // Checking if the data is coming through post and validate it
            {
                $this->model_setting_setting->editSetting($this->payment_module_name, $this->request->post); // saving all the data into  the database
                $this->session->data['success'] = $this->language->get('text_success'); // Success Identifier
                $this->redirect(HTTPS_SERVER . 'index.php?route=extension/payment&token=' . $this->session->data['token']); // Redirecting to the payment modules list
            }

    Introduction Validation

    The following is the validation function that validates the required data:

    private $error = array(); // All errors will be saved into this array
        private function validate()
        {
        // User Module Permission Check 
            if (!$this->user->hasPermission('modify', 'payment/'.$this->payment_module_name)) 
            {
                $this->error['warning'] = $this->language->get('error_permission'); 
            }
        // User Module Permission Check Ends
        
        // Check if the API Key is not empty
            if (!$this->request->post['bitpay_api_key']) 
            {
                $this->error['api_key'] = $this->language->get('error_api_key');
            }
        // Api Check ends here
    
        // If there is no error, the function returns True else False
            if (!$this->error)
            {
                return TRUE;
            }
            else
            {
                return FALSE;
            }    
            // Boolean Check Ends here
        }

    We are done creating the payment module layout for the dashboard, and you should be able to test-drive the admin panel. Remember to grant permission to the administration user before testing.

    Conclusion

    In this article, we introduced the administrative portion of the payment module. Note that it's a good idea to give the site administrator more control via an interface than, say, to require that they write in code.

    In the next article, we'll implement the payment module with respect to the front-end. In the meantime, feel free to shoot any questions or comments via the form below.

     

    0 Comments

    Leave a comment › Posted in: Daily

0 Comments

Got anything to add?

(Basic HTML is fine)