如何跳过分页符

时间:2014-01-20 10:35:49

标签: drupal-7 drupal-modules

我是Drupal的全新手,我花了大部分时间和Joomla在一起!我有一个使用Web表单组件的Drupal 7站点。它的步骤定义为:

Steps in the form:

现在分页符组件如下所示:

Registration Break Settings

如果我在优惠券文本字段(我添加)中填写GOMEZ后正确理解了事情,则不应该中断,用户应该转到下一页。但事实并非如此,用户必须通过PayPal进行操作。

我想要发生的是用户输入优惠券代码并跳过PayPal步骤,用户可以填写表格。看来这可以通过使用webform_paypal_permission()任何想法吗?

我很高兴如果我必须修改PHP代码但是如果可以的话我想避免使用它,而是使用我认为存在的功能。

我还在PHP下面包含了用于调试PayPal步骤的PHP:

<?php


/**
 * Implementation of hook_init
 *
 * A bit of a hack,Seems that session_id keeps changing for anon users and we need to track that through to the IPN to
 * know if this session has paid or not.
 *
 * So store it in $_SESSION
 */
function webform_paypal_init() {
  global $_SESSION;
  if (empty($_SESSION['webform-session'])) {
    // anonymous users wont have a session stick, so do it this way (session_id changes on each page)
    $_SESSION['webform-session'] = session_id();
  }
}

/**
 * Implements hook_menu().
 */
