Skip to content
Snippets Groups Projects
Commit ebf13d61 authored by mattwire's avatar mattwire
Browse files

Change the way we assign fields

parent a449d079
Branches
Tags
No related merge requests found
......@@ -202,24 +202,124 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
return $return;
}
/**
* Override CRM_Core_Payment function
*/
public function getPaymentFormFields() {
return array(
'credit_card_type',
'credit_card_number',
'cvv2',
'credit_card_exp_date',
'stripe_token',
'stripe_pub_key',
'stripe_id',
);
}
/**
* Return an array of all the details about the fields potentially required for payment fields.
*
* Only those determined by getPaymentFormFields will actually be assigned to the form
*
* @return array
* field metadata
*/
public function getPaymentFormFieldsMetadata() {
$creditCardType = array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::creditCard();
return array(
'credit_card_number' => array(
'htmlType' => 'text',
'name' => 'credit_card_number',
'title' => ts('Card Number'),
'cc_field' => TRUE,
'attributes' => array(
'size' => 20,
'maxlength' => 20,
'autocomplete' => 'off',
),
'is_required' => TRUE,
),
'cvv2' => array(
'htmlType' => 'text',
'name' => 'cvv2',
'title' => ts('Security Code'),
'cc_field' => TRUE,
'attributes' => array(
'size' => 5,
'maxlength' => 10,
'autocomplete' => 'off',
),
'is_required' => TRUE,
),
'credit_card_exp_date' => array(
'htmlType' => 'date',
'name' => 'credit_card_exp_date',
'title' => ts('Expiration Date'),
'cc_field' => TRUE,
'attributes' => CRM_Core_SelectValues::date('creditCard'),
'is_required' => TRUE,
'month_field' => 'credit_card_exp_date_M',
'year_field' => 'credit_card_exp_date_Y',
),
'credit_card_type' => array(
'htmlType' => 'select',
'name' => 'credit_card_type',
'title' => ts('Card Type'),
'cc_field' => TRUE,
'attributes' => $creditCardType,
'is_required' => FALSE,
),
'stripe_token' => array(
'htmlType' => 'hidden',
'name' => 'stripe_token',
'title' => 'Stripe Token',
'attributes' => array(
'id' => 'stripe-token',
),
'cc_field' => TRUE,
'is_required' => TRUE,
),
'stripe_id' => array(
'htmlType' => 'hidden',
'name' => 'stripe_id',
'title' => 'Stripe ID',
'attributes' => array(
'id' => 'stripe-id',
),
'cc_field' => TRUE,
'is_required' => TRUE,
),
'stripe_pub_key' => array(
'htmlType' => 'hidden',
'name' => 'stripe_pub_key',
'title' => 'Stripe Public Key',
'attributes' => array(
'id' => 'stripe-pub-key',
),
'cc_field' => TRUE,
'is_required' => TRUE,
),
);
}
/**
* Implementation of hook_civicrm_buildForm().
*
* @param $form - reference to the form object
*/
public function buildForm(&$form) {
$stripe_ppid = CRM_Utils_Array::value('id', $form->_paymentProcessor);
// Add the ID to our form so our js can tell if Stripe has been selected.
$form->addElement('hidden', 'stripe_id', $stripe_ppid, array('id' => 'stripe-id'));
if ($form->isSubmitted()) return;
$stripe_ppid = CRM_Utils_Array::value('id', $form->_paymentProcessor);
$stripe_key = self::stripe_get_key($stripe_ppid);
$form->addElement('hidden', 'stripe_pub_key', $stripe_key, array('id' => 'stripe-pub-key'));
// Add email field as it would usually be found on donation forms.
if (!isset($form->_elementIndex['email']) && !empty($form->userEmail)) {
$form->addElement('hidden', 'email', $form->userEmail, array('id' => 'user-email'));
}
// Set ddi_reference
$defaults = array();
$defaults['stripe_id'] = $stripe_ppid;
$defaults['stripe_pub_key'] = $stripe_key;
$form->setDefaults($defaults);
}
/**
......@@ -290,13 +390,15 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
$amount = (int) preg_replace('/[^\d]/', '', strval($amount));
// Use Stripe.js instead of raw card details.
// Token is appended after nulled credit card number
if (!empty($params['credit_card_number']) && (substr($params['credit_card_number'], 16, 4) === 'tok_')) {
$card_details = substr($params['credit_card_number'], 16);
$params['credit_card_number'] = '';
if (!empty($params['stripe_token'])) {
$card_token = $params['stripe_token'];
}
else if(!empty(CRM_Utils_Array::value('stripe_token', $_POST, NULL))) {
$card_token = CRM_Utils_Array::value('stripe_token', $_POST, NULL);
}
else {
CRM_Core_Error::fatal(ts('Stripe.js token was not passed! Report this message to the site administrator.'));
CRM_Core_Error::statusBounce(ts('Unable to complete payment! Please this to the site administrator with a description of what you were trying to do.'));
Civi::log()->debug('Stripe.js token was not passed! Report this message to the site administrator. $params: ' . print_r($params, TRUE));
}
// Check for existing customer, create new otherwise.
......@@ -387,7 +489,7 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
if (!isset($customer_query)) {
$sc_create_params = array(
'description' => 'Donor from CiviCRM',
'card' => $card_details,
'card' => $card_token,
'email' => $email,
);
......@@ -428,7 +530,7 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
// coming through for the 2nd time. Don't need to update customer again.
}
else {
$stripe_customer->card = $card_details;
$stripe_customer->card = $card_token;
$response = $this->stripeCatchErrors('save', $stripe_customer, $params);
if (isset($response) && $this->isErrorReturn($response)) {
return $response;
......@@ -440,7 +542,7 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
// retrieved from Stripe. Was he deleted?
$sc_create_params = array(
'description' => 'Donor from CiviCRM',
'card' => $card_details,
'card' => $card_token,
'email' => $email,
);
......@@ -498,7 +600,7 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
$stripe_charge['customer'] = $stripe_customer->id;
}
else {
$stripe_charge['card'] = $card_details;
$stripe_charge['card'] = $card_token;
}
// Handle recurring payments in doRecurPayment().
......
......@@ -4,11 +4,14 @@
*/
(function($, CRM) {
var $form, $submit, buttonText;
var isWebform = false;
var buttonText;
var stripeFormSubmitted = false;
// Response from Stripe.createToken.
function stripeResponseHandler(status, response) {
$form = getBillingForm();
$submit = getBillingSubmit();
if (response.error) {
$('html, body').animate({scrollTop: 0}, 300);
// Show the errors on the form.
......@@ -23,17 +26,17 @@
+ '</ul>'
+ '</div>');
$submit.removeAttr('disabled').attr('value', buttonText);
stripeFormSubmitted = false;
$submit.prop('disabled', false).attr('value', buttonText);
}
else {
var token = response['id'];
// Update form with the token & submit.
copyCCDetails($form);
// copyCCDetails($form);
removeCCDetails($form);
// We use the credit_card_number field to pass token as this is reliable.
// Inserting an input field is unreliable on ajax forms and often gets missed from POST request for some reason.
var ccNum = $form.find("input#credit_card_number").val();
$form.find("input#credit_card_number").val(ccNum + token);
$form.find("input#stripe-token").val(token);
// Disable unload event handler
window.onbeforeunload = null;
......@@ -47,14 +50,11 @@
loadStripeBillingBlock();
});
// On the frontend, we have a set of radio buttons. Trigger on change.
$('input[name="payment_processor_id"]').change(function() {
loadStripeBillingBlock();
});
// On the backend, we have a select. Trigger on change.
$('select#payment_processor_id').change(function() {
loadStripeBillingBlock();
// Re-prep form when we've loaded a new payproc
$( document ).ajaxComplete(function( event, xhr, settings ) {
if (settings.url.match("/civicrm/payment/form?")) {
loadStripeBillingBlock();
}
});
function loadStripeBillingBlock() {
......@@ -67,33 +67,14 @@
}
}
if ($('.webform-client-form').length) {
isWebform = true;
}
// Get the form containing payment details
$form = CRM.$('input#stripe-pub-key').closest('form');
if (isWebform) {
$submit = $form.find('.button-primary');
}
else {
$submit = $form.find('input[type="submit"][formnovalidate!="1"]');
// If another submit button on the form is pressed (eg. apply discount)
// add a flag that we can set to stop payment submission
$form.data('submit-dont-process', '0');
// Find submit buttons with formnovalidate=1 and add an onclick handler to set flag
$form.find('input[type="submit"][formnovalidate="1"], input[type="submit"].cancel').click( function() {
$form.data('submit-dont-process', 1);
});
// Add a keypress handler to set flag if enter is pressed
$form.find('input#discountcode').keypress( function(e) {
if (e.which === 13) {
$form.data('submit-dont-process', 1);
}
});
$form = getBillingForm();
if (!$form) {
debugging('No billing form!');
return;
}
$submit = getBillingSubmit();
var isWebform = getIsWebform();
// For CiviCRM Webforms.
if (isWebform) {
......@@ -125,12 +106,22 @@
$form.unbind('submit');
// Intercept form submission.
$form.submit(function (event) {
$(document).on('submit', $form, function(event) {
event.preventDefault();
submit(event);
});
function submit(event) {
if (stripeFormSubmitted === true) {
debugging('already submitted');
return true;
}
stripeFormSubmitted = true;
$form = getBillingForm();
$submit = getBillingSubmit();
var isWebform = getIsWebform();
// Don't handle submits generated by non-stripe processors
if (!$('input#stripe-pub-key').length) {
debugging('submit missing stripe-pub-key element');
......@@ -138,7 +129,7 @@
}
// Don't handle submits generated by the CiviDiscount button.
if ($form.data('submit-dont-process') === 1) {
debugging('debug: pvjwy (Discount is in play)');
debugging('Discount is in play');
return true;
}
if (isWebform) {
......@@ -193,47 +184,71 @@
var cc_year = $form.find('#credit_card_exp_date_Y').val();
Stripe.card.createToken({
name: $form.find('#billing_first_name').val() + ' ' + $form.find('#billing_last_name').val(),
name: $form.find('#billing_first_name')
.val() + ' ' + $form.find('#billing_last_name').val(),
address_zip: $form.find('#billing_postal_code-5').val(),
number: $form.find('#credit_card_number').val(),
cvc: $form.find('#cvv2').val(),
exp_month: cc_month,
exp_year: cc_year
number: $form.find('#credit_card_number').val(),
cvc: $form.find('#cvv2').val(),
exp_month: cc_month,
exp_year: cc_year
}, stripeResponseHandler);
debugging('debug: Getting Stripe token');
return false;
}
}
}(cj, CRM));
function removeCCDetails($form) {
// Remove the "name" attribute so params are not submitted
var ccNumElement = $form.find("input#credit_card_number");
var cvv2Element = $form.find("input#cvv2");
var last4digits = ccNumElement.val().substr(12,16);
ccNumElement.val('000000000000' + last4digits);
cvv2Element.val('000');
}
function copyCCDetails($form) {
// Remove the "name" attribute so params are not submitted
var ccNumElement = $form.find("input#credit_card_number");
var cvv2Element = $form.find("input#cvv2");
var ccNum = ccNumElement.val();
var cvv2Num = cvv2Element.val();
var ccDummyElement = ccNumElement.clone();
var cvv2DummyElement = cvv2Element.clone();
ccNumElement.css('display', 'none');
cvv2Element.css('display', 'none');
ccDummyElement.removeAttr('name').removeAttr('id');
cvv2DummyElement.removeAttr('name').removeAttr('id');
ccDummyElement.insertAfter(ccNumElement);
cvv2DummyElement.insertAfter(cvv2Element);
}
function debugging (errorCode) {
// Uncomment the following to debug unexpected returns.
function getIsWebform() {
if ($('.webform-client-form').length) {
return true;
}
else {
return false;
}
}
function getBillingForm() {
return CRM.$('input#stripe-pub-key').closest('form');
}
function getBillingSubmit() {
$form = getBillingForm();
var isWebform = getIsWebform();
if (isWebform) {
$submit = $form.find('.button-primary');
}
else {
$submit = $form.find('input[type="submit"].validate');
// If another submit button on the form is pressed (eg. apply discount)
// add a flag that we can set to stop payment submission
$form.data('submit-dont-process', '0');
// Find submit buttons with formnovalidate=1 and add an onclick handler to set flag
$form.find('input[type="submit"][formnovalidate="1"], input[type="submit"].cancel').click( function() {
$form.data('submit-dont-process', 1);
});
// Add a keypress handler to set flag if enter is pressed
$form.find('input#discountcode').keypress( function(e) {
if (e.which === 13) {
$form.data('submit-dont-process', 1);
}
});
}
return $submit;
}
function removeCCDetails($form) {
// Remove the "name" attribute so params are not submitted
var ccNumElement = $form.find("input#credit_card_number");
var cvv2Element = $form.find("input#cvv2");
var last4digits = ccNumElement.val().substr(12,16);
ccNumElement.val('000000000000' + last4digits);
cvv2Element.val('000');
}
function debugging (errorCode) {
// Uncomment the following to debug unexpected returns.
console.log(errorCode);
}
}
}(cj, CRM));
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment