From 4c6f28ddcd357ee14c34d2b5f2e0d4131bd4cc07 Mon Sep 17 00:00:00 2001 From: drastik <jwjoshuawalker@gmail.com> Date: Sat, 11 Aug 2012 13:46:28 -0700 Subject: [PATCH] Cron ready. Branched for source vs extension installs --- README.txt | 67 +++- .../CRM/Core/BillingBlock.tpl | 0 .../info.xml | 36 +++ .../stripe.php | 287 ++++++++++++++++++ .../extern/civicrm_stripe_cron_live.php | 36 +++ .../extern/civicrm_stripe_cron_test.php | 36 +++ {CRM => source/CRM}/Core/Payment/Stripe.php | 0 .../civicrm_stripe.sql | 0 .../CRM/Core/BillingBlock.tpl | 221 ++++++++++++++ source/extern/civicrm_stripe_cron_live.php | 36 +++ source/extern/civicrm_stripe_cron_test.php | 36 +++ 11 files changed, 742 insertions(+), 13 deletions(-) rename {civicrm_templates => extension-4.1/civicrm_templates}/CRM/Core/BillingBlock.tpl (100%) create mode 100644 extension-4.1/com.drastikbydesign.payment.stripe/info.xml create mode 100644 extension-4.1/com.drastikbydesign.payment.stripe/stripe.php create mode 100644 extension-4.1/extern/civicrm_stripe_cron_live.php create mode 100644 extension-4.1/extern/civicrm_stripe_cron_test.php rename {CRM => source/CRM}/Core/Payment/Stripe.php (100%) rename civicrm_stripe.sql => source/civicrm_stripe.sql (100%) create mode 100644 source/civicrm_templates/CRM/Core/BillingBlock.tpl create mode 100644 source/extern/civicrm_stripe_cron_live.php create mode 100644 source/extern/civicrm_stripe_cron_test.php diff --git a/README.txt b/README.txt index 1fab60f0..8858f02c 100644 --- a/README.txt +++ b/README.txt @@ -1,24 +1,71 @@ ------------ -Important Note: +Please Read: + +There are 3 versions included by directory. Installation instructions for each further below: +extension-4.1: Extension for CiviCRM 4.1 and earlier. +extension-4.2: Extension for CiviCRM 4.2 and earlier. +source: Pre-extension method, folder structure is in tact, place files accordingly. -This version is for CiviCRM 4.1 and prior. -It will work for CiviCRM 4.2+ but there will be a new version to utilize all the new features surrounding Payment Processors in CiviCRM 4.2. -This currently includes everything you need minus a cron file to cancel recurring contributions. Do not allow recurring just yet! You also need a corresponding module for your CMS. Here is where the modules can be found: Drupal: git clone --recursive --branch master http://git.drupal.org/sandbox/drastik/1719796.git civicrm_stripe Joomla: TBD -WordPress: TBD +WordPress: TBD + +IMPORTANT: +It appears in CiviCRM 4.1, extensions aren't properly running their install() function so until further notice, +you will need to run the .sql file to make sure the database tables get created. This can be found in the 'source' folder. + +In all versions except extension-4.2, you will need to create a cron job in order for recurring contributions to be properly ended. +The cron files are the files in the 'extern' folder. There is one file each for live & test mode and files are named accordingly. +In CiviCRM 4.2, just make sure you have the correct "Job Scheduler" cron entry. + +------------ + +Installation Instructions: + +------------ + +For CiviCRM 4.2 +extension-4.2 instructions: + +Install extension + +Place civicrm_templates folder anywhere and inform CiviCRM of your "Custom Templates" location in this admin page: site.com/civicrm/admin/setting/path +(custom template soon to be removed as a requirement) + +Make sure you have a cron entry for CiviCRM's Job Scheduler! + +Copy Stripe's PHP library folder 'stripe-php' to civicrm/packages/stripe-php +You can get Stripe's PHP library here: https://github.com/stripe/stripe-php ------------ -Installing Stripe as a payment processor in CiviCRM 4.x +For CiviCRM 4.1 +extension-4.1 instructions: + +Install extension + +Place civicrm_templates folder anywhere and inform CiviCRM of your "Custom Templates" location in this admin page: site.com/civicrm/admin/setting/path + +Copy files in extern to your CiviCRM extern folder "civicrm/extern" +Make cron entry to hit the file(s) (daily preferred). + +Copy Stripe's PHP library folder 'stripe-php' to civicrm/packages/stripe-php +You can get Stripe's PHP library here: https://github.com/stripe/stripe-php -Folder structure is left in tact. +------------ + +Pre-extension instructions: + +Folder structure is left in tact. Place Stripe.php in civicrm/CRM/Core/Payment/Stripe.php Place civicrm_templates folder anywhere and inform CiviCRM of your "Custom Templates" location in this admin page: site.com/civicrm/admin/setting/path +Copy files in extern to your CiviCRM extern folder "civicrm/extern" +Make cron entry to hit the file(s) (daily preferred). + Copy Stripe's PHP library folder 'stripe-php' to civicrm/packages/stripe-php You can get Stripe's PHP library here: https://github.com/stripe/stripe-php @@ -29,10 +76,4 @@ civicrm_stripe_customers civicrm_stripe_plans civicrm_stripe_subscriptions ------------- -Note: - -This will be packaged as a "CiviCRM Extension" shortly for an alternative installation method. -In <CiviCRM 4.2, you will need to create a cron job in order for recurring contributions to be properly ended. - ------------ \ No newline at end of file diff --git a/civicrm_templates/CRM/Core/BillingBlock.tpl b/extension-4.1/civicrm_templates/CRM/Core/BillingBlock.tpl similarity index 100% rename from civicrm_templates/CRM/Core/BillingBlock.tpl rename to extension-4.1/civicrm_templates/CRM/Core/BillingBlock.tpl diff --git a/extension-4.1/com.drastikbydesign.payment.stripe/info.xml b/extension-4.1/com.drastikbydesign.payment.stripe/info.xml new file mode 100644 index 00000000..78b4ae19 --- /dev/null +++ b/extension-4.1/com.drastikbydesign.payment.stripe/info.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<extension key="com.drastikbydesign.payment.stripe" type="payment"> + <file>stripe</file> + <name>Stripe</name> + <description>Stripe Payment Processor</description> + <urls> + <url desc="Main Extension Page">http://drastikbydesign.com</url> + </urls> + <license>AGPL</license> + <maintainer> + <author>Joshua Walker (drastik) - Drastik by Design</author> + <email>admin (at) drastikbydesign.com</email> + </maintainer> + <releaseDate>2012-08-11</releaseDate> + <version>1.0</version> + <develStage>stable</develStage> + <compatibility><ver>4.1</ver></compatibility> + <comments></comments> + <typeInfo> + <userNameLabel>Secret Key</userNameLabel> + <passwordLabel>Publishable Key</passwordLabel> + <signatureLabel></signatureLabel> + <subjectLabel></subjectLabel> + <urlSiteDefault>https://api.stripe.com/v1</urlSiteDefault> + <urlApiDefault></urlApiDefault> + <urlRecurDefault>https://api.stripe.com/v1</urlRecurDefault> + <urlSiteTestDefault>https://api.stripe.com/v1</urlSiteTestDefault> + <urlApiTestDefault></urlApiTestDefault> + <urlRecurTestDefault>https://api.stripe.com/v1</urlRecurTestDefault> + <urlButtonDefault></urlButtonDefault> + <urlButtonTestDefault></urlButtonTestDefault> + <billingMode>notify</billingMode> + <isRecur>1</isRecur> + <paymentType>1</paymentType> + </typeInfo> +</extension> \ No newline at end of file diff --git a/extension-4.1/com.drastikbydesign.payment.stripe/stripe.php b/extension-4.1/com.drastikbydesign.payment.stripe/stripe.php new file mode 100644 index 00000000..3a5c27d5 --- /dev/null +++ b/extension-4.1/com.drastikbydesign.payment.stripe/stripe.php @@ -0,0 +1,287 @@ +<?php + +require_once 'CRM/Core/Payment.php'; + +class com_drastikbydesign_payment_stripe extends CRM_Core_Payment { + /** + * We only need one instance of this object. So we use the singleton + * pattern and cache the instance in this variable + * + * @var object + * @static + */ + static private $_singleton = null; + + /** + * mode of operation: live or test + * + * @var object + * @static + */ + static protected $_mode = null; + + /** + * Constructor + * + * @param string $mode the mode of operation: live or test + * + * @return void + */ + function __construct($mode, &$paymentProcessor) { + $this->_mode = $mode; + $this->_paymentProcessor = $paymentProcessor; + $this->_processorName = ts('Stripe'); + } + + /** + * Singleton function used to manage this object + * + * @param string $mode the mode of operation: live or test + * + * @return object + * @static + * + */ + static function &singleton($mode, &$paymentProcessor) { + $processorName = $paymentProcessor['name']; + if (self::$_singleton[$processorName] === NULL ) { + self::$_singleton[$processorName] = new com_drastikbydesign_payment_stripe($mode, $paymentProcessor); + } + return self::$_singleton[$processorName]; + } + + /** + * This function checks to see if we have the right config values + * + * @return string the error message if any + * @public + */ + function checkConfig() { + $config = CRM_Core_Config::singleton(); + $error = array(); + + if (empty($this->_paymentProcessor['user_name'])) { + $error[] = ts('The "Secret Key" is not set in the Stripe Payment Processor settings.'); + } + + if (empty($this->_paymentProcessor['password'])) { + $error[] = ts('The "Publishable Key" is not set in the Stripe Payment Processor settings.'); + } + + if (!empty($error)) { + return implode('<p>', $error); + } + else { + return NULL; + } + } + + /* + * CiviCRM extension install() + */ + public function install() { + //Create required tables for Stripe + require_once "CRM/Core/DAO.php"; + CRM_Core_DAO::executeQuery(" + 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, + UNIQUE KEY `email` (`email`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + CREATE TABLE IF NOT EXISTS `civicrm_stripe_plans` ( + `plan_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL, + UNIQUE KEY `plan_id` (`plan_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + 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', + KEY `end_time` (`end_time`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + "); + } + + /* + * CiviCRM extension uninstall() + */ + public function uninstall() { + //Remove Stripe tables on uninstall + 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"); + } + + /** + * Submit a payment using Stripe's PHP API: + * https://stripe.com/docs/api?lang=php + * + * @param array $params assoc array of input parameters for this transaction + * + * @return array the result in a nice formatted array (or an error object) + * @public + */ + function doDirectPayment(&$params) { + //Include Stripe library & Set API credentials. + require_once("stripe-php/lib/Stripe.php"); + Stripe::setApiKey($this->_paymentProcessor['user_name']); + + //Stripe amount required in cents. + $amount = $params['amount'] * 100; + //It would require 3 digits after the decimal for one to make it this far, CiviCRM prevents this, but let's be redundant. + $amount = number_format($amount, 0, '', ''); + + //Check for existing customer, create new otherwise. + $email = $params['email']; + $customer_query = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_stripe_customers WHERE email = '$email'"); + + //Use Stripe.js instead of raw card details. + if(isset($params['stripe_token'])) { + $card_details = $params['stripe_token']; + } else { + CRM_Core_Error::fatal(ts('Stripe.js token was not passed! Have you turned on the CiviCRM-Stripe CMS module?')); + } + + /**** + * If for some reason you cannot use Stripe.js and you are aware of PCI Compliance issues, here is the alternative to Stripe.js: + ****/ + //Prepare Card details in advance to use for new Stripe Customer object if we need. +/* + $cc_name = $params['first_name'] . " "; + if (strlen($params['middle_name']) > 0) { + $cc_name .= $params['middle_name'] . " "; + } + $cc_name .= $params['last_name']; + + $card_details = array( + 'number' => $params['credit_card_number'], + 'exp_month' => $params['month'], + 'exp_year' => $params['year'], + 'cvc' => $params['cvv2'], + 'name' => $cc_name, + 'address_line1' => $params['street_address'], + 'address_state' => $params['state_province'], + 'address_zip' => $params['postal_code'], + ); + */ + + //Create a new Customer in Stripe + if(!isset($customer_query)) { + $stripe_customer = Stripe_Customer::create(array( + 'description' => 'Payment from CiviCRM', + 'card' => $card_details, + 'email' => $email, + )); + + //Store the relationship between CiviCRM's email address for the Contact & Stripe's Customer ID + if(isset($stripe_customer)) { + CRM_Core_DAO::executeQuery("INSERT INTO civicrm_stripe_customers (email, id) VALUES ('$email', '$stripe_customer->id')"); + } else { + CRM_Core_Error::fatal(ts('There was an error saving new customer within Stripe. Is Stripe down?')); + } + } else { + $stripe_customer = Stripe_Customer::retrieve($customer_query); + if(!empty($stripe_customer)) { + $stripe_customer->card = $card_details; + $stripe_customer->save(); + } else { + $stripe_customer = Stripe_Customer::create(array( + 'description' => 'Donor from CiviCRM', + 'card' => $card_details, + 'email' => $email, + )); + + //Somehow a customer ID saved in the system no longer pairs with a Customer within Stripe. (Perhaps deleted using Stripe interface?) + //Store the relationship between CiviCRM's email address for the Contact & Stripe's Customer ID + if(isset($stripe_customer)) { + CRM_Core_DAO::executeQuery("DELETE FROM civicrm_stripe_customers WHERE email = '$email'"); + CRM_Core_DAO::executeQuery("INSERT INTO civicrm_stripe_customers (email, id) VALUES ('$email', '$stripe_customer->id')"); + } else { + CRM_Core_Error::fatal(ts('There was an error saving new customer within Stripe. Is Stripe down?')); + } + } + } + + //Prepare the charge array, minus Customer/Card details. + $stripe_charge = array( + 'amount' => $amount, + 'currency' => 'usd', + 'description' => '# CiviCRM Donation Page # ' . $params['description'] . ' # Invoice ID # ' . $params['invoiceID'], + ); + + //Use Stripe Customer if we have a valid one. Otherwise just use the card. + if(!empty($stripe_customer->id)) { + $stripe_charge['customer'] = $stripe_customer->id; + } else { + $stripe_charge['card'] = $card_details; + } + + //Handle recurring payments in doRecurPayment(). + if (CRM_Utils_Array::value('is_recur', $params) && $params['contributionRecurID']) { + return $this->doRecurPayment($params, $amount, $stripe_customer); + } + + //Fire away! + $stripe_response = Stripe_Charge::create($stripe_charge); + $params['trxn_id'] = $stripe_response->id; + + return $params; + } + + function doRecurPayment(&$params, $amount, $stripe_customer) { + $frequency = $params['frequency_unit']; + $installments = $params['installments']; + $plan_id = "$frequency-$amount"; + + $stripe_plan_query = CRM_Core_DAO::singleValueQuery("SELECT plan_id FROM civicrm_stripe_plans WHERE plan_id = '$plan_id'"); + + if(!isset($stripe_plan_query)) { + $formatted_amount = "$" . number_format(($amount / 100), 2); + //Create a new Plan + $stripe_plan = Stripe_Plan::create(array( + "amount" => $amount, + "interval" => $frequency, + "name" => "CiviCRM $frequency" . 'ly ' . $formatted_amount, + "currency" => "usd", + "id" => $plan_id)); + CRM_Core_DAO::executeQuery("INSERT INTO civicrm_stripe_plans (plan_id) VALUES ('$plan_id')"); + } + + //Attach the Subscription to the Stripe Customer + $stripe_response = $stripe_customer->updateSubscription(array('prorate' => FALSE, 'plan' => $plan_id)); + + $existing_subscription_query = CRM_Core_DAO::singleValueQuery("SELECT invoice_id FROM civicrm_stripe_subscriptions WHERE customer_id = '$stripe_customer->id'"); + if(!empty($existing_subscription_query)) { + //Cancel existing Recurring Contribution in CiviCRM + $cancel_date = date("Y-m-d H:i:s"); + CRM_Core_DAO::executeQuery("UPDATE civicrm_contribution_recur SET cancel_date = '$cancel_date', contribution_status_id = '3' WHERE invoice_id = '$existing_subscription_query'"); + //Delete the Stripe Subscription from our cron watch list. + CRM_Core_DAO::executeQuery("DELETE FROM civicrm_stripe_subscriptions WHERE invoice_id = '$existing_subscription_query'"); + } + + //Calculate timestamp for the last installment + $end_time = strtotime("+$installments $frequency"); + $invoice_id = $params['invoiceID']; + CRM_Core_DAO::executeQuery("INSERT INTO civicrm_stripe_subscriptions (customer_id, invoice_id, end_time) VALUES ('$stripe_customer->id', '$invoice_id', '$end_time')"); + + $trxn_id = $stripe_customer->id . '-' . $end_time; + $params['trxn_id'] = $trxn_id; + + return $params; + } + + /** + * Transfer method not in use + * + * @param array $params name value pair of contribution data + * + * @return void + * @access public + * + */ + function doTransferCheckout(&$params, $component) { + CRM_Core_Error::fatal(ts('Use direct billing instead of Transfer method.')); + } +} \ No newline at end of file diff --git a/extension-4.1/extern/civicrm_stripe_cron_live.php b/extension-4.1/extern/civicrm_stripe_cron_live.php new file mode 100644 index 00000000..2f45723c --- /dev/null +++ b/extension-4.1/extern/civicrm_stripe_cron_live.php @@ -0,0 +1,36 @@ +<?php +/* + * Cron function for CiviCRM 4.1 and below to cancel recurring contributions. + */ + +session_start( ); + +require_once '../civicrm.config.php'; +require_once 'CRM/Core/Config.php'; + +$config =& CRM_Core_Config::singleton(); + +$stripe_key = CRM_Core_DAO::singleValueQuery("SELECT user_name FROM civicrm_payment_processor WHERE payment_processor_type = 'Stripe' AND is_test = '0'"); +require_once("packages/stripe-php/lib/Stripe.php"); +Stripe::setApiKey($stripe_key); + +$time = time(); +print $time; +$query = " +SELECT customer_id, invoice_id +FROM civicrm_stripe_subscriptions +WHERE end_time <= '$time' +"; + +$end_recur_query = CRM_Core_DAO::executeQuery($query); + +while($end_recur_query->fetch()) { + $end_date = date("Y-m-d H:i:s"); + $stripe_customer = Stripe_Customer::retrieve($end_recur_query->customer_id); + if(isset($stripe_customer)) { + $stripe_customer->cancelSubscription(); + CRM_Core_DAO::executeQuery("UPDATE civicrm_contribution_recur SET end_date = '$end_date', contribution_status_id = '1' WHERE invoice_id = '$end_recur_query->invoice_id'"); + //Delete the Stripe Subscription from our cron watch list. + CRM_Core_DAO::executeQuery("DELETE FROM civicrm_stripe_subscriptions WHERE invoice_id = '$end_recur_query->invoice_id'"); + } +} diff --git a/extension-4.1/extern/civicrm_stripe_cron_test.php b/extension-4.1/extern/civicrm_stripe_cron_test.php new file mode 100644 index 00000000..64638938 --- /dev/null +++ b/extension-4.1/extern/civicrm_stripe_cron_test.php @@ -0,0 +1,36 @@ +<?php +/* + * Cron function for CiviCRM 4.1 and below to cancel recurring contributions. + */ + +session_start( ); + +require_once '../civicrm.config.php'; +require_once 'CRM/Core/Config.php'; + +$config =& CRM_Core_Config::singleton(); + +$stripe_key = CRM_Core_DAO::singleValueQuery("SELECT user_name FROM civicrm_payment_processor WHERE payment_processor_type = 'Stripe' AND is_test = '1'"); +require_once("packages/stripe-php/lib/Stripe.php"); +Stripe::setApiKey($stripe_key); + +$time = time(); +print $time; +$query = " +SELECT customer_id, invoice_id +FROM civicrm_stripe_subscriptions +WHERE end_time <= '$time' +"; + +$end_recur_query = CRM_Core_DAO::executeQuery($query); + +while($end_recur_query->fetch()) { + $end_date = date("Y-m-d H:i:s"); + $stripe_customer = Stripe_Customer::retrieve($end_recur_query->customer_id); + if(isset($stripe_customer)) { + $stripe_customer->cancelSubscription(); + CRM_Core_DAO::executeQuery("UPDATE civicrm_contribution_recur SET end_date = '$end_date', contribution_status_id = '1' WHERE invoice_id = '$end_recur_query->invoice_id'"); + //Delete the Stripe Subscription from our cron watch list. + CRM_Core_DAO::executeQuery("DELETE FROM civicrm_stripe_subscriptions WHERE invoice_id = '$end_recur_query->invoice_id'"); + } +} diff --git a/CRM/Core/Payment/Stripe.php b/source/CRM/Core/Payment/Stripe.php similarity index 100% rename from CRM/Core/Payment/Stripe.php rename to source/CRM/Core/Payment/Stripe.php diff --git a/civicrm_stripe.sql b/source/civicrm_stripe.sql similarity index 100% rename from civicrm_stripe.sql rename to source/civicrm_stripe.sql diff --git a/source/civicrm_templates/CRM/Core/BillingBlock.tpl b/source/civicrm_templates/CRM/Core/BillingBlock.tpl new file mode 100644 index 00000000..96a007b2 --- /dev/null +++ b/source/civicrm_templates/CRM/Core/BillingBlock.tpl @@ -0,0 +1,221 @@ +{* + +--------------------------------------------------------------------+ + | CiviCRM version 4.1 | + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC (c) 2004-2011 | + +--------------------------------------------------------------------+ + | This file is a part of CiviCRM. | + | | + | CiviCRM is free software; you can copy, modify, and distribute it | + | under the terms of the GNU Affero General Public License | + | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | + | | + | CiviCRM is distributed in the hope that it will be useful, but | + | WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | + | See the GNU Affero General Public License for more details. | + | | + | You should have received a copy of the GNU Affero General Public | + | License and the CiviCRM Licensing Exception along | + | with this program; if not, contact CiviCRM LLC | + | at info[AT]civicrm[DOT]org. If you have questions about the | + | GNU Affero General Public License or the licensing of CiviCRM, | + | see the CiviCRM license FAQ at http://civicrm.org/licensing | + +--------------------------------------------------------------------+ +*} +{if $form.credit_card_number or $form.bank_account_number} +<!-- START Stripe --> + {if $paymentProcessor.payment_processor_type == 'Stripe'} + + <script type="text/javascript" src="https://js.stripe.com/v1/"></script> + <script type="text/javascript"> + var stripe_publishable_key = '{$paymentProcessor.password}'; + + {literal} + cj(function() { + cj(document).ready(function(){ + //Identify the payment form. Don't reference by form#id since it changes between payment pages (Contribution / Event / etc). + cj("#crm-container>form").addClass('stripe-payment-form'); + Stripe.setPublishableKey(stripe_publishable_key); + cj("form.stripe-payment-form").submit(function(event) { + // disable the submit button to prevent repeated clicks + cj('form.stripe-payment-form input.form-submit').attr("disabled", "disabled"); + + Stripe.createToken({ + number: cj('#credit_card_number').val(), + cvc: cj('#cvv2').val(), + exp_month: cj('#credit_card_exp_date\\[M\\]').val(), + exp_year: cj('#credit_card_exp_date\\[Y\\]').val() + }, stripeResponseHandler); + + // prevent the form from submitting with the default action + return false; + }); + }); + + //Response from Stripe.createToken. + function stripeResponseHandler(status, response) { + if (response.error) { + // show the errors on the form + cj("form.stripe-payment-form").prepend('<div class="messages crm-error">' + +'<strong>Payment Error Response:</strong>' + +'<ul id="errorList">' + +'<li>Error: ' + response.error.message + '</li>' + +'</ul>' + +'</div>'); + + cj('form.stripe-payment-form input.form-submit').removeAttr("disabled"); + + } else { + var token = response['id']; + // Update form with the token & submit + cj("input#stripe-token").val(token); + cj("form.stripe-payment-form").get(0).submit(); + } + } + }); + {/literal} + </script> + {/if} +<!-- END Stripe --> + <div id="payment_information"> + <fieldset class="billing_mode-group {if $paymentProcessor.payment_type & 2}direct_debit_info-group{else}credit_card_info-group{/if}"> + <legend> + {if $paymentProcessor.payment_type & 2} + {ts}Direct Debit Information{/ts} + {else} + {ts}Credit Card Information{/ts} + {/if} + </legend> + {if $paymentProcessor.billing_mode & 2 and !$hidePayPalExpress } + <div class="crm-section no-label paypal_button_info-section"> + <div class="content description"> + {ts}If you have a PayPal account, you can click the PayPal button to continue. Otherwise, fill in the credit card and billing information on this form and click <strong>Continue</strong> at the bottom of the page.{/ts} + </div> + </div> + <div class="crm-section no-label {$form.$expressButtonName.name}-section"> + <div class="content description"> + {$form.$expressButtonName.html} + <div class="description">Save time. Checkout securely. Pay without sharing your financial information. </div> + </div> + </div> + {/if} + + {if $paymentProcessor.billing_mode & 1} + <div class="crm-section billing_mode-section {if $paymentProcessor.payment_type & 2}direct_debit_info-section{else}credit_card_info-section{/if}"> + {if $paymentProcessor.payment_type & 2} + <div class="crm-section {$form.account_holder.name}-section"> + <div class="label">{$form.account_holder.label}</div> + <div class="content">{$form.account_holder.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section {$form.bank_account_number.name}-section"> + <div class="label">{$form.bank_account_number.label}</div> + <div class="content">{$form.bank_account_number.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section {$form.bank_identification_number.name}-section"> + <div class="label">{$form.bank_identification_number.label}</div> + <div class="content">{$form.bank_identification_number.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section {$form.bank_name.name}-section"> + <div class="label">{$form.bank_name.label}</div> + <div class="content">{$form.bank_name.html}</div> + <div class="clear"></div> + </div> + {else} + <div class="crm-section {$form.credit_card_type.name}-section"> + <div class="label">{$form.credit_card_type.label}</div> + <div class="content">{$form.credit_card_type.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section {$form.credit_card_number.name}-section"> + <div class="label">{$form.credit_card_number.label}</div> + <div class="content">{$form.credit_card_number.html} + <div class="description">{ts}Enter numbers only, no spaces or dashes.{/ts}</div> + </div> + <div class="clear"></div> + </div> + <div class="crm-section {$form.cvv2.name}-section"> + <div class="label">{$form.cvv2.label}</div> + <div class="content"> + {$form.cvv2.html} + <img src="{$config->resourceBase}i/mini_cvv2.gif" alt="{ts}Security Code Location on Credit Card{/ts}" style="vertical-align: text-bottom;" /> + <div class="description">{ts}Usually the last 3-4 digits in the signature area on the back of the card.{/ts}</div> + </div> + <div class="clear"></div> + </div> + <div class="crm-section {$form.credit_card_exp_date.name}-section"> + <div class="label">{$form.credit_card_exp_date.label}</div> + <div class="content">{$form.credit_card_exp_date.html}</div> + <div class="clear"></div> + </div> + {/if} + </div> + </fieldset> + + <fieldset class="billing_name_address-group"> + <legend>{ts}Billing Name and Address{/ts}</legend> + <div class="crm-section billing_name_address-section"> + <div class="crm-section billingNameInfo-section"> + <div class="content description"> + {if $paymentProcessor.payment_type & 2} + {ts}Enter the name of the account holder, and the corresponding billing address.{/ts} + {else} + {ts}Enter the name as shown on your credit or debit card, and the billing address for this card.{/ts} + {/if} + </div> + </div> + <div class="crm-section {$form.billing_first_name.name}-section"> + <div class="label">{$form.billing_first_name.label}</div> + <div class="content">{$form.billing_first_name.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section {$form.billing_middle_name.name}-section"> + <div class="label">{$form.billing_middle_name.label}</div> + <div class="content">{$form.billing_middle_name.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section {$form.billing_last_name.name}-section"> + <div class="label">{$form.billing_last_name.label}</div> + <div class="content">{$form.billing_last_name.html}</div> + <div class="clear"></div> + </div> + {assign var=n value=billing_street_address-$bltID} + <div class="crm-section {$form.$n.name}-section"> + <div class="label">{$form.$n.label}</div> + <div class="content">{$form.$n.html}</div> + <div class="clear"></div> + </div> + {assign var=n value=billing_city-$bltID} + <div class="crm-section {$form.$n.name}-section"> + <div class="label">{$form.$n.label}</div> + <div class="content">{$form.$n.html}</div> + <div class="clear"></div> + </div> + {assign var=n value=billing_country_id-$bltID} + <div class="crm-section {$form.$n.name}-section"> + <div class="label">{$form.$n.label}</div> + <div class="content">{$form.$n.html|crmReplace:class:big}</div> + <div class="clear"></div> + </div> + {assign var=n value=billing_state_province_id-$bltID} + <div class="crm-section {$form.$n.name}-section"> + <div class="label">{$form.$n.label}</div> + <div class="content">{$form.$n.html|crmReplace:class:big}</div> + <div class="clear"></div> + </div> + {assign var=n value=billing_postal_code-$bltID} + <div class="crm-section {$form.$n.name}-section"> + <div class="label">{$form.$n.label}</div> + <div class="content">{$form.$n.html}</div> + <div class="clear"></div> + </div> + </div> + </fieldset> + {else} + </fieldset> + {/if} + </div> +{/if} \ No newline at end of file diff --git a/source/extern/civicrm_stripe_cron_live.php b/source/extern/civicrm_stripe_cron_live.php new file mode 100644 index 00000000..2f45723c --- /dev/null +++ b/source/extern/civicrm_stripe_cron_live.php @@ -0,0 +1,36 @@ +<?php +/* + * Cron function for CiviCRM 4.1 and below to cancel recurring contributions. + */ + +session_start( ); + +require_once '../civicrm.config.php'; +require_once 'CRM/Core/Config.php'; + +$config =& CRM_Core_Config::singleton(); + +$stripe_key = CRM_Core_DAO::singleValueQuery("SELECT user_name FROM civicrm_payment_processor WHERE payment_processor_type = 'Stripe' AND is_test = '0'"); +require_once("packages/stripe-php/lib/Stripe.php"); +Stripe::setApiKey($stripe_key); + +$time = time(); +print $time; +$query = " +SELECT customer_id, invoice_id +FROM civicrm_stripe_subscriptions +WHERE end_time <= '$time' +"; + +$end_recur_query = CRM_Core_DAO::executeQuery($query); + +while($end_recur_query->fetch()) { + $end_date = date("Y-m-d H:i:s"); + $stripe_customer = Stripe_Customer::retrieve($end_recur_query->customer_id); + if(isset($stripe_customer)) { + $stripe_customer->cancelSubscription(); + CRM_Core_DAO::executeQuery("UPDATE civicrm_contribution_recur SET end_date = '$end_date', contribution_status_id = '1' WHERE invoice_id = '$end_recur_query->invoice_id'"); + //Delete the Stripe Subscription from our cron watch list. + CRM_Core_DAO::executeQuery("DELETE FROM civicrm_stripe_subscriptions WHERE invoice_id = '$end_recur_query->invoice_id'"); + } +} diff --git a/source/extern/civicrm_stripe_cron_test.php b/source/extern/civicrm_stripe_cron_test.php new file mode 100644 index 00000000..64638938 --- /dev/null +++ b/source/extern/civicrm_stripe_cron_test.php @@ -0,0 +1,36 @@ +<?php +/* + * Cron function for CiviCRM 4.1 and below to cancel recurring contributions. + */ + +session_start( ); + +require_once '../civicrm.config.php'; +require_once 'CRM/Core/Config.php'; + +$config =& CRM_Core_Config::singleton(); + +$stripe_key = CRM_Core_DAO::singleValueQuery("SELECT user_name FROM civicrm_payment_processor WHERE payment_processor_type = 'Stripe' AND is_test = '1'"); +require_once("packages/stripe-php/lib/Stripe.php"); +Stripe::setApiKey($stripe_key); + +$time = time(); +print $time; +$query = " +SELECT customer_id, invoice_id +FROM civicrm_stripe_subscriptions +WHERE end_time <= '$time' +"; + +$end_recur_query = CRM_Core_DAO::executeQuery($query); + +while($end_recur_query->fetch()) { + $end_date = date("Y-m-d H:i:s"); + $stripe_customer = Stripe_Customer::retrieve($end_recur_query->customer_id); + if(isset($stripe_customer)) { + $stripe_customer->cancelSubscription(); + CRM_Core_DAO::executeQuery("UPDATE civicrm_contribution_recur SET end_date = '$end_date', contribution_status_id = '1' WHERE invoice_id = '$end_recur_query->invoice_id'"); + //Delete the Stripe Subscription from our cron watch list. + CRM_Core_DAO::executeQuery("DELETE FROM civicrm_stripe_subscriptions WHERE invoice_id = '$end_recur_query->invoice_id'"); + } +} -- GitLab