Hey all:

I've been working on a custom module for ecommerce that hooks into my company's checkout system. My latest issue has to do with the checkoutapi's invocation of the 'form' op.... here's the first few lines of my checkout api implementation:

function ***_********_checkoutapi($txn, $op, $post_op = NULL, $arg4 = NULL) {
  switch ($op) {
    case 'form':
      drupal_set_message('checkout api form hook called');
      drupal_set_title(t('Credit Card Payment Information'));
      return ***_********_form($txn);
      break;

And here's the first few lines of my form function:

	global $user;
  // Make sure the user owns the transaction or is an admin... something's broken here.
	drupal_set_message('user uid '. $user->uid .' / t uid '. $t->uid);
  if ($user->uid !== $t->uid && $user->uid !== 1 && !user_access('administer store')) {
    return drupal_access_denied();
  }

Seems pretty simple... unfortunately, when the form loads, the checkoutapi form hook is invoked twice, and on the first invocation the transaction uid is not yet loaded, so for non-admin users I always get access denied.

I've attached the results of my form loading (with the above traces) so you can see what I'm ending up with.... note this was loaded with the actual drupal_access_denied() line commented out.

Any ideas/suggestions?

CommentFileSizeAuthor
ecommerce_bug.jpg61.13 KBvegeneric
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

vegeneric’s picture

Status: Active » Needs review

After extensive debugging and putting traces all over cart.module, I believe I isolated this issue. My epiphany started when I realized that not only was my checkoutapi's form $op being called twice, but inbetween them the review hook was also being called. Digging into the module, I noticed function checkout_form() (cart.module ~ line 428) calls checkout_get_screens() twice in a row, once with no parameter (defaults to 'form'), and once with 'review'. That brought me to function checkout_get_screens() (cart.module ~ line 901), where you have the following:

  foreach (module_implements('checkoutapi') as $module) {
    // Only count the $op cases
    $function = "{$module}_checkoutapi";
    if ($module != 'cart' && ($return = $function($module, $op))) {
      $fresh_screens[] = $module;
    }
  }

It appears that the $return = $function($module, $op) portion of the above if statement is actually running my module's hook... which has been causing me all sorts of trouble. By modifying the above code to the following, my issues seem to have been resolved:

  foreach (module_implements('checkoutapi') as $module) {
    // Only count the $op cases
    $function = "{$module}_checkoutapi";
    if ($module != 'cart') {
      $fresh_screens[] = $module;
    }
  }

For reference, here is my checkoutapi implementation (sorry tabbing is screwy):

function ***_ecommerce_checkoutapi($txn, $op, $post_op = NULL, $arg4 = NULL) {
	
  switch ($op) {
    case 'form':
      $form = ***_ecommerce_checkout_form($txn);
			$form[] = array('#type' => 'submit', '#value' => t('Continue'));
			return $form;
			//break;

    case 'save':
			$txn->screen++;
      break;

    case 'review':
			if (is_numeric($txn->account) && $txn->account > 0) {
				include_once 'billing/CBS.php';
				CBS::getInstance();
				$validCc = new CBS_CreditCard($txn->account);
				$form['title'] = array('#value' => '<h2>'. t('Billing Info') .'</h2>');
				$form['***_ecommerce']['name'] = array('#value' => 'Name: '. $validCc->getName() .'<br />');
				$form['***_ecommerce']['address'] = array('#value' => 'Address: '. $validCc->getAddress1() .' '. $validCc->getAddress2() .'<br />');
				$form['***_ecommerce']['citstatezip'] = array('#value' => 'City / State / Zip: '. $validCc->getCity() .', '. $validCc->getState() .' '. $validCc->getZip() .'<br />');
				$form['***_ecommerce']['cc'] = array('#value' => 'Credit Card #: ****-****-****-'. $validCc->getLastFour() .'<br />');
				$discount = ***_ecommerce_current_discount($txn->uid);
				if (is_numeric($discount) && $discount > 0) {
					$form['***_ecommerce']['discount'] = array('#value' => 'Discount total: $'. $discount .'<br />');
				}
				return $form;
			}
			
			break;
			
		case 'review_submit':
			***_ecommerce_order($txn);
			break;
	
  }
	
}

Is this an actual glitch or is my code causing this somehow? Could removing the if check from cart.module have any side effects I'm not seeing?

Thanks for any help on this...