Jump to content
Sign in to follow this  
jasehead

Display but disable payment gateway if conditions met

Recommended Posts

Posted (edited)

I'm about to enable a pay-by-instalment gateway (Oxipay) but I want to disable that gateway if conditions are met, similar to this discussion:
https://forums.cubecart.com/topic/50587-resolved-different-payment-options-for-different-product-categories/

The conditions are:

  • Total basket must be $50 or higher
  • All items must be ready to ship
    • stock control must be on (no infinite stock allowed)
    • no items flagged as pre-order (using Noodleman's Pre-Order plugin)
    • no items with pre-order or preorder in the item name

I still want the pay-by-installment gateway to be visible on the page (to advertise the option and explain the conditions), but disabled so it can't be selected unless the basket is over $50 and all items are in stock and ready to ship.

The check-if-item-flagged-as-pre-order code will be something like this, but needs to check all items in the basket:

{if isset($product.preorder_avail_date) && !is_null($product.preorder_avail_date) && $product.preorder_avail_date != "" && strtotime($product.preorder_avail_date) >= time()}

I'm also using radio buttons for payment gateways from this thread - https://forums.cubecart.com/topic/51515-radio-buttons-for-shipping-on-checkout/ - so my foreach code in content.checkout.php looks like this:

               {foreach from=$GATEWAYS item=gateway}
               <li>
                  <input name="gateway" type="radio" value="{$gateway.folder}" id="{$gateway.folder}" class="nosubmit" required {$gateway.checked} rel="gateway_error"><label for="{$gateway.folder}">{$gateway.description}</label>
                  {if !empty($gateway.help)}
                  <a href="{$gateway.help}" class="info" title="{$LANG.common.information}"><svg class="icon"><use xlink:href="#icon-info-circle"></use></svg></a>
                  {/if}
               </li>
               {/foreach}

Any advice for stacking the different if statements to check all conditions?

Edited by jasehead

Share this post


Link to post
Share on other sites

Posted (edited)

I think this is the logic (needs to work each time the basket is changed or updated) - I feel stumped about the code.

             GATEWAY = OXIPAY
             |              |
            YES             NO
             |              |
Every item available?      Radio enabled
 - after preorder date
 - no preorder text in name
 - stock control on (use_stock_level)
             |              |
            YES             NO
             |              |
      Basket over $50      Radio disabled
      |             |
     YES            NO
      |             |
Radio enabled      Radio disabled

 

Edited by jasehead

Share this post


Link to post
Share on other sites

In admin, Manage Hooks, Code Snippets tab, click Add Snippet.

Enabled: checked
Unique ID: disable_oxipay@cc600+
Execution Order: 1
Description: Disables gateway (Oxipay) if any of several conditions apply
Trigger: class.cubecart.display_gateways
Version: 1.0
Author: https://forums.cubecart.com/topic/53996-display-but-disable-payment-gateway-if-conditions-met/
PHP Code:
<?php
$snippet_target_gateway = "oxipay";
$snippet_disable_gateway = false;
foreach($this->_basket['contents'] as $snippet_item){
  if(empty($snippet_item['use_stock_level']) 
    || (!empty($snippet_item['preorder_avail_date']) && strtotime($snippet_item['preorder_avail_date']) >= time()) 
    || stripos($snippet_item['name'],'preorder') !== false 
    || stripos($snippet_item['name'],'pre-order') !== false) {
    $snippet_disable_gateway = true;
    break;
  }
}
if($this->_basket['subtotal'] < 50) $snippet_disable_gateway = true;

if($gateways && $snippet_disable_gateway){
  foreach($gateways as $i => $gateway){
    if($gateway['folder'] == strtolower($snippet_target_gateway)) $gateways[$i]['status'] = false;
  }
}

Save.

In the skin template content.checkout.php:

Find the radio button input tag:

<input name="gateway" type="radio" value="{$gateway.folder}" id="{$gateway.folder}" class="nosubmit" required {$gateway.checked} rel="gateway_error"><label for="{$gateway.folder}">{$gateway.description}</label>

Change to:

<input name="gateway" type="radio" value="{$gateway.folder}" id="{$gateway.folder}" class="nosubmit" {if $gateway.status}required{else}disabled{/if} {$gateway.checked} rel="gateway_error"><label for="{$gateway.folder}">{$gateway.description}</label>

Because you changed a skin template, you may need to have CubeCart clear its cache.

Share this post


Link to post
Share on other sites
Posted (edited)

That's really great - thank you very much, bsmither.

Is it possible to change:

    || stripos($snippet_item['name'],'preorder') !== false 
    || stripos($snippet_item['name'],'pre-order') !== false) {

to something like this (based on smarty)?

    || stripos($snippet_item['name']|lower|replace:'-':'','preorder') !== false) {

 

I had already cobbled together this long-winded hack below, still not understanding how to write a snippet or use code hooks.

In content.checkout.medium-up.php, I had to declare a global smarty variable to carry the foreach item information into the main checkout template:

<!-- START find any preorders for oxipay-->
{assign "ispreorder" "FALSE" scope="global"}
{foreach from=$ITEMS key=hash item=item}
{*$ispreorder = "FALSE"*}{if ((strpos({$item.name|lower|replace:'-':''}, 'preorder') !== false) || (($item.stock_level < 1) || ($item.use_stock_level == 0)) || isset($item.preorder_avail_date) && !is_null($item.preorder_avail_date) && $item.preorder_avail_date != "" && strtotime($item.preorder_avail_date) >= time())}{$ispreorder="TRUE" scope="global"}{/if}
<!-- END find any preorders for oxipay-->

I don't think this has to be repeated in content.checkout.small.php - the medium version is included but hidden in the main checkout template, so the code is invisible but still works.  I was also able to check if each item listed in the checkout was a preorder match:

Temporarily change:
<a href="{$item.link}"><strong>{$item.name}</strong></a>

To this for testing:
<a href="{$item.link}"><strong>{$item.name}</strong> - {$ifpreorder} - {$item.preorder_avail_date}</a><!--find any preorders for oxipay-->

In content.checkout.php I'm using radio buttons for payment gateways, so my original gateway foreach was this:

{foreach from=$GATEWAYS item=gateway}
<li>
  <input name="gateway" type="radio" value="{$gateway.folder}" id="{$gateway.folder}" required {$gateway.checked} rel="gateway_error"><label for="{$gateway.folder}">{$gateway.description}</label>
    {if !empty($gateway.help)}
    <a href="{$gateway.help}" class="info" title="{$LANG.common.information}"><svg class="icon"><use xlink:href="#icon-info-circle"></use></svg></a>
    {/if}
</li>
{/foreach}

Which I changed to this brilliant mess:

<!--START check if Oxipay and total is less than $50 and if preorder-->
{foreach from=$GATEWAYS item=gateway}
<li>
  {if ($gateway.folder=="Oxipay" && ({$TOTAL|substr:1} < 50 || $ispreorder=="TRUE"))}
	<span style="white-space:nowrap; display:inline-block">
		<input disabled name="gateway" type="radio" value="{$gateway.folder}" id="{$gateway.folder}" class="nosubmit" style="vertical-align:top" required {$gateway.checked} rel="gateway_error">
		<label for="{$gateway.folder}">
			<span class="show-for-medium-up">
				<img src="{$STORE_URL}/skins/{$SKIN_FOLDER}/images/oxipay-logo-orange.svg" alt="Oxipay" style="height: 1.5em;"> the smarter way to pay. Shop today, pay over time. 4 easy fortnightly payments. <br><strong>(Oxipay is available when Grand Total is over $50 and no pre-orders)</strong>
			</span>
			<span class="show-for-small-only">
				<img src="{$STORE_URL}/skins/{$SKIN_FOLDER}/images/oxipay-logo-orange.svg" alt="Oxipay" style="height: 1.5em;"> - 4 easy payments <br><strong>(if total over $50, no pre-orders)</strong>
			</span>
		</label>
	</span>					  
  {else}
  {if ($gateway.folder=="Oxipay")}
	<span style="white-space:nowrap; display:inline-block">
	<input name="gateway" type="radio" value="{$gateway.folder}" id="{$gateway.folder}" class="nosubmit" required {$gateway.checked} rel="gateway_error"><label for="{$gateway.folder}" style="vertical-align:top"><img src="{$STORE_URL}/skins/{$SKIN_FOLDER}/images/oxipay-logo-orange.svg" alt="Oxipay" style="height: 1.5em;"> Breathe easy with <br class="show-for-small-only">Oxipay, an interest-free <br class="show-for-small-only">installment payment plan.<!-- <img src="{$STORE_URL}/skins/{$SKIN_FOLDER}/images/visa-logo.svg" alt="Visa" style="height: 1em;"> <img src="{$STORE_URL}/skins/{$SKIN_FOLDER}/images/mastercard-logo.svg" alt="Mastercard" style="height: 1.5em;">--></label>
	</span>
  {else}
	<input name="gateway" type="radio" value="{$gateway.folder}" id="{$gateway.folder}" class="nosubmit" required {$gateway.checked} rel="gateway_error"><label for="{$gateway.folder}">{$gateway.description}</label>
  {/if}
  {/if}
  {if !empty($gateway.help)}
  <a href="{$gateway.help}" class="info" title="{$LANG.common.information}"><svg class="icon"><use xlink:href="#icon-info-circle"></use></svg></a>
  {/if}
</li>
{/foreach}
<!--END check if Oxipay and total is less than $50 and if preorder-->

The banner image in the Oxipay plugin caused some layout issues and was unreadable on mobile, so I used a logo plus text instead and added line breaks for small/mobile.  I experimented with Visa and Mastercard logos as well but decided not to use them.  The span style and label style help position the radio button at the top line when the label text is multiple lines long.  (SVG images for oxipay, visa and mastercard attached for anyone who wants them.)

mastercard-logo.svg

visa-logo.svg

oxipay-logo-orange.svg

Edited by jasehead

Share this post


Link to post
Share on other sites
Posted (edited)

BTW - this site (woocommerce) uses radio buttons for payment gateways at checkout  - you may have to add some items to cart for testing then have a look towards the bottom of the checkout page. When you click the radio button a line of text or other information appears underneath to help explain and promote the gateway to the customer - would be great to see that available in Cubecart.  There is a Gateway Help option in the Cubecart checkout, but only as a clickable icon and only visible if help is available - never seen it working though.

Edited by jasehead

Share this post


Link to post
Share on other sites

You cannot mix Smarty syntax into PHP code. This:

This:
stripos($snippet_item['name']|lower|replace:'-':'','preorder') !== false

Will need to be this:
strpos(str_replace('-','',strtolower($snippet_item['name'])),'preorder') !== false

stripos is not case sensitive, so it makes strtolower() unneeded.

Yes, you can manage to do the above in the skin's template.

The argument against doing it in the template is that template code should only decide if to display something and how to display it -- which does sound exactly like what you want to do.

But what you are really wanting to do is to affect HTML (gateways) from having tests made on unrelated data (items). This correlation is best performed in PHP.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×