(Note: Originally I posted this as a feature reguest in the VirtueMart Developer Portal. But the portal wiki stripped all indention of my code examples, which makes the code a bit difficult to read. So I decided to post this here in the blog too to give a more clear version to those who wish to copy my modifications to their own use.)
Currently VirtueMart doesn’t have any method to limit payment module availability.
But it would be nice to be able to limit the use of a payment module (ie. hide payment method from selection list during checkout) for example by the following factors:
- Order total minimum and maximum value
- Customer data (like country code)
- Selected shipping method
- Time or date
- Many many other factors
Here is an example of a hack I use myself. It requires only small additions to one VM core file. It is backwords compatible – ie. existing payment modules don’t have to be updated. It gives total freedom to payment module developer to decide which factors he/she uses to limit module availability.
Modify ps_payment_method::list_payment_radio() in ps_payment_method.php
Modify ps_payment_method::list_payment_radio() by adding line
“if ($this->paymentMethodAvailable($db->f(“payment_method_id”))) {“
and its corresponding closing }-character like in the example below:
-
function list_payment_radio($selector, $payment_method_id, $horiz) {
-
global $CURRENCY_DISPLAY, $ps_checkout;
-
-
// … code …
-
-
$db->query($q);
-
$has_result = false;
-
// Start radio list
-
while ($db->next_record()) {
-
if ($this->paymentMethodAvailable($db->f("payment_method_id"))) {
-
$has_result = true;
-
-
// … code …
-
-
echo "</label>";
-
if ($horiz) {
-
echo(" ");
-
} else {
-
echo("<br />");
-
}
-
}
-
}
-
return $has_result;
-
}
Add new ps_payment_method::paymentMethodAvailable() -method to ps_payment_method.php
Add new ps_payment_method::paymentMethodAvailable() -method to anywhere (eg. right after ps_payment_method::list_payment_radio()) in ps_payment_method.php
-
/**
-
* Returns boolean availability status of a payment method
-
*
-
* Returns true if payment method is available or if payment method doesn't
-
* support paymentMethodAvailable()-functionality, false if not available.
-
*
-
* @param int $paymentMethodId
-
* @return boolean
-
*/
-
function paymentMethodAvailable($paymentMethodId)
-
{
-
$paymentSqlQuery = $this->payment_sql($paymentMethodId);
-
$className = $paymentSqlQuery->f('payment_class');
-
$filename = CLASSPATH.'payment/'.$className.'.php';
-
if (file_exists($filename)) {
-
include_once $filename;
-
if (class_exists($className)) {
-
try {
-
$PaymentMethod = new $className();
-
} catch (Exception $e) {
-
return true;
-
}
-
if (method_exists($PaymentMethod, 'isAvailable')) {
-
try {
-
$booleanStatus = $PaymentMethod->isAvailable();
-
} catch (Exception $e) {
-
return true;
-
}
-
return $booleanStatus;
-
}
-
}
-
}
-
return true;
-
}
Example of implementing isAvailable()-method in a payment module
This example limits the payment module availability by order total minimum and maximum (but it is trivial to use other limitin factors too).
-
class ps_payment_module_example
-
{
-
/**
-
* Returns availability status of the payment method
-
*
-
* @param void
-
* @return bool True if available, false if not available
-
*/
-
public function isAvailable()
-
{
-
include_once CLASSPATH."payment/ps_payment_module_example.cfg.php";
-
GLOBAL $order_total;
-
if (floatval($order_total) < floatval(EXAMPLE_CFG_ORDER_TOTAL_MIN) OR
-
floatval($order_total) > floatval(EXAMPLE_CFG_ORDER_TOTAL_MAX)) {
-
return false;
-
}
-
return true;
-
}
-
}
Good afternoon, could you tell me what changes do to limit the method of payment by countries.
Thanks
Carefully
Joao Carvalho
why don´t make a module?
Could you please help!
I need to have a COD (cash on delivery) payment method to be available only for local pick up shipping method. Could you guide me how to do that?
Please, please…
Can you please help me with this very good modification??? I rewrite files by your notes and source code, but if I select “limited order value” method then I get error “The selected Payment Class can’t be instantiated because it doesn’t exist.” what else should I do???
can you send me whole files???
Works like a charm – you really made my day! Thanks a lot for this! :)
Thank you for this update, it works well, and you’ve saved me aq huge headache.
I have the payment module checking to see if an order is above $200, and if so it shows certain payment options.
Ideally it would actually check against the subtotal, but I can’t seem to pass that variable/value into the payment module.
Can anyone point me in the right direction, possibly?
Thank you for your method, it was very helpful, It’s a pity and a shame that they don’t implement it in the core of virtuemart or ar least make something similar.
Thanks!!
Thank you!
This hack works perfectly, well done! :)