...
 
Commits (6)
......@@ -119,17 +119,13 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
* @return string errorMessage (or statusbounce if URL is specified)
*/
public static function handleErrorNotification($err, $bounceURL = NULL) {
$errorMessage = 'Payment Response: <br />' .
'Type: ' . $err['type'] . '<br />' .
'Code: ' . $err['code'] . '<br />' .
'Message: ' . $err['message'] . '<br />';
Civi::log()->debug('Stripe Payment Error: ' . $errorMessage);
$debugMsg = $err['type'] . ' ' . $err['code'] . ' ' . $err['message'];
Civi::log()->debug('Stripe Payment Error: ' . $debugMsg);
if ($bounceURL) {
CRM_Core_Error::statusBounce($errorMessage, $bounceURL, 'Payment Error');
CRM_Core_Error::statusBounce($err['message'], $bounceURL, 'Payment Error');
}
return $errorMessage;
return $debugMsg;
}
/**
......@@ -445,13 +441,15 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
'card_token' => $card_token,
'processor_id' => $this->_paymentProcessor['id'],
'email' => $email,
// Include this to allow redirect within session on payment failure
'stripe_error_url' => $params['stripe_error_url'],
];
$stripeCustomerId = CRM_Stripe_Customer::find($customerParams);
// Customer not in civicrm database. Create a new Customer in Stripe.
if (!isset($stripeCustomerId)) {
$stripeCustomer = CRM_Stripe_Customer::create($customerParams, $this);
$stripeCustomer = CRM_Stripe_Customer::create($customerParams);
}
else {
// Customer was found in civicrm database, fetch from Stripe.
......@@ -472,7 +470,7 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
// Customer doesn't exist, create a new one
CRM_Stripe_Customer::delete($customerParams);
try {
$stripeCustomer = CRM_Stripe_Customer::create($customerParams, $this);
$stripeCustomer = CRM_Stripe_Customer::create($customerParams);
}
catch (Exception $e) {
// We still failed to create a customer
......@@ -529,14 +527,17 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
}
catch (Exception $e) {
$err = self::parseStripeException('charge_create', $e, FALSE);
if ($e instanceof \Stripe\Error\Card) {
civicrm_api3('Note', 'create', [
'entity_id' => $params['contributionID'],
'contact_id' => $this->getContactId($params),
'subject' => $err['type'],
'note' => $err['code'],
'entity_table' => 'civicrm_contribution',
]);
if ($this->getContributionId($params)) {
civicrm_api3('Note', 'create', [
'entity_id' => $this->getContributionId($params),
'contact_id' => $this->getContactId($params),
'subject' => $err['type'],
'note' => $err['code'],
'entity_table' => 'civicrm_contribution',
]);
}
}
$errorMessage = self::handleErrorNotification($err, $params['stripe_error_url']);
throw new \Civi\Payment\Exception\PaymentProcessorException('Failed to create Stripe Charge: ' . $errorMessage);
......
......@@ -151,7 +151,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
* @throws \CRM_Core_Exception
*/
public function retrieve($name, $type, $abort = TRUE) {
$value = CRM_Stripe_Api::getObjectParam($name, $type, $this->_inputParameters->data->object);
$value = CRM_Stripe_Api::getObjectParam($name, $this->_inputParameters->data->object);
$value = CRM_Utils_Type::validate($value, $type, FALSE);
if ($abort && $value === NULL) {
......@@ -359,7 +359,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
*/
public function setInfo() {
$abort = FALSE;
$this->customer_id = CRM_Stripe_Api::getParam('customer_id', $this->_inputParameters);
$this->customer_id = CRM_Stripe_Api::getObjectParam('customer_id', $this->_inputParameters->data->object);
if (empty($this->customer_id)) {
$this->exception('Missing customer_id!');
}
......
<?php
class CRM_Stripe_Api {
public static function getObjectParam($name, $stripeObject) {
$className = get_class($stripeObject);
switch ($className) {
......@@ -33,7 +33,7 @@ class CRM_Stripe_Api {
return (string) $stripeObject->id;
case 'receive_date':
return date("Y-m-d H:i:s", $stripeObject->date);
return $stripeObject->date ? date("Y-m-d H:i:s", $stripeObject->date) : NULL;
case 'subscription_id':
return (string) $stripeObject->subscription;
......@@ -51,7 +51,7 @@ class CRM_Stripe_Api {
return (string) mb_strtoupper($stripeObject->currency);
case 'status_id':
if ((bool)$stripeObject->paid) {
if ((bool) $stripeObject->paid) {
return 'Completed';
}
else {
......@@ -85,7 +85,7 @@ class CRM_Stripe_Api {
return (string) $stripeObject->plan->name;
case 'plan_start':
return date("Y-m-d H:i:s", $stripeObject->start);
return $stripeObject->start ? date("Y-m-d H:i:s", $stripeObject->start) : NULL;
case 'cycle_day':
return date("d", $stripeObject->billing_cycle_anchor);
......
......@@ -397,4 +397,14 @@ class CRM_Stripe_Upgrader extends CRM_Stripe_Upgrader_Base {
return TRUE;
}
public function upgrade_5022() {
$this->ctx->log->info('Applying Stripe update 5021. Remove is_live NOT NULL constraint as we don\'t use this parameter any more');
if (CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_stripe_customers', 'is_live', FALSE)) {
CRM_Core_DAO::executeQuery('ALTER TABLE `civicrm_stripe_customers`
MODIFY COLUMN `is_live` tinyint(4) COMMENT "Whether this is a live or test transaction"');
}
return TRUE;
}
}
......@@ -28,12 +28,14 @@ class CRM_Stripe_Utils_Check_Webhook {
try {
$webhooks = \Stripe\WebhookEndpoint::all(["limit" => 100]);
}
catch (\Stripe\Error\Authentication $e) {
catch (Exception $e) {
$error = $e->getMessage();
$messages[] = new CRM_Utils_Check_Message(
'stripe_webhook',
E::ts('The %1 (%2) Payment Processor has an invalid API key', [
E::ts('The %1 (%2) Payment Processor has an error: %3', [
1 => $pp['name'],
2 => $pp['id'],
3 => $error,
]),
E::ts('Stripe - API Key'),
\Psr\Log\LogLevel::ERROR,
......
<?php
/**
* This api cleans up old data / tables in Stripe.
*
* This api should only be used if you have read the documentation and understand what it does.
*/
/**
* Stripe.Cleanup API specification
*
* @param array $spec description of fields supported by this API call
*
* @return void
*/
function _civicrm_api3_stripe_Cleanup_spec(&$spec) {
$spec['confirm'] = [
'api.required' => TRUE,
'type' => CRM_Utils_Type::T_BOOLEAN,
'title' => 'Set this to TRUE to execute this API function',
];
}
/**
* Stripe.Cleanup API
*
* @param $params
*
* @return array
* @throws \CiviCRM_API3_Exception
*/
function civicrm_api3_stripe_Cleanup($params) {
if (empty($params['confirm'])) {
throw new CiviCRM_API3_Exception('You must set the parameter "confirm" to run the Stripe.cleanup API');
}
CRM_Core_DAO::executeQuery('DROP TABLE IF EXISTS civicrm_stripe_plans');
CRM_Core_DAO::executeQuery('DROP TABLE IF EXISTS civicrm_stripe_subscriptions');
if (CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_stripe_customers', 'is_live')) {
CRM_Core_DAO::executeQuery('ALTER TABLE `civicrm_stripe_customers` DROP COLUMN `is_live`');
}
if (CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_stripe_customers', 'email')) {
CRM_Core_DAO::executeQuery('ALTER TABLE `civicrm_stripe_customers` DROP COLUMN `email`');
}
return civicrm_api3_create_success([]);
}
......@@ -3,19 +3,23 @@ This extension comes with several APIs to help you troubleshoot problems. These
The api commands are:
* `Listevents`: Events are the notifications that Stripe sends to the Webhook. Listevents will list all notifications that have been sent. You can further restrict them with the following parameters:
* `ppid` - Use the given Payment Processor ID. By default, uses the saved, live Stripe payment processor and throws an error if there is more than one.
* `type` - Limit to the given Stripe events type. By default, show invoice.payment_succeeded. Change to 'all' to show all.
* `output` - What information to show. Defaults to 'brief' which provides a summary. Alternatively use raw to get the raw JSON returned by Stripe.
* `limit` - Limit number of results returned (100 is max, 10 is default).
* `starting_after` - Only return results after this event id. This can be used for paging purposes - if you want to retreive more than 100 results.
* `Populatelog`: If you are running a version of CiviCRM that supports the SystemLog - then this API call will populate your SystemLog with all of your past Stripe Events. You can safely re-run and not create duplicates. With a populated SystemLog - you can selectively replay events that may have caused errors the first time or otherwise not been properly recorded. Parameters:
* `ppid` - Use the given Payment Processor ID. By default, uses the saved, live Stripe payment processor and throws an error if there is more than one.
* `Ipn`: Replay a given Stripe Event. Parameters. This will always fetch the chosen Event from Stripe before replaying.
* `id` - The id from the SystemLog of the event to replay.
* `evtid` - The Event ID as provided by Stripe.
* `ppid` - Use the given Payment Processor ID. By default, uses the saved, live Stripe payment processor and throws an error if there is more than one.
* `noreceipt` - Set to 1 if you want to suppress the generation of receipts or set to 0 or leave out to send receipts normally.
* `Listevents`: Events are the notifications that Stripe sends to the Webhook. Listevents will list all notifications that have been sent. You can further restrict them with the following parameters:
* `ppid` - Use the given Payment Processor ID. By default, uses the saved, live Stripe payment processor and throws an error if there is more than one.
* `type` - Limit to the given Stripe events type. By default, show invoice.payment_succeeded. Change to 'all' to show all.
* `output` - What information to show. Defaults to 'brief' which provides a summary. Alternatively use raw to get the raw JSON returned by Stripe.
* `limit` - Limit number of results returned (100 is max, 10 is default).
* `starting_after` - Only return results after this event id. This can be used for paging purposes - if you want to retreive more than 100 results.
* `Populatelog`: If you are running a version of CiviCRM that supports the SystemLog - then this API call will populate your SystemLog with all of your past Stripe Events. You can safely re-run and not create duplicates. With a populated SystemLog - you can selectively replay events that may have caused errors the first time or otherwise not been properly recorded. Parameters:
* `ppid` - Use the given Payment Processor ID. By default, uses the saved, live Stripe payment processor and throws an error if there is more than one.
* `Ipn`: Replay a given Stripe Event. Parameters. This will always fetch the chosen Event from Stripe before replaying.
* `id` - The id from the SystemLog of the event to replay.
* `evtid` - The Event ID as provided by Stripe.
* `ppid` - Use the given Payment Processor ID. By default, uses the saved, live Stripe payment processor and throws an error if there is more than one.
* `noreceipt` - Set to 1 if you want to suppress the generation of receipts or set to 0 or leave out to send receipts normally.
* `Cleanup`: Cleanup and remove old database tables/fields that are no longer required.
## StripeCustomer
......
/* Remove Stripe tables on uninstall. */
DROP TABLE civicrm_stripe_customers;
DROP TABLE IF EXISTS civicrm_stripe_customers;
DROP TABLE IF EXISTS civicrm_stripe_plans;
DROP TABLE IF EXISTS civicrm_stripe_subscriptions;
\ No newline at end of file