*
*/
class CRM_Core_Payment_AuthorizeNetIPN extends CRM_Core_Payment_BaseIPN {
+
/**
- * Constructor
+ * constructor function
+ *
+ * @param $inputData array contents of HTTP REQUEST
+ *
+ * @throws CRM_Core_Exception
*/
- function __construct() {
+ function __construct($inputData) {
+ $this->setInputParameters($inputData);
parent::__construct();
}
//we only get invoice num as a key player from payment gateway response.
//for ARB we get x_subscription_id and x_subscription_paynum
- $x_subscription_id = self::retrieve('x_subscription_id', 'String');
+ $x_subscription_id = $this->retrieve('x_subscription_id', 'String');
if ($x_subscription_id) {
//Approved
return $this->recur($input, $ids, $objects, $first);
}
}
+ return TRUE;
}
/**
* @param array $input
* @param array $ids
- * @param $objects
+ * @param array $objects
* @param $first
*
* @return bool
* @param $ids
*/
function getInput(&$input, &$ids) {
- $input['amount'] = self::retrieve('x_amount', 'String');
- $input['subscription_id'] = self::retrieve('x_subscription_id', 'Integer');
- $input['response_code'] = self::retrieve('x_response_code', 'Integer');
- $input['MD5_Hash'] = self::retrieve('x_MD5_Hash', 'String', FALSE, '');
- $input['response_reason_code'] = self::retrieve('x_response_reason_code', 'String', FALSE);
- $input['response_reason_text'] = self::retrieve('x_response_reason_text', 'String', FALSE);
- $input['subscription_paynum'] = self::retrieve('x_subscription_paynum', 'Integer', FALSE, 0);
- $input['trxn_id'] = self::retrieve('x_trans_id', 'String', FALSE);
+ $input['amount'] = $this->retrieve('x_amount', 'String');
+ $input['subscription_id'] = $this->retrieve('x_subscription_id', 'Integer');
+ $input['response_code'] = $this->retrieve('x_response_code', 'Integer');
+ $input['MD5_Hash'] = $this->retrieve('x_MD5_Hash', 'String', FALSE, '');
+ $input['response_reason_code'] = $this->retrieve('x_response_reason_code', 'String', FALSE);
+ $input['response_reason_text'] = $this->retrieve('x_response_reason_text', 'String', FALSE);
+ $input['subscription_paynum'] = $this->retrieve('x_subscription_paynum', 'Integer', FALSE, 0);
+ $input['trxn_id'] = $this->retrieve('x_trans_id', 'String', FALSE);
+
if ($input['trxn_id']) {
$input['is_test'] = 0;
}
"email-{$billingID}" => 'x_email',
);
foreach ($params as $civiName => $resName) {
- $input[$civiName] = self::retrieve($resName, 'String', FALSE);
+ $input[$civiName] = $this->retrieve($resName, 'String', FALSE);
}
}
* @param $input
*/
function getIDs(&$ids, &$input) {
- $ids['contact'] = self::retrieve('x_cust_id', 'Integer', FALSE, 0);
- $ids['contribution'] = self::retrieve('x_invoice_num', 'Integer');
+ $ids['contact'] = $this->retrieve('x_cust_id', 'Integer', FALSE, 0);
+ $ids['contribution'] = $this->retrieve('x_invoice_num', 'Integer');
// joining with contribution table for extra checks
$sql = "
}
/**
- * @param $name
- * @param $type
- * @param bool $abort
- * @param null $default
- * @param string $location
+ * @param string $name parameter name
+ * @param string $type parameter type
+ * @param bool $abort abort if not present
+ * @param null $default default value
*
+ * @throws CRM_Core_Exception
* @return mixed
*/
- static function retrieve($name, $type, $abort = TRUE, $default = NULL, $location = 'POST') {
- static $store = NULL;
- $value = CRM_Utils_Request::retrieve($name, $type, $store,
- FALSE, $default, $location
+ function retrieve($name, $type, $abort = TRUE, $default = NULL) {
+ $value = CRM_Utils_Type::validate(
+ empty($this->_inputParameters[$name]) ? $default : $this->_inputParameters[$name],
+ $type,
+ FALSE
);
if ($abort && $value === NULL) {
- CRM_Core_Error::debug_log_message("Could not find an entry for $name in $location");
- CRM_Core_Error::debug_var('POST', $_POST);
- CRM_Core_Error::debug_var('REQUEST', $_REQUEST);
- echo "Failure: Missing Parameter<p>";
- exit();
+ throw new CRM_Core_Exception("Could not find an entry for $name");
}
return $value;
- }
+}
/**
* @param $ids
* @var string component
*/
protected $_component = 'contribute';
+
/**
* constructor function
+ *
+ * @param array $inputData contents of HTTP REQUEST
+ *
+ * @throws CRM_Core_Exception
*/
function __construct($inputData) {
$this->setInputParameters($inputData);
$log = new CRM_Utils_SystemLogger();
$log->alert('payment_notification processor_name=AuthNet', $_REQUEST);
-$authorizeNetIPN = new CRM_Core_Payment_AuthorizeNetIPN();
-$authorizeNetIPN->main();
+$authorizeNetIPN = new CRM_Core_Payment_AuthorizeNetIPN($_REQUEST);
+try{
+ $authorizeNetIPN->main();
+}
+catch(CRM_Core_Exception $e) {
+ CRM_Core_Error::debug_log_message($e->getMessage());
+ CRM_Core_Error::debug_var('error data', $e->getErrorData(), TRUE, TRUE);
+ CRM_Core_Error::debug_var('REQUEST', $_REQUEST, TRUE, TRUE);
+ echo "The transaction has failed. Please review the log for more detail";
+}
+
--- /dev/null
+<?php
+
+require_once 'CiviTest/CiviUnitTestCase.php';
+
+/**
+ * Class CRM_Core_Payment_PayPalProIPNTest
+ */
+class CRM_Core_Payment_AuthorizeNetIPNTest extends CiviUnitTestCase {
+ protected $_contributionID;
+ protected $_invoiceID = 'c2r9c15f7be20b4f3fef1f77e4c37424';
+ protected $_financialTypeID = 1;
+ protected $_contactID;
+ protected $_contributionRecurID;
+ protected $_contributionPageID;
+ protected $_paymentProcessorID;
+
+ /**
+ * @return array
+ */
+ function get_info() {
+ return array(
+ 'name' => 'Authorize.net IPN processing',
+ 'description' => 'Authorize.net IPN methods.',
+ 'group' => 'Payment Processor Tests',
+ );
+ }
+
+ function setUp() {
+ parent::setUp();
+ $this->_paymentProcessorID = $this->paymentProcessorCreate(array(
+ 'payment_processor_type_id' => 'AuthNet',
+ ));
+ $this->_contactID = $this->individualCreate();
+ $contributionPage = $this->callAPISuccess('contribution_page', 'create', array(
+ 'title' => "Test Contribution Page",
+ 'financial_type_id' => $this->_financialTypeID,
+ 'currency' => 'USD',
+ 'payment_processor' => $this->_paymentProcessorID,
+ ));
+ $this->_contributionPageID = $contributionPage['id'];
+ }
+
+ function tearDown() {
+ $this->quickCleanUpFinancialEntities();
+ }
+
+ /**
+ * test IPN response updates contribution_recur & contribution for first & second contribution
+ */
+ function testIPNPaymentRecurSuccess() {
+ $this->setupRecurringPaymentProcessorTransaction();
+ $paypalIPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurTransaction());
+ $paypalIPN->main();
+ $contribution = $this->callAPISuccess('contribution', 'getsingle', array('id' => $this->_contributionID));
+ $this->assertEquals(1, $contribution['contribution_status_id']);
+ $this->assertEquals('6511143069', $contribution['trxn_id']);
+ // source gets set by processor
+ $this->assertTrue(substr($contribution['contribution_source'], 0, 20) == "Online Contribution:");
+ $contributionRecur = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $this->_contributionRecurID));
+ $this->assertEquals(5, $contributionRecur['contribution_status_id']);
+ $paypalIPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurSubsequentTransaction());
+ $paypalIPN->main();
+ $contribution = $this->callAPISuccess('contribution', 'get', array('contribution_recur_id' => $this->_contributionRecurID, 'sequential' => 1));
+ $this->assertEquals(2, $contribution['count']);
+ $this->assertEquals('second_one', $contribution['values'][1]['trxn_id']);
+ }
+
+ /**
+ *
+ */
+ function getRecurTransaction() {
+ return array(
+ "x_amount" => "200.00",
+ "x_country" => 'US',
+ "x_phone" => "",
+ "x_fax" => "",
+ "x_email" => "me@gmail.com",
+ "x_description" => "lots of money",
+ "x_type" => "auth_capture",
+ "x_ship_to_first_name" => "",
+ "x_ship_to_last_name" => "",
+ "x_ship_to_company" => "",
+ "x_ship_to_address" => "",
+ "x_ship_to_city" => "",
+ "x_ship_to_state" => "",
+ "x_ship_to_zip" => "",
+ "x_ship_to_country" => "",
+ "x_tax" => "0.00",
+ "x_duty" => "0.00",
+ "x_freight" => "0.00",
+ "x_tax_exempt" => "FALSE",
+ "x_po_num" => "",
+ "x_MD5_Hash" => "1B7C0C5B4DEDD9CAD0636E35E22FC594",
+ "x_cvv2_resp_code" => "",
+ "x_cavv_response" => "",
+ "x_test_request" => "false",
+ "x_subscription_id" => $this->_contributionRecurID,
+ "x_subscription_paynum" => "1",
+ 'x_first_name' => 'Robert',
+ 'x_zip' => '90210',
+ 'x_state' => 'WA',
+ 'x_city' => 'Dallas',
+ 'x_address' => '41 My ST',
+ 'x_invoice_num' => $this->_contributionID,
+ 'x_cust_id' => $this->_contactID,
+ 'x_company' => 'nowhere@civicrm.org',
+ 'x_last_name' => 'Roberts',
+ 'x_account_number' => 'XXXX5077',
+ 'x_card_type' => 'Visa',
+ 'x_method' => 'CC',
+ 'x_trans_id' => '6511143069',
+ 'x_auth_code' => '123456',
+ 'x_avs_code' => 'Z',
+ 'x_response_reason_text' => 'This transaction has been approved.',
+ 'x_response_reason_code' => '1',
+ 'x_response_code' => '1'
+ );
+ }
+
+ /**
+ * @return array
+ */
+ function getRecurSubsequentTransaction() {
+ return array_merge($this->getRecurTransaction(), array(
+ 'x_trans_id' => 'second_one',
+ 'x_MD5_Hash' => 'EA7A3CD65A85757827F51212CA1486A8',
+ ));
+ }
+}
// turn verifySSL off
CRM_Core_BAO_Setting::setItem('0', CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'verifySSL');
- $result = $this->processor->doDirectPayment($params);
+ $this->processor->doDirectPayment($params);
// turn verifySSL on
CRM_Core_BAO_Setting::setItem('0', CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'verifySSL');
function setUp() {
parent::setUp();
$this->input = $this->ids = $this->objects = array();
- $this->IPN = new CRM_Core_Payment_AuthorizeNetIPN();
+ $this->IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->input);
$this->_contactId = $this->individualCreate();
$this->ids['contact'] = $this->_contactId;
)
);
$this->_contributionPageID = $contributionPage['id'];
-
- $this->_financialTypeId = 1;
-
- // copier & paster from A.net - so have commenter out - uncomment if requirer
- //for some strange unknown reason, in batch more this value gets set to null
- // so crure hack here to avoir an exception anr hence an error
- //$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array( );
}
function tearDown() {
* test IPN response updates contribution_recur & contribution for first & second contribution
*/
function testIPNPaymentRecurSuccess() {
- $this->setupPaymentProcessorTransaction();
+ $this->setupRecurringPaymentProcessorTransaction();
$paypalIPN = new CRM_Core_Payment_PayPalProIPN($this->getPaypalProRecurTransaction());
$paypalIPN->main();
$contribution = $this->callAPISuccess('contribution', 'getsingle', array('id' => $this->_contributionID));
* will help future debuggers)
*/
function testIPNPaymentCRM13743() {
- $this->setupPaymentProcessorTransaction();
+ $this->setupRecurringPaymentProcessorTransaction();
$firstPaymentParams = $this->getPaypalProRecurTransaction();
$firstPaymentParams['txn_type'] = 'recurring_payment_failed';
$paypalIPN = new CRM_Core_Payment_PayPalProIPN($firstPaymentParams);
* Obviously if the behaviour is fixed then the test should be updated!
*/
function testIPNPaymentExpressNoError() {
- $this->setupPaymentProcessorTransaction();
+ $this->setupRecurringPaymentProcessorTransaction();
$paypalIPN = new CRM_Core_Payment_PayPalProIPN($this->getPaypalExpressTransactionIPN());
try{
$paypalIPN->main();
$this->fail('The Paypal Express IPN should have caused an exception');
}
-
- function setupPaymentProcessorTransaction() {
- $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', array(
- 'contact_id' => $this->_contactID,
- 'amount' => 1000,
- 'sequential' => 1,
- 'installments' => 5,
- 'frequency_unit' => 'Month',
- 'frequency_interval' => 1,
- 'invoice_id' => $this->_invoiceID,
- 'contribution_status_id' => 2,
- 'api.contribution.create' => array(
- 'total_amount' => '200',
- 'invoice_id' => $this->_invoiceID,
- 'financial_type_id' => 1,
- 'contribution_status_id' => 'Pending',
- 'contact_id' => $this->_contactID,
- 'contribution_page_id' => $this->_contributionPageID,
- 'payment_processor_id' => $this->_paymentProcessorID,
- )
- ));
- $this->_contributionRecurID = $contributionRecur['id'];
- $this->_contributionID = $contributionRecur['values']['0']['api.contribution.create']['id'];
- }
-
/**
* get PaymentExpress IPN for a single transaction
- * @return multitype:string
+ * @return array array representing a Paypal IPN POST
*/
function getPaypalExpressTransactionIPN() {
return array(
}
/**
- * Get IPN results from follow on IPN transations
- * @return multitype:string
+ * Get IPN results from follow on IPN transactions
+ * @return array array representing a Paypal IPN POST
*/
- function getSubsequentPaypalExpressTransation() {
+ function getSubsequentPaypalExpressTransaction() {
return array(
'mc_gross' => '5.00',
'period_type' => ' Regular',
*/
function getPaypalProRecurSubsequentTransaction() {
return array_merge($this->getPaypalProRecurTransaction(), array('txn_id' => 'secondone'));
- ;
}
}
$result = $this->callAPISuccess('payment_processor', 'create', $params);
return $result['id'];
}
+ /**
+ * Set up initial recurring payment allowing subsequent IPN payments
+ */
+ function setupRecurringPaymentProcessorTransaction() {
+ $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', array(
+ 'contact_id' => $this->_contactID,
+ 'amount' => 1000,
+ 'sequential' => 1,
+ 'installments' => 5,
+ 'frequency_unit' => 'Month',
+ 'frequency_interval' => 1,
+ 'invoice_id' => $this->_invoiceID,
+ 'contribution_status_id' => 2,
+ 'processor_id' => $this->_paymentProcessorID,
+ 'api.contribution.create' => array(
+ 'total_amount' => '200',
+ 'invoice_id' => $this->_invoiceID,
+ 'financial_type_id' => 1,
+ 'contribution_status_id' => 'Pending',
+ 'contact_id' => $this->_contactID,
+ 'contribution_page_id' => $this->_contributionPageID,
+ 'payment_processor_id' => $this->_paymentProcessorID,
+ )
+ ));
+ $this->_contributionRecurID = $contributionRecur['id'];
+ $this->_contributionID = $contributionRecur['values']['0']['api.contribution.create']['id'];
+ }
/**