5 replies [Last post]
BayerMeister's picture
Offline
Joined: 07/21/2009
Juice: 197

On the /cart/checkout page there is the selection of the shipping method and of the payment method.
How can I forbid certain combinations of shipping and payment?

The cleanest way would be if there was a way to hide payments, that are not applicable to the selected shipping method. But how? Can this be done without hacking the checkout page?

The not so clean way that I am willing to go is to give the customer a text message, like the one if you don't select any shipping method while it is obligatory - a red error message on top of the checkout page saying "you cant use this payment method if you want this shipping method". Still I did not find answers how to do this.

Can anyone help, please? I really want to get this off the table.

BayerMeister's picture
Offline
Joined: 07/21/2009
Juice: 197
Re: Avail. payment mehods dependent on selected shipping type

This seems to be a common use-case. As I look around on the czech net it is something each shop has in common:
After selecting a delivery (shipping) option only applicable payment options are shown.

I looked at the livetest of Übercart and (after making up an existing US address) found out, that there is no such thing there (as far as I've tested). UPS (2 options) and free shipping don't have influence on the offered payment methods. Damn!

Can someone at least tell me "Yes, it is so, Übercart does not support this"? I already have a dirty solution for myself, but I hate it and I would love to have it done a clean way. Yet, I don't believe there is no simple solution as this is something so common!

BayerMeister's picture
Offline
Joined: 07/21/2009
Juice: 197
Re: Re: Avail. payment mehods dependent on selected shipping typ

Is there anyone who does think this is a good thing to be solved?
Is there anyone who thinks this is something only I am going to use?
Why do I get no replies? Is something wrong with my nick, picture or my language?

paulgrimshaw's picture
Offline
Joined: 05/19/2008
Juice: 91
+1

Hey,

This is something I would like to see too - I want to have home deliveries and collection - I don't want CASH to come up if its a home delivery.

Thanks,
Paul.

Ryan's picture
Offline
Joined: 08/07/2007
Juice: 15422
Re: +1

I don't think this is an incredibly difficult task, it's just one that the payment method selection wasn't developed to accommodate. However, people in the issue tracker have been proposing solutions. I know there's a patch by Lyle that could use review, and I think I saw another issue for this exact same feature.

BayerMeister's picture
Offline
Joined: 07/21/2009
Juice: 197
jQuery and other stuff

OK, I've gone a long way today - never heard of jQuery before, didn't use JavaScript so far. Fine. So here is the plan: (contains a catch which has to be solved)

To alter the behavior of the checkout page I simply want to add an event handler to each shipping-method's radio-button. This would set the .disabled value on payment methods (their names hardcoded in my case).

1. The first idea was to find the place where the radio-buttons are generated (input tags) and simply add the handlers there. I however didn't find this place at first, so I had a chat on #drupal-ubercart. The second possibility (much cleaner) arose:

2. The second idea was to make a module that just adds a .js on the checkout page. So far so good Smiling This .js file would (I thought) use the $(document).ready event to set the handlers. Sounds easy? And now the CATCH! on document.ready the radio-buttons don't exist yet in the DOM - they appear later, when the button "Calculate shipping costs" is pressed or the address is filled out.

So: How... or When (what is the event) can I run the function, that adds the handlers?

Conclusion
I find the clean way... much cleaner and that is why I make this post - to get it done. If I get stuck here, I'll make my hands dirty again.

Code snippets
I won't paste the module.info of course.
Here is the uc_checkout_page_alter.module file:

<?php
function uc_checkout_page_alter_checkout_pane() {
 
drupal_add_js(drupal_get_path('module', 'uc_checkout_page_alter') .'/uc_checkout_page_alter.js');
}
?>

And here is the uc_checkout_page_alter.js file:

//skip reading this function for now - it is copy-pasted,
//it just adds the (func) to the given (obj)ect on (event)
function addEvent(obj, event, funct) {
  if (obj.attachEvent) { //IE
    obj['e' + event + funct] = funct;
    obj['x' + event + funct] = function() {
          obj['e' + event + funct](window.event);
        }
    obj.attachEvent('on' + event, obj['x' + event + funct]);
  } else // other browser
    obj.addEventListener(event, funct, false);
}

//here the call, that should be done some time later (and repeatedly)
$(document).ready(function() {
//note that "cash", "bank-transfer" and "cod" are hardcoded payment method names
    var cash = document.getElementById('edit-panes-payment-payment-method-cash');
    var bank = document.getElementById('edit-panes-payment-payment-method-bank-transfer');
    var cod  = document.getElementById('edit-panes-payment-payment-method-cod');

//this div _will_ contain the shipping radio-buttons
    var quoteDiv = document.getElementById('quote');
    if (quoteDiv == null) return;

//problem: on $(document).ready this <div> is empty - filled later. And updated... so this all must be executed on update of shipping methods.

    var inputs = quoteDiv.getElementsByTagName('input');
//this inputs array is of course empty so far. Here the tested part ends...

//note that these vars will hold the radios of shipping options, "pickup" ("flatrate_1---0"), "dpd" and "dpd2" are hardcoded shipping method names.
    var pickup, dpd, dpd2;

    for (i = 0; i < inputs.length; i++) {
        if (inputs[i].type == "radio") {
            alert("value = " + inputs[i].value);
            if (inputs[i].value == "flatrate_1---0")
                pickup = inputs[i];
            else if (inputs[i].value == "dpd---0")
                dpd = inputs[i];
            else if (inputs[i].value == "dpd2---0")
                dpd2 = inputs[i];
        }
    }

    //if someone alters the methods so that these can not be retrieved (or for another reason), don't do a thing
    if (cash == null || bank == null || cod == null || pickup == null || dpd == null || dpd2 == null)
        return;

    //don't know if the syntax is right - havent tested this - the idea is clear I think. The function called is below
    addEvent(pickup, 'click', function() {
        cash.disabled = false;
        bank.disabled = false;
        cod.disabled = true;
        cod.checked = false;
    });

    //a similar thing with addEvent(dpd... and addEvent(dpd2...
}

Ehm, how do I highlight JS by the way?
Thanks everyone for advice!