From 2ffa185fb99cec03fdcd3edaa6ee8404185a236e Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Thu, 21 Jul 2016 10:29:57 +1000 Subject: [PATCH] stripe initial test --- booking.module | 7 ++ booking.stripe.inc | 205 ++++++++++++++++++++++++++++++++++++++++++++- booking.stripe.js | 65 ++++++++++++++ 3 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 booking.stripe.js diff --git a/booking.module b/booking.module index 4ec3b10..6654ef1 100644 --- a/booking.module +++ b/booking.module @@ -245,6 +245,13 @@ function booking_menu() { 'access arguments' => array('access booking form'), 'type' => MENU_NORMAL_ITEM, ); + // @todo remove this after testing + $items['stripetest'] = array( + 'title' => $bookingTitle . ' Stripe Test', + 'page callback' => 'booking_stripeform_form', + 'access arguments' => array('access booking form'), + 'type' => MENU_NORMAL_ITEM, + ); $items['bookingfinal'] = array( 'title' => $bookingTitle . ' Registration Completed', 'page callback' => 'booking_payment_completed_page', diff --git a/booking.stripe.inc b/booking.stripe.inc index 79c1dbb..7b139f0 100644 --- a/booking.stripe.inc +++ b/booking.stripe.inc @@ -4,4 +4,207 @@ * @file * Functions for stripe payment integration * @see https://github.com/ericthelast/drupal-stripe-form and https://www.webomelette.com/drupal-stripe-integration - */ \ No newline at end of file + */ + + /** + * Get the current stripe api public key + */ +function _booking_get_stripe_public_key() { + if (variable_get('booking_stripe_testmode', 0) == 1) { + return variable_get('booking_stripe_test_public_key', ''); + } + else { + return variable_get('booking_stripe_live_public_key', ''); + } +} + +/** + * Get the current stripe api private key + */ +function _booking_get_stripe_private_key() { + if (variable_get('booking_stripe_testmode', 0) == 1) { + return variable_get('booking_stripe_test_secret_key', ''); + } + else { + return variable_get('booking_stripe_live_secret_key', ''); + } +} + +/** + * Sample Stripe Form. + */ +function booking_stripeform_form($form, &$form_state) { + + // Let's make sure you have the stripe library installed. + if($path = libraries_get_path('stripe-php-latest')) { + if(!is_file($path . '/lib/Stripe.php')) { + form_set_error('form', t('You need to install the stripe library from !link before you can use this form.', array('!link' => l('here', 'https://stripe.com/docs/libraries')))); + } + } else { + form_set_error('form', t('You need to install the stripe library from !link before you can use this form.', array('!link' => l('here', 'https://stripe.com/docs/libraries')))); + } + + $setting = array(); + $setting['booking_stripeform'] = array( + 'pubkey' => _booking_get_stripe_public_key(), + 'form_selector' => str_replace('_', '-', __FUNCTION__), + ); + + $form['#attached'] = array( + 'js' => array( + array('data' => $setting, 'type' => 'setting'), + ), + 'library' => array( + array('booking', 'booking.stripe'), + ), + ); + + $form['stripeToken'] = array( + '#type' => 'hidden', + '#value' => !empty($form_state['input']['stripeToken']) ? $form_state['input']['stripeToken'] : NULL, + ); + + $form['amount'] = array( + '#type' => 'textfield', + '#title' => t('Amount to charge'), + '#description' => t('NOTE: Normally, you would calculate amount on the back end unless the user really can choose their own amount'), + '#size' => 6, + '#required' => TRUE, + ); + + $form['credit_card'] = array( + '#type' => 'fieldset', + '#title' => t('Credit Card Information'), + ); + + $cc = &$form['credit_card']; + + $cc['card_number'] = array( + '#type' => 'textfield', + '#title' => t('Credit Card Number'), + '#pre_render' => array('booking_stripeform_remove_name'), + '#attributes' => array( + 'size' => 20, + 'data-stripe' => 'number', + ), + ); + + $cc['exp_month'] = array( + '#type' => 'select', + '#title' => t('Expiration Month'), + '#options' => drupal_map_assoc(array(1,2,3,4,5,6,7,8,9,10,11,12)), + '#pre_render' => array('booking_stripeform_remove_name'), + '#attributes' => array( + 'data-stripe' => 'exp-month', + ), + '#empty_option' => t('- Select -'), + ); + + $cc['exp_year'] = array( + '#type' => 'select', + '#title' => t('Expiration Year'), + '#options' => array(), + '#pre_render' => array('booking_stripeform_remove_name'), + '#attributes' => array( + 'data-stripe' => 'exp-year', + ), + '#empty_option' => t('- Select -'), + ); + + $year = date('Y'); + for($i = $year; $i <= ($year + 10); $i++) { + $cc['exp_year']['#options'][$i] = $i; + } + + $cc['cvc'] = array( + '#type' => 'textfield', + '#title' => t('CVC Number'), + '#pre_render' => array('booking_stripeform_remove_name'), + '#attributes' => array( + 'size' => 4, + 'data-stripe' => 'cvc', + ), + ); + + $cc['submit'] = array( + '#type' => 'submit', + '#value' => t('Charge It'), + '#attributes' => array( + 'class' => array('btn', 'btn-large', 'btn-primary'), + ), + ); + + // Adds our validation at the end of the build process. + $form['#after_build'][] = 'booking_stripeform_add_final_validation'; + + return $form; +} + +/** + * Tries to add final validation after all else has been added through alters. + */ +function booking_stripeform_add_final_validation($form) { + $form['#validate'][] = 'stripeform_validate_form_payment'; + return $form; +} + +/** + * Form validation callback. + */ +function booking_stripeform_checkout_form_validate($form, &$form_state) { + // Validate normal form elements as needed. +} + +/** + * Processes the stripe payment. + * + * We do this here so that if the payment fails, + * we're still in a validation stage and can return + * early. If success, we'll pass the charge on + * to the submission callback. + */ +function booking_stripeform_validate_form_payment($form, &$form_state) { + if($errors = form_get_errors()) { + return; + } + $path = libraries_get_path('stripe-php-latest'); + require_once($path . '/lib/Stripe.php'); + + Stripe::setApiKey(STRIPEFORM_PRIVATE_KEY); + + $token = $form_state['values']['stripeToken']; + $amount = $form_state['values']['amount'] * 100; + + // Create the charge on Stripe's servers - this will charge the user's card + try { + $charge = Stripe_Charge::create(array( + "amount" => $amount, + "currency" => "usd", + "card" => $token, + "description" => 'test charge', + )); + + $form_state['stripeform_charge'] = $charge; + } catch(Stripe_CardError $e) { + // The card has been declined + watchdog('stripeform', $e->getMessage()); + form_set_error('form', $e->getMessage()); + } +} + +/** + * Form submission handler. + */ +function booking_stripeform_form_submit($form, &$form_state) { + drupal_set_message('Charge successful!'); +} + +/** + * FAPI #pre_render callback. + * + * Removes the name field form a form element. + */ +function booking_stripeform_remove_name($element) { + unset($element['#name']); + return $element; +} \ No newline at end of file diff --git a/booking.stripe.js b/booking.stripe.js new file mode 100644 index 0000000..efe3b7e --- /dev/null +++ b/booking.stripe.js @@ -0,0 +1,65 @@ +(function($) { + $(function() { + Stripe.setPublishableKey(Drupal.settings.booking_stripeform.pubkey); + }); + Drupal.behaviors.booking_stripeform = { + attach: function(context, settings) { + $("#" + settings.booking_stripeform.form_selector, context).submit(function(e) { + e.preventDefault(); + var $form = $(this); + var $obj; + var $submitBtn = $("#edit-submit", context); + settings.booking_stripeform.submitBtnText = $submitBtn.val(); + try { + var $ccnum = $(':input[data-stripe="number"]', $form); + var $exp_month = $(':input[data-stripe="exp-month"]', $form); + var $exp_year = $(':input[data-stripe="exp-year"]', $form); + var $cvc = $(':input[data-stripe="cvc"]', $form); + if(!Stripe.card.validateCardNumber($(':input[data-stripe="number"]', $form).val())) { + $obj = $ccnum; + throw "Invalid credit card number"; + } + if(!Stripe.card.validateExpiry($exp_month.val(), $exp_year.val())) { + $obj = $exp_month; + throw "Invalid expiration month/year"; + } + if(!Stripe.card.validateCVC($cvc.val())) { + $obj = $cvc; + throw "Invalid CVC"; + } + } catch(err) { + $.each([$ccnum, $exp_month, $exp_year, $cvc], function(i, e) { + e.addClass('error'); + }); + $obj.parents('div.control-group').toggleClass('error'); + reportError(err, $obj); + return false; + } + $submitBtn.val('Please wait...').attr('disabled', true); + Stripe.createToken($form, stripeResponseHandler); + return false; + }); + } + } + + var stripeResponseHandler = function(status, response) { + var $form = $("#" + Drupal.settings.booking_stripeform.form_selector); + if (response.error) { + alert(response.error.message); + } else { + // token contains id, last4, and card type + var token = response.id; + // Insert the token into the form so it gets submitted to the server + $('input[name=stripeToken]', $form).val(token); + // and submit + $form.get(0).submit(); + } + }; + + /** + * Uses Bootstrap's popover to alert the user. + */ + function reportError(msg, $el) { + console.log([$el, msg]); + } +}(jQuery)); \ No newline at end of file