Is there any reliable way to get list of enabled payment method instances, same as user sees on payment page?
I've found couple ways how this is happen in Commerce, but none of them is reliable enough as for me.
First one:

  // Invoke the payment methods event that will populate the order with
  // an array of method IDs for available payment methods.
  $order->payment_methods = array();
  rules_invoke_all('commerce_payment_methods', $order);

from modules/payment/includes/commerce_payment.checkout_pane.inc:54, but the issue here is that if I will create a mock of order for use on my custom setting page like this:

  $order = new stdClass();
  $order->type = 'commerce_order';
  $order->status = 'checkout_review';
  $order->payment_methods = array();
  rules_invoke_all('commerce_payment_methods', $order);

$order->payment_methods array will missing some payment methods available on payment page.

If i use:


  $conditions = array(
    'event' => 'commerce_payment_methods',
    'plugin' => 'reaction rule',
    'active' => TRUE,
    'owner' => 'rules',
  );
  $commerce_payment_methods = entity_load('rules_config', FALSE, $conditions);

from commerce_payment_ui.admin.inc:29, I'm not sure how to get instance ID that will will feet to commerce_payment_method_instance_load() from rules entities.

Any help is greatly appreciated.

Comments

rosk0’s picture

This is what I came up with:


  $conditions = array(
    'event' => 'commerce_payment_methods',
    'plugin' => 'reaction rule',
    'active' => TRUE,
    'owner' => 'rules',
  );
  $commerce_payment_methods = entity_load('rules_config', FALSE, $conditions);

  foreach ($commerce_payment_methods as $method) {
    $items = $method->getIterator();
    $action = $items[1];
    $method_id = is_array($action->settings['payment_method']) ? $action->settings['payment_method']['method_id'] : $action->settings['payment_method'];
    $instance_id =  $method_id . '|' . $method->identifier();

    if ($payment_method = commerce_payment_method_instance_load($instance_id)) {
      if (!empty($payment_method['checkout'])) {
        $options[$instance_id] = $payment_method;
        if (isset($method->weight)) {
          $options[$instance_id]['weight'] = $method->weight;
        }
      }
    }
  }
  uasort($options, 'drupal_sort_weight');

Still sure that this is not the best way.

rszrama’s picture

Status: Active » Closed (fixed)

Did you look at what the payment method checkout pane does (see commerce_payment_pane_checkout_form())?

This snippet is responsible for collecting payment methods via Rules that are then stored in that array on the order object:

  // Invoke the payment methods event that will populate the order with
  // an array of method IDs for available payment methods.
  $order->payment_methods = array();
  rules_invoke_all('commerce_payment_methods', $order);

Code below that formats it into an options list for the radio buttons element.

rosk0’s picture

Status: Closed (fixed) » Active

Hi Ryan,
Thanks for your reply. As I stated in description this method worked before for some time, but at some point, probably latest rules or entity update, this method stopped working for mocked order objects.
I'm working on custom form builder module called CRM Core Profile which allows to collect data about multiple entities, most usually contact and activity, but also has an ability to create a payments when this form is submitted. Configuration form of this module allows admin user to select which payment methods are allowed to be used on this form and this is why I have to create mock order object to get list of enabled payment methods, because real order is not created, and shouldn't be, at this stage. So in short: I need to get list of enabled payment methods without using an order object.

artreaktor’s picture

Hi Kirill!
Try this way:

foreach (commerce_payment_methods() as $id => $method) {
  $payment = commerce_payment_method_instance_load("$id|commerce_payment_$id");
  dpm($payment);
}
artreaktor’s picture

Status: Active » Closed (fixed)
rosk0’s picture

Status: Closed (fixed) » Active

@artreaktor: Thanks, but this doesn't work. This method will return only one instance per payment type and what I need is a way to get list of all enabled payment method instances.

artreaktor’s picture

Here is what you want:

  $active_payment_rules = db_select('rules_config', 'rc')
  ->fields('rc', array('id', 'name'))
  ->condition('rc.module', 'commerce_payment')
  ->condition('rc.active', 1)
  ->execute()
  ->fetchAllKeyed(0,1);

  foreach ($active_payment_rules as $rule_name) {
    // Cut "commerce_payment_" to get the id
    $id = substr($rule_name, 17);
    $payment = commerce_payment_method_instance_load("$id|commerce_payment_$id");
    dpm($payment);
  }

UPD: Actually, my solution is pretty similar to yours, so I can confirm there's no more "reliable" way to get the payment instances.

rosk0’s picture

Solution in #7 doesn't do what I need - it will get you a list of methods owned by the commerce_payment module and if you will create one custom payment method, lets say PayPal, and will export it to feature you will not see this method in the list, because it will be owned by the feature module.

aksdax’s picture

Hi,
Why not try and join the rules config and rules trigger table to get what you want ?
rules trigger table has mapping of rule ids and events.

function get_active_payments_method_rules() {
  $query = db_select('rules_config', 'rc');
  $query->join('rules_trigger', 'rt', 'rc.id = rt.id');
  $query->fields('rc', array('id', 'name'))
      ->condition('rt.event', 'commerce_payment_methods')
      ->condition('rc.active', 1);
  $active_payment_rules = $query->execute()->fetchAllKeyed(0, 1);
  foreach ($active_payment_rules as $rule_name) {
    $rule = rules_config_load($rule_name);
    dpm($rule);
foreach ($rule->actions() as $action) {
      $action_machine_name = $action->getElementName();
      dpm($action_machine_name);
    }
  }
}
lucman’s picture

Very old question, but I realized that, since enabled payment methods depend on rules, to get effective enabled payment methods, per user and per order, rules must be evalued.

And evaluation results may depend on many factors and contexts.

The following function returns enabled payment methods on checkout form, but results may depend on contexts (for axample: user country, if a rule has a condition on this)

function mymodule_get_avail_checkout_payment_methods($order){
    if(isset($order->payment_methods)){
        //already set
    }else{
        $order->payment_methods = array();
        rules_invoke_all('commerce_payment_methods', $order);

    }
    $ret = array();
    foreach ($order->payment_methods as $instance_id => $method_info) {
        // Ensure we've received a valid payment method that can be used on the
        // checkout form.
        if ($payment_method = commerce_payment_method_load($method_info['method_id'])) {
            if (!empty($payment_method['checkout'])) {
                $ret[$instance_id] = $payment_method;
            }
        }
    }
    return $ret;
}
rszrama’s picture

Status: Active » Fixed
rszrama’s picture

(fwiw, just marking fixed b/c there are multiple solutions in here now and this is almost certainly outdated. : )

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.