/**
* Handle payment express IPNs.
+ *
* For one off IPNS no actual response is required
* Recurring is more difficult as we have limited confirmation material
* lets look up invoice id in recur_contribution & rely on the unique transaction id to ensure no
// as membership id etc can be derived by the load objects fn
$objects = $ids = $input = array();
$isFirst = FALSE;
+ $input['invoice'] = self::getValue('i', FALSE);
$input['txnType'] = $this->retrieve('txn_type', 'String');
- if ($input['txnType'] != 'recurring_payment') {
+ $contributionRecur = civicrm_api3('contribution_recur', 'getsingle', array(
+ 'return' => 'contact_id, id, payment_processor_id',
+ 'invoice_id' => $input['invoice'],
+ ));
+
+ if ($input['txnType'] !== 'recurring_payment' && $input['txnType'] !== 'recurring_payment_profile_created') {
throw new CRM_Core_Exception('Paypal IPNS not handled other than recurring_payments');
}
- $input['invoice'] = self::getValue('i', FALSE);
+
$this->getInput($input, $ids);
- if ($this->transactionExists($input['trxn_id'])) {
+ if ($input['txnType'] === 'recurring_payment' && $this->transactionExists($input['trxn_id'])) {
throw new CRM_Core_Exception('This transaction has already been processed');
}
- $contributionRecur = civicrm_api3('contribution_recur', 'getsingle', array(
- 'return' => 'contact_id, id',
- 'invoice_id' => $input['invoice'],
- ));
$ids['contact'] = $contributionRecur['contact_id'];
$ids['contributionRecur'] = $contributionRecur['id'];
- $result = civicrm_api3('contribution', 'getsingle', array('invoice_id' => $input['invoice']));
+ $result = civicrm_api3('contribution', 'getsingle', ['invoice_id' => $input['invoice'], 'contribution_test' => '']);
$ids['contribution'] = $result['id'];
//@todo hard - coding 'pending' for now
// membership would be an easy add - but not relevant to my customer...
$this->_component = $input['component'] = 'contribute';
$input['trxn_date'] = date('Y-m-d-H-i-s', strtotime(self::retrieve('time_created', 'String')));
- $paymentProcessorID = self::getPayPalPaymentProcessorID();
+ $paymentProcessorID = $contributionRecur['payment_processor_id'];
if (!$this->validateData($input, $ids, $objects, TRUE, $paymentProcessorID)) {
throw new CRM_Core_Exception('Data did not validate');
}
- return $this->recur($input, $ids, $objects, $isFirst);
+ $this->recur($input, $ids, $objects, $isFirst);
}
/**
'amount_per_cycle' => '5.00',
'payer_status' => 'unverified',
'currency_code' => 'USD',
- 'business' => 'mpa@mainepeoplesalliance.org',
+ 'business' => 'mpa@example.com',
'address_country' => 'UNITED STATES',
'address_city' => 'Limestone',
'verify_sign' => 'AXi4DULbes8quzIiq2YNsdTJH5ciPPPzG9PcQvkQg4BjfvWi8aY9GgDb',
'payment_type' => 'instant',
'last_name' => 'Morrissette',
'address_state' => 'ME',
- 'receiver_email' => 'info@civicrm.org',
+ 'receiver_email' => 'info@example.com',
'payment_fee' => '0.41',
'receiver_id' => 'GTH8P7UQWWTY6',
'txn_type' => 'recurring_payment',
return array_merge($this->getPaypalProRecurTransaction(), array('txn_id' => 'secondone'));
}
+ /**
+ * Test IPN response update for a paypal express profile creation confirmation.
+ */
+ public function testIPNPaymentExpressRecurSuccess() {
+ $this->setupRecurringPaymentProcessorTransaction(['processor_id' => '']);
+ $paypalIPN = new CRM_Core_Payment_PayPalProIPN($this->getPaypalExpressRecurSubscriptionConfirmation());
+ $paypalIPN->main();
+ $contributionRecur = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $this->_contributionRecurID));
+ $this->assertEquals('I-JW77S1PY2032', $contributionRecur['processor_id']);
+ }
+
+ /**
+ * Get response consistent with creating a new profile.
+ *
+ * @return array
+ */
+ public function getPaypalExpressRecurSubscriptionConfirmation() {
+ return [
+ 'payment_cycle' => 'Monthly',
+ 'txn_type' => 'recurring_payment_profile_created',
+ 'last_name' => 'buyer',
+ 'next_payment_date' => '03:00:00 May 09, 2018 PDT',
+ 'residence_country' => 'GB',
+ 'initial_payment_amount' => '0.00',
+ 'rp_invoice_id' => 'i=' . $this->_invoiceID
+ . '&m=&c=' . $this->_contributionID
+ . '&r=' . $this->_contributionRecurID
+ . '&b=' . $this->_contactID
+ . '&p=' . $this->_contributionPageID,
+ 'currency_code' => 'GBP',
+ 'time_created' => '12:39:01 May 09, 2018 PDT',
+ 'verify_sign' => 'AUg223oCjn4HgJXKkrICawXQ3fyUA2gAd1.f1IPJ4r.9sln-nWcB-EJG',
+ 'period_type' => 'Regular',
+ 'payer_status' => 'verified',
+ 'test_ipn' => '1',
+ 'tax' => '0.00',
+ 'payer_email' => 'payer@example.com',
+ 'first_name' => 'test',
+ 'receiver_email' => 'shop@example.com',
+ 'payer_id' => 'BWXXXM8111HDS',
+ 'product_type' => 1,
+ 'shipping' => '0.00',
+ 'amount_per_cycle' => '6.00',
+ 'profile_status' => 'Active',
+ 'charset' => 'windows-1252',
+ 'notify_version' => '3.9',
+ 'amount' => '6.00',
+ 'outstanding_balance' => '0.00',
+ 'recurring_payment_id' => 'I-JW77S1PY2032',
+ 'product_name' => '6 Per 1 month',
+ 'ipn_track_id' => '6255554274055',
+ ];
+ }
+
}