How to force account creation before commerce checkout is complete? I currently have a one-page checkout that works great for anonymous users. After payment is complete, an account is created with the 'Create a new account for an anonymous order' checkout rule.

Now I need to add a subscription product to the site, and plan to use Commerce License and Commerce License Billing to sell a role. To handle recurring payments, I plan to use Commerce Card on File.

This introduces a problem because Card on File requires an authenticated user in order to save cards. See https://www.drupal.org/node/1553468

How can I create a user account before checkout finishes so that Card on File can properly save cards?

Ideally, there would be a custom checkout page that forces account registration as a first step in checkout, but only for users purchasing subscription products.

I don't allow visitors to register on the site at the moment (except via Commerce Checkout), and I'd rather not change that.
I suggest the following steps :


create a custom checkout pane (see  checkout_pane_example.module ) and embed the user register form in that pane:

/**
 * Implements hook_commerce_checkout_pane_info().
 */
function vts_register_commerce_checkout_pane_info() {
  $panes['register'] = array(
    'title' =&gt; t('Create an account'),
    'base' =&gt; 'vts_register_pane',
    'name' =&gt; t('NAME'),
    'page' =&gt; 'checkout',
    'weight' =&gt; -5,
  );
  return $panes;
}
/*
 * Add user_register_form to register pane
 */
function vts_register_pane_checkout_form($form, &amp;$form_state, $checkout_pane, $order) { 
  $pane_form = drupal_get_form('user_register_form');
  return $pane_form;
}
/*
 * Alter checkout form register pane
 */
function vts_register_form_commerce_checkout_form_checkout_alter(&amp;$form, &amp;$form_state, $form_id) {
  unset($form['register']['actions']); 
}
/**
 * checkout form submission callback.
 */
function vts_register_pane_checkout_form_submit($form, &amp;$form_state, $checkout_pane, $order) {
  $new_user = array(
    //dsm to find the correct $form_state['input'] for username here, because I have an altered user register form...
    'name' =&gt; $form_state['input']['field_name_first']['und'][0]['value'].'_'.$form_state['input']['field_name_last']['und'][0]['value'],
    'pass' =&gt; user_password(),
    'mail' =&gt; $form_state['input']['mail'],
    'init' =&gt; $form_state['values']['mail'],
    'status' =&gt; 1,
    'roles' =&gt; array(DRUPAL_AUTHENTICATED_RID =&gt; TRUE),
  );
  if($GLOBALS['user']-&gt;uid == '0') {
    $user = user_save('', $new_user);
    //ASSIGN the current order to created user
    $order-&gt;uid = $user-&gt;uid;
    commerce_order_save($order);
    $GLOBALS['user'] = $user;
  }
  //check that you got a new user and the order was assigned to him
  dsm($user, 'user');
  dsm($order, 'order');
}
/**
 * Validation callback.
 */
function vts_register_pane_checkout_form_validate($form, &amp;$form_state, $checkout_pane, $order) {
  //validation stuff
  return TRUE;
}
/**
 * Ouputs Review checkout pane.
 */
function vts_register_pane_review($form, $form_state, $checkout_pane, $order) {
  // add some info to review pane
  return;
}

Go to admin/commerce/config/checkout and set it as disabled
Install Commerce Rules Extra, it adds the features you need :



  Rules conditions : Total product of type quantity comparison
  
  Rules actions : Change pane properties : Change visibility, page, weight of a pane



Create a rule : 

Event: Process checkout pane.
Conditions : user is anonymous ; subscription product quantity > 0.
Action : Change pane properties : enabled: true; move to checkout.