Jump to content

Dynamically Hide Payment Gateway (Depending on Basket)


Guillaume

Recommended Posts

Hi,

I would like to offer payment by instalments on my payment gateway. As I was advised, I created two separate modules (one for pay at once, another for pay by instalments). Now, the module to pay by instalment has some conditions on parameters to allow the payment by instalments (e.g. minimum and maximum basket amount). If those conditions are not met, I would like to hide the instalments gateways. I have tried a few ideas (below), none of which worked:

  • Changing module['status'] to 0 (which is probably a bad idea, because I don't want to deactivate the whole module, I simply do not want it to be used for this specific basket). It didn't work however, the module being still displayed (I'm guessing Cubecart somewhat protects this variable?)
  • Commenting the transfer or fixedvariable functions in gateway.class.php. The module is still displayed, although of course the payment cannot go through
  • Commenting the instruction $page_content = $module->display(); in admin/index.ini.php. Although I would need to find a way to make it dynamic (depending on the above conditions) in the final version. I thought this was a good guess, but unfortunately my module was still displayed

I have tried looking for similar things in othr gateways, but I didn't found anything. Is there any variable like module['isDisplayedOnCheckOutPage'] which I could dynamically set?

Thanks a lot in advance! Best regards,

Guillaume

Link to comment
Share on other sites

Let's take a look at the file /classes/cubecart.class.php, the private function _displayGateways().

If the customer has not already chosen the gateway ($name), CubeCart will be fetching all active gateway modules ('status' => '1'). We will also know the Cart->basket (by reference).

The database query gives us the list of modules ($gateways), conveniently followed by a hook.

It is in this hook we can make our tests for the conditions of interest, and if satisfied, we can remove from the $gateways array any module that needs to disappear (or be added - just sayin').

What I have not yet solved is when the customer chooses to do more shopping, but has, actually, chosen a gateway to use.

When at Checkout (URL has "_a=checkout"), CubeCart will not let you "submit" that page without choosing a gateway. (Submit buttons are the "Update Basket", "Checkout", "Apply Promo Code", and choosing a different shipping choice). Changing the quantity at checkout requires clicking the Update Basket button.

So, when the basket's conditions change, we need to discover a way to remove any gateway choice (if one was made).

Or we might try to remove the "Required" characteristic of the gateway list when "submitting" this page's form - except when checking out for real.

Link to comment
Share on other sites

Thanks a lot for driving me through this. I'll start with the easiest: it's good to know about the limitation you mentioned in the case the customer updates the cart after having chosen a gateway. I think I'm fine with this limitation for the moment, but it's good to know indeed.

Now the hook. I must say it is very interesting, but not being a developper myself, I didn't fully manage. What I've done is, mimicking what is done in Paypal Commerce (as there is a similar hook there - class.cubecart.display_gateways.php):

  • I've created a folder hooks at the root of the module, with the file class.cubecart.display_gateways.php
  • I've updated the config file with a hooks node and this hook element
  • Now the Paypal commerce does something different from what I intend to do (as I understand they display more functionality in some cases), but that doesn't matter. What I don't understand is:
    • When the hook is supposed to be called. I'm assuming it's always called on a=confirm or a=checkout page, as it is where the private function _displayGateways() is called. However, I've put an echo in my hook hoping to see it displayed on the confirm or checkout page, and I didn't see anything, so I'm assuming my hook isn't called at all
    • Assuming my hook is called. Which exact characteristic of the gateway shall I modify to make it invisible? I don't think it is "status", there is probably something like "isDisplayed" but I couldn't work it out

Thanks again and I really appreciate your continuous support.

Link to comment
Share on other sites

Please know that only plugins can have hooks in a /hooks/ folder. (PayPal manages to do this because that module is, in fact, a plugin.)

If what you are developing is a /gateway/ module, your approach to having that module use hooks is a non-starter.

By using a Code Snippet, we can generalize this task to adding/removing gateways from the list of gateways CubeCart intends to use. Thus, this solution won't necessarily be restricted to just your pair of gateway modules - even though that's what you will be coding for.

 

 

Link to comment
Share on other sites

What I am developping is a module/gateway indeed, so I understand that the above wouldn't work. I understand from what you are mentioning that I am left with two options:

  • Converting the module into a plugin. But I would really want to avoid refactoring my code solely to get the module displayed / non-displayed depending on the cart amount...
  • Inserting the Code Snippet you are mentioning. I believe you are suggesting that I adapt the code of cubecart.class.php so that it also takes gateways into account right? What puzzles me when reading the code, is that I was under the impression that it was working for gateways proper, and that an exception was made to also handle gateways which are coded as plugin (e.g. Paypal):

image.thumb.png.45c85c84e4adce69742db6d8da618a10.png

My only need here was to have the payment by instalment displayed only for a given basket amount range. I'm actually surprised to be the first with such a need (except maybe Paypal and Google Checkout which are plugin). I think I'll probably drop that feature for now, and consider it for a later version.

Link to comment
Share on other sites

Hi,

I just had a look at what is done in goShippo shipping module and indeed the snippet option looks promising. I understand that I shall call it from index.inc.php, but I am really in the blind on how to adapt the below (taken from goShippo):

 

if($_POST['module']['status'] == 1) {

    $code = file_get_contents(CC_ROOT_DIR.'/modules/shipping/goShippo/snippet-class.order_status.php');
    $GLOBALS['db']->insert('CubeCart_code_snippet', array('enabled' => 1, 'unique_id' => 'shippo-transaction-create', 'description' => 'Shippo Create Rate Transaction', 'hook_trigger' => 'class.order.order_status', 'php_code' => base64_encode($code), 'version' => '1.0.0', 'author' => 'CubeCart Limited', 'priority' => 1));

 

To my payment gateway. In particular I have the following questions:

  • I am assuming that 'hook_trigger' => 'class.order.order_status' calls code in classes/order.class. While this snippet simply changes the status of an order, which class would therefore be relevant to display/hide a payment gateway?
  • I am not sure of what 'priority' => 1 means, but I am guessing it ensures the snippet is called indeed?
  • I believe there is no requirement on the value of 'unique_id' except that it shall be unique?
  • As you suggest a snippet to dynamically hide or display the payment gateway, I am coming back to my original point where I wanted to avoid having two different modules (one for pay-at-once, another for pay-by-instalments). Can I use a snippet to display a module twice (but with different settings)? In particular, I might need to have several instances of pay-by-instalments (e.g. if a merchant wants to offer both pay-in-3-times and pay-in-10-times)

 

Thanks a lot in advance for your help. Best regards,

Guillaume

Link to comment
Share on other sites

To change which gateways are displayed, one can use the hook, class.cubecart.display_gateways, found in the CubeCart class, private function _displayGateways().

For all of the snippets loaded to execute a particular hook, the snippets are sorted by 'priority', thus in the execution of the snippets (including plugin hooks), those that need to do very important things are first in line.

The 'unique_id' must be unique, and is limited to 32 ASCII characters.

In PHP, in general, you can instantiate a class multiple times each with having injected a distinct dependency. But CubeCart's management of modules has a tight correlation to the module's folder name. That said, however, in the snippet, one might be able to query the module's static properties to see how it can represent itself in various ways, and add to the gateways array accordingly.

Link to comment
Share on other sites

Cheers, this is really interesting. So in the file admin/index.inc.php I have added these instructions:

 

if($_POST['module']['status'] == 1) {
    $code = file_get_contents(CC_ROOT_DIR.'/modules/gateway/Systempay_multi/snippet-class.display_gateways');
    $GLOBALS['db']->insert('CubeCart_code_snippet', array('enabled' => 1, 'unique_id' => 'systempay-multi-gateway-display', 'description' => 'Systempay Display Multipay Option', 'hook_trigger' => 'class.cubecart.display_gateways', 'php_code' => base64_encode($code), 'version' => '1.0.0', 'author' => 'Guillaume Richard', 'priority' => 1));
}

And of course, the folder of my module is called Systempay_multi and has a file called snippet-class.display_gateways in it. Because I am really unfamiliar with the concept of hooks/snippets, so far I am trying to check that my snippet is actually called, so I have only put this in it, hoping to display a php message on top of the page and change the module description:

image.png.20c559d563f8726771e7633d8ca9ebed.png

But neither action is performed. But maybe it is a wrong indicator, because when I put the same echo in _displayGateways function, it isn't called either.

 

Another thing which puzzles me is that in the cubecart.class.php file, in the _displayGateways function, the hooks called on line 1928 seem to be only to modify the parameters of a given gateway (e.g. change its description). Indeed, afterwards (from line 1923, but especially from line 2022 onwards), we seem to loop on all the gateways and take them as granted. So I'm not sure whether this hook is a good place to display/hide a gateway dynamically. But I'm a beginner in this, so I may very well miss something obvious.

 

Guillaume

 

Link to comment
Share on other sites

  • 5 months later...

Having had a further look at this, would it make sense:

  • either having a hook to enable each module making basket conditions, near line 2041 of cubecart.class.php (where we have other basket conditions)?
  • or including some basic basket conditions (e.g. on amount) triggering the display/hide of the gateway?
  • or both?
Link to comment
Share on other sites

Hi,

Thanks for your feedback. At line 2041, I can see a check on countries to see if the gateway is available in a given country (I'm enclosing the file cubecart.class.php which I have):

cubecart.class.zip

Before trying to play with hooks and snippets, I tried customizing myself the function _displayGateways (starting at line 1913), which I appreciate is semi-deprecated, but I didn't see any better position to try inserting this piece of code.

  • Attempt 1, I've added two characteristics of the module "instalments_min_amount" and "instalments_max_amount" (appreciate I could have made the naming more genric...) and added, after line 2041 the two following conditions. But it proved useless, it seems to be ignored (min amount is 100, and a basket which total value was 20 was displayed the payment method)
Quote

                    // Check basket value
                    if (isset($module['instalments_min_amount']) && !empty($module['instalments_min_amount']) && $GLOBALS['cart']->basket['total'] >= $module['instalments_min_amount']) {
                        continue;
                    }
                    
                    if (isset($module['instalments_max_amount']) && !empty($module['instalments_max_amount']) && $GLOBALS['cart']->basket['total'] <= $module['instalments_max_amount']) {
                        continue;
                    }

  • Attempt 2 was somewhat more radical, where I inserted a false condition (see below) after line 2041. Again it didn't change anything and all gateways are displayed
Quote

                    if (false) {
                        continue;
                    }

My takeaway from this is that, for one reason or the other, the _displayGateways function either is not called, or does not work as expected. As such I'm not sure if it's relevant to try to use the hooks which are within the function?

Happy to try, but being unfamiliar with hooks and snippets, I just want to make sure first, that the function is called indeed. Again, thanks so much for your help.

Best regards,

Guillaume

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...