From: Eileen McNaughton Date: Tue, 7 Jul 2015 10:16:53 +0000 (+1200) Subject: CRM-16737 spport either payment_status_id OR contribution_status_id as processor... X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=b5eacf76c81caf96eb23828b557333abc44f48c3;p=civicrm-core.git CRM-16737 spport either payment_status_id OR contribution_status_id as processor return status In 4.6 the idea is a payment processor can return payment_status_id or contribution_status_id to denote outcome of payment, in 4.7 contribution_status_id is to be removed --- diff --git a/CRM/Member/Form/Membership.php b/CRM/Member/Form/Membership.php index d41d8ae775..ee8f992bbc 100644 --- a/CRM/Member/Form/Membership.php +++ b/CRM/Member/Form/Membership.php @@ -1425,6 +1425,12 @@ WHERE id IN ( ' . implode(' , ', array_keys($membershipType)) . ' )'; if (isset($result['contribution_status_id'])) { $params['contribution_status_id'] = $result['contribution_status_id']; } + elseif (isset($result['payment_status_id'])) { + // CRM-16737 $result['contribution_status_id'] is deprecated in favour + // of payment_status_id as the payment processor only knows whether the payment is complete + // not whether payment completes the contribution + $params['contribution_status_id'] = $params['payment_status_id']; + } // do what used to happen previously else { $params['contribution_status_id'] = !empty($paymentParams['is_recur']) ? 2 : 1; diff --git a/tests/phpunit/api/v3/ContributionPageTest.php b/tests/phpunit/api/v3/ContributionPageTest.php index 62267179d0..ab7fad4a39 100644 --- a/tests/phpunit/api/v3/ContributionPageTest.php +++ b/tests/phpunit/api/v3/ContributionPageTest.php @@ -263,6 +263,72 @@ class api_v3_ContributionPageTest extends CiviUnitTestCase { * - create another - end date should be extended */ public function testSubmitMembershipPriceSetPaymentPaymentProcessorRecur() { + $this->params['is_recur'] = 1; + $var = array(); + $this->params['recur_frequency_unit'] = 'month'; + $this->setUpMembershipContributionPage(); + $dummyPP = CRM_Core_Payment::singleton('live', $this->_paymentProcessor); + $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success')); + + $submitParams = array( + 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']), + 'id' => (int) $this->_ids['contribution_page'], + 'amount' => 10, + 'billing_first_name' => 'Billy', + 'billing_middle_name' => 'Goat', + 'billing_last_name' => 'Gruff', + 'email' => 'billy@goat.gruff', + 'selectMembership' => $this->_ids['membership_type'], + 'payment_processor' => 1, + 'credit_card_number' => '4111111111111111', + 'credit_card_type' => 'Visa', + 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040), + 'cvv2' => 123, + 'is_recur' => 1, + 'frequency_interval' => 1, + 'frequency_unit' => 'month', + ); + + $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL); + $contribution = $this->callAPISuccess('contribution', 'getsingle', array( + 'contribution_page_id' => $this->_ids['contribution_page'], + 'contribution_status_id' => 1, + )); + $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array()); + $this->assertEquals($membershipPayment['contribution_id'], $contribution['id']); + $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id'])); + $this->assertEquals($membership['contact_id'], $contribution['contact_id']); + $this->assertEquals(1, $membership['status_id']); + $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id'])); + //@todo - check with Joe about these not existing + //$this->callAPISuccess('line_item', 'getsingle', array('contribution_id' => $contribution['id'], 'entity_id' => $membership['id'])); + //renew it with processor setting completed - should extend membership + $submitParams['contact_id'] = $contribution['contact_id']; + $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_second_success')); + $this->callAPISuccess('contribution_page', 'submit', $submitParams); + $this->callAPISuccess('contribution', 'getsingle', array( + 'id' => array('NOT IN' => array($contribution['id'])), + 'contribution_page_id' => $this->_ids['contribution_page'], + 'contribution_status_id' => 1, + )); + $renewedMembership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id'])); + $this->assertEquals(date('Y-m-d', strtotime('+ 1 year', strtotime($membership['end_date']))), $renewedMembership['end_date']); + $recurringContribution = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id'])); + $this->assertEquals(2, $recurringContribution['contribution_status_id']); + } + + /** + * Test submit recurring membership with immediate confirmation (IATS style). + * + * Per CRM-16737 we are deprecating the use of contribution_status_id to indicate success in favour of + * payment_status_id. + * + * - we process 2 membership transactions against with a recurring contribution against a contribution page with an immediate + * processor (IATS style - denoted by returning trxn_id) + * - the first creates a new membership, completed contribution, in progress recurring. Check these + * - create another - end date should be extended + */ + public function testLegacySubmitMembershipPriceSetPaymentPaymentProcessorRecur() { $this->params['is_recur'] = 1; $var = array(); $this->params['recur_frequency_unit'] = 'month'; @@ -326,6 +392,87 @@ class api_v3_ContributionPageTest extends CiviUnitTestCase { * - create another - end date should NOT be extended */ public function testSubmitMembershipPriceSetPaymentPaymentProcessorRecurDelayed() { + $this->params['is_recur'] = 1; + $this->params['recur_frequency_unit'] = 'month'; + $this->setUpMembershipContributionPage(); + $dummyPP = CRM_Core_Payment::singleton('live', $this->_paymentProcessor); + $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 2)); + + $submitParams = array( + 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']), + 'id' => (int) $this->_ids['contribution_page'], + 'amount' => 10, + 'billing_first_name' => 'Billy', + 'billing_middle_name' => 'Goat', + 'billing_last_name' => 'Gruff', + 'email' => 'billy@goat.gruff', + 'selectMembership' => $this->_ids['membership_type'], + 'payment_processor' => 1, + 'credit_card_number' => '4111111111111111', + 'credit_card_type' => 'Visa', + 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040), + 'cvv2' => 123, + 'is_recur' => 1, + 'frequency_interval' => 1, + 'frequency_unit' => 'month', + ); + + $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL); + $contribution = $this->callAPISuccess('contribution', 'getsingle', array( + 'contribution_page_id' => $this->_ids['contribution_page'], + 'contribution_status_id' => 2, + )); + $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array()); + $this->assertEquals($membershipPayment['contribution_id'], $contribution['id']); + $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id'])); + $this->assertEquals($membership['contact_id'], $contribution['contact_id']); + $this->assertEquals(5, $membership['status_id']); + //@todo - check with Joe about these not existing + //$this->callAPISuccess('line_item', 'getsingle', array('contribution_id' => $contribution['id'], 'entity_id' => $membership['id'])); + $this->callAPISuccess('contribution', 'completetransaction', array( + 'id' => $contribution['id'], + 'trxn_id' => 'ipn_called', + )); + $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id'])); + //renew it with processor setting completed - should extend membership + $submitParams = array_merge($submitParams, array( + 'contact_id' => $contribution['contact_id'], + 'is_recur' => 1, + 'frequency_interval' => 1, + 'frequency_unit' => 'month', + ) + ); + $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 2)); + $this->callAPISuccess('contribution_page', 'submit', $submitParams); + $newContribution = $this->callAPISuccess('contribution', 'getsingle', array( + 'id' => array( + 'NOT IN' => array($contribution['id']), + ), + 'contribution_page_id' => $this->_ids['contribution_page'], + 'contribution_status_id' => 2, + ) + ); + + $renewedMembership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id'])); + //no renewal as the date hasn't changed + $this->assertEquals($membership['end_date'], $renewedMembership['end_date']); + $recurringContribution = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $newContribution['contribution_recur_id'])); + $this->assertEquals(2, $recurringContribution['contribution_status_id']); + } + + /** + * Test submit recurring membership with delayed confirmation (Authorize.net style) + * - we process 2 membership transactions against with a recurring contribution against a contribution page with a delayed + * processor (Authorize.net style - denoted by NOT returning trxn_id) + * + * Per CRM-16737 we are deprecating the use of contribution_status_id to indicate success in favour of + * payment_status_id. + * + * - the first creates a pending membership, pending contribution, pending recurring. Check these + * - complete the transaction + * - create another - end date should NOT be extended + */ + public function testLegacySubmitMembershipPriceSetPaymentPaymentProcessorRecurDelayed() { $this->params['is_recur'] = 1; $this->params['recur_frequency_unit'] = 'month'; $this->setUpMembershipContributionPage();