From 3c536a114b80827049d1152cbfc048c8d5f94346 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Sun, 14 Jun 2015 12:23:01 +1200 Subject: [PATCH] CRM-16675 move functions only used by (deprecated) contribution processor to that class --- CRM/Contribute/BAO/Contribution/Utils.php | 292 +-------------------- bin/ContributionProcessor.php | 299 +++++++++++++++++++++- 2 files changed, 294 insertions(+), 297 deletions(-) diff --git a/CRM/Contribute/BAO/Contribution/Utils.php b/CRM/Contribute/BAO/Contribution/Utils.php index a94aea1923..921ab5d69e 100644 --- a/CRM/Contribute/BAO/Contribution/Utils.php +++ b/CRM/Contribute/BAO/Contribution/Utils.php @@ -382,15 +382,13 @@ class CRM_Contribute_BAO_Contribution_Utils { } /** - * Get the contribution details by month - * of the year + * Get the contribution details by month of the year. * * @param int $param * Year. * * @return array * associated array - * */ public static function contributionChartMonthly($param) { if ($param) { @@ -430,7 +428,6 @@ INNER JOIN civicrm_contact AS contact ON ( contact.id = contrib.contact_id ) * * @return array * associated array - * */ public static function contributionChartYearly() { $config = CRM_Core_Config::singleton(); @@ -561,293 +558,6 @@ INNER JOIN civicrm_contact contact ON ( contact.id = contrib.contact_id ) return TRUE; } - /** - * @param array $apiParams - * @param $mapper - * @param string $type - * @param bool $category - * - * @return array - */ - public static function formatAPIParams($apiParams, $mapper, $type = 'paypal', $category = TRUE) { - $type = strtolower($type); - - if (!in_array($type, array( - 'paypal', - 'google', - 'csv', - )) - ) { - // return the params as is - return $apiParams; - } - $params = $transaction = array(); - - if ($type == 'paypal') { - foreach ($apiParams as $detail => $val) { - if (isset($mapper['contact'][$detail])) { - $params[$mapper['contact'][$detail]] = $val; - } - elseif (isset($mapper['location'][$detail])) { - $params['address'][1][$mapper['location'][$detail]] = $val; - } - elseif (isset($mapper['transaction'][$detail])) { - switch ($detail) { - case 'l_period2': - // Sadly, PayPal seems to send two distinct data elements in a single field, - // so we break them out here. This is somewhat ugly and tragic. - $freqUnits = array( - 'D' => 'day', - 'W' => 'week', - 'M' => 'month', - 'Y' => 'year', - ); - list($frequency_interval, $frequency_unit) = explode(' ', $val); - $transaction['frequency_interval'] = $frequency_interval; - $transaction['frequency_unit'] = $freqUnits[$frequency_unit]; - break; - - case 'subscriptiondate': - case 'timestamp': - // PayPal dates are in ISO-8601 format. We need a format that - // MySQL likes - $unix_timestamp = strtotime($val); - $transaction[$mapper['transaction'][$detail]] = date('YmdHis', $unix_timestamp); - break; - - case 'note': - case 'custom': - case 'l_number0': - if ($val) { - $val = "[PayPal_field:{$detail}] {$val}"; - $transaction[$mapper['transaction'][$detail]] = !empty($transaction[$mapper['transaction'][$detail]]) ? $transaction[$mapper['transaction'][$detail]] . "
" . $val : $val; - } - break; - - default: - $transaction[$mapper['transaction'][$detail]] = $val; - } - } - } - - if (!empty($transaction) && $category) { - $params['transaction'] = $transaction; - } - else { - $params += $transaction; - } - - self::_fillCommonParams($params, $type); - - return $params; - } - - if ($type == 'csv') { - $header = $apiParams['header']; - unset($apiParams['header']); - foreach ($apiParams as $key => $val) { - if (isset($mapper['contact'][$header[$key]])) { - $params[$mapper['contact'][$header[$key]]] = $val; - } - elseif (isset($mapper['location'][$header[$key]])) { - $params['address'][1][$mapper['location'][$header[$key]]] = $val; - } - elseif (isset($mapper['transaction'][$header[$key]])) { - $transaction[$mapper['transaction'][$header[$key]]] = $val; - } - else { - $params[$header[$key]] = $val; - } - } - - if (!empty($transaction) && $category) { - $params['transaction'] = $transaction; - } - else { - $params += $transaction; - } - - self::_fillCommonParams($params, $type); - - return $params; - } - - if ($type == 'google') { - // return if response smell invalid - if (!array_key_exists('risk-information-notification', $apiParams[1][$apiParams[0]]['notifications'])) { - return FALSE; - } - $riskInfo = &$apiParams[1][$apiParams[0]]['notifications']['risk-information-notification']; - - if (array_key_exists('new-order-notification', $apiParams[1][$apiParams[0]]['notifications'])) { - $newOrder = &$apiParams[1][$apiParams[0]]['notifications']['new-order-notification']; - } - - if ($riskInfo['google-order-number']['VALUE'] == $apiParams[2]['google-order-number']['VALUE']) { - foreach ($riskInfo['risk-information']['billing-address'] as $field => $info) { - if (!empty($mapper['location'][$field])) { - $params['address'][1][$mapper['location'][$field]] = $info['VALUE']; - } - elseif (!empty($mapper['contact'][$field])) { - if ($newOrder && !empty($newOrder['buyer-billing-address']['structured-name'])) { - foreach ($newOrder['buyer-billing-address']['structured-name'] as $namePart => $nameValue) { - $params[$mapper['contact'][$namePart]] = $nameValue['VALUE']; - } - } - else { - $params[$mapper['contact'][$field]] = $info['VALUE']; - } - } - elseif (!empty($mapper['transaction'][$field])) { - $transaction[$mapper['transaction'][$field]] = $info['VALUE']; - } - } - - // Response is an huge array. Lets pickup only those which we ineterested in - // using a local mapper, rather than traversing the entire array. - $localMapper = array( - 'google-order-number' => $riskInfo['google-order-number']['VALUE'], - 'total-charge-amount' => $apiParams[2]['total-charge-amount']['VALUE'], - 'currency' => $apiParams[2]['total-charge-amount']['currency'], - 'item-name' => $newOrder['shopping-cart']['items']['item']['item-name']['VALUE'], - 'timestamp' => $apiParams[2]['timestamp']['VALUE'], - ); - if (array_key_exists('latest-charge-fee', $apiParams[2])) { - $localMapper['latest-charge-fee'] = $apiParams[2]['latest-charge-fee']['total']['VALUE']; - $localMapper['net-amount'] = $localMapper['total-charge-amount'] - $localMapper['latest-charge-fee']; - } - - // This is a subscription (recurring) donation. - if (array_key_exists('subscription', $newOrder['shopping-cart']['items']['item'])) { - $subscription = $newOrder['shopping-cart']['items']['item']['subscription']; - $localMapper['amount'] = $newOrder['order-total']['VALUE']; - $localMapper['times'] = $subscription['payments']['subscription-payment']['times']; - // Convert Google's period to one compatible with the CiviCRM db field. - $freqUnits = array( - 'DAILY' => 'day', - 'WEEKLY' => 'week', - 'MONHTLY' => 'month', - 'YEARLY' => 'year', - ); - $localMapper['period'] = $freqUnits[$subscription['period']]; - // Unlike PayPal, Google has no concept of freq. interval, it is always 1. - $localMapper['frequency_interval'] = '1'; - // Google Checkout dates are in ISO-8601 format. We need a format that - // MySQL likes - $unix_timestamp = strtotime($localMapper['timestamp']); - $mysql_date = date('YmdHis', $unix_timestamp); - $localMapper['modified_date'] = $mysql_date; - $localMapper['start_date'] = $mysql_date; - // This is PayPal's nomenclature, but just use it for Google as well since - // we act on the value of trxn_type in processAPIContribution(). - $localMapper['trxn_type'] = 'subscrpayment'; - } - - foreach ($localMapper as $localKey => $localVal) { - if (!empty($mapper['transaction'][$localKey])) { - $transaction[$mapper['transaction'][$localKey]] = $localVal; - } - } - - if (empty($params) && empty($transaction)) { - continue; - } - - if (!empty($transaction) && $category) { - $params['transaction'] = $transaction; - } - else { - $params += $transaction; - } - - self::_fillCommonParams($params, $type); - } - return $params; - } - } - - /** - * @param array $params - * - * @return bool - */ - public static function processAPIContribution($params) { - if (empty($params) || array_key_exists('error', $params)) { - return FALSE; - } - - // add contact using dedupe rule - $dedupeParams = CRM_Dedupe_Finder::formatParams($params, 'Individual'); - $dedupeParams['check_permission'] = FALSE; - $dupeIds = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual'); - // if we find more than one contact, use the first one - if (!empty($dupeIds[0])) { - $params['contact_id'] = $dupeIds[0]; - } - $contact = CRM_Contact_BAO_Contact::create($params); - if (!$contact->id) { - return FALSE; - } - - // only pass transaction params to contribution::create, if available - if (array_key_exists('transaction', $params)) { - $params = $params['transaction']; - $params['contact_id'] = $contact->id; - } - - // handle contribution custom data - $customFields = CRM_Core_BAO_CustomField::getFields('Contribution', - FALSE, - FALSE, - CRM_Utils_Array::value('financial_type_id', - $params - ) - ); - $params['custom'] = CRM_Core_BAO_CustomField::postProcess($params, - CRM_Utils_Array::value('id', $params, NULL), - 'Contribution' - ); - // create contribution - - // if this is a recurring contribution then process it first - if ($params['trxn_type'] == 'subscrpayment') { - // see if a recurring record already exists - $recurring = new CRM_Contribute_BAO_ContributionRecur(); - $recurring->processor_id = $params['processor_id']; - if (!$recurring->find(TRUE)) { - $recurring = new CRM_Contribute_BAO_ContributionRecur(); - $recurring->invoice_id = $params['invoice_id']; - $recurring->find(TRUE); - } - - // This is the same thing the CiviCRM IPN handler does to handle - // subsequent recurring payments to avoid duplicate contribution - // errors due to invoice ID. See: - // ./CRM/Core/Payment/PayPalIPN.php:200 - if ($recurring->id) { - $params['invoice_id'] = md5(uniqid(rand(), TRUE)); - } - - $recurring->copyValues($params); - $recurring->save(); - if (is_a($recurring, 'CRM_Core_Error')) { - return FALSE; - } - else { - $params['contribution_recur_id'] = $recurring->id; - } - } - - $contribution = &CRM_Contribute_BAO_Contribution::create($params, - CRM_Core_DAO::$_nullArray - ); - if (!$contribution->id) { - return FALSE; - } - - return TRUE; - } - /** * @param int $contactID * diff --git a/bin/ContributionProcessor.php b/bin/ContributionProcessor.php index 45bd0b5229..e6f23f43ad 100644 --- a/bin/ContributionProcessor.php +++ b/bin/ContributionProcessor.php @@ -213,7 +213,7 @@ class CiviContributeProcessor { continue; } - $params = CRM_Contribute_BAO_Contribution_Utils::formatAPIParams($trxnDetails, + $params = self::formatAPIParams($trxnDetails, self::$_paypalParamsMapper, 'paypal' ); @@ -224,7 +224,7 @@ class CiviContributeProcessor { $params['transaction']['is_test'] = 0; } - if (CRM_Contribute_BAO_Contribution_Utils::processAPIContribution($params)) { + if (self::processAPIContribution($params)) { CRM_Core_Error::debug_log_message("Processed - {$trxnDetails['email']}, {$trxnDetails['amt']}, {$value} ..

", TRUE); } else { @@ -291,7 +291,7 @@ class CiviContributeProcessor { // append amount information as well $response[] = $amtData; - $params = CRM_Contribute_BAO_Contribution_Utils::formatAPIParams($response, + $params = self::formatAPIParams($response, self::$_googleParamsMapper, 'google' ); @@ -301,7 +301,7 @@ class CiviContributeProcessor { else { $params['transaction']['is_test'] = 0; } - if (CRM_Contribute_BAO_Contribution_Utils::processAPIContribution($params)) { + if (self::processAPIContribution($params)) { CRM_Core_Error::debug_log_message("Processed - {$params['email']}, {$amtData['total-charge-amount']['VALUE']}, {$amtData['google-order-number']['VALUE']} ..

", TRUE); } else { @@ -331,11 +331,11 @@ class CiviContributeProcessor { while (($data = fgetcsv($handle, 1000, $delimiter)) !== FALSE) { if ($row !== 1) { $data['header'] = $header; - $params = CRM_Contribute_BAO_Contribution_Utils::formatAPIParams($data, + $params = self::formatAPIParams($data, self::$_csvParamsMapper, 'csv' ); - if (CRM_Contribute_BAO_Contribution_Utils::processAPIContribution($params)) { + if (self::processAPIContribution($params)) { CRM_Core_Error::debug_log_message("Processed - line $row of csv file .. {$params['email']}, {$params['transaction']['total_amount']}, {$params['transaction']['trxn_id']} ..

", TRUE); } else { @@ -399,6 +399,293 @@ class CiviContributeProcessor { } } + /** + * @param array $apiParams + * @param $mapper + * @param string $type + * @param bool $category + * + * @return array + */ + public static function formatAPIParams($apiParams, $mapper, $type = 'paypal', $category = TRUE) { + $type = strtolower($type); + + if (!in_array($type, array( + 'paypal', + 'google', + 'csv', + )) + ) { + // return the params as is + return $apiParams; + } + $params = $transaction = array(); + + if ($type == 'paypal') { + foreach ($apiParams as $detail => $val) { + if (isset($mapper['contact'][$detail])) { + $params[$mapper['contact'][$detail]] = $val; + } + elseif (isset($mapper['location'][$detail])) { + $params['address'][1][$mapper['location'][$detail]] = $val; + } + elseif (isset($mapper['transaction'][$detail])) { + switch ($detail) { + case 'l_period2': + // Sadly, PayPal seems to send two distinct data elements in a single field, + // so we break them out here. This is somewhat ugly and tragic. + $freqUnits = array( + 'D' => 'day', + 'W' => 'week', + 'M' => 'month', + 'Y' => 'year', + ); + list($frequency_interval, $frequency_unit) = explode(' ', $val); + $transaction['frequency_interval'] = $frequency_interval; + $transaction['frequency_unit'] = $freqUnits[$frequency_unit]; + break; + + case 'subscriptiondate': + case 'timestamp': + // PayPal dates are in ISO-8601 format. We need a format that + // MySQL likes + $unix_timestamp = strtotime($val); + $transaction[$mapper['transaction'][$detail]] = date('YmdHis', $unix_timestamp); + break; + + case 'note': + case 'custom': + case 'l_number0': + if ($val) { + $val = "[PayPal_field:{$detail}] {$val}"; + $transaction[$mapper['transaction'][$detail]] = !empty($transaction[$mapper['transaction'][$detail]]) ? $transaction[$mapper['transaction'][$detail]] . "
" . $val : $val; + } + break; + + default: + $transaction[$mapper['transaction'][$detail]] = $val; + } + } + } + + if (!empty($transaction) && $category) { + $params['transaction'] = $transaction; + } + else { + $params += $transaction; + } + + CRM_Contribute_BAO_Contribution_Utils::_fillCommonParams($params, $type); + + return $params; + } + + if ($type == 'csv') { + $header = $apiParams['header']; + unset($apiParams['header']); + foreach ($apiParams as $key => $val) { + if (isset($mapper['contact'][$header[$key]])) { + $params[$mapper['contact'][$header[$key]]] = $val; + } + elseif (isset($mapper['location'][$header[$key]])) { + $params['address'][1][$mapper['location'][$header[$key]]] = $val; + } + elseif (isset($mapper['transaction'][$header[$key]])) { + $transaction[$mapper['transaction'][$header[$key]]] = $val; + } + else { + $params[$header[$key]] = $val; + } + } + + if (!empty($transaction) && $category) { + $params['transaction'] = $transaction; + } + else { + $params += $transaction; + } + + CRM_Contribute_BAO_Contribution_Utils::_fillCommonParams($params, $type); + + return $params; + } + + if ($type == 'google') { + // return if response smell invalid + if (!array_key_exists('risk-information-notification', $apiParams[1][$apiParams[0]]['notifications'])) { + return FALSE; + } + $riskInfo = &$apiParams[1][$apiParams[0]]['notifications']['risk-information-notification']; + + if (array_key_exists('new-order-notification', $apiParams[1][$apiParams[0]]['notifications'])) { + $newOrder = &$apiParams[1][$apiParams[0]]['notifications']['new-order-notification']; + } + + if ($riskInfo['google-order-number']['VALUE'] == $apiParams[2]['google-order-number']['VALUE']) { + foreach ($riskInfo['risk-information']['billing-address'] as $field => $info) { + if (!empty($mapper['location'][$field])) { + $params['address'][1][$mapper['location'][$field]] = $info['VALUE']; + } + elseif (!empty($mapper['contact'][$field])) { + if ($newOrder && !empty($newOrder['buyer-billing-address']['structured-name'])) { + foreach ($newOrder['buyer-billing-address']['structured-name'] as $namePart => $nameValue) { + $params[$mapper['contact'][$namePart]] = $nameValue['VALUE']; + } + } + else { + $params[$mapper['contact'][$field]] = $info['VALUE']; + } + } + elseif (!empty($mapper['transaction'][$field])) { + $transaction[$mapper['transaction'][$field]] = $info['VALUE']; + } + } + + // Response is an huge array. Lets pickup only those which we ineterested in + // using a local mapper, rather than traversing the entire array. + $localMapper = array( + 'google-order-number' => $riskInfo['google-order-number']['VALUE'], + 'total-charge-amount' => $apiParams[2]['total-charge-amount']['VALUE'], + 'currency' => $apiParams[2]['total-charge-amount']['currency'], + 'item-name' => $newOrder['shopping-cart']['items']['item']['item-name']['VALUE'], + 'timestamp' => $apiParams[2]['timestamp']['VALUE'], + ); + if (array_key_exists('latest-charge-fee', $apiParams[2])) { + $localMapper['latest-charge-fee'] = $apiParams[2]['latest-charge-fee']['total']['VALUE']; + $localMapper['net-amount'] = $localMapper['total-charge-amount'] - $localMapper['latest-charge-fee']; + } + + // This is a subscription (recurring) donation. + if (array_key_exists('subscription', $newOrder['shopping-cart']['items']['item'])) { + $subscription = $newOrder['shopping-cart']['items']['item']['subscription']; + $localMapper['amount'] = $newOrder['order-total']['VALUE']; + $localMapper['times'] = $subscription['payments']['subscription-payment']['times']; + // Convert Google's period to one compatible with the CiviCRM db field. + $freqUnits = array( + 'DAILY' => 'day', + 'WEEKLY' => 'week', + 'MONHTLY' => 'month', + 'YEARLY' => 'year', + ); + $localMapper['period'] = $freqUnits[$subscription['period']]; + // Unlike PayPal, Google has no concept of freq. interval, it is always 1. + $localMapper['frequency_interval'] = '1'; + // Google Checkout dates are in ISO-8601 format. We need a format that + // MySQL likes + $unix_timestamp = strtotime($localMapper['timestamp']); + $mysql_date = date('YmdHis', $unix_timestamp); + $localMapper['modified_date'] = $mysql_date; + $localMapper['start_date'] = $mysql_date; + // This is PayPal's nomenclature, but just use it for Google as well since + // we act on the value of trxn_type in processAPIContribution(). + $localMapper['trxn_type'] = 'subscrpayment'; + } + + foreach ($localMapper as $localKey => $localVal) { + if (!empty($mapper['transaction'][$localKey])) { + $transaction[$mapper['transaction'][$localKey]] = $localVal; + } + } + + if (empty($params) && empty($transaction)) { + continue; + } + + if (!empty($transaction) && $category) { + $params['transaction'] = $transaction; + } + else { + $params += $transaction; + } + + CRM_Contribute_BAO_Contribution_Utils::_fillCommonParams($params, $type); + } + return $params; + } + } + + /** + * @param array $params + * + * @return bool + */ + public static function processAPIContribution($params) { + if (empty($params) || array_key_exists('error', $params)) { + return FALSE; + } + + // add contact using dedupe rule + $dedupeParams = CRM_Dedupe_Finder::formatParams($params, 'Individual'); + $dedupeParams['check_permission'] = FALSE; + $dupeIds = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual'); + // if we find more than one contact, use the first one + if (!empty($dupeIds[0])) { + $params['contact_id'] = $dupeIds[0]; + } + $contact = CRM_Contact_BAO_Contact::create($params); + if (!$contact->id) { + return FALSE; + } + + // only pass transaction params to contribution::create, if available + if (array_key_exists('transaction', $params)) { + $params = $params['transaction']; + $params['contact_id'] = $contact->id; + } + + // handle contribution custom data + $customFields = CRM_Core_BAO_CustomField::getFields('Contribution', + FALSE, + FALSE, + CRM_Utils_Array::value('financial_type_id', + $params + ) + ); + $params['custom'] = CRM_Core_BAO_CustomField::postProcess($params, + CRM_Utils_Array::value('id', $params, NULL), + 'Contribution' + ); + // create contribution + + // if this is a recurring contribution then process it first + if ($params['trxn_type'] == 'subscrpayment') { + // see if a recurring record already exists + $recurring = new CRM_Contribute_BAO_ContributionRecur(); + $recurring->processor_id = $params['processor_id']; + if (!$recurring->find(TRUE)) { + $recurring = new CRM_Contribute_BAO_ContributionRecur(); + $recurring->invoice_id = $params['invoice_id']; + $recurring->find(TRUE); + } + + // This is the same thing the CiviCRM IPN handler does to handle + // subsequent recurring payments to avoid duplicate contribution + // errors due to invoice ID. See: + // ./CRM/Core/Payment/PayPalIPN.php:200 + if ($recurring->id) { + $params['invoice_id'] = md5(uniqid(rand(), TRUE)); + } + + $recurring->copyValues($params); + $recurring->save(); + if (is_a($recurring, 'CRM_Core_Error')) { + return FALSE; + } + else { + $params['contribution_recur_id'] = $recurring->id; + } + } + + $contribution = &CRM_Contribute_BAO_Contribution::create($params, + CRM_Core_DAO::$_nullArray + ); + if (!$contribution->id) { + return FALSE; + } + + return TRUE; + } + } // bootstrap the environment and run the processor -- 2.25.1