2014-01-20 6 views
2

Я новичок в Drupal, проведший большую часть своего времени с Joomla! У меня есть сайт Drupal 7, который использует компонент веб-формы. Это шаги определяется как:Как пропустить перерыв страницы

Steps in the form:

Теперь компонент разрыв страницы выглядит следующим образом:

Registration Break Settings

Если я понимаю вещи правильно после заполнения Gomez в Купонный текстовом поле (я добавил) перерыв не должен происходить, и пользователь должен перейти на следующую страницу. Однако это не так, и пользователь должен пройти через PayPal.

Я хочу, чтобы пользователь вводил код купона, и шаг PayPal пропускается, и пользователь может заполнить форму. Похоже, это возможно с помощью webform_paypal_permission() Любые идеи?

Я счастлив, если мне нужно изменить PHP-код, но я хочу, чтобы избежать его, если я могу и вместо этого использовать функциональность, которая, я считаю, есть.

Я также включают в себя ниже PHP, который используется для стадии PayPal в случае, если это использовать для отладки это:

<?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; 
} 

ответ

2

Прежде всего, это, кажется, вы используете WebForm 3 с webform_conditional модулем. Я советую вам перейти на Webform 4, на который встроен webform_conditional, и работать с компонентами на одной странице. Webform 4 довольно стабилен, и лично я считаю, что он более стабилен, чем webform 3 + webform_conditional.

Во-вторых, может быть лучше создать новый компонент webform_paypal вместо изменения компонента разрыва страницы, поскольку он может сломать что-то еще. Например, есть webform_paypal module, который является хорошим началом для добавления/изменения кода.

К сожалению, модуль webform_paypal не работает из коробки без разрывов страниц и с условиями как с Webform 3, так и с 4: https://drupal.org/node/1413182. Я даже попытался поместить компонент webform_paypal в набор полей и установить условие в наборе полей, но неудачно провалился.

Прошу прощения, я не могу больше помочь. Я надеюсь, что небольшая информация, которую я предоставил, поставит вас в правильном направлении.

+0

Спасибо за указатели. У меня есть +1 ваш ответ, чтобы вы получили часть награды, поскольку, к сожалению, она не решила мою проблему напрямую. – TheEdge

+0

@ TheEdge Мне очень хотелось бы, чтобы я помог вам больше. Или, может быть, кому-то еще на StackOverflow на пути к ответу. – grim

Смежные вопросы