function webform_paypal_menu() {
  $items = array();

  $items['webform_paypal_ipn/%/%/%'] = array(
    'page callback' => 'webform_paypal_ipn_callback',
    'page arguments' => array(1, 2, 3),
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );

  $items['webform_paypal_lander/%/%'] = array(
    'page callback' => 'webform_paypal_lander',
    'page arguments' => array(1, 2),
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implements hook_permission().
 */
function webform_paypal_permission() {
  return array(
    'bypass payment' => array(
      'title' => t('Bypass payment'),
      'description' => t('Complete the webform without payment.'),
    ),
  );
}

/**
 * This is the 'landing' or 'return' page that return= will return a user to from PayPal
 * It's responsible for waiting for a paypal IPN notification then pushing the user onto the next
 * page as its stored in $_SESSION, it does so by faking a HTTP POST, yuck!
 *
 * @param $nid - the NodeID to resubmit to (will be converted to full URL)
 * @param $cid - the ComponentID that we need to wait to be paid by IPN callback
 *
 */
function webform_paypal_lander($nid, $cid) {
  $output = array();

  // Just do some idle stuff until the IPN notification lands

  $waits = 0;
  while (!webform_paypal_ipn_submission_exists($cid, $nid)) {
    sleep(1);

    $waits++;
    if ($waits > 15) {
      watchdog('webform_paypal', "No IPN update was found from PayPal, cant allow user to continue.", array(), WATCHDOG_ERROR);
      return t('No reply found from PayPal, unable to process your payment at this time.');
    }
  }

  // Once it's here, resubmit the form with their stored previous form submission
  // The IPN should then be registred in the DB by our callback
  // And the #submit processor wont care about them anymore and they will continue on.


  foreach ($_SESSION['page_store'] as $id => $row) {
    if (is_array($row)) {
      foreach ($row as $sub_id => $sub_row) {
        $output[] = $id . "[$sub_id]=$sub_row";
      }
    }
    else {
      $output[] = "$id=$row";
    }
  }

  $cookies = array();
  foreach ($_COOKIE as $name => $value) {
    $cookies[] = "$name=$value";
  }

  $options = array(
    'method' => 'POST',
    'data' => implode('&', $output),
    'timeout' => 15,
    'headers' => array('Content-Type' => 'application/x-www-form-urlencoded', 'Cookie' => implode('; ', $cookies)),
  );

  $url = url('node/' . $nid, array('absolute' => TRUE));
  $result = drupal_http_request($url, $options);

  // Everything should generally work out just fine here
  if ($result->code == 200) {
    print $result->data;
    drupal_exit();
  }
}


/**
 * #submit processor
 *
 * Send the user to the PayPal payment page if neccessary
 *
 * @param $form
 * @param $form_state
 */
function webform_paypal_pause_or_redirect($form, &$form_state) {

  // Know which CID (Component ID) was clicked as part of the 'page_break'
  // page_num would represent number of page_breaks to skip to know
  $page_num = $form_state['webform']['page_num'];

  $current_page = 1;

  foreach ($form_state['webform']['component_tree']['children'] as $cid => $component) {
    if ($component['type'] == 'pagebreak') {
      if ($page_num == $current_page) {
        break;
      }
      $current_page++;
    }

  }

  // See if this component is in any mode to be redirected
  $mode = variable_get('webform_paypal_button_mode_' . $cid, '');

  if ($mode == 'live' || $mode == 'sandbox') {
    // If so, redirect to PayPal if theres no IPN submission from PayPal

    // This should only happen the first time because users returning from PayPal enter a sleep loop to wait
    // for the IPN update.
    // Bypass for users with the 'bypass payment' permission

    if (!webform_paypal_ipn_submission_exists($cid, $form['#node']->nid) && !user_access('bypass payment')) {
      $store = $_POST;
      // Store the form in a session var, we will resubmit the form when we return from PayPal
      // Which should make the user goto the next page if the payment has been received OK
      $_SESSION['page_store'] = $store;
      drupal_goto(webform_paypal_submit_url($form['#node']->nid, $cid));
    }
  }

}

function webform_paypal_ipn_submission_exists($cid, $nid) {

  $result = db_select('webform_paypal_ipn', 'wp_ipn')
    ->fields('wp_ipn', array('extra'))
    ->condition('cid', $cid)
    ->condition('sessionID', $_SESSION['webform-session'])
    ->condition('nid', $nid)
    ->execute();

  return $result->rowCount();
}

/**
 * Implements of hook_form_alter().
 *
 * @todo there must be a better way to theme in the button than to use a form_alter
 */
function webform_paypal_form_alter(&$form, &$form_state, $form_id) {

  // Handle a redirect to PayPal if neccessary
  if (strpos($form_id, 'webform_client_form_') !== FALSE) {
    $form['#submit'][] = 'webform_paypal_pause_or_redirect';
  }


  // Add the config to the pagebreak component
  if ($form_id == 'webform_component_edit_form') {
    $cid = arg(4);
    if ($form['type']['#value'] == 'pagebreak') {
      $form['webform_paypal'] = array(
        '#type' => 'fieldset',
        '#title' => t('Paypal Button integration'),
      );
      $form['webform_paypal']['webform_paypal_button_id'] = array(
        '#type' => 'textfield',
        '#title' => t('PayPal Button ID'),
        '#default_value' => variable_get('webform_paypal_button_id_' . $cid, ''),
        '#description' => t('If this is requires a PayPal Payment to continue, enter the Button ID here'),
        '#weight' => -8
      );
      $form['webform_paypal']['webform_button_mode'] = array(
        '#type' => 'select',
        '#title' => t('PayPal Button Mode'),
        '#default_value' => variable_get('webform_paypal_button_mode_' . $cid, ''),
        '#options' => array('disabled' => t('DISABLED'), 'sandbox' => t('SANDBOX'), 'live' => t('LIVE')),
        '#weight' => -9
      );
      $form['#submit'][] = 'webform_paypal_component_edit_submit';
    }
  }
}

function webform_paypal_component_edit_submit($form, &$form_state) {

  $cid = $form_state['values']['cid'];

  $id = $form_state['values']['webform_paypal']['webform_paypal_button_id'];
  variable_set('webform_paypal_button_id_' . $cid, $id);

  $id = $form_state['values']['webform_paypal']['webform_button_mode'];
  variable_set('webform_paypal_button_mode_' . $cid, $id);


}

/**
 * Get the URL for the user to connect to PayPal
 *
 * This special URL includes things like return URL's, IPN etc
 */
function webform_paypal_submit_url($nid, $cid, $tracking_url = "") {
  global $base_url;
  global $_SESSION;


  $mode = variable_get('webform_paypal_button_mode_' . $cid, '');

  if($mode == 'live') {
    $url = 'https://www.paypal.com/cgi-bin/webscr';
  }
  else {
    $url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
  }

  $post_data = array();
  $post_data['cmd'] = '_s-xclick';

  $post_data['return'] = $base_url . '/webform_paypal_lander/' . $nid . '/' . $cid;

  $post_data['hosted_button_id'] = variable_get('webform_paypal_button_id_' . $cid, '');

  //send return path to submission for better tracking
  $post_data['custom'] = $tracking_url;

  // setup IPN callback
  $post_data['notify_url'] = $base_url . '/webform_paypal_ipn/' . $nid . '/' . $cid . '/' . $_SESSION['webform-session'];

  // return the URL
  $url = url($url, array('query' => $post_data, 'external' => TRUE));

  return $url;

}

/**
 * Menu callback for receving the PayPal IPN calls
 * Arguments were handed to PayPal in the IPN link
 *
 * @param $nid Node ID
 * @param $cid Component ID
 * @param $sessionID Session ID from session_id() of the submitter
 */
function webform_paypal_ipn_callback($nid, $cid, $sessionID) {

  // get the URL depending on the components configuration
  $mode = variable_get('webform_paypal_button_mode_' . $cid, '');

  if ($mode == 'live') {
    $url = 'https://www.paypal.com/cgi-bin/webscr';
  }
  else {
    $url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
  }

  if (webform_paypal_ipn_verify_message($url)) {
    $key = array(
      'nid' => $nid,
      'cid' => $cid,
      'sessionID' => $sessionID
    );

    db_merge('webform_paypal_ipn')
      ->key($key)
      ->fields(array_merge($key, array(
        'extra' => serialize($_POST)
      )))
      ->execute();
  }

  return 'OK';
}

/**
 * Input IPN processor
 * from https://developer.paypal.com/webapps/developer/docs/classic/ipn/ht_ipn/
 *
 * @return bool
 */
function webform_paypal_ipn_verify_message($url) {
  // STEP 1: read POST data
// Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
// Instead, read raw POST data from the input stream.
  $raw_post_data = file_get_contents('php://input');
  $raw_post_array = explode('&', $raw_post_data);
  $myPost = array();
  foreach ($raw_post_array as $keyval) {
    $keyval = explode('=', $keyval);
    if (count($keyval) == 2) {
      $myPost[$keyval[0]] = urldecode($keyval[1]);
    }
  }
// read the IPN message sent from PayPal and prepend 'cmd=_notify-validate'
  $req = 'cmd=_notify-validate';
  if (function_exists('get_magic_quotes_gpc')) {
    $get_magic_quotes_exists = TRUE;
  }
  foreach ($myPost as $key => $value) {
    if ($get_magic_quotes_exists == TRUE && get_magic_quotes_gpc() == 1) {
      $value = urlencode(stripslashes($value));
    }
    else {
      $value = urlencode($value);
    }
    $req .= "&$key=$value";
  }


// Step 2: POST IPN data back to PayPal to validate

  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, variable_get('webform_paypal_verifypeer', TRUE));
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
  curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
  curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));

// In wamp-like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set
// the directory path of the certificate as shown below:
  if ($cacert = variable_get('webform_paypal_cacert', FALSE)) {
    if (!file_exists($cacert)) {
      watchdog('webform_paypal', "unable to open cert file", array(), WATCHDOG_ERROR);
    }
    curl_setopt($ch, CURLOPT_CAINFO, drupal_realpath($cacert));
  }

  if (!($res = curl_exec($ch))) {
    watchdog('webform_paypal', curl_error($ch), array(), WATCHDOG_ERROR);
    curl_close($ch);
    exit;
  }
  curl_close($ch);

// inspect IPN validation result and act accordingly

  if (strcmp($res, "VERIFIED") == 0) {

    // The IPN is verified, process it:
    // check whether the payment_status is Completed
    // check that txn_id has not been previously processed
    // check that receiver_email is your Primary PayPal email
    // check that payment_amount/payment_currency are correct
    // process the notification

    // assign posted variables to local variables
    $item_name = $_POST['item_name'];
    $item_number = $_POST['item_number'];
    $payment_status = $_POST['payment_status'];
    $payment_amount = $_POST['mc_gross'];
    $payment_currency = $_POST['mc_currency'];
    $txn_id = $_POST['txn_id'];
    $receiver_email = $_POST['receiver_email'];
    $payer_email = $_POST['payer_email'];
    if ($payment_status == 'Completed') {
      watchdog('webform_paypal', "PayPal IPN success verification %id", array("%id" => $txn_id));
      return TRUE;
    }
    else {
      watchdog('webform_paypal', "PayPal IPN FAIL verification %id (not Completed)", array("%id" => $txn_id));
    }
  }

  watchdog('webform_paypal', "PayPal IPN success FAIL (Not verified) - %msg", array("%msg" => $res));
  return FALSE;
}

1 个答案:

答案 0 :(得分:2)

首先,您似乎正在使用带有webform_conditional模块的Webform 3。我建议您升级到包含webform_conditional的Webform 4,并在同一页面上的组件上工作。 Webform 4相当稳定,我个人认为它比webform 3 + webform_conditional更稳定。

其次,最好是创建一个新的webform_paypal组件,而不是改变分页符组件,因为它可能会破坏其他内容。例如,webform_paypal module是您添加/编辑代码的良好开端。

不幸的是,webform_paypal模块开箱即用,既没有分页符也没有Webform 3和4的条件:https://drupal.org/node/1413182。 我甚至试图将webform_paypal组件放在一个字段集中,并在字段集上设置条件但是失败了。

对不起,我无法帮助更多。我希望我提供的一些小信息能让你朝着正确的方向前进。