Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-Store Support #6

Open
syntaxerror opened this issue Feb 1, 2018 · 12 comments
Open

Multi-Store Support #6

syntaxerror opened this issue Feb 1, 2018 · 12 comments

Comments

@syntaxerror
Copy link
Contributor

syntaxerror commented Feb 1, 2018

OpenCart, Magento and some other of the supported carts have multi-store support.

This means they can be running several stores, using different domains (or sub-domains), from the same admin (about 50% of our clients use this).

Bambora supports normally only one domain per account (merchant id), as I have understood, but possibly have some workaround to allow several domains per account (still unclear to me).

So as a minimum, the modules should at least support using different payment windows (logo and name) per store/domain. But preferably also different Bambora accounts per domain, unless this domain restriction is going to change soon at Bamboras end.

@syntaxerror
Copy link
Contributor Author

syntaxerror commented Feb 1, 2018

I don't recall any modules having "store-front" based settings, but I have one displaying feed url's for each. I'll post the code, in case it gives you any ideas.
skjermdump fra 2018-02-01 17-52-23

From the controller file:

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

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

        $data['stores'][] = array(
            'store_id'    => '0',
            'name'        => 'Default',
            'url'        => HTTP_CATALOG,
            'ssl'        => ($this->request->server['HTTPS']) ? HTTPS_CATALOG : HTTP_CATALOG,
        );

        $data['stores'] = array_merge($data['stores'], $this->model_setting_store->getStores());

And the view:

                                    <fieldset>
                                    <?php if ($stores) { ?>
                                    <legend><?php echo $fieldset_data_feeds; ?></legend>
                                    <?php } else { ?>
                                    <legend><?php echo $fieldset_data_feed; ?></legend>
                                    <?php } ?>
                                    <?php foreach ($stores as $store) { ?>
                                    <div class="form-group">
                                        <label class="col-sm-2 control-label" for="input-data-feed-<?php echo $store['store_id']; ?>">
                                            <?php echo $store['name']; ?>
                                        </label>
                                        <div class="col-sm-10">
                                            <textarea rows="1" readonly="readonly" id="input-data-feed-<?php echo $store['store_id']; ?>" class="form-control"><?php echo (($store['ssl']) ? $store['ssl'] : $store['url']) . $feed_url ?></textarea>
                                            <button type="button" class="btn btn-default badge" onclick="copyToClipboard('#input-data-feed-<?php echo $store['store_id']; ?>')"><?php echo $text_copy; ?></a>
                                        </div>
                                    </div>
                                    <?php } ?>
                                    </fieldset>

@AllanWLie
Copy link
Collaborator

Hi @syntaxerror

Thank you for your input for the module. I have added your request to our backlog, but I can not say when or if the feature will be implemented.

Have a nice day

Best regards
Allan

@mehov
Copy link

mehov commented May 20, 2021

Hi everyone,

We have a multistore with 15 domain names. The actual store is the same, it is operated by the same company, and the websites only differ by language and ccTLDs for SEO reasons.

We received 15 merchant IDs from Bambora, but this official extension accepts only one, most likely because it was designed with one backend = one store logic in mind.

If we implement and contribute the changes required to make the extension work with multiple merchant IDs, will you consider merging them? Provided, they're submitted here using Github via a pull request where you can see which files had been changed and where exactly.

Or maybe due to some regulations (who knows) you can only publish the code that originated from within your organisation?

The change I can think of would be:

  • Admin: loop though the defined stores and show a set of the Merchant ID, Secret Key etc. inputs per each. Save them into the config indexed by the store_id.
  • Catalog: fetch the configs by the id of the current store (e.g. here, or maybe even in a reusable fashion inside getConfigBaseName())

What do you think?

@sessan
Copy link
Contributor

sessan commented May 21, 2021

Hi @mehov!
I have now posed the question to Product :) Will get back to you when a decision has been made!
Best Regards
Jessica, Developer Bambora Online

@mehov
Copy link

mehov commented Oct 8, 2021

@sessan Hi, it's been 5 months, are there any news maybe? Please let me know. Thank you!

@syntaxerror
Copy link
Contributor Author

syntaxerror commented Oct 8, 2021

