Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • extensions/stripe
  • madhavi/stripe
  • wmortada/stripe
  • jamie/stripe
  • michaelmcandrew/stripe
  • bgm/stripe
  • noah/stripe
  • laryn/stripe
  • phani/stripe
  • JonGold/stripe
  • scardinius/stripe
  • varshith/stripe
  • naomi/stripe
  • jhoskins98/stripe
  • artfulrobot/stripe
  • jitendra/stripe
  • justinfreeman/stripe
  • revati_gawas/stripe
  • capo/stripe
  • pradeep/stripe
  • partners/ixiam/stripe
  • homotechsual/stripe
  • Edselopez/stripe
  • goron/stripe
  • tapash/stripe
  • petednz/stripe
  • kartik1000/stripe
  • ananelson/stripe
  • Samuele.Masetto/stripe
  • sluc23/stripe
  • aaron/stripe
  • DaveD/stripe
  • konadave/stripe
  • partners/coopsymbiotic/stripe
  • kurund/stripe
  • AllenShaw/stripe
  • awestbha/stripe
  • mathavan/stripe
  • BjoernE/stripe
  • alietz/stripe
  • seamuslee/stripe
  • damo-civi/stripe
  • dmunio/stripe
  • ufundo/stripe
44 results
Show changes
Commits on Source (4)
Showing
with 417 additions and 420 deletions
......@@ -3,6 +3,8 @@
* https://civicrm.org/licensing
*/
use CRM_Stripe_ExtensionUtil as E;
/**
* Class CRM_Core_Payment_Stripe
*/
......@@ -14,7 +16,7 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
*
* @var string
*/
const API_VERSION = '2019-05-16';
const API_VERSION = '2019-08-14';
/**
* Mode of operation: live or test.
......@@ -31,10 +33,11 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
*
* @param string $mode
* The mode of operation: live or test.
* @param array $paymentProcessor
*
* @return void
*/
public function __construct($mode, &$paymentProcessor) {
public function __construct($mode, $paymentProcessor) {
$this->_mode = $mode;
$this->_paymentProcessor = $paymentProcessor;
$this->_processorName = ts('Stripe');
......@@ -46,7 +49,7 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
* @return string
*/
public static function getSecretKey($paymentProcessor) {
return trim(CRM_Utils_Array::value('user_name', $paymentProcessor));
return trim(CRM_Utils_Array::value('password', $paymentProcessor));
}
/**
......@@ -55,7 +58,7 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
* @return string
*/
public static function getPublicKey($paymentProcessor) {
return trim(CRM_Utils_Array::value('password', $paymentProcessor));
return trim(CRM_Utils_Array::value('user_name', $paymentProcessor));
}
/**
......@@ -262,11 +265,11 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
*/
public function getPaymentFormFields() {
return array(
'credit_card_type',
'credit_card_number',
'cvv2',
'credit_card_exp_date',
'stripe_token',
//'credit_card_type',
//'credit_card_number',
//'cvv2',
//'credit_card_exp_date',
//'stripe_token',
'stripe_pub_key',
'stripe_id',
);
......@@ -402,6 +405,11 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
'stripe_pub_key' => $publishableKey,
];
$form->setDefaults($defaults);
// Add help and javascript
CRM_Core_Region::instance('billing-block')->add(
['template' => 'CRM/Core/Payment/Stripe/Card.tpl', 'weight' => -1]);
CRM_Core_Resources::singleton()->addStyleFile(E::LONG_NAME, 'css/elements.css', 0, 'html-header');
}
/**
......@@ -422,13 +430,6 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
* @throws \Civi\Payment\Exception\PaymentProcessorException
*/
public function doPayment(&$params, $component = 'contribute') {
if (array_key_exists('credit_card_number', $params)) {
$cc = $params['credit_card_number'];
if (!empty($cc) && substr($cc, 0, 8) != '00000000') {
Civi::log()->debug(ts('ALERT! Unmasked credit card received in back end. Please report this error to the site administrator.'));
}
}
$completedStatusId = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed');
$pendingStatusId = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Pending');
......@@ -456,11 +457,8 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
$amount = self::getAmount($params);
// Use Stripe.js instead of raw card details.
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);
if(!empty(CRM_Utils_Array::value('stripeToken', $_POST, NULL))) {
$cardToken = CRM_Utils_Array::value('stripeToken', $_POST, NULL);
}
else {
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.'));
......@@ -473,7 +471,7 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
// See if we already have a stripe customer
$customerParams = [
'contact_id' => $contactId,
'card_token' => $card_token,
'card_token' => $cardToken,
'processor_id' => $this->_paymentProcessor['id'],
'email' => $email,
// Include this to allow redirect within session on payment failure
......@@ -514,7 +512,7 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
}
}
$stripeCustomer->card = $card_token;
$stripeCustomer->card = $cardToken;
try {
$stripeCustomer->save();
}
......@@ -554,7 +552,7 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
$stripeChargeParams['customer'] = $stripeCustomer->id;
}
else {
$stripeChargeParams['card'] = $card_token;
$stripeChargeParams['card'] = $cardToken;
}
try {
......
......@@ -16,7 +16,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
protected $transaction_id;
// By default, always retrieve the event from stripe to ensure we are
// not being fed garbage. However, allow an override so when we are
// not being fed garbage. However, allow an override so when we are
// testing, we can properly test a failed recurring contribution.
protected $verify_event = TRUE;
......@@ -39,7 +39,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
protected $frequency_unit = NULL;
protected $plan_name = NULL;
protected $plan_start = NULL;
// Derived properties.
protected $contribution_recur_id = NULL;
protected $event_id = NULL;
......@@ -119,10 +119,10 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
// Determine the proper Stripe Processor ID so we can get the secret key
// and initialize Stripe.
$this->getPaymentProcessor();
$processor = new CRM_Core_Payment_Stripe('', civicrm_api3('PaymentProcessor', 'getsingle', ['id' => $this->_paymentProcessor['id']]));
$processor->setAPIParams();
// Now re-retrieve the data from Stripe to ensure it's legit.
\Stripe\Stripe::setApiKey($this->_paymentProcessor['user_name']);
// Special case if this is the test webhook
if (substr($parameters->id, -15, 15) === '_00000000000000') {
http_response_code(200);
......@@ -194,7 +194,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
));
}
// Successful charge & more to come.
// Successful charge & more to come.
civicrm_api3('ContributionRecur', 'create', array(
'id' => $this->contribution_recur_id,
'failure_count' => 0,
......@@ -353,7 +353,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
* Gather and set info as class properties.
*
* Given the data passed to us via the Stripe Event, try to determine
* as much as we can about this event and set that information as
* as much as we can about this event and set that information as
* properties to be used later.
*
* @throws \CRM_Core_Exception
......
<?php
/**
* Collection of upgrade steps.
* DO NOT USE a naming scheme other than upgrade_N, where N is an integer.
* Naming scheme upgrade_X_Y_Z is offically wrong!
* DO NOT USE a naming scheme other than upgrade_N, where N is an integer.
* Naming scheme upgrade_X_Y_Z is offically wrong!
* https://chat.civicrm.org/civicrm/pl/usx3pfjzjbrhzpewuggu1e6ftw
*/
class CRM_Stripe_Upgrader extends CRM_Stripe_Upgrader_Base {
......@@ -56,7 +56,7 @@ class CRM_Stripe_Upgrader extends CRM_Stripe_Upgrader_Base {
CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_stripe_plans ADD COLUMN `processor_id` int(10) DEFAULT NULL COMMENT "ID from civicrm_payment_processor"');
CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_stripe_subscriptions ADD COLUMN `processor_id` int(10) DEFAULT NULL COMMENT "ID from civicrm_payment_processor"');
}
return TRUE;
return TRUE;
}
......@@ -70,14 +70,14 @@ class CRM_Stripe_Upgrader extends CRM_Stripe_Upgrader_Base {
$config = CRM_Core_Config::singleton();
$dbName = DB::connect($config->dsn)->_db;
$null_count = CRM_Core_DAO::executeQuery('SELECT COUNT(*) FROM civicrm_stripe_customers where processor_id IS NULL') +
$null_count = CRM_Core_DAO::executeQuery('SELECT COUNT(*) FROM civicrm_stripe_customers where processor_id IS NULL') +
CRM_Core_DAO::executeQuery('SELECT COUNT(*) FROM civicrm_stripe_plans where processor_id IS NULL') +
CRM_Core_DAO::executeQuery('SELECT COUNT(*) FROM civicrm_stripe_subscriptions where processor_id IS NULL');
if ( $null_count == 0 ) {
$this->ctx->log->info('Skipped civicrm_stripe update 5002. No nulls found in column processor_id in our tables.');
return TRUE;
}
else {
}
else {
try {
// Set processor ID if there's only one.
$processorCount = civicrm_api3('PaymentProcessorType', 'get', array(
......@@ -109,8 +109,8 @@ class CRM_Stripe_Upgrader extends CRM_Stripe_Upgrader_Base {
return TRUE;
}
/**
/**
* Add subscription_id column to civicrm_stripe_subscriptions table.
*
* @return TRUE on success
......@@ -131,11 +131,11 @@ class CRM_Stripe_Upgrader extends CRM_Stripe_Upgrader_Base {
CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_stripe_subscriptions ADD COLUMN `subscription_id` varchar(255) DEFAULT NULL COMMENT "Subscription ID from Stripe" FIRST');
CRM_Core_DAO::executeQuery('ALTER TABLE `civicrm_stripe_subscriptions` ADD UNIQUE KEY(`subscription_id`)');
}
return TRUE;
}
/**
return TRUE;
}
/**
* Populates the subscription_id column in table civicrm_stripe_subscriptions.
*
* @return TRUE on success
......@@ -145,51 +145,43 @@ class CRM_Stripe_Upgrader extends CRM_Stripe_Upgrader_Base {
$config = CRM_Core_Config::singleton();
$dbName = DB::connect($config->dsn)->_db;
$null_count = CRM_Core_DAO::executeQuery('SELECT COUNT(*) FROM civicrm_stripe_subscriptions where subscription_id IS NULL');
$null_count = CRM_Core_DAO::executeQuery('SELECT COUNT(*) FROM civicrm_stripe_subscriptions where subscription_id IS NULL');
if ( $null_count == 0 ) {
$this->ctx->log->info('Skipped civicrm_stripe update 5004. No nulls found in column subscription_id in our civicrm_stripe_subscriptions table.');
}
else {
$customer_infos = CRM_Core_DAO::executeQuery("SELECT customer_id,processor_id
}
else {
$customer_infos = CRM_Core_DAO::executeQuery("SELECT customer_id,processor_id
FROM `civicrm_stripe_subscriptions`;");
while ( $customer_infos->fetch() ) {
$processor_id = $customer_infos->processor_id;
$customer_id = $customer_infos->customer_id;
try {
$stripe_key = civicrm_api3('PaymentProcessor', 'getvalue', array(
'return' => 'user_name',
'id' => $processor_id,
));
}
catch (Exception $e) {
Civi::log()->debug('Update 5004 failed. Has Stripe been removed as a payment processor?', $out = false);
return;
}
try {
\Stripe\Stripe::setApiKey($stripe_key);
$subscription = \Stripe\Subscription::all(array(
'customer'=> $customer_id,
'limit'=>1,
));
}
catch (Exception $e) {
// Don't quit here. A missing customer in Stipe is OK. They don't exist, so they can't have a subscription.
Civi::log()->debug('Cannot find Stripe API key: ' . $e->getMessage());
}
if (!empty($subscription['data'][0]['id'])) {
$query_params = array(
1 => array($subscription['data'][0]['id'], 'String'),
2 => array($customer_id, 'String'),
);
CRM_Core_DAO::executeQuery('UPDATE civicrm_stripe_subscriptions SET subscription_id = %1 where customer_id = %2;', $query_params);
unset($subscription);
}
try {
$processor = new CRM_Core_Payment_Stripe('', civicrm_api3('PaymentProcessor', 'getsingle', ['id' => $processor_id]));
$processor->setAPIParams();
$subscription = \Stripe\Subscription::all(array(
'customer'=> $customer_id,
'limit'=>1,
));
}
catch (Exception $e) {
// Don't quit here. A missing customer in Stipe is OK. They don't exist, so they can't have a subscription.
Civi::log()->debug('Cannot find Stripe API key: ' . $e->getMessage());
}
if (!empty($subscription['data'][0]['id'])) {
$query_params = array(
1 => array($subscription['data'][0]['id'], 'String'),
2 => array($customer_id, 'String'),
);
CRM_Core_DAO::executeQuery('UPDATE civicrm_stripe_subscriptions SET subscription_id = %1 where customer_id = %2;', $query_params);
unset($subscription);
}
}
}
return TRUE;
return TRUE;
}
/**
/**
* Add contribution_recur_id column to civicrm_stripe_subscriptions table.
*
* @return TRUE on success
......@@ -213,10 +205,10 @@ class CRM_Stripe_Upgrader extends CRM_Stripe_Upgrader_Base {
CRM_Core_DAO::executeQuery('ALTER TABLE `civicrm_stripe_subscriptions` ADD INDEX(`contribution_recur_id`);');
CRM_Core_DAO::executeQuery('ALTER TABLE `civicrm_stripe_subscriptions` ADD CONSTRAINT `FK_civicrm_stripe_contribution_recur_id` FOREIGN KEY (`contribution_recur_id`) REFERENCES `civicrm_contribution_recur`(`id`) ON DELETE SET NULL ON UPDATE RESTRICT;');
}
return TRUE;
return TRUE;
}
/**
/**
* Method 1 for populating the contribution_recur_id column in the civicrm_stripe_subscriptions table.
* ( A simple approach if that works if there have never been any susbcription edits in the Stripe UI. )
......@@ -230,93 +222,93 @@ class CRM_Stripe_Upgrader extends CRM_Stripe_Upgrader_Base {
$subscriptions = CRM_Core_DAO::executeQuery("SELECT invoice_id,is_live
FROM `civicrm_stripe_subscriptions`;");
while ( $subscriptions->fetch() ) {
$test_mode = (int)!$subscriptions->is_live;
try {
// Fetch the recurring contribution Id.
$recur_id = civicrm_api3('Contribution', 'getvalue', array(
'sequential' => 1,
'return' => "contribution_recur_id",
'invoice_id' => $subscriptions->invoice_id,
'contribution_test' => $test_mode,
));
}
catch (CiviCRM_API3_Exception $e) {
// Don't quit here. If we can't find the recurring ID for a single customer, make a note in the error log and carry on.
Civi::log()->debug('Recurring contribution search: ' . $e->getMessage());
}
if (!empty($recur_id)) {
$p = array(
1 => array($recur_id, 'Integer'),
2 => array($subscriptions->invoice_id, 'String'),
);
CRM_Core_DAO::executeQuery('UPDATE civicrm_stripe_subscriptions SET contribution_recur_id = %1 WHERE invoice_id = %2;', $p);
}
while ( $subscriptions->fetch() ) {
$test_mode = (int)!$subscriptions->is_live;
try {
// Fetch the recurring contribution Id.
$recur_id = civicrm_api3('Contribution', 'getvalue', array(
'sequential' => 1,
'return' => "contribution_recur_id",
'invoice_id' => $subscriptions->invoice_id,
'contribution_test' => $test_mode,
));
}
catch (CiviCRM_API3_Exception $e) {
// Don't quit here. If we can't find the recurring ID for a single customer, make a note in the error log and carry on.
Civi::log()->debug('Recurring contribution search: ' . $e->getMessage());
}
return TRUE;
if (!empty($recur_id)) {
$p = array(
1 => array($recur_id, 'Integer'),
2 => array($subscriptions->invoice_id, 'String'),
);
CRM_Core_DAO::executeQuery('UPDATE civicrm_stripe_subscriptions SET contribution_recur_id = %1 WHERE invoice_id = %2;', $p);
}
}
return TRUE;
}
/**
/**
* Method 2 for populating the contribution_recur_id column in the civicrm_stripe_subscriptions table. Uncomment this and comment 5006.
* ( A more convoluted approach that works if there HAVE been susbcription edits in the Stripe UI. )
* @return TRUE on success. Please let users uncomment this as needed and increment past 5007 for the next upgrade.
* @throws Exception
*/
/*
public function upgrade_5007() {
$config = CRM_Core_Config::singleton();
$dbName = DB::connect($config->dsn)->_db;
$subscriptions = CRM_Core_DAO::executeQuery("SELECT customer_id,is_live,processor_id
FROM `civicrm_stripe_subscriptions`;");
while ( $subscriptions->fetch() ) {
$test_mode = (int)!$subscriptions->is_live;
$p = array(
1 => array($subscriptions->customer_id, 'String'),
2 => array($subscriptions->is_live, 'Integer'),
);
$customer = CRM_Core_DAO::executeQuery("SELECT email
FROM `civicrm_stripe_customers` WHERE id = %1 AND is_live = %2;", $p);
$customer->fetch();
// Try the billing email first, since that's what we send to Stripe.
try {
$contact = civicrm_api3('Email', 'get', array(
'sequential' => 1,
'return' => "contact_id",
'is_billing' => 1,
'email' => $customer->email,
'api.ContributionRecur.get' => array('return' => "id", 'contact_id' => "\$value.contact_id", 'contribution_status_id' => "In Progress"),
));
}
catch (CiviCRM_API3_Exception $e) {
// Uh oh, that didn't work. Try to retrieve the recurring id using the primary email.
$contact = civicrm_api3('Contact', 'get', array(
'sequential' => 1,
'return' => "id",
'email' => $customer->email,
'api.ContributionRecur.get' => array('sequential' => 1, 'return' => "id", 'contact_id' => "\$values.id", 'contribution_status_id' => "In Progress"),
));
}
/*
public function upgrade_5007() {
$config = CRM_Core_Config::singleton();
$dbName = DB::connect($config->dsn)->_db;
$subscriptions = CRM_Core_DAO::executeQuery("SELECT customer_id,is_live,processor_id
FROM `civicrm_stripe_subscriptions`;");
while ( $subscriptions->fetch() ) {
$test_mode = (int)!$subscriptions->is_live;
$p = array(
1 => array($subscriptions->customer_id, 'String'),
2 => array($subscriptions->is_live, 'Integer'),
);
$customer = CRM_Core_DAO::executeQuery("SELECT email
FROM `civicrm_stripe_customers` WHERE id = %1 AND is_live = %2;", $p);
$customer->fetch();
// Try the billing email first, since that's what we send to Stripe.
try {
$contact = civicrm_api3('Email', 'get', array(
'sequential' => 1,
'return' => "contact_id",
'is_billing' => 1,
'email' => $customer->email,
'api.ContributionRecur.get' => array('return' => "id", 'contact_id' => "\$value.contact_id", 'contribution_status_id' => "In Progress"),
));
}
catch (CiviCRM_API3_Exception $e) {
// Uh oh, that didn't work. Try to retrieve the recurring id using the primary email.
$contact = civicrm_api3('Contact', 'get', array(
'sequential' => 1,
'return' => "id",
'email' => $customer->email,
'api.ContributionRecur.get' => array('sequential' => 1, 'return' => "id", 'contact_id' => "\$values.id", 'contribution_status_id' => "In Progress"),
));
}
if (!empty($contact['values'][0]['api.ContributionRecur.get']['values'][0]['id'])) {
$recur_id = $contact['values'][0]['api.ContributionRecur.get']['values'][0]['id'];
$p = array(
1 => array($recur_id, 'Integer'),
2 => array($subscriptions->customer_id, 'String'),
);
CRM_Core_DAO::executeQuery('UPDATE civicrm_stripe_subscriptions SET contribution_recur_id = %1 WHERE customer_id = %2;', $p);
} else {
// Crap.
$this->ctx->log->info('Update 5007 failed. Consider adding recurring IDs manuallly to civicrm_stripe_subscriptions. ');
return;
if (!empty($contact['values'][0]['api.ContributionRecur.get']['values'][0]['id'])) {
$recur_id = $contact['values'][0]['api.ContributionRecur.get']['values'][0]['id'];
$p = array(
1 => array($recur_id, 'Integer'),
2 => array($subscriptions->customer_id, 'String'),
);
CRM_Core_DAO::executeQuery('UPDATE civicrm_stripe_subscriptions SET contribution_recur_id = %1 WHERE customer_id = %2;', $p);
} else {
// Crap.
$this->ctx->log->info('Update 5007 failed. Consider adding recurring IDs manuallly to civicrm_stripe_subscriptions. ');
return;
}
}
}
return TRUE;
}
*/
return TRUE;
}
*/
/**
/**
* Add change default NOT NULL to NULL in vestigial invoice_id column in civicrm_stripe_subscriptions table if needed. (issue #192)
*
* @return TRUE on success
......@@ -338,7 +330,7 @@ class CRM_Stripe_Upgrader extends CRM_Stripe_Upgrader_Base {
MODIFY COLUMN `invoice_id` varchar(255) NULL default ""
COMMENT "Safe to remove this column if the update retrieving subscription IDs completed satisfactorily."');
}
return TRUE;
return TRUE;
}
/**
......@@ -407,4 +399,25 @@ class CRM_Stripe_Upgrader extends CRM_Stripe_Upgrader_Base {
return TRUE;
}
public function upgrade_5023() {
$this->ctx->log->info('Applying Stripe update 5023. Swap over public/secret key settings');
$stripeProcessors = civicrm_api3('PaymentProcessor', 'get', [
'payment_processor_type_id' => "Stripe",
]);
foreach ($stripeProcessors['values'] as $processor) {
if ((substr($processor['user_name'], 0, 3) === 'sk_')
&& (substr($processor['password'], 0, 3) === 'pk_')) {
// Need to switch over parameters
$createParams = [
'id' => $processor['id'],
'user_name' => $processor['password'],
'password' => $processor['user_name'],
];
civicrm_api3('PaymentProcessor', 'create', $createParams);
}
}
CRM_Utils_System::flushCache();
return TRUE;
}
}
......@@ -26,7 +26,9 @@ class CRM_Stripe_Webhook {
$messageTexts = [];
$webhook_path = self::getWebhookPath($paymentProcessor['id']);
\Stripe\Stripe::setApiKey(CRM_Core_Payment_Stripe::getSecretKey($paymentProcessor));
$processor = new CRM_Core_Payment_Stripe('', civicrm_api3('PaymentProcessor', 'getsingle', ['id' => $paymentProcessor['id']]));
$processor->setAPIParams();
try {
$webhooks = \Stripe\WebhookEndpoint::all(["limit" => 100]);
}
......@@ -118,7 +120,8 @@ class CRM_Stripe_Webhook {
* @param int $paymentProcessorId
*/
public static function createWebhook($paymentProcessorId) {
\Stripe\Stripe::setApiKey(CRM_Core_Payment_Stripe::getSecretKeyById($paymentProcessorId));
$processor = new CRM_Core_Payment_Stripe('', civicrm_api3('PaymentProcessor', 'getsingle', ['id' => $paymentProcessorId]));
$processor->setAPIParams();
$params = [
'enabled_events' => self::getDefaultEnabledEvents(),
......
<?php
/**
* This api allows you to replay Stripe events.
* This api allows you to replay Stripe events.
*
* You can either pass the id of an entry in the System Log (which can
* be populated with the Stripe.PopulateLog call) or you can pass a
* event id from Stripe directly.
*
* When processing an event, the event will always be re-fetched from the
* Stripe server first, so this will not work while offline or with
* Stripe server first, so this will not work while offline or with
* events that were not generated by the Stripe server.
*/
*/
/**
* Stripe.Ipn API specification
......@@ -57,12 +57,9 @@ function civicrm_api3_stripe_Ipn($params) {
throw new API_Exception('Please pass the payment processor id (ppid) if using evtid.', 3236);
}
$ppid = $params['ppid'];
$results = civicrm_api3('PaymentProcessor', 'getsingle', array('id' => $ppid));
// YES! I know, password and user are backwards. wtf??
$sk = $results['user_name'];
$processor = new CRM_Core_Payment_Stripe('', civicrm_api3('PaymentProcessor', 'getsingle', ['id' => $ppid]));
$processor->setAPIParams();
require_once ("vendor/stripe/stripe-php/init.php");
\Stripe\Stripe::setApiKey($sk);
$object = \Stripe\Event::retrieve($params['evtid']);
}
// Avoid a SQL error if this one has been processed already.
......@@ -74,7 +71,7 @@ function civicrm_api3_stripe_Ipn($params) {
return civicrm_api3_create_error("Ipn already processed.");
}
if (class_exists('CRM_Core_Payment_StripeIPN')) {
// The $_GET['processor_id'] value is normally set by
// The $_GET['processor_id'] value is normally set by
// CRM_Core_Payment::handlePaymentMethod
$_GET['processor_id'] = $ppid;
$ipnClass = new CRM_Core_Payment_StripeIPN($object);
......
......@@ -9,7 +9,7 @@
/**
* Stripe.ListEvents API specification
*
*
*
* @param array $spec description of fields supported by this API call
* @return void
......@@ -17,12 +17,13 @@
*/
function _civicrm_api3_stripe_ListEvents_spec(&$spec) {
$spec['ppid']['title'] = ts("Use the given Payment Processor ID");
$spec['ppid']['type'] = CRM_Utils_Type::T_INT;
$spec['ppid']['type'] = CRM_Utils_Type::T_INT;
$spec['ppid']['api.required'] = TRUE;
$spec['type']['title'] = ts("Limit to the given Stripe events type, defaults to invoice.payment_succeeded.");
$spec['type']['api.default'] = 'invoice.payment_succeeded';
$spec['limit']['title'] = ts("Limit number of results returned (100 is max)");
$spec['starting_after']['title'] = ts("Only return results after this event id.");
$spec['output']['api.default'] = 'brief';
$spec['output']['api.default'] = 'brief';
$spec['output']['title'] = ts("How to format the output, brief or raw. Defaults to brief.");
}
......@@ -122,18 +123,17 @@ function civicrm_api3_stripe_VerifyEventType($eventType) {
* Process parameters to determine ppid and sk.
*
* @param array $params
*
* @return array
* @throws \API_Exception
*/
function civicrm_api3_stripe_ProcessParams($params) {
$ppid = NULL;
$type = NULL;
$created = NULL;
$limit = NULL;
$starting_after = NULL;
$sk = NULL;
if (array_key_exists('ppid', $params) ) {
$ppid = $params['ppid'];
}
if (array_key_exists('created', $params) ) {
$created = $params['created'];
}
......@@ -144,29 +144,6 @@ function civicrm_api3_stripe_ProcessParams($params) {
$starting_after = $params['starting_after'];
}
// Select the right payment processor to use.
if ($ppid) {
$query_params = array('id' => $ppid);
}
else {
// By default, select the live stripe processor (we expect there to be
// only one).
$query_params = array('class_name' => 'Payment_Stripe', 'is_test' => 0);
}
try {
$results = civicrm_api3('PaymentProcessor', 'getsingle', $query_params);
// YES! I know, password and user are backwards. wtf??
$sk = $results['user_name'];
}
catch (CiviCRM_API3_Exception $e) {
if(preg_match('/Expected one PaymentProcessor but/', $e->getMessage())) {
throw new API_Exception("Expected one live Stripe payment processor, but found none or more than one. Please specify ppid=.", 1234);
}
else {
throw new API_Exception("Error getting the Stripe Payment Processor to use", 1235);
}
}
// Check to see if we should filter by type.
if (array_key_exists('type', $params) ) {
// Validate - since we will be appending this to an URL.
......@@ -185,7 +162,7 @@ function civicrm_api3_stripe_ProcessParams($params) {
throw new API_Exception("Created can only be passed in programatically as an array", 1237);
}
}
return array('sk' => $sk, 'type' => $type, 'created' => $created, 'limit' => $limit, 'starting_after' => $starting_after);
return ['type' => $type, 'created' => $created, 'limit' => $limit, 'starting_after' => $starting_after];
}
/**
......@@ -199,7 +176,6 @@ function civicrm_api3_stripe_ProcessParams($params) {
*/
function civicrm_api3_stripe_Listevents($params) {
$parsed = civicrm_api3_stripe_ProcessParams($params);
$sk = $parsed['sk'];
$type = $parsed['type'];
$created = $parsed['created'];
$limit = $parsed['limit'];
......@@ -218,9 +194,10 @@ function civicrm_api3_stripe_Listevents($params) {
if ($starting_after) {
$args['starting_after'] = $starting_after;
}
require_once ("vendor/stripe/stripe-php/init.php");
\Stripe\Stripe::setApiKey($sk);
$processor = new CRM_Core_Payment_Stripe('', civicrm_api3('PaymentProcessor', 'getsingle', ['id' => $params['ppid']]));
$processor->setAPIParams();
$data_list = \Stripe\Event::all($args);
if (array_key_exists('error', $data_list)) {
$err = $data_list['error'];
......
......@@ -149,9 +149,10 @@ function civicrm_api3_stripe_subscription_import($params) {
$paymentProcessor = \Civi\Payment\System::singleton()->getById($params['payment_processor_id'])->getPaymentProcessor();
// Now re-retrieve the data from Stripe to ensure it's legit.
\Stripe\Stripe::setApiKey($paymentProcessor['user_name']);
$processor = new CRM_Core_Payment_Stripe('', $paymentProcessor);
$processor->setAPIParams();
// Now re-retrieve the data from Stripe to ensure it's legit.
$stripeSubscription = \Stripe\Subscription::retrieve($params['subscription_id']);
// Create the stripe customer in CiviCRM
......
......@@ -8,16 +8,16 @@
"packages": [
{
"name": "stripe/stripe-php",
"version": "v6.40.0",
"version": "v6.43.1",
"source": {
"type": "git",
"url": "https://github.com/stripe/stripe-php.git",
"reference": "9c22ffab790ef4dae0f371929de50e8b53c9ec8d"
"reference": "42fcdaf99c44bb26937223f8eae1f263491d5ab8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/9c22ffab790ef4dae0f371929de50e8b53c9ec8d",
"reference": "9c22ffab790ef4dae0f371929de50e8b53c9ec8d",
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/42fcdaf99c44bb26937223f8eae1f263491d5ab8",
"reference": "42fcdaf99c44bb26937223f8eae1f263491d5ab8",
"shasum": ""
},
"require": {
......@@ -60,7 +60,7 @@
"payment processing",
"stripe"
],
"time": "2019-06-27T23:24:51+00:00"
"time": "2019-08-29T16:56:12+00:00"
}
],
"packages-dev": [],
......
#card-element {
padding: 2%;
margin: 2%;
background-color: ghostwhite;
-webkit-box-shadow: 10px 10px 7px -6px rgba(0,0,0,0.81);
-moz-box-shadow: 10px 10px 7px -6px rgba(0, 0, 0, 0.81);
box-shadow: 10px 10px 7px -6px rgba(0, 0, 0, 0.81);
}
#card-errors {
margin: 2%;
display: none;
}
## Release 6.0 (not yet released)
* Stripe API Version: 2019-08-14
* Switch publishable key/secret key in settings (upgrader does this automatically) so they are now "correct" per CiviCRM settings pages.
## Release 5.4.1
* Don't overwrite system messages when performing webhook checks.
* Add form to handle creating/updating webhooks instead of automatically during system check (Thanks @artfulrobot)
......
......@@ -12,9 +12,9 @@
<author>Matthew Wire (MJW Consulting)</author>
<email>mjw@mjwconsult.co.uk</email>
</maintainer>
<releaseDate>2019-07-21</releaseDate>
<version>5.4.1</version>
<develStage>stable</develStage>
<releaseDate>2019-08-31</releaseDate>
<version>6.0.dev</version>
<develStage>beta</develStage>
<compatibility>
<ver>5.13</ver>
</compatibility>
......
......@@ -4,44 +4,41 @@
*/
CRM.$(function($) {
// 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.
if ($(".messages.crm-error.stripe-message").length > 0) {
$(".messages.crm-error.stripe-message").slideUp();
$(".messages.crm-error.stripe-message:first").remove();
}
$form.prepend('<div class="messages alert alert-block alert-danger error crm-error stripe-message">'
+ '<strong>Payment Error Response:</strong>'
+ '<ul id="errorList">'
+ '<li>Error: ' + response.error.message + '</li>'
+ '</ul>'
+ '</div>');
removeCCDetails($form, true);
$form.data('submitted', false);
$submit.prop('disabled', false);
}
else {
var token = response['id'];
// Update form with the token & submit.
removeCCDetails($form, false);
$form.find("input#stripe-token").val(token);
// Disable unload event handler
window.onbeforeunload = null;
// Restore any onclickAction that was removed.
$submit.attr('onclick', onclickAction);
var stripe;
var card;
var form;
var submitButton;
function stripeTokenHandler(token) {
debugging('stripeTokenHandler');
// Insert the token ID into the form so it gets submitted to the server
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
// This triggers submit without generating a submit event (so we don't run submit handler again)
$form.get(0).submit();
}
function createToken() {
debugging('createToken');
stripe.createToken(card).then(function(result) {
if (result.error) {
debugging('createToken failed');
// Inform the user if there was an error
var errorElement = document.getElementById('card-errors');
errorElement.style.display = 'block';
errorElement.textContent = result.error.message;
submitButton.removeAttribute('disabled');
document.querySelector('#billing-payment-block').scrollIntoView();
window.scrollBy(0, -50);
} else {
// Send the token to your server
stripeTokenHandler(result.token);
}
});
}
// Prepare the form.
......@@ -51,12 +48,11 @@ CRM.$(function($) {
window.onbeforeunload = null;
// Load Stripe onto the form.
loadStripeBillingBlock();
$submit = getBillingSubmit();
// Store and remove any onclick Action currently assigned to the form.
// We will re-add it if the transaction goes through.
onclickAction = $submit.attr('onclick');
$submit.removeAttr('onclick');
//onclickAction = submitButton.getAttribute('onclick');
//submitButton.removeAttribute('onclick');
// Quickform doesn't add hidden elements via standard method. On a form where payment processor may
// be loaded via initial form load AND ajax (eg. backend live contribution page with payproc dropdown)
......@@ -126,80 +122,82 @@ CRM.$(function($) {
// Setup Stripe.Js
var $stripePubKey = $('#stripe-pub-key');
if ($stripePubKey.length) {
if (!$().Stripe) {
$.getScript('https://js.stripe.com/v2/', function () {
Stripe.setPublishableKey($('#stripe-pub-key').val());
});
}
if (!$stripePubKey.length) {
return;
}
stripe = Stripe($('#stripe-pub-key').val());
var elements = stripe.elements();
var style = {
base: {
fontSize: '20px',
},
};
// Create an instance of the card Element.
card = elements.create('card', {style: style});
card.mount('#card-element');
// Get the form containing payment details
$form = getBillingForm();
if (!$form.length) {
form = getBillingForm();
if (!form.length) {
debugging('No billing form!');
return;
}
$submit = getBillingSubmit();
submitButton = getBillingSubmit();
// 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');
form.dataset.submitdontprocess = false;
var button = document.createElement("input");
button.type = "submit";
button.value = "im a button";
button.classList.add('cancel');
form.appendChild(button);
// Find submit buttons which should not submit payment
$form.find('[type="submit"][formnovalidate="1"], ' +
var nonPaymentSubmitButtons = form.querySelectorAll('[type="submit"][formnovalidate="1"], ' +
'[type="submit"][formnovalidate="formnovalidate"], ' +
'[type="submit"].cancel, ' +
'[type="submit"].webform-previous').click( function() {
debugging('adding submit-dont-process');
$form.data('submit-dont-process', 1);
});
'[type="submit"].webform-previous'), i;
for (i = 0; i < nonPaymentSubmitButtons.length; ++i) {
nonPaymentSubmitButtons[i].addEventListener('click', function () {
debugging('adding submitdontprocess');
form.dataset.submitdontprocess = true;
});
}
$submit.click( function(event) {
submitButton.addEventListener('click', function(event) {
// Take over the click function of the form.
debugging('clearing submit-dont-process');
$form.data('submit-dont-process', 0);
debugging('clearing submitdontprocess');
form.dataset.submitdontprocess = false;
// Run through our own submit, that executes Stripe submission if
// appropriate for this submit.
var ret = submit(event);
if (ret) {
// True means it's not our form. We are bailing and not trying to
// process Stripe.
// Restore any onclickAction that was removed.
$form = getBillingForm();
$submit = getBillingSubmit();
$submit.attr('onclick', onclickAction);
$form.get(0).submit();
return true;
}
// Otherwise, this is a stripe submission - don't handle normally.
// The code for completing the submission is all managed in the
// stripe handler (stripeResponseHandler) which gets execute after
// stripe finishes.
return false;
return submit(event);
});
// 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);
}
});
var isWebform = getIsWebform($form);
//form.querySelector('input#discountcode').keypress( function(e) {
// if (e.which === 13) {
// form.dataset.submitdontprocess = true;
// }
//});
// For CiviCRM Webforms.
if (isWebform) {
if (getIsDrupalWebform()) {
// We need the action field for back/submit to work and redirect properly after submission
if (!($('#action').length)) {
$form.append($('<input type="hidden" name="op" id="action" />'));
form.append($('<input type="hidden" name="op" id="action" />'));
}
var $actions = $form.find('[type=submit]');
var $actions = form.querySelector('[type=submit]');
$('[type=submit]').click(function() {
$('#action').val(this.value);
});
// If enter pressed, use our submit function
$form.keypress(function(event) {
form.keypress(function(event) {
if (event.which === 13) {
$('#action').val(this.value);
submit(event);
......@@ -208,41 +206,37 @@ CRM.$(function($) {
$('#billingcheckbox:input').hide();
$('label[for="billingcheckbox"]').hide();
}
else {
// As we use credit_card_number to pass token, make sure it is empty when shown
$form.find("input#credit_card_number").val('');
$form.find("input#cvv2").val('');
}
function submit(event) {
event.preventDefault();
debugging('submit handler');
if ($form.data('submitted') === true) {
if (form.dataset.submitted === true) {
debugging('form already submitted');
return false;
}
var isWebform = getIsWebform($form);
var stripeProcessorId;
var chosenProcessorId;
// Handle multiple payment options and Stripe not being chosen.
if (isWebform) {
var stripeProcessorId;
var chosenProcessorId;
if (getIsDrupalWebform()) {
stripeProcessorId = $('#stripe-id').val();
// this element may or may not exist on the webform, but we are dealing with a single (stripe) processor enabled.
if (!$('input[name="submitted[civicrm_1_contribution_1_contribution_payment_processor_id]"]').length) {
chosenProcessorId = stripeProcessorId;
} else {
chosenProcessorId = $form.find('input[name="submitted[civicrm_1_contribution_1_contribution_payment_processor_id]"]:checked').val();
chosenProcessorId = form.querySelector('input[name="submitted[civicrm_1_contribution_1_contribution_payment_processor_id]"]:checked').val();
}
}
else {
// Most forms have payment_processor-section but event registration has credit_card_info-section
if (($form.find(".crm-section.payment_processor-section").length > 0)
|| ($form.find(".crm-section.credit_card_info-section").length > 0)) {
if ((form.querySelector(".crm-section.payment_processor-section") !== null)
|| (form.querySelector(".crm-section.credit_card_info-section") !== null)) {
stripeProcessorId = $('#stripe-id').val();
chosenProcessorId = $form.find('input[name="payment_processor_id"]:checked').val();
if (form.querySelector('input[name="payment_processor_id"]:checked') !== null) {
chosenProcessorId = form.querySelector('input[name="payment_processor_id"]:checked').value;
}
}
}
......@@ -260,22 +254,18 @@ CRM.$(function($) {
debugging('Stripe is the selected payprocessor');
}
$form = getBillingForm();
// Don't handle submits generated by non-stripe processors
if (!$('input#stripe-pub-key').length || !($('input#stripe-pub-key').val())) {
debugging('submit missing stripe-pub-key element or value');
return true;
}
// Don't handle submits generated by the CiviDiscount button.
if ($form.data('submit-dont-process')) {
if (form.dataset.submitdontprocess === true) {
debugging('non-payment submit detected - not submitting payment');
return true;
}
$submit = getBillingSubmit();
if (isWebform) {
if (getIsDrupalWebform()) {
// If we have selected Stripe but amount is 0 we don't submit via Stripe
if ($('#billing-payment-block').is(':hidden')) {
debugging('no payment processor on webform');
......@@ -303,100 +293,64 @@ CRM.$(function($) {
}
}
// If there's no credit card field, no use in continuing (probably wrong
// context anyway)
if (!$form.find('#credit_card_number').length) {
debugging('No credit card field');
return true;
}
// Lock to prevent multiple submissions
if ($form.data('submitted') === true) {
if (form.dataset.submitted === true) {
// Previously submitted - don't submit again
alert('Form already submitted. Please wait.');
return false;
} else {
// Mark it so that the next submit can be ignored
// ADDED requirement that form be valid
if($form.valid()) {
$form.data('submitted', true);
}
form.dataset.submitted = true;
}
// Disable the submit button to prevent repeated clicks
$submit.prop('disabled', true);
var cc_month = $form.find('#credit_card_exp_date_M').val();
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(),
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
}, stripeResponseHandler);
submitButton.setAttribute('disabled', true);
// Create a token when the form is submitted.
createToken();
debugging('Created Stripe token');
return false;
return true;
}
}
function getIsWebform(form) {
// Pass in the billingForm object
// If the form has the webform-client-form (drupal 7) or webform-submission-form (drupal 8) class then it's a drupal webform!
return form.hasClass('webform-client-form') || form.hasClass('webform-submission-form');
function getIsDrupalWebform() {
// form class for drupal webform: webform-client-form (drupal 7); webform-submission-form (drupal 8)
if (form !== null) {
return form.classList.contains('webform-client-form') || form.classList.contains('webform-submission-form');
}
return false;
}
function getBillingForm() {
// If we have a stripe billing form on the page
var $billingForm = $('input#stripe-pub-key').closest('form');
//if (!$billingForm.length && getIsWebform()) {
// If we are in a webform
// $billingForm = $('.webform-client-form');
//}
if (!$billingForm.length) {
var billingFormID = $('input#stripe-pub-key').closest('form').prop('id');
if (!billingFormID.length) {
// If we have multiple payment processors to select and stripe is not currently loaded
$billingForm = $('input[name=hidden_processor]').closest('form');
billingFormID = $('input[name=hidden_processor]').closest('form').prop('id');
}
return $billingForm;
// We have to use document.getElementById here so we have the right elementtype for appendChild()
return document.getElementById(billingFormID);
}
function getBillingSubmit() {
$form = getBillingForm();
var isWebform = getIsWebform($form);
if (isWebform) {
$submit = $form.find('[type="submit"].webform-submit');
if (!$submit.length) {
var submit = null;
if (getIsDrupalWebform()) {
submit = form.querySelector('[type="submit"].webform-submit');
if (!submit.length) {
// drupal 8 webform
$submit = $form.find('[type="submit"].webform-button--submit');
submit = form.querySelector('[type="submit"].webform-button--submit');
}
}
else {
$submit = $form.find('[type="submit"].validate');
}
return $submit;
}
function removeCCDetails($form, $truncate) {
// Remove the "name" attribute so params are not submitted
var ccNumElement = $form.find("input#credit_card_number");
var cvv2Element = $form.find("input#cvv2");
if ($truncate) {
ccNumElement.val('');
cvv2Element.val('');
}
else {
var last4digits = ccNumElement.val().substr(12, 16);
ccNumElement.val('000000000000' + last4digits);
cvv2Element.val('000');
submit = form.querySelector('[type="submit"].validate');
}
return submit;
}
function debugging (errorCode) {
// Uncomment the following to debug unexpected returns.
//console.log(new Date().toISOString() + ' civicrm_stripe.js: ' + errorCode);
console.log(new Date().toISOString() + ' civicrm_stripe.js: ' + errorCode);
}
});
......@@ -15,8 +15,8 @@ return [
'title' => 'Stripe',
'description' => 'Stripe Payment Processor',
'class_name' => 'Payment_Stripe',
'user_name_label' => 'Secret Key',
'password_label' => 'Publishable key',
'user_name_label' => 'Publishable key',
'password_label' => 'Secret Key',
'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',
......
{* https://civicrm.org/licensing *}
<script src="https://js.stripe.com/v3/"></script>
<label for="card-element">
<legend>Credit or debit card</legend>
</label>
<div id="card-element">
<!-- a Stripe Element will be inserted here. -->
</div>
{* Area for Stripe to report errors *}
<div id="card-errors" role="alert" class="alert alert-danger"></div>
......@@ -39,7 +39,7 @@ class CRM_Stripe_BaseTest extends \PHPUnit_Framework_TestCase implements Headles
// Secret/public keys are PTP test keys.
protected $_sk = 'sk_test_TlGdeoi8e1EOPC3nvcJ4q5UZ';
protected $_pk = 'pk_test_k2hELLGpBLsOJr6jZ2z9RaYh';
protected $_cc = NULL;
protected $_cc = NULL;
public function setUpHeadless() {
// Civi\Test has many helpers, like install(), uninstall(), sql(), and sqlFile().
......@@ -111,8 +111,8 @@ class CRM_Stripe_BaseTest extends \PHPUnit_Framework_TestCase implements Headles
$processor = array_pop($result['values']);
$this->_sk = $processor['user_name'];
$this->_pk = $processor['password'];
$this->_paymentProcessor = $processor;
$this->_paymentProcessorID = $result['id'];
$this->_paymentProcessor = $processor;
$this->_paymentProcessorID = $result['id'];
}
/**
......@@ -132,9 +132,9 @@ class CRM_Stripe_BaseTest extends \PHPUnit_Framework_TestCase implements Headles
), $params);
$result = civicrm_api3('ContributionPage', 'create', $params);
$this->assertEquals(0, $result['is_error']);
$this->_contributionPageID = $result['id'];
$this->_contributionPageID = $result['id'];
}
/**
* Submit to stripe
*/
......@@ -179,8 +179,9 @@ class CRM_Stripe_BaseTest extends \PHPUnit_Framework_TestCase implements Headles
public function assertValidTrxn() {
$this->assertNotEmpty($this->_trxn_id, "A trxn id was assigned");
\Stripe\Stripe::setApiKey($this->_sk);
$found = FALSE;
$processor = new CRM_Core_Payment_Stripe('', civicrm_api3('PaymentProcessor', 'getsingle', ['id' => $this->_paymentProcessorID]));
$processor->setAPIParams();
try {
$results = \Stripe\Charge::retrieve(array( "id" => $this->_trxn_id));
$found = TRUE;
......@@ -188,10 +189,10 @@ class CRM_Stripe_BaseTest extends \PHPUnit_Framework_TestCase implements Headles
catch (Stripe_Error $e) {
$found = FALSE;
}
$this->assertTrue($found, 'Assigned trxn_id is valid.');
}
}
/**
* Create contribition
*/
......@@ -213,7 +214,7 @@ class CRM_Stripe_BaseTest extends \PHPUnit_Framework_TestCase implements Headles
), $params));
$this->assertEquals(0, $contribution['is_error']);
$this->_contributionID = $contribution['id'];
}
}
public function createOrganization() {
if (!empty($this->_orgID)) {
......@@ -230,7 +231,7 @@ class CRM_Stripe_BaseTest extends \PHPUnit_Framework_TestCase implements Headles
CRM_Member_PseudoConstant::flush('membershipType');
CRM_Core_Config::clearDBCache();
$this->createOrganization();
$params = array(
$params = array(
'name' => 'General',
'duration_unit' => 'year',
'duration_interval' => 1,
......@@ -251,5 +252,5 @@ class CRM_Stripe_BaseTest extends \PHPUnit_Framework_TestCase implements Headles
CRM_Utils_Cache::singleton()->flush();
}
}
......@@ -27,7 +27,7 @@ class CRM_Stripe_IpnTest extends CRM_Stripe_BaseTest {
protected $_frequency_interval = 1;
protected $_membershipID;
// This test is particularly dirty for some reason so we have to
// This test is particularly dirty for some reason so we have to
// force a reset.
public function setUpHeadless() {
$force = TRUE;
......@@ -71,13 +71,15 @@ class CRM_Stripe_IpnTest extends CRM_Stripe_BaseTest {
$this->doPayment($payment_extra_params);
// Now check to see if an event was triggered and if so, process it.
$payment_object = $this->getEvent('invoice.payment_succeeded');
$payment_object = $this->getEvent('invoice.payment_succeeded');
if ($payment_object) {
$this->ipn($payment_object);
}
// Now that we have a recurring contribution, let's update it.
\Stripe\Stripe::setApiKey($this->_sk);
// Now that we have a recurring contribution, let's update it.
$processor = new CRM_Core_Payment_Stripe('', civicrm_api3('PaymentProcessor', 'getsingle', ['id' => $this->_paymentProcessorID]));
$processor->setAPIParams();
$sub = \Stripe\Subscription::retrieve($this->_subscriptionID);
// Create a new plan if it doesn't yet exist.
......@@ -110,7 +112,7 @@ class CRM_Stripe_IpnTest extends CRM_Stripe_BaseTest {
$sub->save();
// Now check to see if an event was triggered and if so, process it.
$payment_object = $this->getEvent('customer.subscription.updated');
$payment_object = $this->getEvent('customer.subscription.updated');
if ($payment_object) {
$this->ipn($payment_object);
}
......@@ -123,8 +125,8 @@ class CRM_Stripe_IpnTest extends CRM_Stripe_BaseTest {
'return' => array('id'),
);
$result = civicrm_api3('ContributionRecur', 'getsingle', $params);
$newContributionRecurID = $result['id'];
$newContributionRecurID = $result['id'];
// Now ensure that the membership record is updated to have this
// new recurring contribution id.
$membership_contribution_recur_id = civicrm_api3('Membership', 'getvalue', array(
......@@ -135,7 +137,7 @@ class CRM_Stripe_IpnTest extends CRM_Stripe_BaseTest {
// Delete the new plan so we can cleanly run the next time.
$plan->delete();
}
/**
......@@ -155,7 +157,7 @@ class CRM_Stripe_IpnTest extends CRM_Stripe_BaseTest {
$this->doPayment($payment_extra_params);
// Now check to see if an event was triggered and if so, process it.
$payment_object = $this->getEvent('invoice.payment_succeeded');
$payment_object = $this->getEvent('invoice.payment_succeeded');
if ($payment_object) {
// Now manipulate the transaction so it appears to be a failed one.
$payment_object->type = 'invoice.payment_failed';
......@@ -192,7 +194,7 @@ class CRM_Stripe_IpnTest extends CRM_Stripe_BaseTest {
$this->doPayment($payment_extra_params);
// Now check to see if an event was triggered and if so, process it.
$payment_object = $this->getEvent('invoice.payment_succeeded');
$payment_object = $this->getEvent('invoice.payment_succeeded');
if ($payment_object) {
$this->ipn($payment_object);
}
......@@ -201,15 +203,17 @@ class CRM_Stripe_IpnTest extends CRM_Stripe_BaseTest {
$this->assertEquals(1, $contribution_status_id, "Recurring payment was properly processed via a stripe event.");
// Now, cancel the subscription and ensure it is properly cancelled.
\Stripe\Stripe::setApiKey($this->_sk);
$processor = new CRM_Core_Payment_Stripe('', civicrm_api3('PaymentProcessor', 'getsingle', ['id' => $this->_paymentProcessorID]));
$processor->setAPIParams();
$sub = \Stripe\Subscription::retrieve($this->_subscriptionID);
$sub->cancel();
$sub_object = $this->getEvent('customer.subscription.deleted');
$sub_object = $this->getEvent('customer.subscription.deleted');
if ($sub_object) {
$this->ipn($sub_object);
}
$this->assertContributionRecurIsCancelled();
$this->assertContributionRecurIsCancelled();
}
public function assertContributionRecurIsCancelled() {
......@@ -239,7 +243,7 @@ class CRM_Stripe_IpnTest extends CRM_Stripe_BaseTest {
$params['output'] = 'raw';
// Now try to retrieve this transaction.
$transactions = civicrm_api3('Stripe', 'listevents', $params );
$transactions = civicrm_api3('Stripe', 'listevents', $params );
foreach($transactions['values']['data'] as $transaction) {
if ($transaction->data->object->$property == $this->_subscriptionID) {
return $transaction;
......@@ -254,7 +258,7 @@ class CRM_Stripe_IpnTest extends CRM_Stripe_BaseTest {
*
*/
public function ipn($data, $verify = TRUE) {
// The $_GET['processor_id'] value is normally set by
// The $_GET['processor_id'] value is normally set by
// CRM_Core_Payment::handlePaymentMethod
$_GET['processor_id'] = $this->_paymentProcessorID;
$ipnClass = new CRM_Core_Payment_StripeIPN($data, $verify);
......@@ -272,7 +276,7 @@ class CRM_Stripe_IpnTest extends CRM_Stripe_BaseTest {
'amount' => $this->_total,
'sequential' => 1,
'installments' => $this->_installments,
'frequency_unit' => $this->_frequency_unit,
'frequency_unit' => $this->_frequency_unit,
'frequency_interval' => $this->_frequency_interval,
'invoice_id' => $this->_invoiceID,
'contribution_status_id' => 2,
......@@ -293,5 +297,5 @@ class CRM_Stripe_IpnTest extends CRM_Stripe_BaseTest {
$this->assertEquals(0, $contributionRecur['is_error']);
$this->_contributionRecurID = $contributionRecur['id'];
$this->_contributionID = $contributionRecur['values']['0']['api.contribution.create']['id'];
}
}
}
......@@ -51,7 +51,8 @@ while ($dao->fetch()) {
if (!$paymentProcessor) {
echo "Failed to find a stripe payment processor for recurring contrib $dao->contribution_recur_id\n";
}
Stripe::setApiKey(CRM_Core_Payment_Stripe::getSecretKey($paymentProcessor));
$processor = new CRM_Core_Payment_Stripe('', civicrm_api3('PaymentProcessor', 'getsingle', ['id' => $paymentProcessor['id']]));
$processor->setAPIParams();
try {
$results = Charge::retrieve(['id' => $dao->trxn_id]);
......
[
{
"name": "stripe/stripe-php",
"version": "v6.40.0",
"version_normalized": "6.40.0.0",
"version": "v6.43.1",
"version_normalized": "6.43.1.0",
"source": {
"type": "git",
"url": "https://github.com/stripe/stripe-php.git",
"reference": "9c22ffab790ef4dae0f371929de50e8b53c9ec8d"
"reference": "42fcdaf99c44bb26937223f8eae1f263491d5ab8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/9c22ffab790ef4dae0f371929de50e8b53c9ec8d",
"reference": "9c22ffab790ef4dae0f371929de50e8b53c9ec8d",
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/42fcdaf99c44bb26937223f8eae1f263491d5ab8",
"reference": "42fcdaf99c44bb26937223f8eae1f263491d5ab8",
"shasum": ""
},
"require": {
......@@ -26,7 +26,7 @@
"squizlabs/php_codesniffer": "~2.0",
"symfony/process": "~2.8"
},
"time": "2019-06-27T23:24:51+00:00",
"time": "2019-08-29T16:56:12+00:00",
"type": "library",
"extra": {
"branch-alias": {
......
# Changelog
## 6.43.1 - 2019-08-29
* [#722](https://github.com/stripe/stripe-php/pull/722) Make `LoggerInterface::error` compatible with its PSR-3 counterpart
* [#714](https://github.com/stripe/stripe-php/pull/714) Add `pending_setup_intent` property in `Subscription`
* [#713](https://github.com/stripe/stripe-php/pull/713) Add typehint to `ApiResponse`
* [#712](https://github.com/stripe/stripe-php/pull/712) Fix comment
* [#701](https://github.com/stripe/stripe-php/pull/701) Start testing PHP 7.3
## 6.43.0 - 2019-08-09
* [#694](https://github.com/stripe/stripe-php/pull/694) Add `SubscriptionItem::createUsageRecord` method
## 6.42.0 - 2019-08-09
* [#688](https://github.com/stripe/stripe-php/pull/688) Remove `SubscriptionScheduleRevision`
* Note that this is technically a breaking change, however we've chosen to release it as a minor version in light of the fact that this resource and its API methods were virtually unused.
## 6.41.0 - 2019-07-31
* [#683](https://github.com/stripe/stripe-php/pull/683) Move the List Balance History API to `/v1/balance_transactions`
## 6.40.0 - 2019-06-27
* [#675](https://github.com/stripe/stripe-php/pull/675) Add support for `SetupIntent` resource and APIs
......@@ -57,7 +74,7 @@
* [#642](https://github.com/stripe/stripe-php/pull/642) Fix an issue where existing idempotency keys would be overwritten when using automatic retries
## 6.34.1 - 2019-04-25
* [#640](https://github.com/stripe/stripe-php/pull/640) Add missing phpdocs
* [#640](https://github.com/stripe/stripe-php/pull/640) Add missing phpdocs
## 6.34.0 - 2019-04-24
* [#626](https://github.com/stripe/stripe-php/pull/626) Add support for the `TaxRate` resource and APIs
......@@ -145,7 +162,7 @@
* [#564](https://github.com/stripe/stripe-php/pull/564) Add event name constants for subscription schedule aborted/expiring
## 6.23.0 - 2018-11-27
* [#542](https://github.com/stripe/stripe-php/pull/542) Add support for `ValueList` and `ValueListItem` for Radar
* [#542](https://github.com/stripe/stripe-php/pull/542) Add support for `ValueList` and `ValueListItem` for Radar
## 6.22.1 - 2018-11-20
* [#561](https://github.com/stripe/stripe-php/pull/561) Add cast and some docs to telemetry introduced in 6.22.0/#549
......@@ -399,7 +416,7 @@ Pull requests included in this release:
* Add support for payouts and recipient transfers
## 4.6.0 - 2017-04-06
* Please see 4.7.0 instead (no-op release)
* Please see 4.7.0 instead (no-op release)
## 4.5.1 - 2017-03-22
* Remove hard dependency on cURL
......