stripe.php 8.89 KB
Newer Older
1 2 3 4 5
<?php

require_once 'stripe.civix.php';

/**
6
 * Implementation of hook_civicrm_config().
7 8 9
 */
function stripe_civicrm_config(&$config) {
  _stripe_civix_civicrm_config($config);
Eileen McNaughton's avatar
Eileen McNaughton committed
10 11 12
  $extRoot = dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'packages' . DIRECTORY_SEPARATOR;
  $include_path = $extRoot . PATH_SEPARATOR . get_include_path( );
  set_include_path( $include_path );
13 14 15
}

/**
16
 * Implementation of hook_civicrm_xmlMenu().
17 18 19 20 21 22 23 24
 *
 * @param $files array(string)
 */
function stripe_civicrm_xmlMenu(&$files) {
  _stripe_civix_civicrm_xmlMenu($files);
}

/**
25
 * Implementation of hook_civicrm_install().
26 27
 */
function stripe_civicrm_install() {
28
  // Create required tables for Stripe.
29 30
  require_once "CRM/Core/DAO.php";
  CRM_Core_DAO::executeQuery("
31 32 33
  CREATE TABLE IF NOT EXISTS `civicrm_stripe_customers` (
    `email` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
    `id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
34
    `is_live` tinyint(4) NOT NULL COMMENT 'Whether this is a live or test transaction',
35
    UNIQUE KEY `id` (`id`)
36 37
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
  ");
38

39
  CRM_Core_DAO::executeQuery("
40 41
  CREATE TABLE IF NOT EXISTS `civicrm_stripe_plans` (
    `plan_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
42
    `is_live` tinyint(4) NOT NULL COMMENT 'Whether this is a live or test transaction',
43 44 45
    UNIQUE KEY `plan_id` (`plan_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
  ");
46 47

  CRM_Core_DAO::executeQuery("
48 49 50 51 52 53 54 55
  CREATE TABLE IF NOT EXISTS `civicrm_stripe_subscriptions` (
    `customer_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
    `invoice_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
    `end_time` int(11) NOT NULL DEFAULT '0',
    `is_live` tinyint(4) NOT NULL COMMENT 'Whether this is a live or test transaction',
    KEY `end_time` (`end_time`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
  ");
56 57 58 59 60

  return _stripe_civix_civicrm_install();
}

/**
61
 * Implementation of hook_civicrm_uninstall().
62 63
 */
function stripe_civicrm_uninstall() {
64
  // Remove Stripe tables on uninstall.
65 66 67 68
  require_once "CRM/Core/DAO.php";
  CRM_Core_DAO::executeQuery("DROP TABLE civicrm_stripe_customers");
  CRM_Core_DAO::executeQuery("DROP TABLE civicrm_stripe_plans");
  CRM_Core_DAO::executeQuery("DROP TABLE civicrm_stripe_subscriptions");
69

70 71 72 73
  return _stripe_civix_civicrm_uninstall();
}

/**
74
 * Implementation of hook_civicrm_enable().
75 76
 */
function stripe_civicrm_enable() {
77 78 79 80 81 82 83 84 85 86 87
  $UF_webhook_paths = array(
    "Drupal"    => "/civicrm/stripe/webhook",
    "Drupal6"   => "/civicrm/stripe/webhook",
    "Joomla"    => "/index.php/component/civicrm/?task=civicrm/stripe/webhook",
    "WordPress" => "/?page=CiviCRM&q=civicrm/stripe/webhook"
  );
  // Use Drupal path as default if the UF isn't in the map above
  $webookhook_path = (array_key_exists(CIVICRM_UF, $UF_webhook_paths)) ?
    CIVICRM_UF_BASEURL . $UF_webhook_paths[CIVICRM_UF] :
    CIVICRM_UF_BASEURL . "civicrm/stripe/webhook";

88 89
  CRM_Core_Session::setStatus("Stripe Payment Processor Message:
    <br />Don't forget to set up Webhooks in Stripe so that recurring contributions are ended!
90
    <br />Webhook path to enter in Stripe:<br/><em>$webookhook_path</em>
91 92
    <br />");

93 94 95 96
  return _stripe_civix_civicrm_enable();
}

/**
97
 * Implementation of hook_civicrm_disable().
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
 */
function stripe_civicrm_disable() {
  return _stripe_civix_civicrm_disable();
}

/**
 * Implementation of hook_civicrm_upgrade
 *
 * @param $op string, the type of operation being performed; 'check' or 'enqueue'
 * @param $queue CRM_Queue_Queue, (for 'enqueue') the modifiable list of pending up upgrade tasks
 *
 * @return mixed  based on op. for 'check', returns array(boolean) (TRUE if upgrades are pending)
 *                for 'enqueue', returns void
 */
function stripe_civicrm_upgrade($op, CRM_Queue_Queue $queue = NULL) {
  return _stripe_civix_civicrm_upgrade($op, $queue);
}

116 117 118 119 120 121 122 123 124 125 126 127
/**
 * Implementation of hook_civicrm_validateForm().
 *
 * Prevent server validation of cc fields
 *
 * @param $formName - the name of the form
 * @param $fields - Array of name value pairs for all 'POST'ed form values
 * @param $files - Array of file properties as sent by PHP POST protocol
 * @param $form - reference to the form object
 * @param $errors - Reference to the errors array.
 */
function stripe_civicrm_validateForm($formName, &$fields, &$files, &$form, &$errors) {
128 129 130 131 132 133
  if (empty($form->_paymentProcessor['payment_processor_type'])) {
    return;
  }
  // If Stripe is active here.
  if (isset($form->_elementIndex['stripe_token'])) {
    if ($form->elementExists('credit_card_number')) {
134 135 136
      $cc_field = $form->getElement('credit_card_number');
      $form->removeElement('credit_card_number', true);
      $form->addElement($cc_field);
137
    }
138
    if ($form->elementExists('cvv2')) {
139 140 141
      $cvv2_field = $form->getElement('cvv2');
      $form->removeElement('cvv2', true);
      $form->addElement($cvv2_field);
142 143 144 145
    }
  }
}

146 147
/**
 * Implementation of hook_civicrm_buildForm().
148
 *
149 150 151 152
 * @param $formName - the name of the form
 * @param $form - reference to the form object
 */
function stripe_civicrm_buildForm($formName, &$form) {
153
  $stripe_key = stripe_get_key($form);
154 155 156
  // If this is not a form Stripe is involved in, do nothing.
  if (empty($stripe_key)) {
    return;
157
  }
158 159 160 161 162 163
  $params = $form->get('params');
  // Contrib forms store this in $params, Event forms in $params[0].
  if (!empty($params[0]['stripe_token'])) {
    $params = $params[0];
  }
  $stripe_token = (empty($params['stripe_token']) ? NULL : $params['stripe_token']);
164

165 166 167 168 169 170 171 172 173 174
  // Add some hidden fields for Stripe.
  if (!$form->elementExists('stripe_token')) {
    $form->setAttribute('class', $form->getAttribute('class') . ' stripe-payment-form');
    $form->addElement('hidden', 'stripe_token', $stripe_token, array('id' => 'stripe-token'));
  }
  stripe_add_stripe_js($stripe_key, $form);

  // 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'));
175 176 177 178
  }
}

/**
179
 * Return the stripe api public key (aka password)
180 181 182
 *
 * If this form could conceiveably now or at any time in the future
 * contain a Stripe payment processor, return the api public key for
183
 * that processor.
184
 */
185
function stripe_get_key($form) {
186 187 188 189 190
  // Only return first value if Stripe is the only/default.
  if ($form->_paymentProcessor['payment_processor_type'] == 'Stripe') {
    if (isset($form->_paymentProcessor['password'])) {
      return $form->_paymentProcessor['password'];
    }
191
  }
192 193

  // Otherwise we need to look through all active payprocs and find Stripe.
194
  $is_test = 0;
195
  if (isset($form->_mode)) {
196
    $is_test = $form->_mode == 'live' ? 0 : 1;
197 198
  }

199 200 201 202 203 204 205 206
  // The _paymentProcessors array seems to be the most reliable way to find
  // if the form is using Stripe.
  if (!empty($form->_paymentProcessors)) {
    foreach ($form->_paymentProcessors as $pp) {
      if ($pp['payment_processor_type'] == 'Stripe') {
        if (!empty($pp['password'])) {
          return $pp['password'];
        }
207 208
        // We have a match.
        return stripe_get_key_for_name($pp['name'], $is_test);
209
      }
210
    }
211
  }
212 213
  // Return NULL if this is not a form with Stripe involved.
  return NULL;
214 215 216 217 218 219 220 221 222
}

/**
 * Given a payment processor name, return the pub key.
 */
function stripe_get_key_for_name($name, $is_test) {
  try {
    $params = array('name' => $name, 'is_test' => $is_test);
    $results = civicrm_api3('PaymentProcessor', 'get', $params);
223
    if ($results['count'] == 1) {
224 225 226 227 228
      $result = array_pop($results['values']);
      return $result['password'];
    }
  }
  catch (CiviCRM_API3_Exception $e) {
229
    return NULL;
230 231
  }
}
232

233 234 235 236 237
/**
 * Add publishable key and event bindings for Stripe.js.
 */
function stripe_add_stripe_js($stripe_key, $form) {
  $form->addElement('hidden', 'stripe_pub_key', $stripe_key, array('id' => 'stripe-pub-key'));
238
  CRM_Core_Resources::singleton()->addScriptFile('com.drastikbydesign.stripe', 'js/civicrm_stripe.js', 0);
239 240 241
}

/**
242
 * Implementation of hook_civicrm_managed().
243 244 245 246 247 248
 *
 * Generate a list of entities to create/deactivate/delete when this module
 * is installed, disabled, uninstalled.
 */
function stripe_civicrm_managed(&$entities) {
  $entities[] = array(
249 250 251 252 253
    'module' => 'com.drastikbydesign.stripe',
    'name' => 'Stripe',
    'entity' => 'PaymentProcessorType',
    'params' => array(
      'version' => 3,
254 255 256 257 258 259 260
      'name' => 'Stripe',
      'title' => 'Stripe',
      'description' => 'Stripe Payment Processor',
      'class_name' => 'Payment_Stripe',
      'billing_mode' => 'form',
      'user_name_label' => 'Secret Key',
      'password_label' => 'Publishable Key',
261 262 263 264
      'url_site_default' => 'https://api.stripe.com/v2',
      'url_recur_default' => 'https://api.stripe.com/v2',
      'url_site_test_default' => 'https://api.stripe.com/v2',
      'url_recur_test_default' => 'https://api.stripe.com/v2',
265
      'is_recur' => 1,
266 267 268
      'payment_type' => 1
    ),
  );
269

270 271
  return _stripe_civix_civicrm_managed($entities);
}