The change I can think of would be:

  • Admin: loop though the defined stores and show a set of the Merchant ID, Secret Key etc. inputs per each. Save them into the config indexed by the store_id.
  • Catalog: fetch the configs by the id of the current store (e.g. here, or maybe even in a reusable fashion inside getConfigBaseName())

What do you think?

If anything is done with this, the easiest is probably to add the store id's to the returned values in getConfigBaseName(), plus the needed loop in admin for setting up the config for each. T.ex.:
protected function getConfigBaseName() { if($this->is_oc_3()) { return "payment_{$this->module_name}_{$this->config->get('config_store_id')}"; } else { return {$this->module_name}_{$this->config->get('config_store_id')}; } }

@syntaxerror
Copy link
Contributor Author

Or maybe due to some regulations (who knows) you can only publish the code that originated from within your organisation?

When it comes to this I hardly see any issue, as long as the quality control is done by Worldline (Bambora), the module already includes t.ex. my code, and also lots of OpenCart code.

And actually since it's built on and with OpenCart code, it's still GPL licensed code, no mater what's stated in the file headings, and actually the headers are GPL license violations #3

@sessan
Copy link
Contributor

sessan commented Oct 11, 2021

We have brought this request up to Product but it is not prioritised at the moment unfortunately.

@mehov
Copy link

mehov commented Oct 12, 2021

To whoever is stuck with this like we are, here comes:

First commit:

---
 .../payment/bambora_online_checkout.php       | 42 ++++++++++--
 .../payment/bambora_online_checkout.php       | 12 +++-
 .../payment/bambora_online_checkout.tpl       | 65 ++++++++++---------
 .../payment/bambora_online_checkout.php       |  2 +-
 .../payment/bambora_online_checkout.php       | 32 ++++++++-
 5 files changed, 111 insertions(+), 42 deletions(-)

diff --git a/admin/controller/extension/payment/bambora_online_checkout.php b/admin/controller/extension/payment/bambora_online_checkout.php
index 2d14b173..40e6f71b 100644
--- a/admin/controller/extension/payment/bambora_online_checkout.php
+++ b/admin/controller/extension/payment/bambora_online_checkout.php
@@ -37,7 +37,34 @@ class ControllerExtensionPaymentBamboraOnlineCheckout extends Controller
     /**
      * @var array();
      */
-    private $errorFields = array('merchant', 'access_token', 'secret_token', 'permission');
+    private $errorFields = array('permission');
+
+    /**
+     * A list of store-dependent fields
+     *
+     * @var array()
+     * @access private
+     */
+    private $storeFields = array('merchant', 'access_token', 'secret_token', 'md5');
+
+    /**
+     * Returns all stores including the Default configured in this Opencart
+     *
+     * @access private
+     * @return array()
+     */
+    private function getConfiguredStores() {
+        // Get the list of all stores
+        $this->load->model('setting/store');
+        $stores = $this->model_setting_store->getStores();
+        // Prepend the default store to the list
+        array_unshift($stores, array(
+            'store_id' => 0,
+            'name' => $this->config->get('config_name') . $this->language->get('text_default'),
+            'url' => HTTP_CATALOG,
+        ));
+        return $stores;
+    }
 
     /**
      * Inits the module admin section
@@ -148,6 +175,8 @@ class ControllerExtensionPaymentBamboraOnlineCheckout extends Controller
         $this->data['order_statuses'] = $this->model_localisation_order_status->getOrderStatuses();
         $this->load->model('localisation/geo_zone');
         $this->data['geo_zones'] = $this->model_localisation_geo_zone->getGeoZones();
+        $this->data['stores'] = $this->getConfiguredStores();
+        $this->data['stores_merchants_fields'] = $this->storeFields;
         $this->data['header'] = $this->load->controller('common/header');
         $this->data['column_left'] = $this->load->controller('common/column_left');
         $this->data['footer'] = $this->load->controller('common/footer');
@@ -200,10 +229,6 @@ class ControllerExtensionPaymentBamboraOnlineCheckout extends Controller
     {
         $fields = array(
             'status',
-            'merchant',
-            'access_token',
-            'secret_token',
-            'md5',
             'window_state',
             'window_id',
             'surcharge',
@@ -231,6 +256,13 @@ class ControllerExtensionPaymentBamboraOnlineCheckout extends Controller
             'order_status_completed' => '5'
         );
 
+        $stores = $this->getConfiguredStores();
+        foreach ($this->storeFields as $key) {
+            foreach ($stores as $store) {
+                $fields[] = $store['store_id'].'_'.$key;
+            }
+        }
+
         // Loop through configuration fields and populate them
         foreach ($fields as $field) {
             $field = $this->getConfigBaseName() . '_' . $field;
diff --git a/admin/model/extension/payment/bambora_online_checkout.php b/admin/model/extension/payment/bambora_online_checkout.php
index 8df5e316..5825046e 100644
--- a/admin/model/extension/payment/bambora_online_checkout.php
+++ b/admin/model/extension/payment/bambora_online_checkout.php
@@ -184,9 +184,15 @@ class ModelExtensionPaymentBamboraOnlineCheckout extends Model
      */
     protected function getApiKey()
     {
-        $accesstoken = $this->config->get($this->getConfigBaseName() . '_access_token');
-        $merchantNumber = $this->config->get($this->getConfigBaseName() . '_merchant');
-        $secretToken = $this->config->get($this->getConfigBaseName() . '_secret_token');
+        $values = array();
+        foreach ($this->storeFields as $field) {
+            $values[] = $this->config->get(implode('_', [
+                $this->getConfigBaseName(),
+                $this->config->get('config_store_id'),
+                $field,
+            ]));
+        }
+        list($merchantNumber, $accesstoken, $secretToken, $md5) = $values;
 
         $combined = $accesstoken . '@' . $merchantNumber . ':' . $secretToken;
         $encoded_key = base64_encode($combined);
diff --git a/admin/view/template/extension/payment/bambora_online_checkout.tpl b/admin/view/template/extension/payment/bambora_online_checkout.tpl
index b48ef319..7f0d152c 100644
--- a/admin/view/template/extension/payment/bambora_online_checkout.tpl
+++ b/admin/view/template/extension/payment/bambora_online_checkout.tpl
@@ -49,39 +49,44 @@ echo $column_left;
               </select>
             </div>
           </div>      
-          <div class="form-group required">
-            <label class="col-sm-2 control-label" for="input-merchant"><span data-toggle="tooltip" title="<?php echo $help_merchant; ?>"><?php echo $entry_merchant; ?></span></label>
-            <div class="col-sm-10">
-              <input type="text" name="bambora_online_checkout_merchant" value="<?php echo $bambora_online_checkout_merchant; ?>" placeholder="<?php echo $entry_merchant; ?>" id="input-merchant" class="form-control" />
-              <?php if($error_merchant) { ?>
-              <div class="text-danger"><?php echo $error_merchant; ?></div>
-              <?php } ?>
-            </div>
-          </div>
-          <div class="form-group required">
-            <label class="col-sm-2 control-label" for="input-access-token"><span data-toggle="tooltip" title="<?php echo $help_access_token; ?>"> <?php echo $entry_access_token; ?></span></label>
-            <div class="col-sm-10">
-              <input type="text" name="bambora_online_checkout_access_token" value="<?php echo $bambora_online_checkout_access_token; ?>" placeholder="<?php echo $entry_access_token; ?>" id="input-accesstoken" class="form-control" />
-              <?php if($error_access_token) { ?> 
-              <div class="text-danger"><?php echo $error_access_token; ?></div>
-              <?php } ?> 
-            </div>
-          </div>
-          <div class="form-group required">
-            <label class="col-sm-2 control-label" for="input-secret-token"><span data-toggle="tooltip" title="<?php echo $help_secret_token; ?>"><?php echo $entry_secret_token; ?></span></label>
-            <div class="col-sm-10">
-              <input type="password" name="bambora_online_checkout_secret_token" value="<?php echo $bambora_online_checkout_secret_token; ?>" placeholder="<?php echo $entry_secret_token; ?>" id="input-secrettoken" class="form-control" />
-              <?php if($error_secret_token) { ?>
-              <div class="text-danger"><?php echo $error_secret_token; ?></div>
-              <?php } ?>
-            </div>
-          </div>
+
           <div class="form-group">
-            <label class="col-sm-2 control-label" for="input-md5"><span data-toggle="tooltip" title="<?php echo $help_md5; ?>"><?php echo $entry_md5; ?></span></label>
-            <div class="col-sm-10">
-              <input type="password" name="bambora_online_checkout_md5" value="<?php echo $bambora_online_checkout_md5; ?>" placeholder="<?php echo $entry_md5; ?>" id="input-md5" class="form-control" />
+            <div class="col-sm-10 col-sm-offset-2">
+                <table class="table table-bordered">
+                    <thead>
+                        <tr>
+                            <td>Store</td>
+<?php foreach ($stores_merchants_fields as $key): ?>
+                            <td>
+                                <span data-toggle="tooltip" title="<?=${'help_'.$key}?>">
+                                    <?=${'entry_'.$key}?>
+                                </span>
+                            </td>
+<?php endforeach; ?>
+                        </tr>
+                    </thead>
+                    <tbody>
+<?php foreach ($stores as $store) : ?>
+                        <tr>
+                            <td><?=$store['name']?></td>
+<?php foreach ($stores_merchants_fields as $key): ?>
+                            <td>
+                                <input
+                                    name="bambora_online_checkout_<?=$store['store_id']?>_<?=$key?>"
+                                    value="<?=${'bambora_online_checkout_'.$store['store_id'].'_'.$key}?>"
+                                    title="<?=${'entry_'.$key}?>"
+                                    placeholder="<?=${'entry_'.$key}?>"
+                                    class="form-control"
+                                    >
+                            </td>
+<?php endforeach; ?>
+                        </tr>
+<?php endforeach; ?>
+                    </tbody>
+                </table>
             </div>
           </div>
+
           <div class="form-group">
             <label class="col-sm-2 control-label" for="input-window-state"><span data-toggle="tooltip" title="<?php echo $help_window_state; ?>"><?php echo $entry_window_state; ?></span></label>
             <div class="col-sm-10">
diff --git a/catalog/controller/extension/payment/bambora_online_checkout.php b/catalog/controller/extension/payment/bambora_online_checkout.php
index 1a9ed22d..738befc4 100644
--- a/catalog/controller/extension/payment/bambora_online_checkout.php
+++ b/catalog/controller/extension/payment/bambora_online_checkout.php
@@ -498,7 +498,7 @@ class ControllerExtensionPaymentBamboraOnlineCheckout extends Controller
             return false;
         }
         // Validate MD5!
-        $merchantMd5Key = $this->config->get($this->getConfigBaseName() . '_md5');
+        $merchantMd5Key = $this->config->get($this->getConfigBaseName().'_'.$this->config->get('config_store_id').'_md5');
         if(!empty($merchantMd5Key)) {
             $concatenatedValues  = '';
             foreach ($getParameteres as $key => $value) {
diff --git a/catalog/model/extension/payment/bambora_online_checkout.php b/catalog/model/extension/payment/bambora_online_checkout.php
index be001bdd..40bf2930 100644
--- a/catalog/model/extension/payment/bambora_online_checkout.php
+++ b/catalog/model/extension/payment/bambora_online_checkout.php
@@ -27,6 +27,14 @@ class ModelExtensionPaymentBamboraOnlineCheckout extends Model
      */
     private $module_version = '1.3.0';
 
+    /**
+     * A list of store-dependent fields
+     *
+     * @var array()
+     * @access private
+     */
+    private $storeFields = array('merchant', 'access_token', 'secret_token', 'md5');
+
     /**
      * Returns method data
      *
@@ -49,6 +57,18 @@ class ModelExtensionPaymentBamboraOnlineCheckout extends Model
         } else {
             $status = false;
         }
+        // Abort if some important store-based setting values are missing
+        foreach ($this->storeFields as $field) {
+            if (!$status) {
+                break;
+            }
+            $field = implode('_', [
+                $this->getConfigBaseName(),
+                $this->config->get('config_store_id'),
+                $field,
+            ]);
+            $status = $status && !!$this->config->get($field);
+        }
 
         $method_data = array();
 
@@ -193,9 +213,15 @@ class ModelExtensionPaymentBamboraOnlineCheckout extends Model
      */
     protected function getApiKey()
     {
-        $accesstoken = $this->config->get($this->getConfigBaseName() . '_access_token');
-        $merchantNumber = $this->config->get($this->getConfigBaseName() . '_merchant');
-        $secretToken = $this->config->get($this->getConfigBaseName() . '_secret_token');
+        $values = array();
+        foreach ($this->storeFields as $field) {
+            $values[] = $this->config->get(implode('_', [
+                $this->getConfigBaseName(),
+                $this->config->get('config_store_id'),
+                $field,
+            ]));
+        }
+        list($merchantNumber, $accesstoken, $secretToken, $md5) = $values;
 
         $combined = $accesstoken . '@' . $merchantNumber . ':' . $secretToken;
         $encoded_key = base64_encode($combined);
-- 

Followed by:

---
 .../extension/payment/bambora_online_checkout.php      | 10 +++++++++-
 .../extension/payment/bambora_online_checkout.php      |  2 +-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/admin/model/extension/payment/bambora_online_checkout.php b/admin/model/extension/payment/bambora_online_checkout.php
index 5825046e..cd115594 100644
--- a/admin/model/extension/payment/bambora_online_checkout.php
+++ b/admin/model/extension/payment/bambora_online_checkout.php
@@ -27,6 +27,14 @@ class ModelExtensionPaymentBamboraOnlineCheckout extends Model
      */
     private $module_name = 'bambora_online_checkout';
 
+    /**
+     * A list of store-dependent fields
+     *
+     * @var array()
+     * @access private
+     */
+    private $storeFields = array('merchant', 'access_token', 'secret_token', 'md5');
+
     /**
      * Install and create Bambora Online Checkout Transaction table
      */
@@ -188,7 +196,7 @@ class ModelExtensionPaymentBamboraOnlineCheckout extends Model
         foreach ($this->storeFields as $field) {
             $values[] = $this->config->get(implode('_', [
                 $this->getConfigBaseName(),
-                $this->config->get('config_store_id'),
+                (int)$this->config->get('config_store_id'),
                 $field,
             ]));
         }
diff --git a/catalog/model/extension/payment/bambora_online_checkout.php b/catalog/model/extension/payment/bambora_online_checkout.php
index 40bf2930..e17a0d62 100644
--- a/catalog/model/extension/payment/bambora_online_checkout.php
+++ b/catalog/model/extension/payment/bambora_online_checkout.php
@@ -217,7 +217,7 @@ class ModelExtensionPaymentBamboraOnlineCheckout extends Model
         foreach ($this->storeFields as $field) {
             $values[] = $this->config->get(implode('_', [
                 $this->getConfigBaseName(),
-                $this->config->get('config_store_id'),
+                (int)$this->config->get('config_store_id'),
                 $field,
             ]));
         }
-- 

I initially wanted to make this into a pull request, but I guess chances are it will be ignored, plus if you said yourself that you don't need it, then why should we even bother, right?

And it looks like Opencart is a sinking ship anyway.

@syntaxerror
Copy link
Contributor Author

I initially wanted to make this into a pull request, but I guess chances are it will be ignored, plus if you said yourself that you don't need it, then why should we even bother, right?

A pull request is probably easier for many to read and use than the old fashion diffs, even if WorldLine (Bambora) ignores it, or have it pending forever. But sure they have some weird priorities at Product... :)

And it looks like Opencart is a sinking ship anyway.

Sure OpenCart and its dev is what it is, and we probably wouldn't build any new stores on it at this point, but still using search stats as a measurement for the use of it probably isn't the best idea - most software have some of the same drop. Better look at something like https://trends.builtwith.com/shop

@sessan
Copy link
Contributor

sessan commented Oct 20, 2021

Hi! I've brought this up again with the product team and it has finally been prioritised (multi store setups for all the different shopping carts we provide) so we can look into it! So it would be very helpful if you could provide a pull request @mehov
So I'm opening this again @syntaxerror :)

@sessan sessan reopened this Oct 20, 2021
@introlone
Copy link

I'm looking to implement Bambora in a multi-store setup. It's been a few months since this was last discussed. Any updates @sessan ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants