Commit aa6ded5a authored by jsacksick's avatar jsacksick

Issue #3043109 by jsacksick: Complete the 'shortcut' flow implementation.

parent 1e9298f6
<?php
/**
* @file
* Remove variables required by Commerce PayPal Checkout.
*/
/**
* Implements hook_uninstall().
*/
function commerce_paypal_checkout_uninstall() {
variable_del('commerce_paypal_checkout_review_embedded_panes');
}
......@@ -41,6 +41,73 @@ function commerce_paypal_checkout_method_instance_load($rule_name) {
return commerce_payment_method_instance_load("paypal_checkout|$rule_name");
}
/**
* Implements hook_commerce_checkout_page_info().
*/
function commerce_paypal_checkout_commerce_checkout_page_info() {
$checkout_pages = array();
$checkout_pages['paypal_checkout'] = array(
'title' => t('Confirm order'),
'help' => t('Confirm your order information and use the button at the bottom of the page to finalize your payment.'),
'status_cart' => FALSE,
'locked' => TRUE,
'buttons' => FALSE,
'weight' => 30,
);
return $checkout_pages;
}
/**
* Implements hook_commerce_checkout_pane_info().
*/
function commerce_paypal_checkout_commerce_checkout_pane_info() {
$checkout_panes = array();
$checkout_panes['paypal_checkout_review'] = array(
'title' => t('Review and confirm your order'),
'name' => t('PayPal Checkout review and confirm (only to be used on the confirm order page)'),
'file' => 'includes/commerce_paypal_checkout.checkout_pane.inc',
'base' => 'commerce_paypal_checkout_review_pane',
'page' => 'paypal_checkout',
'fieldset' => FALSE,
);
return $checkout_panes;
}
/**
* Implements hook_commerce_checkout_router().
*/
function commerce_paypal_checkout_commerce_checkout_router($order, $checkout_page) {
// If the current page is the PayPal Checkout page but the current order did
// not use the shortcut Checkout flow...
if ($checkout_page['page_id'] == 'paypal_checkout' &&
(empty($order->data['commerce_paypal_checkout']['flow']) || $order->data['commerce_paypal_checkout']['flow'] != 'shortcut')) {
// Update the order status to the next checkout page.
$next_page = $checkout_page['next_page'];
$order = commerce_order_status_update($order, 'checkout_' . $next_page, FALSE, FALSE);
// Inform modules of checkout completion if the next page is Completed.
if ($next_page == 'complete') {
commerce_checkout_complete($order);
}
// Redirect to the URL for the new checkout page.
$target_uri = commerce_checkout_order_uri($order);
return drupal_goto($target_uri);
}
}
/**
* Returns the checkout pane IDs of checkout panes that should be embedded in
* the PayPal Checkout review and confirm page.
*/
function commerce_paypal_checkout_embedded_checkout_panes() {
return array_filter(variable_get('commerce_paypal_checkout_review_embedded_panes', array()));
}
/**
* Implements hook_commerce_payment_method_info().
*/
......@@ -828,3 +895,42 @@ function commerce_paypal_checkout_customer_profile($order, $profile_type, $paypa
$order_wrapper->save();
}
}
/**
* Update the PayPal order.
*
* @param $order
* The order.
* @param $payment_method
* The payment method instance.
*
* @return bool
* TRUE if the update was successful, FALSE otherwise.
*
* @see commerce_paypal_checkout_review_pane_checkout_form_submit()
*/
function commerce_paypal_checkout_update_order($order, $payment_method) {
if (!isset($order->data['commerce_paypal_checkout']['remote_id'])) {
return FALSE;
}
$remote_id = $order->data['commerce_paypal_checkout']['remote_id'];
$request_body = commerce_paypal_checkout_prepare_order_request($order, $payment_method['settings']);
$update_params = array(
array(
'op' => 'replace',
'path' => "/purchase_units/@reference_id=='default'",
'value' => $request_body['purchase_units'][0],
),
);
$api_client = commerce_paypal_checkout_api_client($payment_method['settings']);
try {
$api_client->updateOrder($remote_id, $update_params);
// Assume the update worked if we ended up here, if the update failed,
// an exception was thrown.
return TRUE;
}
catch (\Exception $exception) {
watchdog_exception('commerce_paypal_checkout', $exception);
return FALSE;
}
}
<?php
/**
* @file
* Checkout pane callback functions for the PayPal Checkout module.
*/
/**
* Checkout pane callback: returns the PayPal Checkout pane's settings form.
*/
function commerce_paypal_checkout_review_pane_settings_form() {
$form = array();
// List the core checkout panes to exclude from the review and confirm page.
$excluded_panes = array(
'account',
'cart_contents',
'commerce_payment',
'commerce_payment_redirect',
'checkout_review',
'checkout_completion_message',
'paypal_ec_review',
'paypal_checkout_review',
);
// Create a list of checkout panes that may be included on the PayPal Checkout
// review and order page. All core Commerce panes listed above and all panes
// defined by the Customer module will be excluded.
$options = array();
foreach (commerce_checkout_panes() as $pane_id => $checkout_pane) {
if (!in_array($pane_id, $excluded_panes) && $checkout_pane['module'] != 'commerce_customer' ) {
$options[$pane_id] = check_plain($checkout_pane['name']);
}
}
// If we have available checkout panes for this page...
if (!empty($options)) {
// Allow the administrator to choose which panes the customer should see
// upon returning from PayPal Checkout.
$form['commerce_paypal_checkout_review_embedded_panes'] = array(
'#type' => 'checkboxes',
'#title' => t('Checkout panes to include on the PayPal Checkout review and confirm page'),
'#options' => $options,
'#default_value' => variable_get('commerce_paypal_checkout_review_embedded_panes', array()),
);
}
return $form;
}
/**
* Checkout pane callback: returns a pane allowing the customer to review the
* final details of the order and provide any final information required.
*/
function commerce_paypal_checkout_review_pane_checkout_form(&$form, &$form_state, $checkout_pane, $order) {
$form_state['build_info']['files']['pane'] = drupal_get_path('module', 'commerce_paypal_ec') . '/includes/commerce_paypal_checkout.checkout_pane.inc';
$form_state['order'] = $order;
// Adjust the weights of the help text and pane form to appear before the
// embedded checkout panes.
$form['help']['#weight'] = -10;
$pane_form = array(
'#weight' => -5,
);
// Duplicate the review checkout pane's contents.
$pane_form['review'] = array(
'#theme' => 'commerce_checkout_review',
'#data' => array(),
);
// Loop through all the pages before the review page...
foreach (commerce_checkout_pages() as $page_id => $checkout_page) {
// Exit the loop once the review page is reached.
if ($page_id == 'review') {
break;
}
// Loop through all the panes on the current page specifying review...
foreach (commerce_checkout_panes(array('page' => $page_id, 'enabled' => TRUE, 'review' => TRUE)) as $pane_id => $checkout_pane_local) {
// If the pane has a valid review callback...
if ($callback = commerce_checkout_pane_callback($checkout_pane_local, 'review')) {
// Get the review data for this pane.
$pane_data = $callback($form, $form_state, $checkout_pane_local, $order);
// Only display the pane if there is data in the pane.
if (!empty($pane_data)) {
// Add a row for it in the review data.
$pane_form['review']['#data'][$pane_id] = array(
'title' => $checkout_pane_local['title'],
'data' => $pane_data,
);
}
}
}
}
// Embed other specified checkout panes in this checkout pane.
foreach (commerce_paypal_checkout_embedded_checkout_panes() as $embedded_pane_id) {
$embedded_pane = commerce_checkout_pane_load($embedded_pane_id);
// If the checkout pane defines a checkout form callback...
if ($embedded_pane && $callback = commerce_checkout_pane_callback($embedded_pane, 'checkout_form')) {
// Get the form for the embedded checkout pane.
$embedded_pane_form = $callback($form, $form_state, $embedded_pane, $order);
// Embed it on this checkout pane if the form returned data.
if (!empty($embedded_pane_form)) {
$form[$embedded_pane_id] = array(
'#type' => $embedded_pane['fieldset'] ? 'fieldset' : 'container',
'#title' => check_plain($embedded_pane['title']),
'#collapsible' => $embedded_pane['collapsible'],
'#collapsed' => $embedded_pane['collapsed'],
'#attributes' => array('class' => array($embedded_pane_id)),
'#tree' => TRUE,
) + $embedded_pane_form;
}
}
}
$form['pay_now'] = array(
'#type' => 'submit',
'#value' => t('Pay Now'),
'#validate' => array('commerce_paypal_checkout_review_pane_checkout_form_validate'),
'#submit' => array('commerce_paypal_checkout_review_pane_checkout_form_submit'),
);
return $pane_form;
}
/**
* Validate handler for the PayPal Checkout review and confirm page.
*/
function commerce_paypal_checkout_review_pane_checkout_form_validate($form, &$form_state) {
$order = $form_state['order'];
$form_validate = TRUE;
// Loop through the enabled checkout panes included in this page to validate
// and submit them.
foreach (commerce_paypal_checkout_embedded_checkout_panes() as $embedded_pane_id) {
$embedded_pane_validate = TRUE;
// Load the checkout pane to find its checkout pane validate callback.
$embedded_checkout_pane = commerce_checkout_pane_load($embedded_pane_id);
// If it has a validate callback.
if ($callback = commerce_checkout_pane_callback($embedded_checkout_pane, 'checkout_form_validate')) {
// Give it a chance to process the submitted data.
$embedded_pane_validate &= $callback($form, $form_state, $embedded_checkout_pane, $order);
}
// Submit the pane if it validated.
if ($embedded_pane_validate && $callback = commerce_checkout_pane_callback($embedded_checkout_pane, 'checkout_form_submit')) {
$callback($form, $form_state, $embedded_checkout_pane, $order);
}
// A failed pane makes the form fail.
$form_validate &= $embedded_pane_validate;
}
// Save the updated order object.
commerce_order_save($order);
// If a pane failed validation or the form state has otherwise been altered to
// initiate a rebuild, return without moving to the next checkout page.
if (!$form_validate || $form_state['rebuild']) {
$form_state['rebuild'] = TRUE;
}
}
/**
* Submit handler for the PayPal Checkout review and confirm page.
*/
function commerce_paypal_checkout_review_pane_checkout_form_submit($form, &$form_state) {
$order = $form_state['order'];
$payment_method = commerce_payment_method_instance_load($order->data['payment_method']);
// Update the order in PayPal to make sure it reflects the current state of
// the order in Drupal.
// If the order could not be updated in PayPal, stop here.
if (!commerce_paypal_checkout_update_order($order, $payment_method)) {
drupal_set_message(t('We could not complete your payment with PayPal. Please try again or contact us if the problem persists.'), 'error');
watchdog('commerce_paypal_checkout', 'Could not update the PayPal order for order @order_number.', array('@order_number' => $order->order_number), WATCHDOG_ERROR);
return;
}
// Attempt to process the payment.
if (commerce_paypal_checkout_do_payment($order, $payment_method)) {
// Proceed to the next page if it succeeded.
$order_status = commerce_order_status_load($order->status);
$checkout_page = commerce_checkout_page_load($order_status['checkout_page']);
$next_page = $checkout_page['next_page'];
// Update the order status to the next checkout page.
$order = commerce_order_status_update($order, 'checkout_' . $next_page, FALSE, FALSE);
// Inform modules of checkout completion if the next page is completed.
if ($next_page == 'complete') {
commerce_checkout_complete($order);
}
// Redirect to the URL for the new checkout page.
$form_state['redirect'] = commerce_checkout_order_uri($order);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment