/** * Add payment fields depending on payment processor. The payment processor can implement the following functions to override the built in fields. * * - getPaymentFormFields() * - getPaymentFormFieldsMetadata() * (planned - getBillingDetailsFormFields(), getBillingDetailsFormFieldsMetadata() * * Note that this code is written to accommodate the possibility CiviCRM will switch to implementing pay later as a manual processor in future * * @param CRM_Contribute_Form_AbstractEditPayment|CRM_Contribute_Form_Contribution_Main $form * @param array $processor * Array of properties including 'object' as loaded from CRM_Financial_BAO_PaymentProcessor::getPaymentProcessors. * @param bool $forceBillingFieldsForPayLater * Display billing fields even for pay later. */ public static function setPaymentFieldsByProcessor(&$form, $processor, $forceBillingFieldsForPayLater = FALSE) { $form->billingFieldSets = array(); if ($processor != NULL) { // ie it is pay later $paymentFields = self::getPaymentFields($processor); $paymentTypeName = self::getPaymentTypeName($processor); $paymentTypeLabel = self::getPaymentTypeLabel($processor); //@todo if we switch to iterating through $form->billingFieldSets we won't need to assign these directly $form->assign('paymentTypeName', $paymentTypeName); $form->assign('paymentTypeLabel', $paymentTypeLabel); $form->billingFieldSets[$paymentTypeName]['fields'] = $form->_paymentFields = array_intersect_key(self::getPaymentFieldMetadata($processor), array_flip($paymentFields)); $form->billingPane = array($paymentTypeName => $paymentTypeLabel); $form->assign('paymentFields', $paymentFields); } // @todo - replace this section with one similar to above per discussion - probably use a manual processor shell class to stand in for that capability //return without adding billing fields if billing_mode = 4 (@todo - more the ability to set that to the payment processor) // or payment processor is NULL (pay later) if ($processor == NULL && !$forceBillingFieldsForPayLater || CRM_Utils_Array::value('billing_mode', $processor) == 4) { return; } //@todo setPaymentFields defines the billing fields - this should be moved to the processor class & renamed getBillingFields // potentially pay later would also be a payment processor //also set the billingFieldSet to hold all the details required to render the fieldset so we can iterate through the fieldset - making // it easier to re-order in hooks etc. The billingFieldSets param is used to determine whether to show the billing pane CRM_Core_Payment_Form::setBillingDetailsFields($form); $form->billingFieldSets['billing_name_address-group']['fields'] = array(); }
/** create all fields needed for direct debit transaction * * @return void * @access public */ function setDirectDebitFields(&$form) { CRM_Core_Payment_Form::_setPaymentFields($form); $form->_fields['account_holder'] = array('htmlType' => 'text', 'name' => 'account_holder', 'title' => ts('Account Holder'), 'cc_field' => true, 'attributes' => array('size' => 20, 'maxlength' => 34, 'autocomplete' => 'on'), 'is_required' => true); //e.g. IBAN can have maxlength of 34 digits $form->_fields['bank_account_number'] = array('htmlType' => 'text', 'name' => 'bank_account_number', 'title' => ts('Bank Account Number'), 'cc_field' => true, 'attributes' => array('size' => 20, 'maxlength' => 34, 'autocomplete' => 'off'), 'is_required' => true); //e.g. SWIFT-BIC can have maxlength of 11 digits $form->_fields['bank_identification_number'] = array('htmlType' => 'text', 'name' => 'bank_identification_number', 'title' => ts('Bank Identification Number'), 'cc_field' => true, 'attributes' => array('size' => 20, 'maxlength' => 11, 'autocomplete' => 'off'), 'is_required' => true); $form->_fields['bank_name'] = array('htmlType' => 'text', 'name' => 'bank_name', 'title' => ts('Bank Name'), 'cc_field' => true, 'attributes' => array('size' => 20, 'maxlength' => 64, 'autocomplete' => 'off'), 'is_required' => true); }
public function testCreditCardCSSName() { $params = array('name' => 'API_Test_PP_Type', 'title' => 'API Test Payment Processor Type', 'class_name' => 'CRM_Core_Payment_APITest', 'billing_mode' => 'form', 'payment_processor_type_id' => 1, 'is_recur' => 0, 'domain_id' => 1, 'accepted_credit_cards' => json_encode(array('Visa' => 'Visa', 'Mastercard' => 'Mastercard', 'Amex' => 'Amex'))); $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::create($params); $cards = CRM_Financial_BAO_PaymentProcessor::getCreditCards($paymentProcessor->id); $CSSCards = CRM_Core_Payment_Form::getCreditCardCSSNames($cards); $expectedCSSCards = array('visa' => 'Visa', 'mastercard' => 'Mastercard', 'amex' => 'Amex'); $this->assertEquals($CSSCards, $expectedCSSCards, 'Verify correct credit card types are returned'); $CSSCards2 = CRM_Core_Payment_Form::getCreditCardCSSNames(array()); $allCards = array('visa' => 'Visa', 'mastercard' => 'MasterCard', 'amex' => 'Amex', 'discover' => 'Discover'); $this->assertEquals($CSSCards2, $allCards, 'Verify correct credit card types are returned'); }
/** * Submit a payment using Advanced Integration Method. * * @param array $params * Assoc array of input parameters for this transaction. * * @return array * the result in a nice formatted array (or an error object) */ public function doDirectPayment(&$params) { // Invoke hook_civicrm_paymentProcessor // In Dummy's case, there is no translation of parameters into // the back-end's canonical set of parameters. But if a processor // does this, it needs to invoke this hook after it has done translation, // but before it actually starts talking to its proprietary back-end. // no translation in Dummy processor $cookedParams = $params; CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $cookedParams); // This means we can test failing transactions by setting a past year in expiry. A full expiry check would // be more complete. if (!empty($params['credit_card_exp_date']['Y']) && date('Y') > CRM_Core_Payment_Form::getCreditCardExpirationYear($params)) { $error = new CRM_Core_Error(ts('transaction failed')); return $error; } //end of hook invocation if (!empty($this->_doDirectPaymentResult)) { $result = $this->_doDirectPaymentResult; $result['trxn_id'] = array_shift($this->_doDirectPaymentResult['trxn_id']); return $result; } if ($this->_mode == 'test') { $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'test\\_%'"; $p = array(); $trxn_id = strval(CRM_Core_Dao::singleValueQuery($query, $p)); $trxn_id = str_replace('test_', '', $trxn_id); $trxn_id = intval($trxn_id) + 1; $params['trxn_id'] = 'test_' . $trxn_id . '_' . uniqid(); } else { $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'live_%'"; $p = array(); $trxn_id = strval(CRM_Core_Dao::singleValueQuery($query, $p)); $trxn_id = str_replace('live_', '', $trxn_id); $trxn_id = intval($trxn_id) + 1; $params['trxn_id'] = 'live_' . $trxn_id . '_' . uniqid(); } $params['gross_amount'] = $params['amount']; // Add a fee_amount so we can make sure fees are handled properly in underlying classes. $params['fee_amount'] = 1.5; $params['net_amount'] = $params['gross_amount'] - $params['fee_amount']; return $params; }
/** * Process the form * * @return void * @access public */ public function postProcess() { $config = CRM_Core_Config::singleton(); $contactID = $this->getContactID(); // add a description field at the very beginning $this->_params['description'] = ts('Online Contribution') . ': ' . ($this->_pcpInfo['title'] ? $this->_pcpInfo['title'] : $this->_values['title']); // also add accounting code $this->_params['accountingCode'] = CRM_Utils_Array::value('accountingCode', $this->_values); // fix currency ID $this->_params['currencyID'] = $config->defaultCurrency; $premiumParams = $membershipParams = $tempParams = $params = $this->_params; //carry payment processor id. if ($paymentProcessorId = CRM_Utils_Array::value('id', $this->_paymentProcessor)) { $this->_params['payment_processor_id'] = $paymentProcessorId; foreach (array('premiumParams', 'membershipParams', 'tempParams', 'params') as $p) { ${$p}['payment_processor_id'] = $paymentProcessorId; } } $fields = array(); if (!empty($params['image_URL'])) { CRM_Contact_BAO_Contact::processImageParams($params); } // set email for primary location. $fields['email-Primary'] = 1; // get the add to groups $addToGroups = array(); // now set the values for the billing location. foreach ($this->_fields as $name => $value) { $fields[$name] = 1; // get the add to groups for uf fields if (!empty($value['add_to_group_id'])) { $addToGroups[$value['add_to_group_id']] = $value['add_to_group_id']; } } if (!array_key_exists('first_name', $fields)) { $nameFields = array('first_name', 'middle_name', 'last_name'); foreach ($nameFields as $name) { $fields[$name] = 1; if (array_key_exists("billing_{$name}", $params)) { $params[$name] = $params["billing_{$name}"]; $params['preserveDBName'] = TRUE; } } } // billing email address $fields["email-{$this->_bltID}"] = 1; //unset the billing parameters if it is pay later mode //to avoid creation of billing location if ($params['is_pay_later']) { $billingFields = array('billing_first_name', 'billing_middle_name', 'billing_last_name', "billing_street_address-{$this->_bltID}", "billing_city-{$this->_bltID}", "billing_state_province-{$this->_bltID}", "billing_state_province_id-{$this->_bltID}", "billing_postal_code-{$this->_bltID}", "billing_country-{$this->_bltID}", "billing_country_id-{$this->_bltID}"); foreach ($billingFields as $value) { unset($params[$value]); unset($fields[$value]); } } // if onbehalf-of-organization contribution, take out // organization params in a separate variable, to make sure // normal behavior is continued. And use that variable to // process on-behalf-of functionality. if (!empty($this->_params['hidden_onbehalf_profile'])) { $behalfOrganization = array(); $orgFields = array('organization_name', 'organization_id', 'org_option'); foreach ($orgFields as $fld) { if (array_key_exists($fld, $params)) { $behalfOrganization[$fld] = $params[$fld]; unset($params[$fld]); } } if (is_array($params['onbehalf']) && !empty($params['onbehalf'])) { foreach ($params['onbehalf'] as $fld => $values) { if (strstr($fld, 'custom_')) { $behalfOrganization[$fld] = $values; } elseif (!strstr($fld, '-')) { if (in_array($fld, array('contribution_campaign_id', 'member_campaign_id'))) { $fld = 'campaign_id'; } else { $behalfOrganization[$fld] = $values; } $this->_params[$fld] = $values; } } } if (array_key_exists('onbehalf_location', $params) && is_array($params['onbehalf_location'])) { foreach ($params['onbehalf_location'] as $block => $vals) { //fix for custom data (of type checkbox, multi-select) if (substr($block, 0, 7) == 'custom_') { continue; } // fix the index of block elements if (is_array($vals)) { foreach ($vals as $key => $val) { //dont adjust the index of address block as //it's index is WRT to location type $newKey = $block == 'address' ? $key : ++$key; $behalfOrganization[$block][$newKey] = $val; } } } unset($params['onbehalf_location']); } if (!empty($params['onbehalf[image_URL]'])) { $behalfOrganization['image_URL'] = $params['onbehalf[image_URL]']; } } // check for profile double opt-in and get groups to be subscribed $subscribeGroupIds = CRM_Core_BAO_UFGroup::getDoubleOptInGroupIds($params, $contactID); // since we are directly adding contact to group lets unset it from mailing if (!empty($addToGroups)) { foreach ($addToGroups as $groupId) { if (isset($subscribeGroupIds[$groupId])) { unset($subscribeGroupIds[$groupId]); } } } foreach ($addToGroups as $k) { if (array_key_exists($k, $subscribeGroupIds)) { unset($addToGroups[$k]); } } if (empty($contactID)) { $dupeParams = $params; if (!empty($dupeParams['onbehalf'])) { unset($dupeParams['onbehalf']); } $dedupeParams = CRM_Dedupe_Finder::formatParams($dupeParams, 'Individual'); $dedupeParams['check_permission'] = FALSE; $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual'); // if we find more than one contact, use the first one $contact_id = CRM_Utils_Array::value(0, $ids); // Fetch default greeting id's if creating a contact if (!$contact_id) { foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) { if (!isset($params[$greeting])) { $params[$greeting] = CRM_Contact_BAO_Contact_Utils::defaultGreeting('Individual', $greeting); } } } $contactID = CRM_Contact_BAO_Contact::createProfileContact($params, $fields, $contact_id, $addToGroups, NULL, NULL, TRUE); } else { $ctype = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contactID, 'contact_type'); $contactID = CRM_Contact_BAO_Contact::createProfileContact($params, $fields, $contactID, $addToGroups, NULL, $ctype, TRUE); } // Make the contact ID associated with the contribution available at the Class level. // Also make available to the session. //@todo consider handling this in $this->getContactID(); $this->set('contactID', $contactID); $this->_contactID = $contactID; //get email primary first if exist $subscribtionEmail = array('email' => CRM_Utils_Array::value('email-Primary', $params)); if (!$subscribtionEmail['email']) { $subscribtionEmail['email'] = CRM_Utils_Array::value("email-{$this->_bltID}", $params); } // subscribing contact to groups if (!empty($subscribeGroupIds) && $subscribtionEmail['email']) { CRM_Mailing_Event_BAO_Subscribe::commonSubscribe($subscribeGroupIds, $subscribtionEmail, $contactID); } // If onbehalf-of-organization contribution / signup, add organization // and it's location. if (isset($params['hidden_onbehalf_profile']) && isset($behalfOrganization['organization_name'])) { $ufFields = array(); foreach ($this->_fields['onbehalf'] as $name => $value) { $ufFields[$name] = 1; } self::processOnBehalfOrganization($behalfOrganization, $contactID, $this->_values, $this->_params, $ufFields); } else { if (!empty($this->_membershipContactID) && $contactID != $this->_membershipContactID) { // this is an onbehalf renew case for inherited membership. For e.g a permissioned member of household, // store current user id as related contact for later use for mailing / activity.. $this->_values['related_contact'] = $contactID; $this->_params['related_contact'] = $contactID; // swap contact like we do for on-behalf-org case, so parent/primary membership is affected $contactID = $this->_membershipContactID; } } // lets store the contactID in the session // for things like tell a friend $session = CRM_Core_Session::singleton(); if (!$session->get('userID')) { $session->set('transaction.userID', $contactID); } else { $session->set('transaction.userID', NULL); } $this->_useForMember = $this->get('useForMember'); // store the fact that this is a membership and membership type is selected $processMembership = FALSE; if (!empty($membershipParams['selectMembership']) && $membershipParams['selectMembership'] != 'no_thanks' || $this->_useForMember) { $processMembership = TRUE; if (!$this->_useForMember) { $this->assign('membership_assign', TRUE); $this->set('membershipTypeID', $this->_params['selectMembership']); } if ($this->_action & CRM_Core_Action::PREVIEW) { $membershipParams['is_test'] = 1; } if ($this->_params['is_pay_later']) { $membershipParams['is_pay_later'] = 1; } } if ($processMembership) { CRM_Core_Payment_Form::mapParams($this->_bltID, $this->_params, $membershipParams, TRUE); // added new parameter for cms user contact id, needed to distinguish behaviour for on behalf of sign-ups if (isset($this->_params['related_contact'])) { $membershipParams['cms_contactID'] = $this->_params['related_contact']; } else { $membershipParams['cms_contactID'] = $contactID; } //inherit campaign from contirb page. if (!array_key_exists('campaign_id', $membershipParams)) { $membershipParams['campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values); } if (!empty($membershipParams['onbehalf']) && is_array($membershipParams['onbehalf']) && !empty($membershipParams['onbehalf']['member_campaign_id'])) { $this->_params['campaign_id'] = $membershipParams['onbehalf']['member_campaign_id']; } $customFieldsFormatted = $fieldTypes = array(); if (!empty($membershipParams['onbehalf']) && is_array($membershipParams['onbehalf'])) { foreach ($membershipParams['onbehalf'] as $key => $value) { if (strstr($key, 'custom_')) { $customFieldId = explode('_', $key); CRM_Core_BAO_CustomField::formatCustomField($customFieldId[1], $customFieldsFormatted, $value, 'Membership', NULL, $contactID); } } $fieldTypes = array('Contact', 'Organization', 'Membership'); } $priceFieldIds = $this->get('memberPriceFieldIDS'); if (!empty($priceFieldIds)) { $contributionTypeID = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceFieldIds['id'], 'financial_type_id'); unset($priceFieldIds['id']); $membershipTypeIds = array(); $membershipTypeTerms = array(); foreach ($priceFieldIds as $priceFieldId) { if ($id = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue', $priceFieldId, 'membership_type_id')) { $membershipTypeIds[] = $id; $term = 1; if ($term = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue', $priceFieldId, 'membership_num_terms')) { $membershipTypeTerms[$id] = $term > 1 ? $term : 1; } else { $membershipTypeTerms[$id] = 1; } } } $membershipParams['selectMembership'] = $membershipTypeIds; $membershipParams['financial_type_id'] = $contributionTypeID; $membershipParams['types_terms'] = $membershipTypeTerms; } if (!empty($membershipParams['selectMembership'])) { // CRM-12233 if ($this->_separateMembershipPayment && $this->_values['amount_block_is_active']) { foreach ($this->_values['fee'] as $key => $feeValues) { if ($feeValues['name'] == 'membership_amount') { $fieldId = $this->_params['price_' . $key]; $this->_memLineItem[$this->_priceSetId][$fieldId] = $this->_lineItem[$this->_priceSetId][$fieldId]; unset($this->_lineItem[$this->_priceSetId][$fieldId]); break; } } } CRM_Member_BAO_Membership::postProcessMembership($membershipParams, $contactID, $this, $premiumParams, $customFieldsFormatted, $fieldTypes); } } else { // at this point we've created a contact and stored its address etc // all the payment processors expect the name and address to be in the // so we copy stuff over to first_name etc. $paymentParams = $this->_params; $contributionTypeId = $this->_values['financial_type_id']; $fieldTypes = array(); if (!empty($paymentParams['onbehalf']) && is_array($paymentParams['onbehalf'])) { foreach ($paymentParams['onbehalf'] as $key => $value) { if (strstr($key, 'custom_')) { $this->_params[$key] = $value; } } $fieldTypes = array('Contact', 'Organization', 'Contribution'); } CRM_Contribute_BAO_Contribution_Utils::processConfirm($this, $paymentParams, $premiumParams, $contactID, $contributionTypeId, 'contribution', $fieldTypes); } }
/** * Function to process the form * * @access public */ public function postProcess() { if ($this->_action & CRM_Core_Action::DELETE) { require_once "CRM/Event/BAO/Participant.php"; CRM_Event_BAO_Participant::deleteParticipant($this->_participantId); return; } // get the submitted form values. $params = $this->controller->exportValues($this->_name); // set the contact, when contact is selected if (CRM_Utils_Array::value('contact_select_id', $params)) { $this->_contactID = CRM_Utils_Array::value('contact_select_id', $params); } $config =& CRM_Core_Config::singleton(); //check if discount is selected if (CRM_Utils_Array::value('discount_id', $params)) { $discountId = $params['discount_id']; } else { $params['discount_id'] = 'null'; $discountId = null; } if ($this->_isPaidEvent) { //lets carry currency, CRM-4453 $params['fee_currency'] = $config->defaultCurrency; // fix for CRM-3088 if ($discountId && !empty($this->_values['discount'][$discountId])) { $params['amount_level'] = $this->_values['discount'][$discountId][$params['amount']]['label']; $params['amount'] = $this->_values['discount'][$discountId][$params['amount']]['value']; $this->assign('amount_level', $params['amount_level']); } else { if (!isset($params['priceSetId'])) { $params['amount_level'] = $this->_values['fee'][$params['amount']]['label']; $params['amount'] = $this->_values['fee'][$params['amount']]['value']; $this->assign('amount_level', $params['amount_level']); } else { if (!$this->_online) { $lineItem = array(); CRM_Price_BAO_Set::processAmount($this->_values['fee']['fields'], $params, $lineItem[0]); $this->set('lineItem', $lineItem); $this->assign('lineItem', $lineItem); $this->_lineItem = $lineItem; } } } $params['fee_level'] = $params['amount_level']; $contributionParams = array(); $contributionParams['total_amount'] = $params['amount']; } //fix for CRM-3086 $params['fee_amount'] = $params['amount']; $this->_params = $params; unset($params['amount']); $params['register_date'] = CRM_Utils_Date::processDate($params['register_date'], $params['register_date_time']); $params['receive_date'] = CRM_Utils_Date::processDate(CRM_Utils_Array::value('receive_date', $params)); $params['contact_id'] = $this->_contactID; if ($this->_participantId) { $params['id'] = $this->_participantId; } $status = null; if ($this->_action & CRM_Core_Action::UPDATE) { $participantBAO =& new CRM_Event_BAO_Participant(); $participantBAO->id = $this->_participantId; $participantBAO->find(); while ($participantBAO->fetch()) { $status = $participantBAO->status_id; $contributionParams['total_amount'] = $participantBAO->fee_amount; } $params['discount_id'] = null; //re-enter the values for UPDATE mode $params['fee_level'] = $params['amount_level'] = $participantBAO->fee_level; $params['fee_amount'] = $participantBAO->fee_amount; } require_once 'CRM/Contact/BAO/Contact.php'; // Retrieve the name and email of the current user - this will be the FROM for the receipt email $session =& CRM_Core_Session::singleton(); $userID = $session->get('userID'); list($userName, $userEmail) = CRM_Contact_BAO_Contact_Location::getEmailDetails($userID); require_once "CRM/Event/BAO/Participant.php"; if ($this->_mode) { if (!$this->_isPaidEvent) { CRM_Core_Error::fatal(ts('Selected Event is not Paid Event ')); } //modify params according to parameter used in create //participant method (addParticipant) $params['participant_status_id'] = $params['status_id']; $params['participant_role_id'] = $params['role_id']; $params['participant_register_date'] = $params['register_date']; $params['participant_source'] = $params['source']; require_once 'CRM/Core/BAO/PaymentProcessor.php'; $this->_paymentProcessor = CRM_Core_BAO_PaymentProcessor::getPayment($this->_params['payment_processor_id'], $this->_mode); require_once "CRM/Contact/BAO/Contact.php"; $now = date('YmdHis'); $fields = array(); // set email for primary location. $fields["email-Primary"] = 1; $params["email-Primary"] = $params["email-{$this->_bltID}"] = $this->_contributorEmail; $params['register_date'] = $now; // now set the values for the billing location. foreach ($this->_fields as $name => $dontCare) { $fields[$name] = 1; } // also add location name to the array $params["address_name-{$this->_bltID}"] = CRM_Utils_Array::value('billing_first_name', $params) . ' ' . CRM_Utils_Array::value('billing_middle_name', $params) . ' ' . CRM_Utils_Array::value('billing_last_name', $params); $params["address_name-{$this->_bltID}"] = trim($params["address_name-{$this->_bltID}"]); $fields["address_name-{$this->_bltID}"] = 1; $fields["email-{$this->_bltID}"] = 1; $ctype = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_contactID, 'contact_type'); $nameFields = array('first_name', 'middle_name', 'last_name'); foreach ($nameFields as $name) { $fields[$name] = 1; if (array_key_exists("billing_{$name}", $params)) { $params[$name] = $params["billing_{$name}"]; $params['preserveDBName'] = true; } } $contactID = CRM_Contact_BAO_Contact::createProfileContact($params, $fields, $this->_contactID, null, null, $ctype); } // build custom data getFields array $customFieldsRole = CRM_Core_BAO_CustomField::getFields('Participant', false, false, CRM_Utils_Array::value('role_id', $params), $this->_roleCustomDataTypeID); $customFieldsEvent = CRM_Core_BAO_CustomField::getFields('Participant', false, false, CRM_Utils_Array::value('event_id', $params), $this->_eventNameCustomDataTypeID); $customFields = CRM_Utils_Array::crmArrayMerge($customFieldsRole, CRM_Core_BAO_CustomField::getFields('Participant', false, false, null, null, true)); $customFields = CRM_Utils_Array::crmArrayMerge($customFieldsEvent, $customFields); $params['custom'] = CRM_Core_BAO_CustomField::postProcess($params, $customFields, $this->_participantId, 'Participant'); if ($this->_mode) { // add all the additioanl payment params we need $this->_params["state_province-{$this->_bltID}"] = $this->_params["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($this->_params["billing_state_province_id-{$this->_bltID}"]); $this->_params["country-{$this->_bltID}"] = $this->_params["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($this->_params["billing_country_id-{$this->_bltID}"]); $this->_params['year'] = $this->_params['credit_card_exp_date']['Y']; $this->_params['month'] = $this->_params['credit_card_exp_date']['M']; $this->_params['ip_address'] = CRM_Utils_System::ipAddress(); $this->_params['amount'] = $params['fee_amount']; $this->_params['amount_level'] = $params['amount_level']; $this->_params['currencyID'] = $config->defaultCurrency; $this->_params['payment_action'] = 'Sale'; $this->_params['invoiceID'] = md5(uniqid(rand(), true)); // at this point we've created a contact and stored its address etc // all the payment processors expect the name and address to be in the // so we copy stuff over to first_name etc. $paymentParams = $this->_params; if (CRM_Utils_Array::value('send_receipt', $this->_params)) { $paymentParams['email'] = $this->_contributorEmail; } require_once 'CRM/Core/Payment/Form.php'; CRM_Core_Payment_Form::mapParams($this->_bltID, $this->_params, $paymentParams, true); $payment =& CRM_Core_Payment::singleton($this->_mode, 'Event', $this->_paymentProcessor, $this); $result =& $payment->doDirectPayment($paymentParams); if (is_a($result, 'CRM_Core_Error')) { CRM_Core_Error::displaySessionError($result); CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/view/participant', "reset=1&action=add&cid={$this->_contactID}&context=participant&mode={$this->_mode}")); } if ($result) { $this->_params = array_merge($this->_params, $result); } $this->_params['receive_date'] = $now; if (CRM_Utils_Array::value('send_receipt', $this->_params)) { $this->_params['receipt_date'] = $now; } else { $this->_params['receipt_date'] = null; } $this->set('params', $this->_params); $this->assign('trxn_id', $result['trxn_id']); $this->assign('receive_date', CRM_Utils_Date::processDate($this->_params['receive_date'])); // set source if not set $this->_params['description'] = ts('Submit Credit Card for Event Registration by: %1', array(1 => $userName)); require_once 'CRM/Event/Form/Registration/Confirm.php'; require_once 'CRM/Event/Form/Registration.php'; //add contribution record $this->_params['contribution_type_id'] = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $params['event_id'], 'contribution_type_id'); $this->_params['mode'] = $this->_mode; //add contribution reocord $contribution = CRM_Event_Form_Registration_Confirm::processContribution($this, $this->_params, $result, $contactID, false); // add participant record $participants = array(); $participants[] = CRM_Event_Form_Registration::addParticipant($this->_params, $contactID); //add custom data for participant require_once 'CRM/Core/BAO/CustomValueTable.php'; CRM_Core_BAO_CustomValueTable::postProcess($this->_params, CRM_Core_DAO::$_nullArray, 'civicrm_participant', $participants[0]->id, 'Participant'); //add participant payment require_once 'CRM/Event/BAO/ParticipantPayment.php'; $paymentParticipant = array('participant_id' => $participants[0]->id, 'contribution_id' => $contribution->id); $ids = array(); CRM_Event_BAO_ParticipantPayment::create($paymentParticipant, $ids); $eventTitle = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $params['event_id'], 'title'); $this->_contactIds[] = $this->_contactID; } else { $participants = array(); // fix note if deleted if (!$params['note']) { $params['note'] = 'null'; } if ($this->_single) { $participants[] = CRM_Event_BAO_Participant::create($params); } else { foreach ($this->_contactIds as $contactID) { $commonParams = $params; $commonParams['contact_id'] = $contactID; $participants[] = CRM_Event_BAO_Participant::create($commonParams); } } if (isset($params['event_id'])) { $eventTitle = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $params['event_id'], 'title'); } if ($this->_single) { $this->_contactIds[] = $this->_contactID; } if (CRM_Utils_Array::value('record_contribution', $params)) { if (CRM_Utils_Array::value('id', $params)) { if ($this->_onlinePendingContributionId) { $ids['contribution'] = $this->_onlinePendingContributionId; } else { $ids['contribution'] = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $params['id'], 'contribution_id', 'participant_id'); } } unset($params['note']); //build contribution params if (!$this->_onlinePendingContributionId) { $contributionParams['source'] = "{$eventTitle}: Offline registration (by {$userName})"; } $contributionParams['currency'] = $config->defaultCurrency; $contributionParams['non_deductible_amount'] = 'null'; $contributionParams['receipt_date'] = CRM_Utils_Array::value('send_receipt', $params) ? CRM_Utils_Array::value('receive_date', $params) : 'null'; $recordContribution = array('contact_id', 'contribution_type_id', 'payment_instrument_id', 'trxn_id', 'contribution_status_id', 'receive_date', 'check_number'); foreach ($recordContribution as $f) { $contributionParams[$f] = CRM_Utils_Array::value($f, $params); if ($f == 'trxn_id') { $this->assign('trxn_id', $contributionParams[$f]); } } //insert contribution type name in receipt. $this->assign('contributionTypeName', CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionType', $contributionParams['contribution_type_id'])); require_once 'CRM/Contribute/BAO/Contribution.php'; $contributions = array(); if ($this->_single) { $contributions[] =& CRM_Contribute_BAO_Contribution::create($contributionParams, $ids); } else { $ids = array(); foreach ($this->_contactIds as $contactID) { $contributionParams['contact_id'] = $contactID; $contributions[] =& CRM_Contribute_BAO_Contribution::create($contributionParams, $ids); } } //insert payment record for this participation if (!$ids['contribution']) { require_once 'CRM/Event/DAO/ParticipantPayment.php'; foreach ($this->_contactIds as $num => $contactID) { $ppDAO =& new CRM_Event_DAO_ParticipantPayment(); $ppDAO->participant_id = $participants[$num]->id; $ppDAO->contribution_id = $contributions[$num]->id; $ppDAO->save(); } } } } // also store lineitem stuff here if ($this->_lineItem) { require_once 'CRM/Price/BAO/LineItem.php'; foreach ($this->_contactIds as $num => $contactID) { foreach ($this->_lineItem as $key => $value) { if (is_array($value) && $value != 'skip') { foreach ($value as $line) { $line['entity_table'] = 'civicrm_participant'; $line['entity_id'] = $participants[$num]->id; CRM_Price_BAO_LineItem::create($line); } } } } } $updateStatusMsg = null; //send mail when participant status changed, CRM-4326 if ($this->_participantId && $this->_statusId && $this->_statusId != CRM_Utils_Array::value('status_id', $params) && CRM_Utils_Array::value('is_notify', $params)) { require_once "CRM/Event/BAO/Participant.php"; $updateStatusMsg = CRM_Event_BAO_Participant::updateStatusMessage($this->_participantId, $params['status_id'], $this->_statusId); } if (CRM_Utils_Array::value('send_receipt', $params)) { $receiptFrom = "{$userName} <{$userEmail}>"; $this->assign('module', 'Event Registration'); //use of the message template below requires variables in different format $event = $events = array(); $returnProperties = array('fee_label', 'start_date', 'end_date', 'is_show_location', 'title'); //get all event details. CRM_Core_DAO::commonRetrieveAll('CRM_Event_DAO_Event', 'id', $params['event_id'], $events, $returnProperties); $event = $events[$params['event_id']]; unset($event['start_date']); unset($event['end_date']); $role = CRM_Event_PseudoConstant::participantRole(); $event['participant_role'] = $role[$params['role_id']]; $event['is_monetary'] = $this->_isPaidEvent; if ($params['receipt_text']) { $event['confirm_email_text'] = $params['receipt_text']; } $this->assign('isAmountzero', 1); $this->assign('event', $event); $this->assign('isShowLocation', $event['is_show_location']); if (CRM_Utils_Array::value('is_show_location', $event) == 1) { $locationParams = array('entity_id' => $params['event_id'], 'entity_table' => 'civicrm_event'); require_once 'CRM/Core/BAO/Location.php'; $location = CRM_Core_BAO_Location::getValues($locationParams, true); $this->assign('location', $location); } $status = CRM_Event_PseudoConstant::participantStatus(); if ($this->_isPaidEvent) { $paymentInstrument = CRM_Contribute_PseudoConstant::paymentInstrument(); if (!$this->_mode) { $this->assign('paidBy', CRM_Utils_Array::value($params['payment_instrument_id'], $paymentInstrument)); } $this->assign('totalAmount', $contributionParams['total_amount']); $this->assign('isPrimary', 1); $this->assign('checkNumber', CRM_Utils_Array::value('check_number', $params)); } if ($this->_mode) { if (CRM_Utils_Array::value('billing_first_name', $params)) { $name = $params['billing_first_name']; } if (CRM_Utils_Array::value('billing_middle_name', $params)) { $name .= " {$params['billing_middle_name']}"; } if (CRM_Utils_Array::value('billing_last_name', $params)) { $name .= " {$params['billing_last_name']}"; } $this->assign('billingName', $name); // assign the address formatted up for display $addressParts = array("street_address-{$this->_bltID}", "city-{$this->_bltID}", "postal_code-{$this->_bltID}", "state_province-{$this->_bltID}", "country-{$this->_bltID}"); $addressFields = array(); foreach ($addressParts as $part) { list($n, $id) = explode('-', $part); if (isset($this->_params['billing_' . $part])) { $addressFields[$n] = $this->_params['billing_' . $part]; } } require_once 'CRM/Utils/Address.php'; $this->assign('address', CRM_Utils_Address::format($addressFields)); $date = CRM_Utils_Date::format($params['credit_card_exp_date']); $date = CRM_Utils_Date::mysqlToIso($date); $this->assign('credit_card_exp_date', $date); $this->assign('credit_card_number', CRM_Utils_System::mungeCreditCard($params['credit_card_number'])); $this->assign('credit_card_type', $params['credit_card_type']); $this->assign('contributeMode', 'direct'); $this->assign('isAmountzero', 0); $this->assign('is_pay_later', 0); $this->assign('isPrimary', 1); } $this->assign('register_date', $params['register_date']); if ($params['receive_date']) { $this->assign('receive_date', $params['receive_date']); } $participant = array(array('participant_id', '=', $participants[0]->id, 0, 0)); // check whether its a test drive ref CRM-3075 if (CRM_Utils_Array::value('is_test', $this->_defaultValues)) { $participant[] = array('participant_test', '=', 1, 0, 0); } $template =& CRM_Core_Smarty::singleton(); $customGroup = array(); //format submitted data foreach ($params['custom'] as $fieldID => $values) { foreach ($values as $fieldValue) { $customValue = array('data' => $fieldValue['value']); $customFields[$fieldID]['id'] = $fieldID; $formattedValue = CRM_Core_BAO_CustomGroup::formatCustomValues($customValue, $customFields[$fieldID]); $customGroup[$customFields[$fieldID]['groupTitle']][$customFields[$fieldID]['label']] = str_replace(' ', '', $formattedValue); } } foreach ($this->_contactIds as $num => $contactID) { // Retrieve the name and email of the contact - this will be the TO for receipt email list($this->_contributorDisplayName, $this->_contributorEmail, $this->_toDoNotEmail) = CRM_Contact_BAO_Contact::getContactDetails($contactID); $this->_contributorDisplayName = $this->_contributorDisplayName == ' ' ? $this->_contributorEmail : $this->_contributorDisplayName; $this->assign('customGroup', $customGroup); $this->assign('contactID', $contactID); $this->assign('participantID', $participants[$num]->id); if ($this->_isPaidEvent) { // fix amount for each of participants ( for bulk mode ) $eventAmount = array(); $eventAmount[$num] = array('label' => $params['amount_level'], 'amount' => $params['fee_amount']); //as we are using same template for online & offline registration. //So we have to build amount as array. $this->assign('amount', $eventAmount); } $sendTemplateParams = array('groupName' => 'msg_tpl_workflow_event', 'valueName' => 'event_offline_receipt', 'contactId' => $contactID, 'isTest' => (bool) CRM_Utils_Array::value('is_test', $this->_defaultValues)); // try to send emails only if email id is present // and the do-not-email option is not checked for that contact if ($this->_contributorEmail and !$this->_toDoNotEmail) { $sendTemplateParams['from'] = $receiptFrom; $sendTemplateParams['toName'] = $this->_contributorDisplayName; $sendTemplateParams['toEmail'] = $this->_contributorEmail; } require_once 'CRM/Core/BAO/MessageTemplates.php'; list($mailSent, $subject, $message, $html) = CRM_Core_BAO_MessageTemplates::sendTemplate($sendTemplateParams); if ($mailSent) { $sent[] = $contactID; } else { $notSent[] = $contactID; } } } if ($this->_action & CRM_Core_Action::UPDATE) { $statusMsg = ts('Event registration information for %1 has been updated.', array(1 => $this->_contributorDisplayName)); if ($params['send_receipt'] && count($sent)) { $statusMsg .= ' ' . ts('A confirmation email has been sent to %1', array(1 => $this->_contributorEmail)); } if ($updateStatusMsg) { $statusMsg = "{$statusMsg} {$updateStatusMsg}"; } } elseif ($this->_action & CRM_Core_Action::ADD) { if ($this->_single) { $statusMsg = ts('Event registration for %1 has been added.', array(1 => $this->_contributorDisplayName)); if (CRM_Utils_Array::value('send_receipt', $params) && count($sent)) { $statusMsg .= ' ' . ts('A confirmation email has been sent to %1.', array(1 => $this->_contributorEmail)); } } else { $statusMsg = ts('Total Participant(s) added to event: %1.', array(1 => count($this->_contactIds))); if (count($notSent) > 0) { $statusMsg .= ' ' . ts('Email has NOT been sent to %1 contact - communication preferences specify DO NOT EMAIL OR valid Email is NOT present. ', array(1 => count($notSent))); } elseif (isset($params['send_receipt'])) { $statusMsg .= ' ' . ts('A confirmation email has been sent to ALL participants'); } } } require_once "CRM/Core/Session.php"; CRM_Core_Session::setStatus("{$statusMsg}"); $buttonName = $this->controller->getButtonName(); if ($this->_context == 'standalone') { if ($buttonName == $this->getButtonName('upload', 'new')) { $session->replaceUserContext(CRM_Utils_System::url('civicrm/participant/add', 'reset=1&action=add&context=standalone')); } else { $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->_contactID}&selectedChild=participant")); } } else { if ($buttonName == $this->getButtonName('upload', 'new')) { $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view/participant', "reset=1&action=add&context=participant&cid={$this->_contactID}")); } } }
/** * Submit function. * * This is also accessed by unit tests. * * @param array $formValues * * @return array */ public function submit($formValues) { $isTest = $this->_mode == 'test' ? 1 : 0; $joinDate = $startDate = $endDate = NULL; $membershipTypes = $membership = $calcDate = array(); $membershipType = NULL; $mailSend = FALSE; $formValues = $this->setPriceSetParameters($formValues); $params = $softParams = $ids = array(); $allMemberStatus = CRM_Member_PseudoConstant::membershipStatus(); $allContributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(); if ($this->_id) { $ids['membership'] = $params['id'] = $this->_id; } $ids['userId'] = CRM_Core_Session::singleton()->get('userID'); // Set variables that we normally get from context. // In form mode these are set in preProcess. //TODO: set memberships, fixme $this->setContextVariables($formValues); $this->_memTypeSelected = self::getSelectedMemberships($this->_priceSet, $formValues); if (empty($formValues['financial_type_id'])) { $formValues['financial_type_id'] = $this->_priceSet['financial_type_id']; } $config = CRM_Core_Config::singleton(); $this->convertDateFieldsToMySQL($formValues); $membershipTypeValues = array(); foreach ($this->_memTypeSelected as $memType) { $membershipTypeValues[$memType]['membership_type_id'] = $memType; } //take the required membership recur values. if ($this->_mode && !empty($formValues['auto_renew'])) { $params['is_recur'] = $formValues['is_recur'] = TRUE; $mapping = array('frequency_interval' => 'duration_interval', 'frequency_unit' => 'duration_unit'); $count = 0; foreach ($this->_memTypeSelected as $memType) { $recurMembershipTypeValues = CRM_Utils_Array::value($memType, $this->_recurMembershipTypes, array()); foreach ($mapping as $mapVal => $mapParam) { $membershipTypeValues[$memType][$mapVal] = CRM_Utils_Array::value($mapParam, $recurMembershipTypeValues); if (!$count) { $formValues[$mapVal] = CRM_Utils_Array::value($mapParam, $recurMembershipTypeValues); } } $count++; } } $isQuickConfig = $this->_priceSet['is_quick_config']; $termsByType = array(); $lineItem = array($this->_priceSetId => array()); CRM_Price_BAO_PriceSet::processAmount($this->_priceSet['fields'], $formValues, $lineItem[$this->_priceSetId]); if (CRM_Utils_Array::value('tax_amount', $formValues)) { $params['tax_amount'] = $formValues['tax_amount']; } $params['total_amount'] = CRM_Utils_Array::value('amount', $formValues); $submittedFinancialType = CRM_Utils_Array::value('financial_type_id', $formValues); if (!empty($lineItem[$this->_priceSetId])) { foreach ($lineItem[$this->_priceSetId] as &$li) { if (!empty($li['membership_type_id'])) { if (!empty($li['membership_num_terms'])) { $termsByType[$li['membership_type_id']] = $li['membership_num_terms']; } } ///CRM-11529 for quick config backoffice transactions //when financial_type_id is passed in form, update the //lineitems with the financial type selected in form if ($isQuickConfig && $submittedFinancialType) { $li['financial_type_id'] = $submittedFinancialType; } } } $this->storeContactFields($formValues); $params['contact_id'] = $this->_contactID; $fields = array('status_id', 'source', 'is_override', 'campaign_id'); foreach ($fields as $f) { $params[$f] = CRM_Utils_Array::value($f, $formValues); } // fix for CRM-3724 // when is_override false ignore is_admin statuses during membership // status calculation. similarly we did fix for import in CRM-3570. if (empty($params['is_override'])) { $params['exclude_is_admin'] = TRUE; } // process date params to mysql date format. $dateTypes = array('join_date' => 'joinDate', 'start_date' => 'startDate', 'end_date' => 'endDate'); foreach ($dateTypes as $dateField => $dateVariable) { ${$dateVariable} = CRM_Utils_Date::processDate($formValues[$dateField]); } $memTypeNumTerms = empty($termsByType) ? CRM_Utils_Array::value('num_terms', $formValues) : NULL; $calcDates = array(); foreach ($this->_memTypeSelected as $memType) { if (empty($memTypeNumTerms)) { $memTypeNumTerms = CRM_Utils_Array::value($memType, $termsByType, 1); } $calcDates[$memType] = CRM_Member_BAO_MembershipType::getDatesForMembershipType($memType, $joinDate, $startDate, $endDate, $memTypeNumTerms); } foreach ($calcDates as $memType => $calcDate) { foreach (array_keys($dateTypes) as $d) { //first give priority to form values then calDates. $date = CRM_Utils_Array::value($d, $formValues); if (!$date) { $date = CRM_Utils_Array::value($d, $calcDate); } $membershipTypeValues[$memType][$d] = CRM_Utils_Date::processDate($date); } } // max related memberships - take from form or inherit from membership type foreach ($this->_memTypeSelected as $memType) { if (array_key_exists('max_related', $formValues)) { $membershipTypeValues[$memType]['max_related'] = CRM_Utils_Array::value('max_related', $formValues); } $membershipTypeValues[$memType]['custom'] = CRM_Core_BAO_CustomField::postProcess($formValues, $this->_id, 'Membership'); $membershipTypes[$memType] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $memType); } $membershipType = implode(', ', $membershipTypes); // Retrieve the name and email of the current user - this will be the FROM for the receipt email list($userName) = CRM_Contact_BAO_Contact_Location::getEmailDetails($ids['userId']); //CRM-13981, allow different person as a soft-contributor of chosen type if ($this->_contributorContactID != $this->_contactID) { $params['contribution_contact_id'] = $this->_contributorContactID; if (!empty($formValues['soft_credit_type_id'])) { $softParams['soft_credit_type_id'] = $formValues['soft_credit_type_id']; $softParams['contact_id'] = $this->_contactID; } } if (!empty($formValues['record_contribution'])) { $recordContribution = array('total_amount', 'financial_type_id', 'payment_instrument_id', 'trxn_id', 'contribution_status_id', 'check_number', 'campaign_id', 'receive_date'); foreach ($recordContribution as $f) { $params[$f] = CRM_Utils_Array::value($f, $formValues); } if (!$this->_onlinePendingContributionId) { if (empty($formValues['source'])) { $params['contribution_source'] = ts('%1 Membership: Offline signup (by %2)', array(1 => $membershipType, 2 => $userName)); } else { $params['contribution_source'] = $formValues['source']; } } if (empty($params['is_override']) && CRM_Utils_Array::value('contribution_status_id', $params) == array_search('Pending', CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'))) { $params['status_id'] = array_search('Pending', $allMemberStatus); $params['skipStatusCal'] = TRUE; $params['is_pay_later'] = 1; $this->assign('is_pay_later', 1); } if (!empty($formValues['send_receipt'])) { $params['receipt_date'] = CRM_Utils_Array::value('receive_date', $formValues); } //insert financial type name in receipt. $formValues['contributionType_name'] = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialType', $formValues['financial_type_id']); } // process line items, until no previous line items. if (!empty($lineItem)) { $params['lineItems'] = $lineItem; $params['processPriceSet'] = TRUE; } $createdMemberships = array(); if ($this->_mode) { $params['total_amount'] = CRM_Utils_Array::value('total_amount', $formValues, 0); if (!$isQuickConfig) { $params['financial_type_id'] = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'financial_type_id'); } else { $params['financial_type_id'] = CRM_Utils_Array::value('financial_type_id', $formValues); } $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($formValues['payment_processor_id'], $this->_mode); //get the payment processor id as per mode. $params['payment_processor_id'] = $formValues['payment_processor_id'] = $this->_paymentProcessor['id']; $now = date('YmdHis'); $fields = array(); // set email for primary location. $fields['email-Primary'] = 1; $formValues['email-5'] = $formValues['email-Primary'] = $this->_memberEmail; $params['register_date'] = $now; // now set the values for the billing location. foreach ($this->_fields as $name => $dontCare) { $fields[$name] = 1; } // also add location name to the array $formValues["address_name-{$this->_bltID}"] = CRM_Utils_Array::value('billing_first_name', $formValues) . ' ' . CRM_Utils_Array::value('billing_middle_name', $formValues) . ' ' . CRM_Utils_Array::value('billing_last_name', $formValues); $formValues["address_name-{$this->_bltID}"] = trim($formValues["address_name-{$this->_bltID}"]); $fields["address_name-{$this->_bltID}"] = 1; //ensure we don't over-write the payer's email with the member's email if ($this->_contributorContactID == $this->_contactID) { $fields["email-{$this->_bltID}"] = 1; } $nameFields = array('first_name', 'middle_name', 'last_name'); foreach ($nameFields as $name) { $fields[$name] = 1; if (array_key_exists("billing_{$name}", $formValues)) { $formValues[$name] = $formValues["billing_{$name}"]; $formValues['preserveDBName'] = TRUE; } } if ($this->_contributorContactID == $this->_contactID) { //see CRM-12869 for discussion of why we don't do this for separate payee payments CRM_Contact_BAO_Contact::createProfileContact($formValues, $fields, $this->_contributorContactID, NULL, NULL, CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_contactID, 'contact_type')); } // add all the additional payment params we need $formValues["state_province-{$this->_bltID}"] = $formValues["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($formValues["billing_state_province_id-{$this->_bltID}"]); $formValues["country-{$this->_bltID}"] = $formValues["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($formValues["billing_country_id-{$this->_bltID}"]); $formValues['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($formValues); $formValues['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($formValues); $formValues['ip_address'] = CRM_Utils_System::ipAddress(); $formValues['amount'] = $params['total_amount']; $formValues['currencyID'] = $config->defaultCurrency; $formValues['description'] = ts("Contribution submitted by a staff person using member's credit card for signup"); $formValues['invoiceID'] = md5(uniqid(rand(), TRUE)); $formValues['financial_type_id'] = $params['financial_type_id']; // at this point we've created a contact and stored its address etc // all the payment processors expect the name and address to be in the // so we copy stuff over to first_name etc. $paymentParams = $formValues; $paymentParams['contactID'] = $this->_contributorContactID; //CRM-10377 if payment is by an alternate contact then we need to set that person // as the contact in the payment params if ($this->_contributorContactID != $this->_contactID) { if (!empty($formValues['soft_credit_type_id'])) { $softParams['contact_id'] = $params['contact_id']; $softParams['soft_credit_type_id'] = $formValues['soft_credit_type_id']; } } if (!empty($formValues['send_receipt'])) { $paymentParams['email'] = $this->_contributorEmail; } CRM_Core_Payment_Form::mapParams($this->_bltID, $formValues, $paymentParams, TRUE); // CRM-7137 -for recurring membership, // we do need contribution and recurring records. $result = NULL; if (!empty($paymentParams['is_recur'])) { $financialType = new CRM_Financial_DAO_FinancialType(); $financialType->id = $params['financial_type_id']; $financialType->find(TRUE); $this->_params = $formValues; $contribution = CRM_Contribute_Form_Contribution_Confirm::processFormContribution($this, $paymentParams, NULL, array('contact_id' => $this->_contributorContactID, 'line_item' => $lineItem, 'is_test' => $isTest, 'campaign_id' => CRM_Utils_Array::value('campaign_id', $paymentParams), 'contribution_page_id' => CRM_Utils_Array::value('contribution_page_id', $formValues), 'source' => CRM_Utils_Array::value('source', $paymentParams, CRM_Utils_Array::value('description', $paymentParams)), 'thankyou_date' => CRM_Utils_Array::value('thankyou_date', $paymentParams), 'payment_instrument_id' => $this->_paymentProcessor['payment_instrument_id']), $financialType, TRUE, FALSE, $this->_bltID); //create new soft-credit record, CRM-13981 if ($softParams) { $softParams['contribution_id'] = $contribution->id; $softParams['currency'] = $contribution->currency; $softParams['amount'] = $contribution->total_amount; CRM_Contribute_BAO_ContributionSoft::add($softParams); } $paymentParams['contactID'] = $this->_contactID; $paymentParams['contributionID'] = $contribution->id; $paymentParams['contributionTypeID'] = $contribution->financial_type_id; $paymentParams['contributionPageID'] = $contribution->contribution_page_id; $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id; $ids['contribution'] = $contribution->id; $params['contribution_recur_id'] = $paymentParams['contributionRecurID']; } if ($params['total_amount'] > 0.0) { $payment = $this->_paymentProcessor['object']; try { $result = $payment->doPayment($paymentParams); $formValues = array_merge($formValues, $result); // Assign amount to template if payment was successful. $this->assign('amount', $params['total_amount']); } catch (PaymentProcessorException $e) { if (!empty($paymentParams['contributionID'])) { CRM_Contribute_BAO_Contribution::failPayment($paymentParams['contributionID'], $this->_contactID, $e->getMessage()); } if (!empty($paymentParams['contributionRecurID'])) { CRM_Contribute_BAO_ContributionRecur::deleteRecurContribution($paymentParams['contributionRecurID']); } CRM_Core_Error::displaySessionError($result); CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/view/membership', "reset=1&action=add&cid={$this->_contactID}&context=&mode={$this->_mode}")); } } if ($formValues['payment_status_id'] != array_search('Completed', $allContributionStatus)) { $params['status_id'] = array_search('Pending', $allMemberStatus); $params['skipStatusCal'] = TRUE; // unset send-receipt option, since receipt will be sent when ipn is received. unset($formValues['send_receipt'], $formValues['send_receipt']); //as membership is pending set dates to null. $memberDates = array('join_date' => 'joinDate', 'start_date' => 'startDate', 'end_date' => 'endDate'); foreach ($memberDates as $dv) { ${$dv} = NULL; foreach ($this->_memTypeSelected as $memType) { $membershipTypeValues[$memType][$dv] = NULL; } } } $params['receive_date'] = $now; $params['invoice_id'] = $formValues['invoiceID']; $params['contribution_source'] = ts('%1 Membership Signup: Credit card or direct debit (by %2)', array(1 => $membershipType, 2 => $userName)); $params['source'] = $formValues['source'] ? $formValues['source'] : $params['contribution_source']; $params['trxn_id'] = CRM_Utils_Array::value('trxn_id', $result); $params['payment_instrument_id'] = 1; $params['is_test'] = $this->_mode == 'live' ? 0 : 1; if (!empty($formValues['send_receipt'])) { $params['receipt_date'] = $now; } else { $params['receipt_date'] = NULL; } $this->set('params', $formValues); $this->assign('trxn_id', CRM_Utils_Array::value('trxn_id', $result)); $this->assign('receive_date', CRM_Utils_Date::mysqlToIso($params['receive_date'])); // required for creating membership for related contacts $params['action'] = $this->_action; //create membership record. $count = 0; foreach ($this->_memTypeSelected as $memType) { if ($count && ($relateContribution = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id))) { $membershipTypeValues[$memType]['relate_contribution_id'] = $relateContribution; } $membershipParams = array_merge($membershipTypeValues[$memType], $params); //CRM-15366 if (!empty($softParams) && empty($paymentParams['is_recur'])) { $membershipParams['soft_credit'] = $softParams; } // This is required to trigger the recording of the membership contribution in the // CRM_Member_BAO_Membership::Create function. // @todo stop setting this & 'teach' the create function to respond to something // appropriate as part of our 2-step always create the pending contribution & then finally add the payment // process - // @see http://wiki.civicrm.org/confluence/pages/viewpage.action?pageId=261062657#Payments&AccountsRoadmap-Movetowardsalwaysusinga2-steppaymentprocess $membershipParams['contribution_status_id'] = CRM_Utils_Array::value('payment_status_id', $result); if (!empty($paymentParams['is_recur'])) { // The earlier process created the line items (although we want to get rid of the earlier one in favour // of a single path! unset($membershipParams['lineItems']); } $membership = CRM_Member_BAO_Membership::create($membershipParams, $ids); $params['contribution'] = CRM_Utils_Array::value('contribution', $membershipParams); unset($params['lineItems']); $this->_membershipIDs[] = $membership->id; $createdMemberships[$memType] = $membership; $count++; } } else { $params['action'] = $this->_action; if ($this->_onlinePendingContributionId && !empty($formValues['record_contribution'])) { // update membership as well as contribution object, CRM-4395 $params['contribution_id'] = $this->_onlinePendingContributionId; $params['componentId'] = $params['id']; $params['componentName'] = 'contribute'; $result = CRM_Contribute_BAO_Contribution::transitionComponents($params, TRUE); if (!empty($result) && !empty($params['contribution_id'])) { $lineItem = array(); $lineItems = CRM_Price_BAO_LineItem::getLineItems($params['contribution_id'], 'contribution', NULL, TRUE, TRUE); $itemId = key($lineItems); $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $lineItems[$itemId]['price_field_id'], 'price_set_id'); $lineItems[$itemId]['unit_price'] = $params['total_amount']; $lineItems[$itemId]['line_total'] = $params['total_amount']; $lineItems[$itemId]['id'] = $itemId; $lineItem[$priceSetId] = $lineItems; $contributionBAO = new CRM_Contribute_BAO_Contribution(); $contributionBAO->id = $params['contribution_id']; $contributionBAO->contact_id = $params['contact_id']; $contributionBAO->find(); CRM_Price_BAO_LineItem::processPriceSet($params['contribution_id'], $lineItem, $contributionBAO, 'civicrm_membership'); //create new soft-credit record, CRM-13981 if ($softParams) { $softParams['contribution_id'] = $params['contribution_id']; while ($contributionBAO->fetch()) { $softParams['currency'] = $contributionBAO->currency; $softParams['amount'] = $contributionBAO->total_amount; } CRM_Contribute_BAO_ContributionSoft::add($softParams); } } //carry updated membership object. $membership = new CRM_Member_DAO_Membership(); $membership->id = $this->_id; $membership->find(TRUE); $cancelled = TRUE; if ($membership->end_date) { //display end date w/ status message. $endDate = $membership->end_date; if (!in_array($membership->status_id, array(array_search('Cancelled', CRM_Member_PseudoConstant::membershipStatus(NULL, " name = 'Cancelled' ", 'name', FALSE, TRUE)), array_search('Expired', CRM_Member_PseudoConstant::membershipStatus())))) { $cancelled = FALSE; } } // suppress form values in template. $this->assign('cancelled', $cancelled); $createdMemberships[] = $membership; } else { $count = 0; foreach ($this->_memTypeSelected as $memType) { if ($count && !empty($formValues['record_contribution']) && ($relateContribution = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id))) { $membershipTypeValues[$memType]['relate_contribution_id'] = $relateContribution; } $membershipParams = array_merge($params, $membershipTypeValues[$memType]); if (!empty($formValues['int_amount'])) { $init_amount = array(); foreach ($formValues as $key => $value) { if (strstr($key, 'txt-price')) { $init_amount[$key] = $value; } } $membershipParams['init_amount'] = $init_amount; } if (!empty($softParams)) { $membershipParams['soft_credit'] = $softParams; } $membership = CRM_Member_BAO_Membership::create($membershipParams, $ids); $params['contribution'] = CRM_Utils_Array::value('contribution', $membershipParams); unset($params['lineItems']); $this->_membershipIDs[] = $membership->id; $createdMemberships[$memType] = $membership; $count++; } } } if (!empty($lineItem[$this->_priceSetId])) { $invoiceSettings = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings'); $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings); $taxAmount = FALSE; $totalTaxAmount = 0; foreach ($lineItem[$this->_priceSetId] as &$priceFieldOp) { if (!empty($priceFieldOp['membership_type_id'])) { $priceFieldOp['start_date'] = $membershipTypeValues[$priceFieldOp['membership_type_id']]['start_date'] ? CRM_Utils_Date::customFormat($membershipTypeValues[$priceFieldOp['membership_type_id']]['start_date'], '%B %E%f, %Y') : '-'; $priceFieldOp['end_date'] = $membershipTypeValues[$priceFieldOp['membership_type_id']]['end_date'] ? CRM_Utils_Date::customFormat($membershipTypeValues[$priceFieldOp['membership_type_id']]['end_date'], '%B %E%f, %Y') : '-'; } else { $priceFieldOp['start_date'] = $priceFieldOp['end_date'] = 'N/A'; } if ($invoicing && isset($priceFieldOp['tax_amount'])) { $taxAmount = TRUE; $totalTaxAmount += $priceFieldOp['tax_amount']; } } if ($invoicing) { $dataArray = array(); foreach ($lineItem[$this->_priceSetId] as $key => $value) { if (isset($value['tax_amount']) && isset($value['tax_rate'])) { if (isset($dataArray[$value['tax_rate']])) { $dataArray[$value['tax_rate']] = $dataArray[$value['tax_rate']] + CRM_Utils_Array::value('tax_amount', $value); } else { $dataArray[$value['tax_rate']] = CRM_Utils_Array::value('tax_amount', $value); } } } if ($taxAmount) { $this->assign('totalTaxAmount', $totalTaxAmount); $this->assign('taxTerm', CRM_Utils_Array::value('tax_term', $invoiceSettings)); } $this->assign('dataArray', $dataArray); } } $this->assign('lineItem', !empty($lineItem) && !$isQuickConfig ? $lineItem : FALSE); $receiptSend = FALSE; $contributionId = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id); $membershipIds = $this->_membershipIDs; if ($contributionId && !empty($membershipIds)) { $contributionDetails = CRM_Contribute_BAO_Contribution::getContributionDetails(CRM_Export_Form_Select::MEMBER_EXPORT, $this->_membershipIDs); if ($contributionDetails[$membership->id]['contribution_status'] == 'Completed') { $receiptSend = TRUE; } } if (!empty($formValues['send_receipt']) && $receiptSend) { $formValues['contact_id'] = $this->_contactID; $formValues['contribution_id'] = $contributionId; // We really don't need a distinct receipt_text_signup vs receipt_text_renewal as they are // handled in the receipt. But by setting one we avoid breaking templates for now // although at some point we should switch in the templates. $formValues['receipt_text_signup'] = $formValues['receipt_text']; // send email receipt $mailSend = self::emailReceipt($this, $formValues, $membership); } // finally set membership id if already not set if (!$this->_id) { $this->_id = $membership->id; } $isRecur = CRM_Utils_Array::value('is_recur', $params); $this->setStatusMessage($membership, $endDate, $receiptSend, $membershipTypes, $createdMemberships, $isRecur, $calcDates, $mailSend); return $createdMemberships; }
/** * Process the form submission. */ public function postProcess() { // get the submitted form values. $params = $this->controller->exportValues($this->_name); if ($this->_action & CRM_Core_Action::DELETE) { if (CRM_Utils_Array::value('delete_participant', $params) == 2) { $additionalId = CRM_Event_BAO_Participant::getAdditionalParticipantIds($this->_id); $participantLinks = CRM_Event_BAO_Participant::getAdditionalParticipantUrl($additionalId); } if (CRM_Utils_Array::value('delete_participant', $params) == 1) { $additionalIds = CRM_Event_BAO_Participant::getAdditionalParticipantIds($this->_id); foreach ($additionalIds as $value) { CRM_Event_BAO_Participant::deleteParticipant($value); } } CRM_Event_BAO_Participant::deleteParticipant($this->_id); CRM_Core_Session::setStatus(ts('Selected participant was deleted successfully.'), ts('Record Deleted'), 'success'); if (!empty($participantLinks)) { $status = ts('The following participants no longer have an event fee recorded. You can edit their registration and record a replacement contribution by clicking the links below:') . '<br/>' . $participantLinks; CRM_Core_Session::setStatus($status, ts('Group Payment Deleted')); } return; } // When adding a single contact, the formRule prevents you from adding duplicates // (See above in formRule()). When adding more than one contact, the duplicates are // removed automatically and the user receives one notification. if ($this->_action & CRM_Core_Action::ADD) { $event_id = $this->_eventId; if (empty($event_id) && !empty($params['event_id'])) { $event_id = $params['event_id']; } if (!$this->_single && !empty($event_id)) { $duplicateContacts = 0; while (list($k, $dupeCheckContactId) = each($this->_contactIds)) { // Eliminate contacts that have already been assigned to this event. $dupeCheck = new CRM_Event_BAO_Participant(); $dupeCheck->contact_id = $dupeCheckContactId; $dupeCheck->event_id = $event_id; $dupeCheck->find(TRUE); if (!empty($dupeCheck->id)) { $duplicateContacts++; unset($this->_contactIds[$k]); } } if ($duplicateContacts > 0) { $msg = ts("%1 contacts have already been assigned to this event. They were not added a second time.", array(1 => $duplicateContacts)); CRM_Core_Session::setStatus($msg); } if (count($this->_contactIds) == 0) { CRM_Core_Session::setStatus(ts("No participants were added.")); return; } // We have to re-key $this->_contactIds so each contact has the same // key as their corresponding record in the $participants array that // will be created below. $this->_contactIds = array_values($this->_contactIds); } } $participantStatus = CRM_Event_PseudoConstant::participantStatus(); // set the contact, when contact is selected if (!empty($params['contact_id'])) { $this->_contactId = $params['contact_id']; } if ($this->_priceSetId && ($isQuickConfig = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config'))) { $this->_quickConfig = $isQuickConfig; } if ($this->_id) { $params['id'] = $this->_id; } $config = CRM_Core_Config::singleton(); if ($this->_isPaidEvent) { $contributionParams = array(); $lineItem = array(); $additionalParticipantDetails = array(); if (CRM_Contribute_BAO_Contribution::checkContributeSettings('deferred_revenue_enabled')) { $eventStartDate = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $this->_eventId, 'start_date'); if ($eventStartDate) { $contributionParams['revenue_recognition_date'] = date('Ymd', strtotime($eventStartDate)); } } if ($this->_id && $this->_action & CRM_Core_Action::UPDATE && $this->_paymentId) { $participantBAO = new CRM_Event_BAO_Participant(); $participantBAO->id = $this->_id; $participantBAO->find(TRUE); $contributionParams['total_amount'] = $participantBAO->fee_amount; $params['discount_id'] = NULL; //re-enter the values for UPDATE mode $params['fee_level'] = $params['amount_level'] = $participantBAO->fee_level; $params['fee_amount'] = $participantBAO->fee_amount; if (isset($params['priceSetId'])) { $lineItem[0] = CRM_Price_BAO_LineItem::getLineItems($this->_id); } //also add additional participant's fee level/priceset if (CRM_Event_BAO_Participant::isPrimaryParticipant($this->_id)) { $additionalIds = CRM_Event_BAO_Participant::getAdditionalParticipantIds($this->_id); $hasLineItems = CRM_Utils_Array::value('priceSetId', $params, FALSE); $additionalParticipantDetails = CRM_Event_BAO_Participant::getFeeDetails($additionalIds, $hasLineItems); } } else { //check if discount is selected if (!empty($params['discount_id'])) { $discountId = $params['discount_id']; } else { $discountId = $params['discount_id'] = 'null'; } //lets carry currency, CRM-4453 $params['fee_currency'] = $config->defaultCurrency; CRM_Price_BAO_PriceSet::processAmount($this->_values['fee'], $params, $lineItem[0]); //CRM-11529 for quick config backoffice transactions //when financial_type_id is passed in form, update the //lineitems with the financial type selected in form $submittedFinancialType = CRM_Utils_Array::value('financial_type_id', $params); $isPaymentRecorded = CRM_Utils_Array::value('record_contribution', $params); if ($isPaymentRecorded && $this->_quickConfig && $submittedFinancialType) { foreach ($lineItem[0] as &$values) { $values['financial_type_id'] = $submittedFinancialType; } } $params['fee_level'] = $params['amount_level']; $contributionParams['total_amount'] = $params['amount']; if ($this->_quickConfig && !empty($params['total_amount']) && $params['status_id'] != array_search('Partially paid', $participantStatus)) { $params['fee_amount'] = $params['total_amount']; } else { //fix for CRM-3086 $params['fee_amount'] = $params['amount']; } } if (isset($params['priceSetId'])) { if (!empty($lineItem[0])) { $this->set('lineItem', $lineItem); $this->_lineItem = $lineItem; $lineItem = array_merge($lineItem, $additionalParticipantDetails); $participantCount = array(); foreach ($lineItem as $k) { foreach ($k as $v) { if (CRM_Utils_Array::value('participant_count', $v) > 0) { $participantCount[] = $v['participant_count']; } } } } if (isset($participantCount)) { $this->assign('pricesetFieldsCount', $participantCount); } $this->assign('lineItem', empty($lineItem[0]) || $this->_quickConfig ? FALSE : $lineItem); } else { $this->assign('amount_level', $params['amount_level']); } } $this->_params = $params; $amountOwed = NULL; if (isset($params['amount'])) { $amountOwed = $params['amount']; unset($params['amount']); } $params['register_date'] = CRM_Utils_Date::processDate($params['register_date'], $params['register_date_time']); $params['receive_date'] = CRM_Utils_Date::processDate(CRM_Utils_Array::value('receive_date', $params), CRM_Utils_Array::value('receive_date_time', $params)); $params['contact_id'] = $this->_contactId; // overwrite actual payment amount if entered if (!empty($params['total_amount'])) { $contributionParams['total_amount'] = CRM_Utils_Array::value('total_amount', $params); } // Retrieve the name and email of the current user - this will be the FROM for the receipt email $userName = CRM_Core_Session::singleton()->getLoggedInContactDisplayName(); if ($this->_contactId) { list($this->_contributorDisplayName, $this->_contributorEmail, $this->_toDoNotEmail) = CRM_Contact_BAO_Contact::getContactDetails($this->_contactId); } //modify params according to parameter used in create //participant method (addParticipant) $this->_params['participant_status_id'] = $params['status_id']; $this->_params['participant_role_id'] = is_array($params['role_id']) ? $params['role_id'] : explode(',', $params['role_id']); $this->_params['participant_register_date'] = $params['register_date']; $roleIdWithSeparator = implode(CRM_Core_DAO::VALUE_SEPARATOR, $this->_params['participant_role_id']); if ($this->_mode) { if (!$this->_isPaidEvent) { CRM_Core_Error::fatal(ts('Selected Event is not Paid Event ')); } $eventTitle = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $params['event_id'], 'title'); // set source if not set if (empty($params['source'])) { $this->_params['participant_source'] = ts('Offline Registration for Event: %2 by: %1', array(1 => $userName, 2 => $eventTitle)); } else { $this->_params['participant_source'] = $params['source']; } $this->_params['description'] = $this->_params['participant_source']; $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($this->_params['payment_processor_id'], $this->_mode); $now = date('YmdHis'); $fields = array(); // set email for primary location. $fields['email-Primary'] = 1; $params['email-Primary'] = $params["email-{$this->_bltID}"] = $this->_contributorEmail; $params['register_date'] = $now; // now set the values for the billing location. foreach ($this->_fields as $name => $dontCare) { $fields[$name] = 1; } // also add location name to the array $params["address_name-{$this->_bltID}"] = CRM_Utils_Array::value('billing_first_name', $params) . ' ' . CRM_Utils_Array::value('billing_middle_name', $params) . ' ' . CRM_Utils_Array::value('billing_last_name', $params); $params["address_name-{$this->_bltID}"] = trim($params["address_name-{$this->_bltID}"]); $fields["address_name-{$this->_bltID}"] = 1; $fields["email-{$this->_bltID}"] = 1; $ctype = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_contactId, 'contact_type'); $nameFields = array('first_name', 'middle_name', 'last_name'); foreach ($nameFields as $name) { $fields[$name] = 1; if (array_key_exists("billing_{$name}", $params)) { $params[$name] = $params["billing_{$name}"]; $params['preserveDBName'] = TRUE; } } $contactID = CRM_Contact_BAO_Contact::createProfileContact($params, $fields, $this->_contactId, NULL, NULL, $ctype); } if (!empty($this->_params['participant_role_id'])) { $customFieldsRole = array(); foreach ($this->_params['participant_role_id'] as $roleKey) { $customFieldsRole = CRM_Utils_Array::crmArrayMerge(CRM_Core_BAO_CustomField::getFields('Participant', FALSE, FALSE, $roleKey, $this->_roleCustomDataTypeID), $customFieldsRole); } $customFieldsEvent = CRM_Core_BAO_CustomField::getFields('Participant', FALSE, FALSE, CRM_Utils_Array::value('event_id', $params), $this->_eventNameCustomDataTypeID); $customFieldsEventType = CRM_Core_BAO_CustomField::getFields('Participant', FALSE, FALSE, $this->_eventTypeId, $this->_eventTypeCustomDataTypeID); $customFields = CRM_Utils_Array::crmArrayMerge($customFieldsRole, CRM_Core_BAO_CustomField::getFields('Participant', FALSE, FALSE, NULL, NULL, TRUE)); $customFields = CRM_Utils_Array::crmArrayMerge($customFieldsEvent, $customFields); $customFields = CRM_Utils_Array::crmArrayMerge($customFieldsEventType, $customFields); $params['custom'] = CRM_Core_BAO_CustomField::postProcess($params, $this->_id, 'Participant'); } //do cleanup line items if participant edit the Event Fee. if (($this->_lineItem || !isset($params['proceSetId'])) && !$this->_paymentId && $this->_id) { CRM_Price_BAO_LineItem::deleteLineItems($this->_id, 'civicrm_participant'); } if ($this->_mode) { // add all the additional payment params we need $this->_params["state_province-{$this->_bltID}"] = $this->_params["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($this->_params["billing_state_province_id-{$this->_bltID}"]); $this->_params["country-{$this->_bltID}"] = $this->_params["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($this->_params["billing_country_id-{$this->_bltID}"]); $this->_params['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($this->_params); $this->_params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($this->_params); $this->_params['ip_address'] = CRM_Utils_System::ipAddress(); $this->_params['amount'] = $params['fee_amount']; $this->_params['amount_level'] = $params['amount_level']; $this->_params['currencyID'] = $config->defaultCurrency; $this->_params['invoiceID'] = md5(uniqid(rand(), TRUE)); // at this point we've created a contact and stored its address etc // all the payment processors expect the name and address to be in the // so we copy stuff over to first_name etc. $paymentParams = $this->_params; if (!empty($this->_params['send_receipt'])) { $paymentParams['email'] = $this->_contributorEmail; } // The only reason for merging in the 'contact_id' rather than ensuring it is set // is that this patch is being done around the time of the stable release // so more conservative approach is called for. // In fact the use of $params and $this->_params & $this->_contactId vs $contactID // needs rationalising. $mapParams = array_merge(array('contact_id' => $contactID), $this->_params); CRM_Core_Payment_Form::mapParams($this->_bltID, $mapParams, $paymentParams, TRUE); $payment = $this->_paymentProcessor['object']; // CRM-15622: fix for incorrect contribution.fee_amount $paymentParams['fee_amount'] = NULL; $result = $payment->doPayment($paymentParams); if (is_a($result, 'CRM_Core_Error')) { CRM_Core_Error::displaySessionError($result); CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/view/participant', "reset=1&action=add&cid={$this->_contactId}&context=participant&mode={$this->_mode}")); } if ($result) { $this->_params = array_merge($this->_params, $result); } $this->_params['receive_date'] = $now; if (!empty($this->_params['send_receipt'])) { $this->_params['receipt_date'] = $now; } else { $this->_params['receipt_date'] = NULL; } $this->set('params', $this->_params); $this->assign('trxn_id', $result['trxn_id']); $this->assign('receive_date', CRM_Utils_Date::processDate($this->_params['receive_date'])); //add contribution record $this->_params['financial_type_id'] = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $params['event_id'], 'financial_type_id'); $this->_params['mode'] = $this->_mode; //add contribution record $contributions[] = $contribution = CRM_Event_Form_Registration_Confirm::processContribution($this, $this->_params, $result, $contactID, FALSE); // add participant record $participants = array(); if (!empty($this->_params['role_id']) && is_array($this->_params['role_id'])) { $this->_params['role_id'] = implode(CRM_Core_DAO::VALUE_SEPARATOR, $this->_params['role_id']); } //CRM-15372 patch to fix fee amount replacing amount $this->_params['fee_amount'] = $this->_params['amount']; $participants[] = CRM_Event_Form_Registration::addParticipant($this, $contactID); //add custom data for participant CRM_Core_BAO_CustomValueTable::postProcess($this->_params, 'civicrm_participant', $participants[0]->id, 'Participant'); //add participant payment $paymentParticipant = array('participant_id' => $participants[0]->id, 'contribution_id' => $contribution->id); $ids = array(); CRM_Event_BAO_ParticipantPayment::create($paymentParticipant, $ids); $this->_contactIds[] = $this->_contactId; } else { $participants = array(); if ($this->_single) { if ($params['role_id']) { $params['role_id'] = $roleIdWithSeparator; } else { $params['role_id'] = 'NULL'; } $participants[] = CRM_Event_BAO_Participant::create($params); } else { foreach ($this->_contactIds as $contactID) { $commonParams = $params; $commonParams['contact_id'] = $contactID; if ($commonParams['role_id']) { $commonParams['role_id'] = $commonParams['role_id'] = str_replace(',', CRM_Core_DAO::VALUE_SEPARATOR, $params['role_id']); } else { $commonParams['role_id'] = 'NULL'; } $participants[] = CRM_Event_BAO_Participant::create($commonParams); } } if (isset($params['event_id'])) { $eventTitle = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $params['event_id'], 'title'); } if ($this->_single) { $this->_contactIds[] = $this->_contactId; } $contributions = array(); if (!empty($params['record_contribution'])) { if (!empty($params['id'])) { if ($this->_onlinePendingContributionId) { $ids['contribution'] = $this->_onlinePendingContributionId; } else { $ids['contribution'] = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $params['id'], 'contribution_id', 'participant_id'); } } unset($params['note']); //build contribution params if (!$this->_onlinePendingContributionId) { if (empty($params['source'])) { $contributionParams['source'] = ts('%1 : Offline registration (by %2)', array(1 => $eventTitle, 2 => $userName)); } else { $contributionParams['source'] = $params['source']; } } $contributionParams['currency'] = $config->defaultCurrency; $contributionParams['non_deductible_amount'] = 'null'; $contributionParams['receipt_date'] = !empty($params['send_receipt']) ? CRM_Utils_Array::value('receive_date', $params) : 'null'; $recordContribution = array('contact_id', 'financial_type_id', 'payment_instrument_id', 'trxn_id', 'contribution_status_id', 'receive_date', 'check_number', 'campaign_id'); foreach ($recordContribution as $f) { $contributionParams[$f] = CRM_Utils_Array::value($f, $params); if ($f == 'trxn_id') { $this->assign('trxn_id', $contributionParams[$f]); } } //insert financial type name in receipt. $this->assign('financialTypeName', CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialType', $contributionParams['financial_type_id'])); // legacy support $this->assign('contributionTypeName', CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialType', $contributionParams['financial_type_id'])); $contributionParams['skipLineItem'] = 1; if ($this->_id) { $contributionParams['contribution_mode'] = 'participant'; $contributionParams['participant_id'] = $this->_id; } // Set is_pay_later flag for back-office offline Pending status contributions if ($contributionParams['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Pending', 'name')) { $contributionParams['is_pay_later'] = 1; } elseif ($contributionParams['contribution_status_id'] == CRM_Core_OptionGroup::getValue('contribution_status', 'Completed', 'name')) { $contributionParams['is_pay_later'] = 0; } if ($params['status_id'] == array_search('Partially paid', $participantStatus)) { if (!$amountOwed && $this->_action & CRM_Core_Action::UPDATE) { $amountOwed = $params['fee_amount']; } // if multiple participants are link, consider contribution total amount as the amount Owed if ($this->_id && CRM_Event_BAO_Participant::isPrimaryParticipant($this->_id)) { $amountOwed = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $ids['contribution'], 'total_amount'); } // CRM-13964 partial_payment_total if ($amountOwed > $params['total_amount']) { // the owed amount $contributionParams['partial_payment_total'] = $amountOwed; // the actual amount paid $contributionParams['partial_amount_pay'] = $params['total_amount']; } } if (CRM_Utils_Array::value('tax_amount', $this->_params)) { $contributionParams['tax_amount'] = $this->_params['tax_amount']; } if ($this->_single) { if (empty($ids)) { $ids = array(); } $contributions[] = CRM_Contribute_BAO_Contribution::create($contributionParams, $ids); } else { $ids = array(); foreach ($this->_contactIds as $contactID) { $contributionParams['contact_id'] = $contactID; $contributions[] = CRM_Contribute_BAO_Contribution::create($contributionParams, $ids); } } //insert payment record for this participation if (empty($ids['contribution'])) { foreach ($this->_contactIds as $num => $contactID) { $ppDAO = new CRM_Event_DAO_ParticipantPayment(); $ppDAO->participant_id = $participants[$num]->id; $ppDAO->contribution_id = $contributions[$num]->id; $ppDAO->save(); } } // next create the transaction record $transaction = new CRM_Core_Transaction(); // CRM-11124 if ($this->_params['discount_id']) { CRM_Event_BAO_Participant::createDiscountTrxn($this->_eventId, $contributionParams, NULL, CRM_Price_BAO_PriceSet::parseFirstPriceSetValueIDFromParams($this->_params)); } $transaction->commit(); } } // also store lineitem stuff here if ($this->_lineItem & $this->_action & CRM_Core_Action::ADD || $this->_lineItem && CRM_Core_Action::UPDATE && !$this->_paymentId) { foreach ($this->_contactIds as $num => $contactID) { foreach ($this->_lineItem as $key => $value) { if (is_array($value) && $value != 'skip') { foreach ($value as $lineKey => $line) { //10117 update the line items for participants if contribution amount is recorded if ($this->_quickConfig && !empty($params['total_amount']) && $params['status_id'] != array_search('Partially paid', $participantStatus)) { $line['unit_price'] = $line['line_total'] = $params['total_amount']; if (!empty($params['tax_amount'])) { $line['unit_price'] = $line['unit_price'] - $params['tax_amount']; $line['line_total'] = $line['line_total'] - $params['tax_amount']; } } $lineItem[$this->_priceSetId][$lineKey] = $line; } CRM_Price_BAO_LineItem::processPriceSet($participants[$num]->id, $lineItem, CRM_Utils_Array::value($num, $contributions, NULL), 'civicrm_participant'); CRM_Contribute_BAO_Contribution::addPayments($value, $contributions); } } } } $updateStatusMsg = NULL; //send mail when participant status changed, CRM-4326 if ($this->_id && $this->_statusId && $this->_statusId != CRM_Utils_Array::value('status_id', $params) && !empty($params['is_notify'])) { $updateStatusMsg = CRM_Event_BAO_Participant::updateStatusMessage($this->_id, $params['status_id'], $this->_statusId); } $sent = array(); $notSent = array(); if (!empty($params['send_receipt'])) { if (array_key_exists($params['from_email_address'], $this->_fromEmails['from_email_id'])) { $receiptFrom = $params['from_email_address']; } $this->assign('module', 'Event Registration'); //use of the message template below requires variables in different format $event = $events = array(); $returnProperties = array('fee_label', 'start_date', 'end_date', 'is_show_location', 'title'); //get all event details. CRM_Core_DAO::commonRetrieveAll('CRM_Event_DAO_Event', 'id', $params['event_id'], $events, $returnProperties); $event = $events[$params['event_id']]; unset($event['start_date']); unset($event['end_date']); $role = CRM_Event_PseudoConstant::participantRole(); $participantRoles = CRM_Utils_Array::value('role_id', $params); if (is_array($participantRoles)) { $selectedRoles = array(); foreach ($participantRoles as $roleId) { $selectedRoles[] = $role[$roleId]; } $event['participant_role'] = implode(', ', $selectedRoles); } else { $event['participant_role'] = CRM_Utils_Array::value($participantRoles, $role); } $event['is_monetary'] = $this->_isPaidEvent; if ($params['receipt_text']) { $event['confirm_email_text'] = $params['receipt_text']; } $this->assign('isAmountzero', 1); $this->assign('event', $event); $this->assign('isShowLocation', $event['is_show_location']); if (CRM_Utils_Array::value('is_show_location', $event) == 1) { $locationParams = array('entity_id' => $params['event_id'], 'entity_table' => 'civicrm_event'); $location = CRM_Core_BAO_Location::getValues($locationParams, TRUE); $this->assign('location', $location); } $status = CRM_Event_PseudoConstant::participantStatus(); if ($this->_isPaidEvent) { $paymentInstrument = CRM_Contribute_PseudoConstant::paymentInstrument(); if (!$this->_mode) { if (isset($params['payment_instrument_id'])) { $this->assign('paidBy', CRM_Utils_Array::value($params['payment_instrument_id'], $paymentInstrument)); } } $this->assign('totalAmount', $contributionParams['total_amount']); if (isset($contributionParams['partial_payment_total'])) { // balance amount $balanceAmount = $contributionParams['partial_payment_total'] - $contributionParams['partial_amount_pay']; $this->assign('balanceAmount', $balanceAmount); } $this->assign('isPrimary', 1); $this->assign('checkNumber', CRM_Utils_Array::value('check_number', $params)); } if ($this->_mode) { if (!empty($params['billing_first_name'])) { $name = $params['billing_first_name']; } if (!empty($params['billing_middle_name'])) { $name .= " {$params['billing_middle_name']}"; } if (!empty($params['billing_last_name'])) { $name .= " {$params['billing_last_name']}"; } $this->assign('billingName', $name); // assign the address formatted up for display $addressParts = array("street_address-{$this->_bltID}", "city-{$this->_bltID}", "postal_code-{$this->_bltID}", "state_province-{$this->_bltID}", "country-{$this->_bltID}"); $addressFields = array(); foreach ($addressParts as $part) { list($n, $id) = explode('-', $part); if (isset($this->_params['billing_' . $part])) { $addressFields[$n] = $this->_params['billing_' . $part]; } } $this->assign('address', CRM_Utils_Address::format($addressFields)); $date = CRM_Utils_Date::format($params['credit_card_exp_date']); $date = CRM_Utils_Date::mysqlToIso($date); $this->assign('credit_card_exp_date', $date); $this->assign('credit_card_number', CRM_Utils_System::mungeCreditCard($params['credit_card_number'])); $this->assign('credit_card_type', $params['credit_card_type']); // The concept of contributeMode is deprecated. $this->assign('contributeMode', 'direct'); $this->assign('isAmountzero', 0); $this->assign('is_pay_later', 0); $this->assign('isPrimary', 1); } $this->assign('register_date', $params['register_date']); if ($params['receive_date']) { $this->assign('receive_date', $params['receive_date']); } $participant = array(array('participant_id', '=', $participants[0]->id, 0, 0)); // check whether its a test drive ref CRM-3075 if (!empty($this->_defaultValues['is_test'])) { $participant[] = array('participant_test', '=', 1, 0, 0); } $template = CRM_Core_Smarty::singleton(); $customGroup = array(); //format submitted data foreach ($params['custom'] as $fieldID => $values) { foreach ($values as $fieldValue) { $customFields[$fieldID]['id'] = $fieldID; $formattedValue = CRM_Core_BAO_CustomField::displayValue($fieldValue['value'], $fieldID, $participants[0]->id); $customGroup[$customFields[$fieldID]['groupTitle']][$customFields[$fieldID]['label']] = str_replace(' ', '', $formattedValue); } } foreach ($this->_contactIds as $num => $contactID) { // Retrieve the name and email of the contact - this will be the TO for receipt email list($this->_contributorDisplayName, $this->_contributorEmail, $this->_toDoNotEmail) = CRM_Contact_BAO_Contact::getContactDetails($contactID); $this->_contributorDisplayName = $this->_contributorDisplayName == ' ' ? $this->_contributorEmail : $this->_contributorDisplayName; $waitStatus = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Waiting'"); if ($waitingStatus = CRM_Utils_Array::value($params['status_id'], $waitStatus)) { $this->assign('isOnWaitlist', TRUE); } $this->assign('customGroup', $customGroup); $this->assign('contactID', $contactID); $this->assign('participantID', $participants[$num]->id); $this->_id = $participants[$num]->id; if ($this->_isPaidEvent) { // fix amount for each of participants ( for bulk mode ) $eventAmount = array(); $invoiceSettings = Civi::settings()->get('contribution_invoice_settings'); $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings); $totalTaxAmount = 0; //add dataArray in the receipts in ADD and UPDATE condition $dataArray = array(); if ($this->_action & CRM_Core_Action::ADD) { $line = $lineItem[0]; } elseif ($this->_action & CRM_Core_Action::UPDATE) { $line = $this->_values['line_items']; } if ($invoicing) { foreach ($line as $key => $value) { if (isset($value['tax_amount'])) { $totalTaxAmount += $value['tax_amount']; if (isset($dataArray[(string) $value['tax_rate']])) { $dataArray[(string) $value['tax_rate']] = $dataArray[(string) $value['tax_rate']] + CRM_Utils_Array::value('tax_amount', $value); } else { $dataArray[(string) $value['tax_rate']] = CRM_Utils_Array::value('tax_amount', $value); } } } $this->assign('totalTaxAmount', $totalTaxAmount); $this->assign('taxTerm', CRM_Utils_Array::value('tax_term', $invoiceSettings)); $this->assign('dataArray', $dataArray); } if (!empty($additionalParticipantDetails)) { $params['amount_level'] = preg_replace('//', '', $params['amount_level']) . ' - ' . $this->_contributorDisplayName; } $eventAmount[$num] = array('label' => preg_replace('//', '', $params['amount_level']), 'amount' => $params['fee_amount']); //as we are using same template for online & offline registration. //So we have to build amount as array. $eventAmount = array_merge($eventAmount, $additionalParticipantDetails); $this->assign('amount', $eventAmount); } $sendTemplateParams = array('groupName' => 'msg_tpl_workflow_event', 'valueName' => 'event_offline_receipt', 'contactId' => $contactID, 'isTest' => !empty($this->_defaultValues['is_test']), 'PDFFilename' => ts('confirmation') . '.pdf'); // try to send emails only if email id is present // and the do-not-email option is not checked for that contact if ($this->_contributorEmail and !$this->_toDoNotEmail) { $sendTemplateParams['from'] = $receiptFrom; $sendTemplateParams['toName'] = $this->_contributorDisplayName; $sendTemplateParams['toEmail'] = $this->_contributorEmail; $sendTemplateParams['cc'] = CRM_Utils_Array::value('cc', $this->_fromEmails); $sendTemplateParams['bcc'] = CRM_Utils_Array::value('bcc', $this->_fromEmails); } //send email with pdf invoice $template = CRM_Core_Smarty::singleton(); $taxAmt = $template->get_template_vars('dataArray'); $contributionId = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $this->_id, 'contribution_id', 'participant_id'); $prefixValue = Civi::settings()->get('contribution_invoice_settings'); $invoicing = CRM_Utils_Array::value('invoicing', $prefixValue); if (count($taxAmt) > 0 && (isset($invoicing) && isset($prefixValue['is_email_pdf']))) { $sendTemplateParams['isEmailPdf'] = TRUE; $sendTemplateParams['contributionId'] = $contributionId; } list($mailSent, $subject, $message, $html) = CRM_Core_BAO_MessageTemplate::sendTemplate($sendTemplateParams); if ($mailSent) { $sent[] = $contactID; foreach ($participants as $ids => $values) { if ($values->contact_id == $contactID) { $values->details = CRM_Utils_Array::value('receipt_text', $params); CRM_Activity_BAO_Activity::addActivity($values, 'Email'); break; } } } else { $notSent[] = $contactID; } } } // set the participant id if it is not set if (!$this->_id) { $this->_id = $participants[0]->id; } if ($this->_action & CRM_Core_Action::UPDATE) { $statusMsg = ts('Event registration information for %1 has been updated.', array(1 => $this->_contributorDisplayName)); if (!empty($params['send_receipt']) && count($sent)) { $statusMsg .= ' ' . ts('A confirmation email has been sent to %1', array(1 => $this->_contributorEmail)); } if ($updateStatusMsg) { $statusMsg = "{$statusMsg} {$updateStatusMsg}"; } } elseif ($this->_action & CRM_Core_Action::ADD) { if ($this->_single) { $statusMsg = ts('Event registration for %1 has been added.', array(1 => $this->_contributorDisplayName)); if (!empty($params['send_receipt']) && count($sent)) { $statusMsg .= ' ' . ts('A confirmation email has been sent to %1.', array(1 => $this->_contributorEmail)); } } else { $statusMsg = ts('Total Participant(s) added to event: %1.', array(1 => count($this->_contactIds))); if (count($notSent) > 0) { $statusMsg .= ' ' . ts('Email has NOT been sent to %1 contact(s) - communication preferences specify DO NOT EMAIL OR valid Email is NOT present. ', array(1 => count($notSent))); } elseif (isset($params['send_receipt'])) { $statusMsg .= ' ' . ts('A confirmation email has been sent to ALL participants'); } } } CRM_Core_Session::setStatus($statusMsg, ts('Saved'), 'success'); $session = CRM_Core_Session::singleton(); $buttonName = $this->controller->getButtonName(); if ($this->_context == 'standalone') { if ($buttonName == $this->getButtonName('upload', 'new')) { $urlParams = 'reset=1&action=add&context=standalone'; if ($this->_mode) { $urlParams .= '&mode=' . $this->_mode; } if ($this->_eID) { $urlParams .= '&eid=' . $this->_eID; } $session->replaceUserContext(CRM_Utils_System::url('civicrm/participant/add', $urlParams)); } else { $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->_contactId}&selectedChild=participant")); } } elseif ($buttonName == $this->getButtonName('upload', 'new')) { $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view/participant', "reset=1&action=add&context={$this->_context}&cid={$this->_contactId}")); } }
/** * Global form rule. * * @param array $fields * The input form values. * @param array $files * The uploaded files if any. * @param CRM_Core_Form $self * * @return bool|array * true if no errors, else array of errors */ public static function formRule($fields, $files, $self) { $errors = array(); $amount = self::computeAmount($fields, $self->_values); if (CRM_Utils_Array::value('auto_renew', $fields) && CRM_Utils_Array::value('payment_processor_id', $fields) == 0) { $errors['auto_renew'] = ts('You cannot have auto-renewal on if you are paying later.'); } if (!empty($fields['selectMembership']) && $fields['selectMembership'] != 'no_thanks' || !empty($fields['priceSetId']) && $self->_useForMember) { $isTest = $self->_action & CRM_Core_Action::PREVIEW ? TRUE : FALSE; $lifeMember = CRM_Member_BAO_Membership::getAllContactMembership($self->_membershipContactID, $isTest, TRUE); $membershipOrgDetails = CRM_Member_BAO_MembershipType::getMembershipTypeOrganization(); $unallowedOrgs = array(); foreach (array_keys($lifeMember) as $memTypeId) { $unallowedOrgs[] = $membershipOrgDetails[$memTypeId]; } } //check for atleast one pricefields should be selected if (!empty($fields['priceSetId']) && empty($self->_ccid)) { $priceField = new CRM_Price_DAO_PriceField(); $priceField->price_set_id = $fields['priceSetId']; $priceField->orderBy('weight'); $priceField->find(); $check = array(); $membershipIsActive = TRUE; $previousId = $otherAmount = FALSE; while ($priceField->fetch()) { if ($self->_quickConfig && ($priceField->name == 'contribution_amount' || $priceField->name == 'membership_amount')) { $previousId = $priceField->id; if ($priceField->name == 'membership_amount' && !$priceField->is_active) { $membershipIsActive = FALSE; } } if ($priceField->name == 'other_amount') { if ($self->_quickConfig && empty($fields["price_{$priceField->id}"]) && array_key_exists("price_{$previousId}", $fields) && isset($fields["price_{$previousId}"]) && $self->_values['fee'][$previousId]['name'] == 'contribution_amount' && empty($fields["price_{$previousId}"])) { $otherAmount = $priceField->id; } elseif (!empty($fields["price_{$priceField->id}"])) { $otherAmountVal = CRM_Utils_Rule::cleanMoney($fields["price_{$priceField->id}"]); $min = CRM_Utils_Array::value('min_amount', $self->_values); $max = CRM_Utils_Array::value('max_amount', $self->_values); if ($min && $otherAmountVal < $min) { $errors["price_{$priceField->id}"] = ts('Contribution amount must be at least %1', array(1 => $min)); } if ($max && $otherAmountVal > $max) { $errors["price_{$priceField->id}"] = ts('Contribution amount cannot be more than %1.', array(1 => $max)); } } } if (!empty($fields["price_{$priceField->id}"]) || $previousId == $priceField->id && isset($fields["price_{$previousId}"]) && empty($fields["price_{$previousId}"])) { $check[] = $priceField->id; } } $currentMemberships = NULL; if ($membershipIsActive) { $is_test = $self->_mode != 'live' ? 1 : 0; $memContactID = $self->_membershipContactID; // For anonymous user check using dedupe rule // if user has Cancelled Membership if (!$memContactID) { $dedupeParams = CRM_Dedupe_Finder::formatParams($fields, 'Individual'); $dedupeParams['check_permission'] = FALSE; $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual'); // if we find more than one contact, use the first one $memContactID = CRM_Utils_Array::value(0, $ids); } $currentMemberships = CRM_Member_BAO_Membership::getContactsCancelledMembership($memContactID, $is_test); $errorText = 'Your %1 membership was previously cancelled and can not be renewed online. Please contact the site administrator for assistance.'; foreach ($self->_values['fee'] as $fieldKey => $fieldValue) { if ($fieldValue['html_type'] != 'Text' && CRM_Utils_Array::value('price_' . $fieldKey, $fields)) { if (!is_array($fields['price_' . $fieldKey]) && isset($fieldValue['options'][$fields['price_' . $fieldKey]])) { if (array_key_exists('membership_type_id', $fieldValue['options'][$fields['price_' . $fieldKey]]) && in_array($fieldValue['options'][$fields['price_' . $fieldKey]]['membership_type_id'], $currentMemberships)) { $errors['price_' . $fieldKey] = ts($errorText, array(1 => CRM_Member_PseudoConstant::membershipType($fieldValue['options'][$fields['price_' . $fieldKey]]['membership_type_id']))); } } else { if (is_array($fields['price_' . $fieldKey])) { foreach (array_keys($fields['price_' . $fieldKey]) as $key) { if (array_key_exists('membership_type_id', $fieldValue['options'][$key]) && in_array($fieldValue['options'][$key]['membership_type_id'], $currentMemberships)) { $errors['price_' . $fieldKey] = ts($errorText, array(1 => CRM_Member_PseudoConstant::membershipType($fieldValue['options'][$key]['membership_type_id']))); } } } } } } } // CRM-12233 if ($membershipIsActive && !$self->_membershipBlock['is_required'] && $self->_values['amount_block_is_active']) { $membershipFieldId = $contributionFieldId = $errorKey = $otherFieldId = NULL; foreach ($self->_values['fee'] as $fieldKey => $fieldValue) { // if 'No thank you' membership is selected then set $membershipFieldId if ($fieldValue['name'] == 'membership_amount' && CRM_Utils_Array::value('price_' . $fieldKey, $fields) == 0) { $membershipFieldId = $fieldKey; } elseif ($membershipFieldId) { if ($fieldValue['name'] == 'other_amount') { $otherFieldId = $fieldKey; } elseif ($fieldValue['name'] == 'contribution_amount') { $contributionFieldId = $fieldKey; } if (!$errorKey || CRM_Utils_Array::value('price_' . $contributionFieldId, $fields) == '0') { $errorKey = $fieldKey; } } } // $membershipFieldId is set and additional amount is 'No thank you' or NULL then throw error if ($membershipFieldId && !(CRM_Utils_Array::value('price_' . $contributionFieldId, $fields, -1) > 0) && empty($fields['price_' . $otherFieldId])) { $errors["price_{$errorKey}"] = ts('Additional Contribution is required.'); } } if (empty($check) && empty($self->_ccid)) { if ($self->_useForMember == 1 && $membershipIsActive) { $errors['_qf_default'] = ts('Select at least one option from Membership Type(s).'); } else { $errors['_qf_default'] = ts('Select at least one option from Contribution(s).'); } } if ($otherAmount && !empty($check)) { $errors["price_{$otherAmount}"] = ts('Amount is required field.'); } if ($self->_useForMember == 1 && !empty($check) && $membershipIsActive) { $priceFieldIDS = array(); $priceFieldMemTypes = array(); foreach ($self->_priceSet['fields'] as $priceId => $value) { if (!empty($fields['price_' . $priceId]) || $self->_quickConfig && $value['name'] == 'membership_amount' && empty($self->_membershipBlock['is_required'])) { if (!empty($fields['price_' . $priceId]) && is_array($fields['price_' . $priceId])) { foreach ($fields['price_' . $priceId] as $priceFldVal => $isSet) { if ($isSet) { $priceFieldIDS[] = $priceFldVal; } } } elseif (!$value['is_enter_qty'] && !empty($fields['price_' . $priceId])) { // The check for {!$value['is_enter_qty']} is done since, quantity fields allow entering // quantity. And the quantity can't be conisdered as civicrm_price_field_value.id, CRM-9577 $priceFieldIDS[] = $fields['price_' . $priceId]; } if (!empty($value['options'])) { foreach ($value['options'] as $val) { if (!empty($val['membership_type_id']) && ($fields['price_' . $priceId] == $val['id'] || isset($fields['price_' . $priceId]) && !empty($fields['price_' . $priceId][$val['id']]))) { $priceFieldMemTypes[] = $val['membership_type_id']; } } } } } if (!empty($lifeMember)) { foreach ($priceFieldIDS as $priceFieldId) { if (($id = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceFieldValue', $priceFieldId, 'membership_type_id')) && in_array($membershipOrgDetails[$id], $unallowedOrgs)) { $errors['_qf_default'] = ts('You already have a lifetime membership and cannot select a membership with a shorter term.'); break; } } } if (!empty($priceFieldIDS)) { $ids = implode(',', $priceFieldIDS); $priceFieldIDS['id'] = $fields['priceSetId']; $self->set('memberPriceFieldIDS', $priceFieldIDS); $count = CRM_Price_BAO_PriceSet::getMembershipCount($ids); foreach ($count as $id => $occurrence) { if ($occurrence > 1) { $errors['_qf_default'] = ts('You have selected multiple memberships for the same organization or entity. Please review your selections and choose only one membership per entity. Contact the site administrator if you need assistance.'); } } } if (empty($priceFieldMemTypes) && $self->_membershipBlock['is_required'] == 1) { $errors['_qf_default'] = ts('Please select at least one membership option.'); } } CRM_Price_BAO_PriceSet::processAmount($self->_values['fee'], $fields, $lineItem); if ($fields['amount'] < 0) { $errors['_qf_default'] = ts('Contribution can not be less than zero. Please select the options accordingly'); } $amount = $fields['amount']; } if (isset($fields['selectProduct']) && $fields['selectProduct'] != 'no_thanks') { $productDAO = new CRM_Contribute_DAO_Product(); $productDAO->id = $fields['selectProduct']; $productDAO->find(TRUE); $min_amount = $productDAO->min_contribution; if ($amount < $min_amount) { $errors['selectProduct'] = ts('The premium you have selected requires a minimum contribution of %1', array(1 => CRM_Utils_Money::format($min_amount))); CRM_Core_Session::setStatus($errors['selectProduct']); } } //CRM-16285 - Function to handle validation errors on form, for recurring contribution field. CRM_Contribute_BAO_ContributionRecur::validateRecurContribution($fields, $files, $self, $errors); if (!empty($fields['is_recur']) && CRM_Utils_Array::value('payment_processor_id', $fields) == 0) { $errors['_qf_default'] = ts('You cannot set up a recurring contribution if you are not paying online by credit card.'); } // validate PCP fields - if not anonymous, we need a nick name value if ($self->_pcpId && !empty($fields['pcp_display_in_roll']) && CRM_Utils_Array::value('pcp_is_anonymous', $fields) == 0 && CRM_Utils_Array::value('pcp_roll_nickname', $fields) == '') { $errors['pcp_roll_nickname'] = ts('Please enter a name to include in the Honor Roll, or select \'contribute anonymously\'.'); } // return if this is express mode $config = CRM_Core_Config::singleton(); if ($self->_paymentProcessor && $self->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_BUTTON) { if (!empty($fields[$self->_expressButtonName . '_x']) || !empty($fields[$self->_expressButtonName . '_y']) || CRM_Utils_Array::value($self->_expressButtonName, $fields)) { return $errors; } } //validate the pledge fields. if (!empty($self->_values['pledge_block_id'])) { //validation for pledge payment. if (!empty($self->_values['pledge_id'])) { if (empty($fields['pledge_amount'])) { $errors['pledge_amount'] = ts('At least one payment option needs to be checked.'); } } elseif (!empty($fields['is_pledge'])) { if (CRM_Utils_Rule::positiveInteger(CRM_Utils_Array::value('pledge_installments', $fields)) == FALSE) { $errors['pledge_installments'] = ts('Please enter a valid number of pledge installments.'); } else { if (CRM_Utils_Array::value('pledge_installments', $fields) == NULL) { $errors['pledge_installments'] = ts('Pledge Installments is required field.'); } elseif (CRM_Utils_Array::value('pledge_installments', $fields) == 1) { $errors['pledge_installments'] = ts('Pledges consist of multiple scheduled payments. Select one-time contribution if you want to make your gift in a single payment.'); } elseif (CRM_Utils_Array::value('pledge_installments', $fields) == 0) { $errors['pledge_installments'] = ts('Pledge Installments field must be > 1.'); } } //validation for Pledge Frequency Interval. if (CRM_Utils_Rule::positiveInteger(CRM_Utils_Array::value('pledge_frequency_interval', $fields)) == FALSE) { $errors['pledge_frequency_interval'] = ts('Please enter a valid Pledge Frequency Interval.'); } else { if (CRM_Utils_Array::value('pledge_frequency_interval', $fields) == NULL) { $errors['pledge_frequency_interval'] = ts('Pledge Frequency Interval. is required field.'); } elseif (CRM_Utils_Array::value('pledge_frequency_interval', $fields) == 0) { $errors['pledge_frequency_interval'] = ts('Pledge frequency interval field must be > 0'); } } } } // if the user has chosen a free membership or the amount is less than zero // i.e. we don't need to validate payment related fields or profiles. if ((double) $amount <= 0.0) { return $errors; } if (CRM_Utils_Array::value('payment_processor_id', $fields) == NULL) { $errors['payment_processor_id'] = ts('Payment Method is a required field.'); } else { CRM_Core_Payment_Form::validatePaymentInstrument($fields['payment_processor_id'], $fields, $errors, !$self->_isBillingAddressRequiredForPayLater ? NULL : 'billing'); } foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) { if ($greetingType = CRM_Utils_Array::value($greeting, $fields)) { $customizedValue = CRM_Core_OptionGroup::getValue($greeting, 'Customized', 'name'); if ($customizedValue == $greetingType && empty($fielse[$greeting . '_custom'])) { $errors[$greeting . '_custom'] = ts('Custom %1 is a required field if %1 is of type Customized.', array(1 => ucwords(str_replace('_', " ", $greeting)))); } } } return empty($errors) ? TRUE : $errors; }
/** * Process credit card payment. * * @param array $submittedValues * @param array $lineItem * * @param int $contactID * Contact ID * * @return bool|\CRM_Contribute_DAO_Contribution * @throws \CRM_Core_Exception * @throws \Civi\Payment\Exception\PaymentProcessorException */ protected function processCreditCard($submittedValues, $lineItem, $contactID) { $isTest = $this->_mode == 'test' ? 1 : 0; // CRM-12680 set $_lineItem if its not set // @todo - I don't believe this would ever BE set. I can't find anywhere in the code. // It would be better to pass line item out to functions than $this->_lineItem as // we don't know what is being changed where. if (empty($this->_lineItem) && !empty($lineItem)) { $this->_lineItem = $lineItem; } $this->_paymentObject = Civi\Payment\System::singleton()->getById($submittedValues['payment_processor_id']); $this->_paymentProcessor = $this->_paymentObject->getPaymentProcessor(); // Set source if not set if (empty($submittedValues['source'])) { $userID = CRM_Core_Session::singleton()->get('userID'); $userSortName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $userID, 'sort_name'); $submittedValues['source'] = ts('Submit Credit Card Payment by: %1', array(1 => $userSortName)); } $params = $submittedValues; $this->_params = array_merge($this->_params, $submittedValues); // Mapping requiring documentation. $this->_params['payment_processor'] = $submittedValues['payment_processor_id']; $now = date('YmdHis'); // we need to retrieve email address if ($this->_context == 'standalone' && !empty($submittedValues['is_email_receipt'])) { list($this->userDisplayName, $this->userEmail) = CRM_Contact_BAO_Contact_Location::getEmailDetails($contactID); $this->assign('displayName', $this->userDisplayName); } $this->_contributorEmail = $this->userEmail; $this->_contributorContactID = $contactID; $this->processBillingAddress(); if (!empty($params['source'])) { unset($params['source']); } $this->_params['amount'] = $this->_params['total_amount']; // @todo - stop setting amount level in this function & call the CRM_Price_BAO_PriceSet::getAmountLevel // function to get correct amount level consistently. Remove setting of the amount level in // CRM_Price_BAO_PriceSet::processAmount. Extend the unit tests in CRM_Price_BAO_PriceSetTest // to cover all variants. $this->_params['amount_level'] = 0; $this->_params['description'] = ts("Contribution submitted by a staff person using contributor's credit card"); $this->_params['currencyID'] = CRM_Utils_Array::value('currency', $this->_params, CRM_Core_Config::singleton()->defaultCurrency); if (!empty($this->_params['receive_date'])) { $this->_params['receive_date'] = CRM_Utils_Date::processDate($this->_params['receive_date'], $this->_params['receive_date_time']); } $this->_params['pcp_display_in_roll'] = CRM_Utils_Array::value('pcp_display_in_roll', $params); $this->_params['pcp_roll_nickname'] = CRM_Utils_Array::value('pcp_roll_nickname', $params); $this->_params['pcp_personal_note'] = CRM_Utils_Array::value('pcp_personal_note', $params); //Add common data to formatted params CRM_Contribute_Form_AdditionalInfo::postProcessCommon($params, $this->_params, $this); if (empty($this->_params['invoice_id'])) { $this->_params['invoiceID'] = md5(uniqid(rand(), TRUE)); } else { $this->_params['invoiceID'] = $this->_params['invoice_id']; } // At this point we've created a contact and stored its address etc // all the payment processors expect the name and address to be in the // so we copy stuff over to first_name etc. $paymentParams = $this->_params; $paymentParams['contactID'] = $contactID; CRM_Core_Payment_Form::mapParams($this->_bltID, $this->_params, $paymentParams, TRUE); $financialType = new CRM_Financial_DAO_FinancialType(); $financialType->id = $params['financial_type_id']; $financialType->find(TRUE); // Add some financial type details to the params list // if folks need to use it. $paymentParams['contributionType_name'] = $this->_params['contributionType_name'] = $financialType->name; $paymentParams['contributionPageID'] = NULL; if (!empty($this->_params['is_email_receipt'])) { $paymentParams['email'] = $this->userEmail; $paymentParams['is_email_receipt'] = 1; } else { $paymentParams['is_email_receipt'] = 0; $this->_params['is_email_receipt'] = 0; } if (!empty($this->_params['receive_date'])) { $paymentParams['receive_date'] = $this->_params['receive_date']; } $this->_params['receive_date'] = $now; if (!empty($this->_params['is_email_receipt'])) { $this->_params['receipt_date'] = $now; } else { $this->_params['receipt_date'] = CRM_Utils_Date::processDate($this->_params['receipt_date'], $params['receipt_date_time'], TRUE); } $this->set('params', $this->_params); $this->assign('receive_date', $this->_params['receive_date']); // Result has all the stuff we need // lets archive it to a financial transaction if ($financialType->is_deductible) { $this->assign('is_deductible', TRUE); $this->set('is_deductible', TRUE); } $contributionParams = array('contact_id' => $contactID, 'line_item' => $lineItem, 'is_test' => $isTest, 'campaign_id' => CRM_Utils_Array::value('campaign_id', $this->_params), 'contribution_page_id' => CRM_Utils_Array::value('contribution_page_id', $this->_params), 'source' => CRM_Utils_Array::value('source', $paymentParams, CRM_Utils_Array::value('description', $paymentParams)), 'thankyou_date' => CRM_Utils_Array::value('thankyou_date', $this->_params)); if (empty($paymentParams['is_pay_later'])) { // @todo look up payment_instrument_id on payment processor table. $contributionParams['payment_instrument_id'] = 1; } $contribution = CRM_Contribute_Form_Contribution_Confirm::processFormContribution($this, $this->_params, NULL, $contributionParams, $financialType, FALSE, $this->_bltID, CRM_Utils_Array::value('is_recur', $this->_params)); $paymentParams['contributionID'] = $contribution->id; $paymentParams['contributionTypeID'] = $contribution->financial_type_id; $paymentParams['contributionPageID'] = $contribution->contribution_page_id; $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id; if ($paymentParams['amount'] > 0.0) { // force a re-get of the payment processor in case the form changed it, CRM-7179 // NOTE - I expect this is obsolete. $payment = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor); try { $statuses = CRM_Contribute_BAO_Contribution::buildOptions('contribution_status_id'); $result = $payment->doPayment($paymentParams, 'contribute'); $this->assign('trxn_id', $result['trxn_id']); $contribution->trxn_id = $result['trxn_id']; /* Our scenarios here are * 1) the payment failed & an Exception should have been thrown * 2) the payment succeeded but the payment is not immediate (for example a recurring payment * with a delayed start) * 3) the payment succeeded with an immediate payment. * * The doPayment function ensures that payment_status_id is always set * as historically we have had to guess from the context - ie doDirectPayment * = error or success, unless it is a recurring contribution in which case it is pending. */ if ($result['payment_status_id'] == array_search('Completed', $statuses)) { try { civicrm_api3('contribution', 'completetransaction', array('id' => $contribution->id, 'trxn_id' => $result['trxn_id'], 'payment_processor_id' => $this->_paymentProcessor['id'], 'is_transactional' => FALSE, 'fee_amount' => CRM_Utils_Array::value('fee_amount', $result))); // This has now been set to 1 in the DB - declare it here also $contribution->contribution_status_id = 1; } catch (CiviCRM_API3_Exception $e) { if ($e->getErrorCode() != 'contribution_completed') { throw new CRM_Core_Exception('Failed to update contribution in database'); } } } else { // Save the trxn_id. $contribution->save(); } } catch (PaymentProcessorException $e) { CRM_Contribute_BAO_Contribution::failPayment($contribution->id, $paymentParams['contactID'], $e->getMessage()); throw new PaymentProcessorException($e->getMessage()); } } // Send receipt mail. array_unshift($this->statusMessage, ts('The contribution record has been saved.')); if ($contribution->id && !empty($this->_params['is_email_receipt'])) { $this->_params['trxn_id'] = CRM_Utils_Array::value('trxn_id', $result); $this->_params['contact_id'] = $contactID; $this->_params['contribution_id'] = $contribution->id; if (CRM_Contribute_Form_AdditionalInfo::emailReceipt($this, $this->_params, TRUE)) { $this->statusMessage[] = ts('A receipt has been emailed to the contributor.'); } } return $contribution; }
/** * Function to process payment after confirmation * * @param object $form form object * @param array $paymentParams array with payment related key * value pairs * @param array $premiumParams array with premium related key * value pairs * @param int $contactID contact id * @param int $contributionTypeId contribution type id * @param int $component component id * * @return array associated array * * @static * @access public */ static function processConfirm(&$form, &$paymentParams, &$premiumParams, $contactID, $contributionTypeId, $component = 'contribution') { require_once 'CRM/Core/Payment/Form.php'; CRM_Core_Payment_Form::mapParams($form->_bltID, $form->_params, $paymentParams, true); require_once 'CRM/Contribute/DAO/ContributionType.php'; $contributionType = new CRM_Contribute_DAO_ContributionType(); if (isset($paymentParams['contribution_type'])) { $contributionType->id = $paymentParams['contribution_type']; } else { if (CRM_Utils_Array::value('pledge_id', $form->_values)) { $contributionType->id = CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_Pledge', $form->_values['pledge_id'], 'contribution_type_id'); } else { $contributionType->id = $contributionTypeId; } } if (!$contributionType->find(true)) { CRM_Core_Error::fatal('Could not find a system table'); } // add some contribution type details to the params list // if folks need to use it $paymentParams['contributionType_name'] = $form->_params['contributionType_name'] = $contributionType->name; $paymentParams['contributionType_accounting_code'] = $form->_params['contributionType_accounting_code'] = $contributionType->accounting_code; $paymentParams['contributionPageID'] = $form->_params['contributionPageID'] = $form->_values['id']; if ($form->_values['is_monetary'] && $form->_amount > 0.0 && is_array($form->_paymentProcessor)) { require_once 'CRM/Core/Payment.php'; $payment =& CRM_Core_Payment::singleton($form->_mode, $form->_paymentProcessor, $form); } //fix for CRM-2062 $now = date('YmdHis'); $result = null; if ($form->_contributeMode == 'notify' || $form->_params['is_pay_later']) { // this is not going to come back, i.e. we fill in the other details // when we get a callback from the payment processor // also add the contact ID and contribution ID to the params list $paymentParams['contactID'] = $form->_params['contactID'] = $contactID; $contribution = CRM_Contribute_Form_Contribution_Confirm::processContribution($form, $paymentParams, null, $contactID, $contributionType, true, true, true); $form->_params['contributionID'] = $contribution->id; $form->_params['contributionTypeID'] = $contributionType->id; $form->_params['item_name'] = $form->_params['description']; $form->_params['receive_date'] = $now; if ($form->_values['is_recur'] && $contribution->contribution_recur_id) { $form->_params['contributionRecurID'] = $contribution->contribution_recur_id; } $form->set('params', $form->_params); $form->postProcessPremium($premiumParams, $contribution); if ($form->_values['is_monetary'] && $form->_amount > 0.0) { // add qfKey so we can send to paypal $form->_params['qfKey'] = $form->controller->_key; if ($component == 'membership') { $membershipResult = array(1 => $contribution); return $membershipResult; } else { if (!$form->_params['is_pay_later']) { $result =& $payment->doTransferCheckout($form->_params, 'contribute'); } else { // follow similar flow as IPN // send the receipt mail $form->set('params', $form->_params); if ($contributionType->is_deductible) { $form->assign('is_deductible', true); $form->set('is_deductible', true); } if (isset($paymentParams['contribution_source'])) { $form->_params['source'] = $paymentParams['contribution_source']; } // get the price set values for receipt. if ($form->_priceSetId && $form->_lineItem) { $form->_values['lineItem'] = $form->_lineItem; $form->_values['priceSetID'] = $form->_priceSetId; } require_once 'CRM/Contribute/BAO/ContributionPage.php'; $form->_values['contribution_id'] = $contribution->id; CRM_Contribute_BAO_ContributionPage::sendMail($contactID, $form->_values, $contribution->is_test); return; } } } } elseif ($form->_contributeMode == 'express') { if ($form->_values['is_monetary'] && $form->_amount > 0.0) { //LCD determine if express + recurring and direct accordingly if ($paymentParams['is_recur'] == 1) { $result =& $payment->createRecurringPayments($paymentParams); } else { $result =& $payment->doExpressCheckout($paymentParams); } } } elseif ($form->_values['is_monetary'] && $form->_amount > 0.0) { if ($paymentParams['is_recur'] && $form->_contributeMode == 'direct') { // For recurring contribution, create Contribution Record first. // Contribution ID, Recurring ID and Contact ID needed // When we get a callback from the payment processor $paymentParams['contactID'] = $contactID; $contribution = CRM_Contribute_Form_Contribution_Confirm::processContribution($form, $paymentParams, null, $contactID, $contributionType, true, true, true); $paymentParams['contributionID'] = $contribution->id; $paymentParams['contributionTypeID'] = $contribution->contribution_type_id; $paymentParams['contributionPageID'] = $contribution->contribution_page_id; if ($form->_values['is_recur'] && $contribution->contribution_recur_id) { $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id; } } $result =& $payment->doDirectPayment($paymentParams); } if ($component == 'membership') { $membershipResult = array(); } if (is_a($result, 'CRM_Core_Error')) { //make sure to cleanup db for recurring case. if (CRM_Utils_Array::value('contributionID', $paymentParams)) { CRM_Contribute_BAO_Contribution::deleteContribution($paymentParams['contributionID']); } if (CRM_Utils_Array::value('contributionRecurID', $paymentParams)) { CRM_Contribute_BAO_ContributionRecur::deleteRecurContribution($paymentParams['contributionRecurID']); } if ($component !== 'membership') { CRM_Core_Error::displaySessionError($result); CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contribute/transact', "_qf_Main_display=true&qfKey={$form->_params['qfKey']}")); } $membershipResult[1] = $result; } else { if ($result) { $form->_params = array_merge($form->_params, $result); } $form->_params['receive_date'] = $now; $form->set('params', $form->_params); $form->assign('trxn_id', $result['trxn_id']); $form->assign('receive_date', CRM_Utils_Date::mysqlToIso($form->_params['receive_date'])); // result has all the stuff we need // lets archive it to a financial transaction if ($contributionType->is_deductible) { $form->assign('is_deductible', true); $form->set('is_deductible', true); } if (isset($paymentParams['contribution_source'])) { $form->_params['source'] = $paymentParams['contribution_source']; } // check if pending was set to true by payment processor $pending = false; if (CRM_Utils_Array::value('contribution_status_pending', $form->_params)) { $pending = true; } if (!($paymentParams['is_recur'] && $form->_contributeMode == 'direct')) { $contribution = CRM_Contribute_Form_Contribution_Confirm::processContribution($form, $form->_params, $result, $contactID, $contributionType, true, $pending, true); } $form->postProcessPremium($premiumParams, $contribution); $membershipResult[1] = $contribution; } if ($component == 'membership') { return $membershipResult; } //Do not send an email if Recurring contribution is done via Direct Mode //Email will we send once the IPN will receive. if ($paymentParams['is_recur'] && $form->_contributeMode == 'direct') { return true; } // get the price set values for receipt. if ($form->_priceSetId && $form->_lineItem) { $form->_values['lineItem'] = $form->_lineItem; $form->_values['priceSetID'] = $form->_priceSetId; } // finally send an email receipt require_once 'CRM/Contribute/BAO/ContributionPage.php'; $form->_values['contribution_id'] = $contribution->id; CRM_Contribute_BAO_ContributionPage::sendMail($contactID, $form->_values, $contribution->is_test); }
/** * @param $form */ static function buildQuickform(&$form) { $form->addElement('hidden', 'hidden_processor', 1); $profileAddressFields = $form->get('profileAddressFields'); if (!empty($profileAddressFields)) { $form->assign('profileAddressFields', $profileAddressFields); } // before we do this lets see if the payment processor has implemented a buildForm method if (method_exists($form->_paymentProcessor['instance'], 'buildForm') && is_callable(array($form->_paymentProcessor['instance'], 'buildForm'))) { // the payment processor implements the buildForm function, let the payment // processor do the work $form->_paymentProcessor['instance']->buildForm($form); return; } if ($form->_paymentProcessor['payment_type'] & CRM_Core_Payment::PAYMENT_TYPE_DIRECT_DEBIT) { CRM_Core_Payment_Form::buildDirectDebit($form); } elseif ($form->_paymentProcessor['payment_type'] & CRM_Core_Payment::PAYMENT_TYPE_CREDIT_CARD) { CRM_Core_Payment_Form::buildCreditCard($form); } }
/** * Build the form object. * * @return void */ public function buildQuickForm() { if ($this->_mode) { $this->add('select', 'payment_processor_id', ts('Payment Processor'), $this->_processors, TRUE, array('onChange' => "buildAutoRenew( null, this.value );")); CRM_Core_Payment_Form::buildPaymentForm($this, $this->_paymentProcessor, FALSE, TRUE); } if ($this->_action & CRM_Core_Action::RENEW) { $this->addButtons(array(array('type' => 'upload', 'name' => ts('Renew'), 'isDefault' => TRUE), array('type' => 'cancel', 'name' => ts('Cancel')))); } elseif ($this->_action & CRM_Core_Action::DELETE) { $this->addButtons(array(array('type' => 'next', 'name' => ts('Delete'), 'isDefault' => TRUE), array('type' => 'cancel', 'name' => ts('Cancel')))); } else { $this->addButtons(array(array('type' => 'upload', 'name' => ts('Save'), 'isDefault' => TRUE), array('type' => 'upload', 'name' => ts('Save and New'), 'subName' => 'new'), array('type' => 'cancel', 'name' => ts('Cancel')))); } }
/** * Function to process the form * * @access public * * @return None */ public function postProcess() { // get the submitted form values. $params = $this->controller->exportValues($this->_name); //set as Primary participant $params['is_primary'] = 1; if ($this->_values['event']['is_pay_later'] && !array_key_exists('hidden_processor', $params)) { $params['is_pay_later'] = 1; } else { $params['is_pay_later'] = 0; } $this->set('is_pay_later', $params['is_pay_later']); // assign pay later stuff $this->_params['is_pay_later'] = CRM_Utils_Array::value('is_pay_later', $params, FALSE); $this->assign('is_pay_later', $params['is_pay_later']); if ($params['is_pay_later']) { $this->assign('pay_later_text', $this->_values['event']['pay_later_text']); $this->assign('pay_later_receipt', $this->_values['event']['pay_later_receipt']); } if (!$this->_allowConfirmation) { // check if the participant is already registered if (!$this->_skipDupeRegistrationCheck) { $params['contact_id'] = self::checkRegistration($params, $this, FALSE, TRUE, TRUE); } } if (CRM_Utils_Array::value('image_URL', $params)) { CRM_Contact_BAO_Contact::processImageParams($params); } //carry campaign to partcipants. if (array_key_exists('participant_campaign_id', $params)) { $params['campaign_id'] = $params['participant_campaign_id']; } else { $params['campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values['event']); } //hack to allow group to register w/ waiting $primaryParticipantCount = self::getParticipantCount($this, $params); $totalParticipants = $primaryParticipantCount; if (CRM_Utils_Array::value('additional_participants', $params)) { $totalParticipants += $params['additional_participants']; } if (!$this->_allowConfirmation && CRM_Utils_Array::value('bypass_payment', $params) && is_numeric($this->_availableRegistrations) && $totalParticipants > $this->_availableRegistrations) { $this->_allowWaitlist = TRUE; $this->set('allowWaitlist', TRUE); } //carry participant id if pre-registered. if ($this->_allowConfirmation && $this->_participantId) { $params['participant_id'] = $this->_participantId; } $params['defaultRole'] = 1; if (array_key_exists('participant_role', $params)) { $params['participant_role_id'] = $params['participant_role']; } if (array_key_exists('participant_role_id', $params)) { $params['defaultRole'] = 0; } if (!CRM_Utils_Array::value('participant_role_id', $params) && $this->_values['event']['default_role_id']) { $params['participant_role_id'] = $this->_values['event']['default_role_id']; } $config = CRM_Core_Config::singleton(); $params['currencyID'] = $config->defaultCurrency; if ($this->_values['event']['is_monetary']) { // we first reset the confirm page so it accepts new values $this->controller->resetPage('Confirm'); //added for discount $discountId = CRM_Core_BAO_Discount::findSet($this->_eventId, 'civicrm_event'); if (!empty($this->_values['discount'][$discountId])) { $params['discount_id'] = $discountId; $params['amount_level'] = $this->_values['discount'][$discountId][$params['amount']]['label']; $params['amount'] = $this->_values['discount'][$discountId][$params['amount']]['value']; } elseif (empty($params['priceSetId'])) { if (!empty($params['amount'])) { $params['amount_level'] = $this->_values['fee'][$params['amount']]['label']; $params['amount'] = $this->_values['fee'][$params['amount']]['value']; } else { $params['amount_level'] = $params['amount'] = ''; } } else { $lineItem = array(); CRM_Price_BAO_PriceSet::processAmount($this->_values['fee'], $params, $lineItem); $this->set('lineItem', array($lineItem)); $this->set('lineItemParticipantsCount', array($primaryParticipantCount)); } $this->set('amount', $params['amount']); $this->set('amount_level', $params['amount_level']); // generate and set an invoiceID for this transaction $invoiceID = md5(uniqid(rand(), TRUE)); $this->set('invoiceID', $invoiceID); if (is_array($this->_paymentProcessor)) { $payment = CRM_Core_Payment::singleton($this->_mode, $this->_paymentProcessor, $this); } // default mode is direct $this->set('contributeMode', 'direct'); if (isset($params["state_province_id-{$this->_bltID}"]) && $params["state_province_id-{$this->_bltID}"]) { $params["state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($params["state_province_id-{$this->_bltID}"]); } if (isset($params["country_id-{$this->_bltID}"]) && $params["country_id-{$this->_bltID}"]) { $params["country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($params["country_id-{$this->_bltID}"]); } if (isset($params['credit_card_exp_date'])) { $params['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($params); $params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($params); } if ($this->_values['event']['is_monetary']) { $params['ip_address'] = CRM_Utils_System::ipAddress(); $params['currencyID'] = $config->defaultCurrency; $params['payment_action'] = 'Sale'; $params['invoiceID'] = $invoiceID; } $this->_params = array(); $this->_params[] = $params; $this->set('params', $this->_params); if ($this->_paymentProcessor && $this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_BUTTON) { //get the button name $buttonName = $this->controller->getButtonName(); if (in_array($buttonName, array($this->_expressButtonName, $this->_expressButtonName . '_x', $this->_expressButtonName . '_y')) && !CRM_Utils_Array::value('is_pay_later', $params) && !$this->_allowWaitlist && !$this->_requireApproval) { $this->set('contributeMode', 'express'); // Send Event Name & Id in Params $params['eventName'] = $this->_values['event']['title']; $params['eventId'] = $this->_values['event']['id']; $params['cancelURL'] = CRM_Utils_System::url('civicrm/event/register', "_qf_Register_display=1&qfKey={$this->controller->_key}", TRUE, NULL, FALSE); if (CRM_Utils_Array::value('additional_participants', $params, FALSE)) { $urlArgs = "_qf_Participant_1_display=1&rfp=1&qfKey={$this->controller->_key}"; } else { $urlArgs = "_qf_Confirm_display=1&rfp=1&qfKey={$this->controller->_key}"; } $params['returnURL'] = CRM_Utils_System::url('civicrm/event/register', $urlArgs, TRUE, NULL, FALSE); $params['invoiceID'] = $invoiceID; //default action is Sale $params['payment_action'] = 'Sale'; $token = $payment->setExpressCheckout($params); if (is_a($token, 'CRM_Core_Error')) { CRM_Core_Error::displaySessionError($token); CRM_Utils_System::redirect($params['cancelURL']); } $this->set('token', $token); $paymentURL = $this->_paymentProcessor['url_site'] . "/cgi-bin/webscr?cmd=_express-checkout&token={$token}"; CRM_Utils_System::redirect($paymentURL); } } elseif ($this->_paymentProcessor && $this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_NOTIFY) { $this->set('contributeMode', 'notify'); } } else { $session = CRM_Core_Session::singleton(); $params['description'] = ts('Online Event Registration') . ' ' . $this->_values['event']['title']; $this->_params = array(); $this->_params[] = $params; $this->set('params', $this->_params); if (!CRM_Utils_Array::value('additional_participants', $params)) { self::processRegistration($this->_params); } } // If registering > 1 participant, give status message if (CRM_Utils_Array::value('additional_participants', $params, FALSE)) { $statusMsg = ts('Registration information for participant 1 has been saved.'); CRM_Core_Session::setStatus($statusMsg, ts('Saved'), 'success'); } }
/** * @param $submittedValues */ public function processCreditCard($submittedValues) { $config = CRM_Core_Config::singleton(); $session = CRM_Core_Session::singleton(); $unsetParams = array('trxn_id', 'payment_instrument_id', 'contribution_status_id'); foreach ($unsetParams as $key) { if (isset($submittedValues[$key])) { unset($submittedValues[$key]); } } // Get the required fields value only. $params = $this->_params = $submittedValues; //get the payment processor id as per mode. //@todo unclear relevance of mode - seems like a lot of duplicated params here! $this->_params['payment_processor'] = $params['payment_processor_id'] = $this->_params['payment_processor_id'] = $submittedValues['payment_processor_id'] = $this->_paymentProcessor['id']; $now = date('YmdHis'); $fields = array(); // we need to retrieve email address if ($this->_context == 'standalone' && !empty($submittedValues['is_email_receipt'])) { list($this->userDisplayName, $this->userEmail) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contactId); $this->assign('displayName', $this->userDisplayName); } //set email for primary location. $fields['email-Primary'] = 1; $params['email-Primary'] = $this->_contributorEmail; // now set the values for the billing location. foreach ($this->_fields as $name => $dontCare) { $fields[$name] = 1; } // also add location name to the array $params["address_name-{$this->_bltID}"] = CRM_Utils_Array::value('billing_first_name', $params) . ' ' . CRM_Utils_Array::value('billing_middle_name', $params) . ' ' . CRM_Utils_Array::value('billing_last_name', $params); $params["address_name-{$this->_bltID}"] = trim($params["address_name-{$this->_bltID}"]); $fields["address_name-{$this->_bltID}"] = 1; $ctype = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_contactId, 'contact_type'); $nameFields = array('first_name', 'middle_name', 'last_name'); foreach ($nameFields as $name) { $fields[$name] = 1; if (array_key_exists("billing_{$name}", $params)) { $params[$name] = $params["billing_{$name}"]; $params['preserveDBName'] = TRUE; } } if (!empty($params['source'])) { unset($params['source']); } $contactID = CRM_Contact_BAO_Contact::createProfileContact($params, $fields, $this->_contactId, NULL, NULL, $ctype); // Add all the additional payment params we need. $this->_params["state_province-{$this->_bltID}"] = $this->_params["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($this->_params["billing_state_province_id-{$this->_bltID}"]); $this->_params["country-{$this->_bltID}"] = $this->_params["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($this->_params["billing_country_id-{$this->_bltID}"]); if ($this->_paymentProcessor['payment_type'] & CRM_Core_Payment::PAYMENT_TYPE_CREDIT_CARD) { $this->_params['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($this->_params); $this->_params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($this->_params); } $this->_params['ip_address'] = CRM_Utils_System::ipAddress(); $this->_params['amount'] = $this->_params['total_amount']; // @todo - stop setting amount level in this function & call the CRM_Price_BAO_PriceSet::getAmountLevel // function to get correct amount level consistently. Remove setting of the amount level in // CRM_Price_BAO_PriceSet::processAmount. Extend the unit tests in CRM_Price_BAO_PriceSetTest // to cover all variants. $this->_params['amount_level'] = 0; $this->_params['currencyID'] = CRM_Utils_Array::value('currency', $this->_params, $config->defaultCurrency); if (!empty($this->_params['trxn_date'])) { $this->_params['receive_date'] = CRM_Utils_Date::processDate($this->_params['trxn_date'], $this->_params['trxn_date_time']); } if (empty($this->_params['invoice_id'])) { $this->_params['invoiceID'] = md5(uniqid(rand(), TRUE)); } else { $this->_params['invoiceID'] = $this->_params['invoice_id']; } $this->assignBillingName($params); $this->assign('address', CRM_Utils_Address::getFormattedBillingAddressFieldsFromParameters($params, $this->_bltID)); $date = CRM_Utils_Date::format($params['credit_card_exp_date']); $date = CRM_Utils_Date::mysqlToIso($date); $this->assign('credit_card_type', CRM_Utils_Array::value('credit_card_type', $params)); $this->assign('credit_card_exp_date', $date); $this->assign('credit_card_number', CRM_Utils_System::mungeCreditCard($params['credit_card_number'])); //Add common data to formatted params CRM_Contribute_Form_AdditionalInfo::postProcessCommon($params, $this->_params, $this); // at this point we've created a contact and stored its address etc // all the payment processors expect the name and address to be in the // so we copy stuff over to first_name etc. $paymentParams = $this->_params; $paymentParams['contactID'] = $this->_contactId; CRM_Core_Payment_Form::mapParams($this->_bltID, $this->_params, $paymentParams, TRUE); // add some financial type details to the params list // if folks need to use it $paymentParams['contributionType_name'] = $this->_params['contributionType_name'] = $contributionType->name; $paymentParams['contributionPageID'] = NULL; if (!empty($this->_params['is_email_receipt'])) { $paymentParams['email'] = $this->_contributorEmail; $paymentParams['is_email_receipt'] = 1; } else { $paymentParams['is_email_receipt'] = 0; $this->_params['is_email_receipt'] = 0; } if (!empty($this->_params['receive_date'])) { $paymentParams['receive_date'] = $this->_params['receive_date']; } if (!empty($this->_params['receive_date'])) { $paymentParams['receive_date'] = $this->_params['receive_date']; } $result = NULL; if ($paymentParams['amount'] > 0.0) { try { // force a reget of the payment processor in case the form changed it, CRM-7179 $payment = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor); $result = $payment->doPayment($paymentParams); } catch (\Civi\Payment\Exception\PaymentProcessorException $e) { //set the contribution mode. $urlParams = "action=add&cid={$this->_contactId}&id={$this->_id}&component={$this->_component}"; if ($this->_mode) { $urlParams .= "&mode={$this->_mode}"; } CRM_Core_Error::displaySessionError($result); CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/payment/add', $urlParams)); } } if ($result) { $this->_params = array_merge($this->_params, $result); } if (empty($this->_params['receive_date'])) { $this->_params['receive_date'] = $now; } $this->set('params', $this->_params); // set source if not set if (empty($this->_params['source'])) { $userID = $session->get('userID'); $userSortName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $userID, 'sort_name'); $this->_params['source'] = ts('Submit Credit Card Payment by: %1', array(1 => $userSortName)); } // process the additional payment $participantId = NULL; if ($this->_component == 'event') { $participantId = $this->_id; } $trxnRecord = CRM_Contribute_BAO_Contribution::recordAdditionalPayment($this->_contributionId, $submittedValues, $this->_paymentType, $participantId); if ($trxnRecord->id && !empty($this->_params['is_email_receipt'])) { $sendReceipt = $this->emailReceipt($this->_params); } if ($trxnRecord->id) { $statusMsg = ts('The payment record has been processed.'); if (!empty($this->_params['is_email_receipt']) && $sendReceipt) { $statusMsg .= ' ' . ts('A receipt has been emailed to the contributor.'); } CRM_Core_Session::setStatus($statusMsg, ts('Complete'), 'success'); $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->_contactId}&selectedChild=participant")); } }
/** * Set billing fields for pay later. * * This is considered hacky because pay later has basically been cludged onto the payment processor form. * * See notes on the deprecated function as to how this could be restructured. Alternatively this pay later * handling could be moved out of the payment processor form all together. * * @param CRM_Core_Form $form * @param int $forceBillingFieldsForPayLater */ protected static function hackyHandlePayLaterInPaymentProcessorFunction(&$form, $forceBillingFieldsForPayLater) { if ($forceBillingFieldsForPayLater) { CRM_Core_Payment_Form::setBillingDetailsFields($form); $form->billingFieldSets['billing_name_address-group']['fields'] = array(); } }
/** * Default payment instrument validation. * * Implement the usual Luhn algorithm via a static function in the CRM_Core_Payment_Form if it's a credit card * Not a static function, because I need to check for payment_type. * * @param array $values * @param array $errors */ public function validatePaymentInstrument($values, &$errors) { if ($this->_paymentProcessor['payment_processor_type'] == 'PayPal' && !$this->isPaypalExpress($values)) { CRM_Core_Payment_Form::validateCreditCard($this->_paymentProcessor['id'], $values, $errors); CRM_Core_Form::validateMandatoryFields($this->getMandatoryFields(), $values, $errors); } }
/** * Common block for setting up the parts of a form that relate to credit / debit card * @throws Exception */ protected function assignPaymentRelatedVariables() { try { if ($this->_contactID) { list($this->userDisplayName, $this->userEmail) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contactID); $this->assign('displayName', $this->userDisplayName); } if ($this->_mode) { $this->assignProcessors(); $this->assignBillingType(); $this->_fields = array(); CRM_Core_Payment_Form::setPaymentFieldsByProcessor($this, $this->_paymentProcessor, FALSE, TRUE); } } catch (CRM_Core_Exception $e) { CRM_Core_Error::fatal($e->getMessage()); } }
/** * @param $self * @param $fields * * @return bool */ public function validatePaymentValues($self, $fields) { if (!empty($self->_params[0]['bypass_payment']) || $self->_allowWaitlist || empty($self->_fields) || CRM_Utils_Array::value('amount', $self->_params[0]) > 0) { return TRUE; } $validatePayement = FALSE; if (!empty($fields['priceSetId'])) { $lineItem = array(); CRM_Price_BAO_PriceSet::processAmount($self->_values['fee'], $fields, $lineItem); if ($fields['amount'] > 0) { $validatePayement = TRUE; // $self->_forcePayement = true; // return false; } } elseif (!empty($fields['amount']) && CRM_Utils_Array::value('value', $self->_values['fee'][$fields['amount']]) > 0) { $validatePayement = TRUE; } if (!$validatePayement) { return TRUE; } $errors = array(); CRM_Core_Form::validateMandatoryFields($self->_fields, $fields, $errors); // validate supplied payment instrument values (e.g. credit card number and cvv) $payment_processor_id = $self->_params[0]['payment_processor']; CRM_Core_Payment_Form::validatePaymentInstrument($payment_processor_id, $self->_params[0], $errors, $self); if (!empty($errors)) { return FALSE; } foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) { if ($greetingType = CRM_Utils_Array::value($greeting, $self->_params[0])) { $customizedValue = CRM_Core_OptionGroup::getValue($greeting, 'Customized', 'name'); if ($customizedValue == $greetingType && empty($self->_params[0][$greeting . '_custom'])) { return FALSE; } } } return TRUE; }
/** * Process form submission. * * This function is also accessed by a unit test. */ protected function submit() { $this->storeContactFields($this->_params); $this->beginPostProcess(); $now = CRM_Utils_Date::getToday(NULL, 'YmdHis'); $this->convertDateFieldsToMySQL($this->_params); $this->assign('receive_date', $this->_params['receive_date']); $this->processBillingAddress(); list($userName) = CRM_Contact_BAO_Contact_Location::getEmailDetails(CRM_Core_Session::singleton()->get('userID')); $this->_params['total_amount'] = CRM_Utils_Array::value('total_amount', $this->_params, CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $this->_memType, 'minimum_fee')); $this->_membershipId = $this->_id; $customFieldsFormatted = CRM_Core_BAO_CustomField::postProcess($this->_params, $this->_id, 'Membership'); if (empty($this->_params['financial_type_id'])) { $this->_params['financial_type_id'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $this->_memType, 'financial_type_id'); } $contributionRecurID = NULL; $this->assign('membershipID', $this->_id); $this->assign('contactID', $this->_contactID); $this->assign('module', 'Membership'); $this->assign('receiptType', 'membership renewal'); $this->_params['currencyID'] = CRM_Core_Config::singleton()->defaultCurrency; $this->_params['invoice_id'] = $this->_params['invoiceID'] = md5(uniqid(rand(), TRUE)); if (!empty($this->_params['send_receipt'])) { $this->_params['receipt_date'] = $now; $this->assign('receipt_date', CRM_Utils_Date::mysqlToIso($this->_params['receipt_date'])); } else { $this->_params['receipt_date'] = NULL; } if ($this->_mode) { $this->_params['register_date'] = $now; $this->_params['description'] = ts("Contribution submitted by a staff person using member's credit card for renewal"); $this->_params['amount'] = $this->_params['total_amount']; // at this point we've created a contact and stored its address etc // all the payment processors expect the name and address to be in the passed params // so we copy stuff over to first_name etc. $paymentParams = $this->_params; if (!empty($this->_params['send_receipt'])) { $paymentParams['email'] = $this->_contributorEmail; } $paymentParams['contactID'] = $this->_contributorContactID; CRM_Core_Payment_Form::mapParams($this->_bltID, $this->_params, $paymentParams, TRUE); $payment = $this->_paymentProcessor['object']; if (!empty($this->_params['auto_renew'])) { $contributionRecurParams = $this->processRecurringContribution($paymentParams); $contributionRecurID = $contributionRecurParams['contributionRecurID']; $paymentParams = array_merge($paymentParams, $contributionRecurParams); } $result = $payment->doPayment($paymentParams); $this->_params = array_merge($this->_params, $result); $this->_params['contribution_status_id'] = $result['payment_status_id']; $this->_params['trxn_id'] = $result['trxn_id']; $this->_params['payment_instrument_id'] = 1; $this->_params['is_test'] = $this->_mode == 'live' ? 0 : 1; $this->set('params', $this->_params); $this->assign('trxn_id', $result['trxn_id']); } $renewalDate = !empty($this->_params['renewal_date']) ? $renewalDate = CRM_Utils_Date::processDate($this->_params['renewal_date']) : NULL; // check for test membership. $isTestMembership = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $this->_membershipId, 'is_test'); // chk for renewal for multiple terms CRM-8750 $numRenewTerms = 1; if (is_numeric(CRM_Utils_Array::value('num_terms', $this->_params))) { $numRenewTerms = $this->_params['num_terms']; } //if contribution status is pending then set pay later $this->_params['is_pay_later'] = FALSE; if ($this->_params['contribution_status_id'] == array_search('Pending', CRM_Contribute_PseudoConstant::contributionStatus())) { $this->_params['is_pay_later'] = 1; } // These variable sets prior to renewMembership may not be required for this form. They were in // a function this form shared with other forms. $membershipSource = NULL; if (!empty($this->_params['membership_source'])) { $membershipSource = $this->_params['membership_source']; } $isPending = $this->_params['contribution_status_id'] == 2 ? TRUE : FALSE; list($renewMembership) = CRM_Member_BAO_Membership::renewMembership($this->_contactID, $this->_params['membership_type_id'][1], $isTestMembership, $renewalDate, NULL, $customFieldsFormatted, $numRenewTerms, $this->_membershipId, $isPending, $contributionRecurID, $membershipSource, $this->_params['is_pay_later'], CRM_Utils_Array::value('campaign_id', $this->_params)); $this->endDate = CRM_Utils_Date::processDate($renewMembership->end_date); $this->membershipTypeName = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $renewMembership->membership_type_id, 'name'); if (!empty($this->_params['record_contribution']) || $this->_mode) { // set the source $this->_params['contribution_source'] = "{$this->membershipTypeName} Membership: Offline membership renewal (by {$userName})"; //create line items $lineItem = array(); $this->_params = $this->setPriceSetParameters($this->_params); CRM_Price_BAO_PriceSet::processAmount($this->_priceSet['fields'], $this->_params, $lineItem[$this->_priceSetId]); //CRM-11529 for quick config backoffice transactions //when financial_type_id is passed in form, update the //line items with the financial type selected in form if ($submittedFinancialType = CRM_Utils_Array::value('financial_type_id', $this->_params)) { foreach ($lineItem[$this->_priceSetId] as &$li) { $li['financial_type_id'] = $submittedFinancialType; } } if (!empty($lineItem)) { $this->_params['lineItems'] = $lineItem; $this->_params['processPriceSet'] = TRUE; } //assign contribution contact id to the field expected by recordMembershipContribution if ($this->_contributorContactID != $this->_contactID) { $this->_params['contribution_contact_id'] = $this->_contributorContactID; if (!empty($this->_params['soft_credit_type_id'])) { $this->_params['soft_credit'] = array('soft_credit_type_id' => $this->_params['soft_credit_type_id'], 'contact_id' => $this->_contactID); } } $this->_params['contact_id'] = $this->_contactID; //recordMembershipContribution receives params as a reference & adds one variable. This is // not a great pattern & ideally it would not receive as a reference. We assign our params as a // temporary variable to avoid e-notice & to make it clear to future refactorer that // this function is NOT reliant on that var being set $temporaryParams = array_merge($this->_params, array('membership_id' => $renewMembership->id)); CRM_Member_BAO_Membership::recordMembershipContribution($temporaryParams); } if (!empty($this->_params['send_receipt'])) { $receiptFrom = $this->_params['from_email_address']; if (!empty($this->_params['payment_instrument_id'])) { $paymentInstrument = CRM_Contribute_PseudoConstant::paymentInstrument(); $this->_params['paidBy'] = $paymentInstrument[$this->_params['payment_instrument_id']]; } //get the group Tree $this->_groupTree = CRM_Core_BAO_CustomGroup::getTree('Membership', $this, $this->_id, FALSE, $this->_memType); // retrieve custom data $customFields = $customValues = $fo = array(); foreach ($this->_groupTree as $groupID => $group) { if ($groupID == 'info') { continue; } foreach ($group['fields'] as $k => $field) { $field['title'] = $field['label']; $customFields["custom_{$k}"] = $field; } } $members = array(array('member_id', '=', $this->_membershipId, 0, 0)); // check whether its a test drive if ($this->_mode == 'test') { $members[] = array('member_test', '=', 1, 0, 0); } CRM_Core_BAO_UFGroup::getValues($this->_contactID, $customFields, $customValues, FALSE, $members); $this->assign_by_ref('formValues', $this->_params); if (!empty($this->_params['contribution_id'])) { $this->assign('contributionID', $this->_params['contribution_id']); } $this->assign('membership_name', CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $renewMembership->membership_type_id)); $this->assign('customValues', $customValues); $this->assign('mem_start_date', CRM_Utils_Date::customFormat($renewMembership->start_date)); $this->assign('mem_end_date', CRM_Utils_Date::customFormat($renewMembership->end_date)); if ($this->_mode) { // assign the address formatted up for display $addressParts = array("street_address-{$this->_bltID}", "city-{$this->_bltID}", "postal_code-{$this->_bltID}", "state_province-{$this->_bltID}", "country-{$this->_bltID}"); $addressFields = array(); foreach ($addressParts as $part) { list($n) = explode('-', $part); if (isset($this->_params['billing_' . $part])) { $addressFields[$n] = $this->_params['billing_' . $part]; } } $this->assign('address', CRM_Utils_Address::format($addressFields)); $this->assign('contributeMode', 'direct'); $this->assign('isAmountzero', 0); $this->assign('is_pay_later', 0); $this->assign('isPrimary', 1); $this->assign('receipt_text_renewal', $this->_params['receipt_text']); if ($this->_mode == 'test') { $this->assign('action', '1024'); } } list($this->isMailSent) = CRM_Core_BAO_MessageTemplate::sendTemplate(array('groupName' => 'msg_tpl_workflow_membership', 'valueName' => 'membership_offline_receipt', 'contactId' => $this->_receiptContactId, 'from' => $receiptFrom, 'toName' => $this->_contributorDisplayName, 'toEmail' => $this->_contributorEmail, 'isTest' => $this->_mode == 'test')); } }
/** * Post form submission handling. * * This is also called from the test suite. * * @param int $contactID * * @return array */ protected function processFormSubmission($contactID) { $isPayLater = $this->_params['is_pay_later']; if (!isset($this->_params['payment_processor_id'])) { // If there is no processor we are using the pay-later manual pseudo-processor. // (note it might make sense to make this a row in the processor table in the db). $this->_params['payment_processor_id'] = 0; } if (isset($this->_params['payment_processor_id']) && $this->_params['payment_processor_id'] == 0) { $this->_params['is_pay_later'] = $isPayLater = TRUE; } // add a description field at the very beginning $this->_params['description'] = ts('Online Contribution') . ': ' . ($this->_pcpInfo['title'] ? $this->_pcpInfo['title'] : $this->_values['title']); $this->_params['accountingCode'] = CRM_Utils_Array::value('accountingCode', $this->_values); // fix currency ID $this->_params['currencyID'] = CRM_Core_Config::singleton()->defaultCurrency; //carry payment processor id. if (CRM_Utils_Array::value('id', $this->_paymentProcessor)) { $this->_params['payment_processor_id'] = $this->_paymentProcessor['id']; } $premiumParams = $membershipParams = $params = $this->_params; if (!empty($params['image_URL'])) { CRM_Contact_BAO_Contact::processImageParams($params); } $fields = array('email-Primary' => 1); // get the add to groups $addToGroups = array(); // now set the values for the billing location. foreach ($this->_fields as $name => $value) { $fields[$name] = 1; // get the add to groups for uf fields if (!empty($value['add_to_group_id'])) { $addToGroups[$value['add_to_group_id']] = $value['add_to_group_id']; } } $fields = $this->formatParamsForPaymentProcessor($fields); // billing email address $fields["email-{$this->_bltID}"] = 1; // if onbehalf-of-organization contribution, take out // organization params in a separate variable, to make sure // normal behavior is continued. And use that variable to // process on-behalf-of functionality. if (!empty($this->_values['onbehalf_profile_id'])) { $behalfOrganization = array(); $orgFields = array('organization_name', 'organization_id', 'org_option'); foreach ($orgFields as $fld) { if (array_key_exists($fld, $params)) { $behalfOrganization[$fld] = $params[$fld]; unset($params[$fld]); } } if (is_array($params['onbehalf']) && !empty($params['onbehalf'])) { foreach ($params['onbehalf'] as $fld => $values) { if (strstr($fld, 'custom_')) { $behalfOrganization[$fld] = $values; } elseif (!strstr($fld, '-')) { if (in_array($fld, array('contribution_campaign_id', 'member_campaign_id'))) { $fld = 'campaign_id'; } else { $behalfOrganization[$fld] = $values; } $this->_params[$fld] = $values; } } } if (array_key_exists('onbehalf_location', $params) && is_array($params['onbehalf_location'])) { foreach ($params['onbehalf_location'] as $block => $vals) { //fix for custom data (of type checkbox, multi-select) if (substr($block, 0, 7) == 'custom_') { continue; } // fix the index of block elements if (is_array($vals)) { foreach ($vals as $key => $val) { //dont adjust the index of address block as //it's index is WRT to location type $newKey = $block == 'address' ? $key : ++$key; $behalfOrganization[$block][$newKey] = $val; } } } unset($params['onbehalf_location']); } if (!empty($params['onbehalf[image_URL]'])) { $behalfOrganization['image_URL'] = $params['onbehalf[image_URL]']; } } // check for profile double opt-in and get groups to be subscribed $subscribeGroupIds = CRM_Core_BAO_UFGroup::getDoubleOptInGroupIds($params, $contactID); // since we are directly adding contact to group lets unset it from mailing if (!empty($addToGroups)) { foreach ($addToGroups as $groupId) { if (isset($subscribeGroupIds[$groupId])) { unset($subscribeGroupIds[$groupId]); } } } foreach ($addToGroups as $k) { if (array_key_exists($k, $subscribeGroupIds)) { unset($addToGroups[$k]); } } if (empty($contactID)) { $dupeParams = $params; if (!empty($dupeParams['onbehalf'])) { unset($dupeParams['onbehalf']); } if (!empty($dupeParams['honor'])) { unset($dupeParams['honor']); } $dedupeParams = CRM_Dedupe_Finder::formatParams($dupeParams, 'Individual'); $dedupeParams['check_permission'] = FALSE; $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual'); // if we find more than one contact, use the first one $contactID = CRM_Utils_Array::value(0, $ids); // Fetch default greeting id's if creating a contact if (!$contactID) { foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) { if (!isset($params[$greeting])) { $params[$greeting] = CRM_Contact_BAO_Contact_Utils::defaultGreeting('Individual', $greeting); } } } $contactType = NULL; } else { $contactType = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contactID, 'contact_type'); } $contactID = CRM_Contact_BAO_Contact::createProfileContact($params, $fields, $contactID, $addToGroups, NULL, $contactType, TRUE); // Make the contact ID associated with the contribution available at the Class level. // Also make available to the session. //@todo consider handling this in $this->getContactID(); $this->set('contactID', $contactID); $this->_contactID = $contactID; //get email primary first if exist $subscriptionEmail = array('email' => CRM_Utils_Array::value('email-Primary', $params)); if (!$subscriptionEmail['email']) { $subscriptionEmail['email'] = CRM_Utils_Array::value("email-{$this->_bltID}", $params); } // subscribing contact to groups if (!empty($subscribeGroupIds) && $subscriptionEmail['email']) { CRM_Mailing_Event_BAO_Subscribe::commonSubscribe($subscribeGroupIds, $subscriptionEmail, $contactID); } // If onbehalf-of-organization contribution / signup, add organization // and it's location. if (isset($this->_values['onbehalf_profile_id']) && isset($behalfOrganization['organization_name'])) { $ufFields = array(); foreach ($this->_fields['onbehalf'] as $name => $value) { $ufFields[$name] = 1; } self::processOnBehalfOrganization($behalfOrganization, $contactID, $this->_values, $this->_params, $ufFields); } elseif (!empty($this->_membershipContactID) && $contactID != $this->_membershipContactID) { // this is an onbehalf renew case for inherited membership. For e.g a permissioned member of household, // store current user id as related contact for later use for mailing / activity.. $this->_values['related_contact'] = $contactID; $this->_params['related_contact'] = $contactID; // swap contact like we do for on-behalf-org case, so parent/primary membership is affected $contactID = $this->_membershipContactID; } // lets store the contactID in the session // for things like tell a friend $session = CRM_Core_Session::singleton(); if (!$session->get('userID')) { $session->set('transaction.userID', $contactID); } else { $session->set('transaction.userID', NULL); } $this->_useForMember = $this->get('useForMember'); // store the fact that this is a membership and membership type is selected if (!empty($membershipParams['selectMembership']) && $membershipParams['selectMembership'] != 'no_thanks' || $this->_useForMember) { if (!$this->_useForMember) { $this->assign('membership_assign', TRUE); $this->set('membershipTypeID', $this->_params['selectMembership']); } if ($this->_action & CRM_Core_Action::PREVIEW) { $membershipParams['is_test'] = 1; } if ($this->_params['is_pay_later']) { $membershipParams['is_pay_later'] = 1; } //inherit campaign from contribution page. if (!array_key_exists('campaign_id', $membershipParams)) { $membershipParams['campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values); } CRM_Core_Payment_Form::mapParams($this->_bltID, $this->_params, $membershipParams, TRUE); $this->doMembershipProcessing($contactID, $membershipParams, $premiumParams, $isPayLater); } else { // at this point we've created a contact and stored its address etc // all the payment processors expect the name and address to be in the // so we copy stuff over to first_name etc. $paymentParams = $this->_params; if (!empty($paymentParams['onbehalf']) && is_array($paymentParams['onbehalf'])) { foreach ($paymentParams['onbehalf'] as $key => $value) { if (strstr($key, 'custom_')) { $this->_params[$key] = $value; } } } $result = CRM_Contribute_BAO_Contribution_Utils::processConfirm($this, $paymentParams, $contactID, $this->wrangleFinancialTypeID($this->_values['financial_type_id']), 'contribution', $this->_mode == 'test' ? 1 : 0, CRM_Utils_Array::value('is_recur', $paymentParams)); if (empty($result['is_payment_failure'])) { // @todo move premium processing to complete transaction if it truly is an 'after' action. $this->postProcessPremium($premiumParams, $result['contribution']); } if (!empty($result['contribution'])) { // Not quite sure why it would be empty at this stage but tests show it can be ... at least in tests. $this->completeTransaction($result, $result['contribution']->id); } return $result; } }
/** * Default payment instrument validation. * * Implement the usual Luhn algorithm via a static function in the CRM_Core_Payment_Form if it's a credit card * Not a static function, because I need to check for payment_type. * * @param array $values * @param array $errors */ public function validatePaymentInstrument($values, &$errors) { if ($this->_paymentProcessor['payment_type'] == 1) { CRM_Core_Payment_Form::validateCreditCard($values, $errors); } }
/** * Add JS to show icons for the accepted credit cards. */ public static function addCreditCardJs() { $creditCardTypes = CRM_Core_Payment_Form::getCreditCardCSSNames(); CRM_Core_Resources::singleton()->addScriptFile('civicrm', 'templates/CRM/Core/BillingBlock.js', 10)->addScript('CRM.config.creditCardTypes = ' . json_encode($creditCardTypes) . ';'); }
/** * Process credit card payment. * * @param array $submittedValues * @param array $lineItem * * @throws CRM_Core_Exception */ protected function processCreditCard($submittedValues, $lineItem) { $sendReceipt = $contribution = FALSE; $unsetParams = array('trxn_id', 'payment_instrument_id', 'contribution_status_id', 'cancel_date', 'cancel_reason'); foreach ($unsetParams as $key) { if (isset($submittedValues[$key])) { unset($submittedValues[$key]); } } $isTest = $this->_mode == 'test' ? 1 : 0; // CRM-12680 set $_lineItem if its not set if (empty($this->_lineItem) && !empty($lineItem)) { $this->_lineItem = $lineItem; } //Get the require fields value only. $params = $this->_params = $submittedValues; $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($this->_params['payment_processor_id'], $this->_mode); // Get the payment processor id as per mode. $this->_params['payment_processor'] = $params['payment_processor_id'] = $this->_params['payment_processor_id'] = $submittedValues['payment_processor_id'] = $this->_paymentProcessor['id']; $now = date('YmdHis'); $fields = array(); // we need to retrieve email address if ($this->_context == 'standalone' && !empty($submittedValues['is_email_receipt'])) { list($this->userDisplayName, $this->userEmail) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contactID); $this->assign('displayName', $this->userDisplayName); } // Set email for primary location. $fields['email-Primary'] = 1; $params['email-Primary'] = $this->userEmail; // now set the values for the billing location. foreach (array_keys($this->_fields) as $name) { $fields[$name] = 1; } // also add location name to the array $params["address_name-{$this->_bltID}"] = CRM_Utils_Array::value('billing_first_name', $params) . ' ' . CRM_Utils_Array::value('billing_middle_name', $params) . ' ' . CRM_Utils_Array::value('billing_last_name', $params); $params["address_name-{$this->_bltID}"] = trim($params["address_name-{$this->_bltID}"]); $fields["address_name-{$this->_bltID}"] = 1; $ctype = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_contactID, 'contact_type'); $nameFields = array('first_name', 'middle_name', 'last_name'); foreach ($nameFields as $name) { $fields[$name] = 1; if (array_key_exists("billing_{$name}", $params)) { $params[$name] = $params["billing_{$name}"]; $params['preserveDBName'] = TRUE; } } if (!empty($params['source'])) { unset($params['source']); } $contactID = CRM_Contact_BAO_Contact::createProfileContact($params, $fields, $this->_contactID, NULL, NULL, $ctype); // add all the additional payment params we need if (!empty($this->_params["billing_state_province_id-{$this->_bltID}"])) { $this->_params["state_province-{$this->_bltID}"] = $this->_params["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($this->_params["billing_state_province_id-{$this->_bltID}"]); } if (!empty($this->_params["billing_country_id-{$this->_bltID}"])) { $this->_params["country-{$this->_bltID}"] = $this->_params["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($this->_params["billing_country_id-{$this->_bltID}"]); } $legacyCreditCardExpiryCheck = FALSE; if ($this->_paymentProcessor['payment_type'] & CRM_Core_Payment::PAYMENT_TYPE_CREDIT_CARD && !isset($this->_paymentFields)) { $legacyCreditCardExpiryCheck = TRUE; } if ($legacyCreditCardExpiryCheck || in_array('credit_card_exp_date', array_keys($this->_paymentFields))) { $this->_params['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($this->_params); $this->_params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($this->_params); } $this->_params['ip_address'] = CRM_Utils_System::ipAddress(); $this->_params['amount'] = $this->_params['total_amount']; $this->_params['amount_level'] = 0; $this->_params['description'] = ts('Office Credit Card contribution'); $this->_params['currencyID'] = CRM_Utils_Array::value('currency', $this->_params, CRM_Core_Config::singleton()->defaultCurrency); $this->_params['payment_action'] = 'Sale'; if (!empty($this->_params['receive_date'])) { $this->_params['receive_date'] = CRM_Utils_Date::processDate($this->_params['receive_date'], $this->_params['receive_date_time']); } if (!empty($params['soft_credit_to'])) { $this->_params['soft_credit_to'] = $params['soft_credit_to']; $this->_params['pcp_made_through_id'] = $params['pcp_made_through_id']; } $this->_params['pcp_display_in_roll'] = CRM_Utils_Array::value('pcp_display_in_roll', $params); $this->_params['pcp_roll_nickname'] = CRM_Utils_Array::value('pcp_roll_nickname', $params); $this->_params['pcp_personal_note'] = CRM_Utils_Array::value('pcp_personal_note', $params); //Add common data to formatted params CRM_Contribute_Form_AdditionalInfo::postProcessCommon($params, $this->_params, $this); if (empty($this->_params['invoice_id'])) { $this->_params['invoiceID'] = md5(uniqid(rand(), TRUE)); } else { $this->_params['invoiceID'] = $this->_params['invoice_id']; } // At this point we've created a contact and stored its address etc // all the payment processors expect the name and address to be in the // so we copy stuff over to first_name etc. $paymentParams = $this->_params; $paymentParams['contactID'] = $this->_contactID; CRM_Core_Payment_Form::mapParams($this->_bltID, $this->_params, $paymentParams, TRUE); $contributionType = new CRM_Financial_DAO_FinancialType(); $contributionType->id = $params['financial_type_id']; // Add some financial type details to the params list // if folks need to use it. $paymentParams['contributionType_name'] = $this->_params['contributionType_name'] = $contributionType->name; $paymentParams['contributionPageID'] = NULL; if (!empty($this->_params['is_email_receipt'])) { $paymentParams['email'] = $this->userEmail; $paymentParams['is_email_receipt'] = 1; } else { $paymentParams['is_email_receipt'] = 0; $this->_params['is_email_receipt'] = 0; } if (!empty($this->_params['receive_date'])) { $paymentParams['receive_date'] = $this->_params['receive_date']; } // For recurring contribution, create Contribution Record first. // Contribution ID, Recurring ID and Contact ID needed // When we get a callback from the payment processor, CRM-7115 if (!empty($paymentParams['is_recur'])) { $contribution = CRM_Contribute_Form_Contribution_Confirm::processContribution($this, $this->_params, NULL, $this->_contactID, $contributionType, TRUE, FALSE, $isTest, $this->_lineItem); $paymentParams['contributionID'] = $contribution->id; $paymentParams['contributionTypeID'] = $contribution->financial_type_id; $paymentParams['contributionPageID'] = $contribution->contribution_page_id; $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id; } $result = array(); if ($paymentParams['amount'] > 0.0) { // force a re-get of the payment processor in case the form changed it, CRM-7179 $payment = CRM_Core_Payment::singleton($this->_mode, $this->_paymentProcessor, $this, TRUE); try { $result = $payment->doPayment($paymentParams, 'contribute'); } catch (CRM_Core_Exception $e) { $message = ts("Payment Processor Error message") . $e->getMessage(); $this->cleanupDBAfterPaymentFailure($paymentParams, $message); // Set the contribution mode. $urlParams = "action=add&cid={$this->_contactID}"; if ($this->_mode) { $urlParams .= "&mode={$this->_mode}"; } if (!empty($this->_ppID)) { $urlParams .= "&context=pledge&ppid={$this->_ppID}"; } CRM_Core_Error::statusBounce($message, $urlParams, ts('Payment Processor Error')); } } $this->_params = array_merge($this->_params, $result); $this->_params['receive_date'] = $now; if (!empty($this->_params['is_email_receipt'])) { $this->_params['receipt_date'] = $now; } else { $this->_params['receipt_date'] = CRM_Utils_Date::processDate($this->_params['receipt_date'], $params['receipt_date_time'], TRUE); } $this->set('params', $this->_params); $this->assign('trxn_id', $result['trxn_id']); $this->assign('receive_date', $this->_params['receive_date']); // Result has all the stuff we need // lets archive it to a financial transaction if ($contributionType->is_deductible) { $this->assign('is_deductible', TRUE); $this->set('is_deductible', TRUE); } // Set source if not set if (empty($this->_params['source'])) { $userID = CRM_Core_Session::singleton()->get('userID'); $userSortName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $userID, 'sort_name'); $this->_params['source'] = ts('Submit Credit Card Payment by: %1', array(1 => $userSortName)); } // Build custom data getFields array $customFieldsContributionType = CRM_Core_BAO_CustomField::getFields('Contribution', FALSE, FALSE, CRM_Utils_Array::value('financial_type_id', $params)); $customFields = CRM_Utils_Array::crmArrayMerge($customFieldsContributionType, CRM_Core_BAO_CustomField::getFields('Contribution', FALSE, FALSE, NULL, NULL, TRUE)); $params['custom'] = CRM_Core_BAO_CustomField::postProcess($params, $customFields, $this->_id, 'Contribution'); if (empty($paymentParams['is_recur'])) { $contribution = CRM_Contribute_Form_Contribution_Confirm::processContribution($this, $this->_params, $result, $this->_contactID, $contributionType, FALSE, FALSE, $isTest, $this->_lineItem); } // Send receipt mail. if ($contribution->id && !empty($this->_params['is_email_receipt'])) { $this->_params['trxn_id'] = CRM_Utils_Array::value('trxn_id', $result); $this->_params['contact_id'] = $this->_contactID; $this->_params['contribution_id'] = $contribution->id; $sendReceipt = CRM_Contribute_Form_AdditionalInfo::emailReceipt($this, $this->_params, TRUE); } //process the note if ($contribution->id && isset($params['note'])) { CRM_Contribute_Form_AdditionalInfo::processNote($params, $contactID, $contribution->id, NULL); } //process premium if ($contribution->id && isset($params['product_name'][0])) { CRM_Contribute_Form_AdditionalInfo::processPremium($params, $contribution->id, NULL, $this->_options); } //update pledge payment status. if ($this->_ppID && $contribution->id) { // Store contribution id in payment record. CRM_Core_DAO::setFieldValue('CRM_Pledge_DAO_PledgePayment', $this->_ppID, 'contribution_id', $contribution->id); CRM_Pledge_BAO_PledgePayment::updatePledgePaymentStatus($this->_pledgeID, array($this->_ppID), $contribution->contribution_status_id, NULL, $contribution->total_amount); } if ($contribution->id) { $statusMsg = ts('The contribution record has been processed.'); if (!empty($this->_params['is_email_receipt']) && $sendReceipt) { $statusMsg .= ' ' . ts('A receipt has been emailed to the contributor.'); } CRM_Core_Session::setStatus($statusMsg, ts('Complete'), 'success'); } }
/** * Build the form object. * * @param CRM_Core_Form $form * * @return void */ public static function buildQuickForm(&$form) { if ($form->_eventId) { $form->_isPaidEvent = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $form->_eventId, 'is_monetary'); if ($form->_isPaidEvent) { $form->addElement('hidden', 'hidden_feeblock', 1); } // make sure this is for backoffice registration. if ($form->getName() == 'Participant') { $eventfullMsg = CRM_Event_BAO_Participant::eventFullMessage($form->_eventId, $form->_pId); $form->addElement('hidden', 'hidden_eventFullMsg', $eventfullMsg, array('id' => 'hidden_eventFullMsg')); } } if ($form->_pId) { if (CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $form->_pId, 'contribution_id', 'participant_id')) { $form->_online = TRUE; } } if ($form->_isPaidEvent) { $params = array('id' => $form->_eventId); CRM_Event_BAO_Event::retrieve($params, $event); //retrieve custom information $form->_values = array(); CRM_Event_Form_Registration::initEventFee($form, $event['id']); CRM_Event_Form_Registration_Register::buildAmount($form, TRUE, $form->_discountId); $lineItem = array(); $invoiceSettings = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings'); $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings); $totalTaxAmount = 0; if (!CRM_Utils_System::isNull(CRM_Utils_Array::value('line_items', $form->_values))) { $lineItem[] = $form->_values['line_items']; foreach ($form->_values['line_items'] as $key => $value) { $totalTaxAmount = $value['tax_amount'] + $totalTaxAmount; } } if ($invoicing) { $form->assign('totalTaxAmount', $totalTaxAmount); } $form->assign('lineItem', empty($lineItem) ? FALSE : $lineItem); $discounts = array(); if (!empty($form->_values['discount'])) { foreach ($form->_values['discount'] as $key => $value) { $value = current($value); $discounts[$key] = $value['name']; } $element = $form->add('select', 'discount_id', ts('Discount Set'), array(0 => ts('- select -')) + $discounts, FALSE, array('class' => "crm-select2")); if ($form->_online) { $element->freeze(); } } if ($form->_mode) { CRM_Core_Payment_Form::buildPaymentForm($form, $form->_paymentProcessor, FALSE); } elseif (!$form->_mode) { $form->addElement('checkbox', 'record_contribution', ts('Record Payment?'), NULL, array('onclick' => "return showHideByValue('record_contribution','','payment_information','table-row','radio',false);")); $form->add('select', 'financial_type_id', ts('Financial Type'), array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::financialType()); $form->addDate('receive_date', ts('Received'), FALSE, array('formatType' => 'activityDate')); $form->add('select', 'payment_instrument_id', ts('Paid By'), array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::paymentInstrument(), FALSE, array('onChange' => "return showHideByValue('payment_instrument_id','4','checkNumber','table-row','select',false);")); // don't show transaction id in batch update mode $path = CRM_Utils_System::currentPath(); $form->assign('showTransactionId', FALSE); if ($path != 'civicrm/contact/search/basic') { $form->add('text', 'trxn_id', ts('Transaction ID')); $form->addRule('trxn_id', ts('Transaction ID already exists in Database.'), 'objectExists', array('CRM_Contribute_DAO_Contribution', $form->_eventId, 'trxn_id')); $form->assign('showTransactionId', TRUE); } $status = CRM_Contribute_PseudoConstant::contributionStatus(); // CRM-14417 suppressing contribution statuses that are NOT relevant to new participant registrations $statusName = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'); foreach (array('Cancelled', 'Failed', 'In Progress', 'Overdue', 'Refunded', 'Pending refund') as $suppress) { unset($status[CRM_Utils_Array::key($suppress, $statusName)]); } $form->add('select', 'contribution_status_id', ts('Payment Status'), $status); $form->add('text', 'check_number', ts('Check Number'), CRM_Core_DAO::getAttribute('CRM_Contribute_DAO_Contribution', 'check_number')); $form->add('text', 'total_amount', ts('Amount'), CRM_Core_DAO::getAttribute('CRM_Contribute_DAO_Contribution', 'total_amount')); } } else { $form->add('text', 'amount', ts('Event Fee(s)')); } $form->assign('onlinePendingContributionId', $form->get('onlinePendingContributionId')); $form->assign('paid', $form->_isPaidEvent); $form->addElement('checkbox', 'send_receipt', ts('Send Confirmation?'), NULL, array('onclick' => "showHideByValue('send_receipt','','notice','table-row','radio',false); showHideByValue('send_receipt','','from-email','table-row','radio',false);")); $form->add('select', 'from_email_address', ts('Receipt From'), $form->_fromEmails['from_email_id']); $form->add('textarea', 'receipt_text', ts('Confirmation Message')); // Retrieve the name and email of the contact - form will be the TO for receipt email ( only if context is not standalone) if ($form->_context != 'standalone') { if ($form->_contactId) { list($form->_contributorDisplayName, $form->_contributorEmail) = CRM_Contact_BAO_Contact_Location::getEmailDetails($form->_contactId); $form->assign('email', $form->_contributorEmail); } else { //show email block for batch update for event $form->assign('batchEmail', TRUE); } } $mailingInfo = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME, 'mailing_backend'); $form->assign('outBound_option', $mailingInfo['outBound_option']); $form->assign('hasPayment', $form->_paymentId); }
/** * Process the form submission. * * * @return void */ public function postProcess() { if ($this->_action & CRM_Core_Action::DELETE) { CRM_Member_BAO_Membership::del($this->_id); return; } $allMemberStatus = CRM_Member_PseudoConstant::membershipStatus(); $allContributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(); $isTest = $this->_mode == 'test' ? 1 : 0; $lineItems = NULL; if (!empty($this->_lineItem)) { $lineItems = $this->_lineItem; } $config = CRM_Core_Config::singleton(); // get the submitted form values. $this->_params = $formValues = $this->controller->exportValues($this->_name); $this->convertDateFieldsToMySQL($formValues); $params = $softParams = $ids = array(); $membershipTypeValues = array(); foreach ($this->_memTypeSelected as $memType) { $membershipTypeValues[$memType]['membership_type_id'] = $memType; } //take the required membership recur values. if ($this->_mode && !empty($this->_params['auto_renew'])) { $params['is_recur'] = $this->_params['is_recur'] = $formValues['is_recur'] = TRUE; $mapping = array('frequency_interval' => 'duration_interval', 'frequency_unit' => 'duration_unit'); $count = 0; foreach ($this->_memTypeSelected as $memType) { $recurMembershipTypeValues = CRM_Utils_Array::value($memType, $this->_recurMembershipTypes, array()); foreach ($mapping as $mapVal => $mapParam) { $membershipTypeValues[$memType][$mapVal] = CRM_Utils_Array::value($mapParam, $recurMembershipTypeValues); if (!$count) { $this->_params[$mapVal] = $formValues[$mapVal] = CRM_Utils_Array::value($mapParam, $recurMembershipTypeValues); } } $count++; } } // process price set and get total amount and line items. $lineItem = array(); $priceSetId = NULL; if (!($priceSetId = CRM_Utils_Array::value('price_set_id', $formValues))) { CRM_Member_BAO_Membership::createLineItems($this, $formValues['membership_type_id'], $priceSetId); } $isQuickConfig = 0; if ($this->_priceSetId && CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) { $isQuickConfig = 1; } $termsByType = array(); if ($priceSetId) { CRM_Price_BAO_PriceSet::processAmount($this->_priceSet['fields'], $this->_params, $lineItem[$priceSetId]); if (CRM_Utils_Array::value('tax_amount', $this->_params)) { $params['tax_amount'] = $this->_params['tax_amount']; } $params['total_amount'] = CRM_Utils_Array::value('amount', $this->_params); $submittedFinancialType = CRM_Utils_Array::value('financial_type_id', $formValues); if (!empty($lineItem[$priceSetId])) { foreach ($lineItem[$priceSetId] as &$li) { if (!empty($li['membership_type_id'])) { if (!empty($li['membership_num_terms'])) { $termsByType[$li['membership_type_id']] = $li['membership_num_terms']; } } ///CRM-11529 for quick config backoffice transactions //when financial_type_id is passed in form, update the //lineitems with the financial type selected in form if ($isQuickConfig && $submittedFinancialType) { $li['financial_type_id'] = $submittedFinancialType; } } } } $this->storeContactFields($formValues); $params['contact_id'] = $this->_contactID; $fields = array('status_id', 'source', 'is_override', 'campaign_id'); foreach ($fields as $f) { $params[$f] = CRM_Utils_Array::value($f, $formValues); } // fix for CRM-3724 // when is_override false ignore is_admin statuses during membership // status calculation. similarly we did fix for import in CRM-3570. if (empty($params['is_override'])) { $params['exclude_is_admin'] = TRUE; } // process date params to mysql date format. $dateTypes = array('join_date' => 'joinDate', 'start_date' => 'startDate', 'end_date' => 'endDate'); foreach ($dateTypes as $dateField => $dateVariable) { ${$dateVariable} = CRM_Utils_Date::processDate($formValues[$dateField]); } $memTypeNumTerms = empty($termsByType) ? CRM_Utils_Array::value('num_terms', $formValues) : NULL; $calcDates = array(); foreach ($this->_memTypeSelected as $memType) { if (empty($memTypeNumTerms)) { $memTypeNumTerms = CRM_Utils_Array::value($memType, $termsByType, 1); } $calcDates[$memType] = CRM_Member_BAO_MembershipType::getDatesForMembershipType($memType, $joinDate, $startDate, $endDate, $memTypeNumTerms); } foreach ($calcDates as $memType => $calcDate) { foreach (array_keys($dateTypes) as $d) { //first give priority to form values then calDates. $date = CRM_Utils_Array::value($d, $formValues); if (!$date) { $date = CRM_Utils_Array::value($d, $calcDate); } $membershipTypeValues[$memType][$d] = CRM_Utils_Date::processDate($date); //$params[$d] = CRM_Utils_Date::processDate( $date ); } } // max related memberships - take from form or inherit from membership type foreach ($this->_memTypeSelected as $memType) { if (array_key_exists('max_related', $formValues)) { $membershipTypeValues[$memType]['max_related'] = CRM_Utils_Array::value('max_related', $formValues); } } if ($this->_id) { $ids['membership'] = $params['id'] = $this->_id; } $session = CRM_Core_Session::singleton(); $ids['userId'] = $session->get('userID'); // membership type custom data foreach ($this->_memTypeSelected as $memType) { $customFields = CRM_Core_BAO_CustomField::getFields('Membership', FALSE, FALSE, $memType); $customFields = CRM_Utils_Array::crmArrayMerge($customFields, CRM_Core_BAO_CustomField::getFields('Membership', FALSE, FALSE, NULL, NULL, TRUE)); $membershipTypeValues[$memType]['custom'] = CRM_Core_BAO_CustomField::postProcess($formValues, $customFields, $this->_id, 'Membership'); } foreach ($this->_memTypeSelected as $memType) { $membershipTypes[$memType] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $memType); } $membershipType = implode(', ', $membershipTypes); // Retrieve the name and email of the current user - this will be the FROM for the receipt email list($userName, $userEmail) = CRM_Contact_BAO_Contact_Location::getEmailDetails($ids['userId']); //CRM-13981, allow different person as a soft-contributor of chosen type if ($this->_contributorContactID != $this->_contactID) { $params['contribution_contact_id'] = $this->_contributorContactID; if (!empty($this->_params['soft_credit_type_id'])) { $softParams['soft_credit_type_id'] = $this->_params['soft_credit_type_id']; $softParams['contact_id'] = $this->_contactID; } } if (!empty($formValues['record_contribution'])) { $recordContribution = array('total_amount', 'financial_type_id', 'payment_instrument_id', 'trxn_id', 'contribution_status_id', 'check_number', 'campaign_id', 'receive_date'); foreach ($recordContribution as $f) { $params[$f] = CRM_Utils_Array::value($f, $formValues); } if (!$this->_onlinePendingContributionId) { if (empty($formValues['source'])) { $params['contribution_source'] = ts('%1 Membership: Offline signup (by %2)', array(1 => $membershipType, 2 => $userName)); } else { $params['contribution_source'] = $formValues['source']; } } if (empty($params['is_override']) && CRM_Utils_Array::value('contribution_status_id', $params) == array_search('Pending', CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'))) { $params['status_id'] = array_search('Pending', $allMemberStatus); $params['skipStatusCal'] = TRUE; $params['is_pay_later'] = 1; $this->assign('is_pay_later', 1); } if (!empty($formValues['send_receipt'])) { $params['receipt_date'] = CRM_Utils_Array::value('receive_date', $formValues); } //insert financial type name in receipt. $formValues['contributionType_name'] = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialType', $formValues['financial_type_id']); } // process line items, until no previous line items. if (!empty($lineItem)) { $params['lineItems'] = $lineItem; $params['processPriceSet'] = TRUE; } $createdMemberships = array(); if ($this->_mode) { if (empty($formValues['total_amount']) && !$priceSetId) { // if total amount not provided minimum for membership type is used $params['total_amount'] = $formValues['total_amount'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $formValues['membership_type_id'][1], 'minimum_fee'); } else { $params['total_amount'] = CRM_Utils_Array::value('total_amount', $formValues, 0); } if ($priceSetId && !$isQuickConfig) { $params['financial_type_id'] = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceSetId, 'financial_type_id'); } else { $params['financial_type_id'] = CRM_Utils_Array::value('financial_type_id', $formValues); } $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($formValues['payment_processor_id'], $this->_mode); //get the payment processor id as per mode. $params['payment_processor_id'] = $this->_params['payment_processor_id'] = $formValues['payment_processor_id'] = $this->_paymentProcessor['id']; $now = date('YmdHis'); $fields = array(); // set email for primary location. $fields['email-Primary'] = 1; $formValues['email-5'] = $formValues['email-Primary'] = $this->_memberEmail; $params['register_date'] = $now; // now set the values for the billing location. foreach ($this->_fields as $name => $dontCare) { $fields[$name] = 1; } // also add location name to the array $formValues["address_name-{$this->_bltID}"] = CRM_Utils_Array::value('billing_first_name', $formValues) . ' ' . CRM_Utils_Array::value('billing_middle_name', $formValues) . ' ' . CRM_Utils_Array::value('billing_last_name', $formValues); $formValues["address_name-{$this->_bltID}"] = trim($formValues["address_name-{$this->_bltID}"]); $fields["address_name-{$this->_bltID}"] = 1; //ensure we don't over-write the payer's email with the member's email if ($this->_contributorContactID == $this->_contactID) { $fields["email-{$this->_bltID}"] = 1; } $ctype = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_contactID, 'contact_type'); $nameFields = array('first_name', 'middle_name', 'last_name'); foreach ($nameFields as $name) { $fields[$name] = 1; if (array_key_exists("billing_{$name}", $formValues)) { $formValues[$name] = $formValues["billing_{$name}"]; $formValues['preserveDBName'] = TRUE; } } if ($this->_contributorContactID == $this->_contactID) { //see CRM-12869 for discussion of why we don't do this for separate payee payments CRM_Contact_BAO_Contact::createProfileContact($formValues, $fields, $this->_contributorContactID, NULL, NULL, $ctype); } // add all the additional payment params we need $this->_params["state_province-{$this->_bltID}"] = $this->_params["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($this->_params["billing_state_province_id-{$this->_bltID}"]); $this->_params["country-{$this->_bltID}"] = $this->_params["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($this->_params["billing_country_id-{$this->_bltID}"]); $this->_params['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($this->_params); $this->_params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($this->_params); $this->_params['ip_address'] = CRM_Utils_System::ipAddress(); $this->_params['amount'] = $params['total_amount']; $this->_params['currencyID'] = $config->defaultCurrency; $this->_params['description'] = ts('Office Credit Card Membership Signup Contribution'); $this->_params['payment_action'] = 'Sale'; $this->_params['invoiceID'] = md5(uniqid(rand(), TRUE)); $this->_params['financial_type_id'] = $params['financial_type_id']; // at this point we've created a contact and stored its address etc // all the payment processors expect the name and address to be in the // so we copy stuff over to first_name etc. $paymentParams = $this->_params; $paymentParams['contactID'] = $this->_contributorContactID; //CRM-10377 if payment is by an alternate contact then we need to set that person // as the contact in the payment params if ($this->_contributorContactID != $this->_contactID) { if (!empty($this->_params['soft_credit_type_id'])) { $softParams['contact_id'] = $params['contact_id']; $softParams['soft_credit_type_id'] = $this->_params['soft_credit_type_id']; } } if (!empty($this->_params['send_receipt'])) { $paymentParams['email'] = $this->_contributorEmail; } CRM_Core_Payment_Form::mapParams($this->_bltID, $this->_params, $paymentParams, TRUE); // CRM-7137 -for recurring membership, // we do need contribution and recuring records. $result = NULL; if (!empty($paymentParams['is_recur'])) { $contributionType = new CRM_Financial_DAO_FinancialType(); $contributionType->id = $params['financial_type_id']; if (!$contributionType->find(TRUE)) { CRM_Core_Error::fatal('Could not find a system table'); } $contribution = CRM_Contribute_Form_Contribution_Confirm::processContribution($this, $paymentParams, $result, $this->_contributorContactID, $contributionType, TRUE, FALSE, $isTest, $lineItems); //create new soft-credit record, CRM-13981 if ($softParams) { $softParams['contribution_id'] = $contribution->id; $softParams['currency'] = $contribution->currency; $softParams['amount'] = $contribution->total_amount; CRM_Contribute_BAO_ContributionSoft::add($softParams); } $paymentParams['contactID'] = $this->_contactID; $paymentParams['contributionID'] = $contribution->id; $paymentParams['contributionTypeID'] = $contribution->financial_type_id; $paymentParams['contributionPageID'] = $contribution->contribution_page_id; $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id; $ids['contribution'] = $contribution->id; $params['contribution_recur_id'] = $paymentParams['contributionRecurID']; } if ($params['total_amount'] > 0.0) { $payment = CRM_Core_Payment::singleton($this->_mode, $this->_paymentProcessor, $this); $result = $payment->doDirectPayment($paymentParams); } if (is_a($result, 'CRM_Core_Error')) { //make sure to cleanup db for recurring case. if (!empty($paymentParams['contributionID'])) { CRM_Contribute_BAO_Contribution::deleteContribution($paymentParams['contributionID']); } if (!empty($paymentParams['contributionRecurID'])) { CRM_Contribute_BAO_ContributionRecur::deleteRecurContribution($paymentParams['contributionRecurID']); } CRM_Core_Error::displaySessionError($result); CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/view/membership', "reset=1&action=add&cid={$this->_contactID}&context=&mode={$this->_mode}")); } if ($result) { $this->_params = array_merge($this->_params, $result); //assign amount to template if payment was successful $this->assign('amount', $params['total_amount']); } // if the payment processor returns a contribution_status_id -> use it! if (isset($result['contribution_status_id'])) { $result['payment_status_id'] = $result['contribution_status_id']; } if (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'] = $result['payment_status_id']; } else { $params['contribution_status_id'] = !empty($paymentParams['is_recur']) ? 2 : 1; } if ($params['contribution_status_id'] != array_search('Completed', $allContributionStatus)) { $params['status_id'] = array_search('Pending', $allMemberStatus); $params['skipStatusCal'] = TRUE; // unset send-receipt option, since receipt will be sent when ipn is received. unset($this->_params['send_receipt'], $formValues['send_receipt']); //as membership is pending set dates to null. $memberDates = array('join_date' => 'joinDate', 'start_date' => 'startDate', 'end_date' => 'endDate'); foreach ($memberDates as $dp => $dv) { ${$dv} = NULL; foreach ($this->_memTypeSelected as $memType) { $membershipTypeValues[$memType][$dv] = NULL; } } } $params['receive_date'] = $now; $params['invoice_id'] = $this->_params['invoiceID']; $params['contribution_source'] = ts('%1 Membership Signup: Credit card or direct debit (by %2)', array(1 => $membershipType, 2 => $userName)); $params['source'] = $formValues['source'] ? $formValues['source'] : $params['contribution_source']; $params['trxn_id'] = CRM_Utils_Array::value('trxn_id', $result); $params['payment_instrument_id'] = 1; $params['is_test'] = $this->_mode == 'live' ? 0 : 1; if (!empty($this->_params['send_receipt'])) { $params['receipt_date'] = $now; } else { $params['receipt_date'] = NULL; } $this->set('params', $this->_params); $this->assign('trxn_id', CRM_Utils_Array::value('trxn_id', $result)); $this->assign('receive_date', CRM_Utils_Date::mysqlToIso($params['receive_date'])); // required for creating membership for related contacts $params['action'] = $this->_action; //create membership record. $count = 0; foreach ($this->_memTypeSelected as $memType) { if ($count && ($relateContribution = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id))) { $membershipTypeValues[$memType]['relate_contribution_id'] = $relateContribution; } $membershipParams = array_merge($membershipTypeValues[$memType], $params); //CRM-15366 if (!empty($softParams) && empty($paymentParams['is_recur'])) { $membershipParams['soft_credit'] = $softParams; } if (!empty($paymentParams['is_recur']) && CRM_Utils_Array::value('payment_status_id', $result) == 1) { // CRM-16993 we have a situation where line items have already been created. unset($membershipParams['lineItems']); } $membership = CRM_Member_BAO_Membership::create($membershipParams, $ids); $params['contribution'] = CRM_Utils_Array::value('contribution', $membershipParams); unset($params['lineItems']); $this->_membershipIDs[] = $membership->id; $createdMemberships[$memType] = $membership; $count++; } } else { $params['action'] = $this->_action; if ($this->_onlinePendingContributionId && !empty($formValues['record_contribution'])) { // update membership as well as contribution object, CRM-4395 $params['contribution_id'] = $this->_onlinePendingContributionId; $params['componentId'] = $params['id']; $params['componentName'] = 'contribute'; $result = CRM_Contribute_BAO_Contribution::transitionComponents($params, TRUE); if (!empty($result) && !empty($params['contribution_id'])) { $lineItem = array(); $lineItems = CRM_Price_BAO_LineItem::getLineItems($params['contribution_id'], 'contribution', NULL, TRUE, TRUE); $itemId = key($lineItems); $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $lineItems[$itemId]['price_field_id'], 'price_set_id'); $fieldType = NULL; if ($itemId && !empty($lineItems[$itemId]['price_field_id'])) { $fieldType = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $lineItems[$itemId]['price_field_id'], 'html_type'); } $lineItems[$itemId]['unit_price'] = $params['total_amount']; $lineItems[$itemId]['line_total'] = $params['total_amount']; $lineItems[$itemId]['id'] = $itemId; $lineItem[$priceSetId] = $lineItems; $contributionBAO = new CRM_Contribute_BAO_Contribution(); $contributionBAO->id = $params['contribution_id']; $contributionBAO->contact_id = $params['contact_id']; $contributionBAO->find(); CRM_Price_BAO_LineItem::processPriceSet($params['contribution_id'], $lineItem, $contributionBAO, 'civicrm_membership'); //create new soft-credit record, CRM-13981 if ($softParams) { $softParams['contribution_id'] = $params['contribution_id']; while ($contributionBAO->fetch()) { $softParams['currency'] = $contributionBAO->currency; $softParams['amount'] = $contributionBAO->total_amount; } CRM_Contribute_BAO_ContributionSoft::add($softParams); } } //carry updated membership object. $membership = new CRM_Member_DAO_Membership(); $membership->id = $this->_id; $membership->find(TRUE); $cancelled = TRUE; if ($membership->end_date) { //display end date w/ status message. $endDate = $membership->end_date; if (!in_array($membership->status_id, array(array_search('Cancelled', CRM_Member_PseudoConstant::membershipStatus(NULL, " name = 'Cancelled' ", 'name', FALSE, TRUE)), array_search('Expired', CRM_Member_PseudoConstant::membershipStatus())))) { $cancelled = FALSE; } } // suppress form values in template. $this->assign('cancelled', $cancelled); // FIX ME: need to recheck this // here we might updated dates, so get from object. foreach ($calcDates[$membership->membership_type_id] as $date => &$val) { if ($membership->{$date}) { $val = $membership->{$date}; } } $createdMemberships[] = $membership; } else { $count = 0; foreach ($this->_memTypeSelected as $memType) { if ($count && !empty($formValues['record_contribution']) && ($relateContribution = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id))) { $membershipTypeValues[$memType]['relate_contribution_id'] = $relateContribution; } $membershipParams = array_merge($params, $membershipTypeValues[$memType]); if (!empty($formValues['int_amount'])) { $init_amount = array(); foreach ($formValues as $key => $value) { if (strstr($key, 'txt-price')) { $init_amount[$key] = $value; } } $membershipParams['init_amount'] = $init_amount; } if (!empty($softParams)) { $membershipParams['soft_credit'] = $softParams; } $membership = CRM_Member_BAO_Membership::create($membershipParams, $ids); $params['contribution'] = CRM_Utils_Array::value('contribution', $membershipParams); unset($params['lineItems']); $this->_membershipIDs[] = $membership->id; $createdMemberships[$memType] = $membership; $count++; } } } if (!empty($lineItem[$priceSetId])) { $invoiceSettings = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings'); $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings); $taxAmount = FALSE; $totalTaxAmount = 0; foreach ($lineItem[$priceSetId] as &$priceFieldOp) { if (!empty($priceFieldOp['membership_type_id'])) { $priceFieldOp['start_date'] = $membershipTypeValues[$priceFieldOp['membership_type_id']]['start_date'] ? CRM_Utils_Date::customFormat($membershipTypeValues[$priceFieldOp['membership_type_id']]['start_date'], '%B %E%f, %Y') : '-'; $priceFieldOp['end_date'] = $membershipTypeValues[$priceFieldOp['membership_type_id']]['end_date'] ? CRM_Utils_Date::customFormat($membershipTypeValues[$priceFieldOp['membership_type_id']]['end_date'], '%B %E%f, %Y') : '-'; } else { $priceFieldOp['start_date'] = $priceFieldOp['end_date'] = 'N/A'; } if ($invoicing && isset($priceFieldOp['tax_amount'])) { $taxAmount = TRUE; $totalTaxAmount += $priceFieldOp['tax_amount']; } } if ($invoicing) { $dataArray = array(); foreach ($lineItem[$priceSetId] as $key => $value) { if (isset($value['tax_amount']) && isset($value['tax_rate'])) { if (isset($dataArray[$value['tax_rate']])) { $dataArray[$value['tax_rate']] = $dataArray[$value['tax_rate']] + CRM_Utils_Array::value('tax_amount', $value); } else { $dataArray[$value['tax_rate']] = CRM_Utils_Array::value('tax_amount', $value); } } } if ($taxAmount) { $this->assign('totalTaxAmount', $totalTaxAmount); $this->assign('taxTerm', CRM_Utils_Array::value('tax_term', $invoiceSettings)); } $this->assign('dataArray', $dataArray); } } $this->assign('lineItem', !empty($lineItem) && !$isQuickConfig ? $lineItem : FALSE); $receiptSend = FALSE; $contributionId = CRM_Member_BAO_Membership::getMembershipContributionId($membership->id); $membershipIds = $this->_membershipIDs; if ($contributionId && !empty($membershipIds)) { $contributionDetails = CRM_Contribute_BAO_Contribution::getContributionDetails(CRM_Export_Form_Select::MEMBER_EXPORT, $this->_membershipIDs); if ($contributionDetails[$membership->id]['contribution_status'] == 'Completed') { $receiptSend = TRUE; } } if (!empty($formValues['send_receipt']) && $receiptSend) { $formValues['contact_id'] = $this->_contactID; $formValues['contribution_id'] = $contributionId; // send email receipt $mailSend = self::emailReceipt($this, $formValues, $membership); } if ($this->_action & CRM_Core_Action::UPDATE) { //end date can be modified by hooks, so if end date is set then use it. $endDate = $membership->end_date ? $membership->end_date : $endDate; $statusMsg = ts('Membership for %1 has been updated.', array(1 => $this->_memberDisplayName)); if ($endDate && $endDate !== 'null') { $endDate = CRM_Utils_Date::customFormat($endDate); $statusMsg .= ' ' . ts('The membership End Date is %1.', array(1 => $endDate)); } if ($receiptSend) { $statusMsg .= ' ' . ts('A confirmation and receipt has been sent to %1.', array(1 => $this->_contributorEmail)); } } elseif ($this->_action & CRM_Core_Action::ADD) { // FIX ME: fix status messages $statusMsg = array(); foreach ($membershipTypes as $memType => $membershipType) { $statusMsg[$memType] = ts('%1 membership for %2 has been added.', array(1 => $membershipType, 2 => $this->_memberDisplayName)); $membership = $createdMemberships[$memType]; $memEndDate = $membership->end_date ? $membership->end_date : $endDate; //get the end date from calculated dates. if (!$memEndDate && empty($params['is_recur'])) { $memEndDate = CRM_Utils_Array::value('end_date', $calcDates[$memType]); } if ($memEndDate && $memEndDate !== 'null') { $memEndDate = CRM_Utils_Date::customFormat($memEndDate); $statusMsg[$memType] .= ' ' . ts('The new membership End Date is %1.', array(1 => $memEndDate)); } } $statusMsg = implode('<br/>', $statusMsg); if ($receiptSend && !empty($mailSend)) { $statusMsg .= ' ' . ts('A membership confirmation and receipt has been sent to %1.', array(1 => $this->_contributorEmail)); } } // finally set membership id if already not set if (!$this->_id) { $this->_id = $membership->id; } CRM_Core_Session::setStatus($statusMsg, ts('Complete'), 'success'); $buttonName = $this->controller->getButtonName(); if ($this->_context == 'standalone') { if ($buttonName == $this->getButtonName('upload', 'new')) { $session->replaceUserContext(CRM_Utils_System::url('civicrm/member/add', 'reset=1&action=add&context=standalone')); } else { $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->_contactID}&selectedChild=member")); } } elseif ($buttonName == $this->getButtonName('upload', 'new')) { $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view/membership', "reset=1&action=add&context=membership&cid={$this->_contactID}")); } }
/** * Build the form object. */ public function buildQuickForm() { if ($this->_mode) { $this->add('select', 'payment_processor_id', ts('Payment Processor'), $this->_processors, TRUE, array('onChange' => "buildAutoRenew( null, this.value, '{$this->_mode}');")); CRM_Core_Payment_Form::buildPaymentForm($this, $this->_paymentProcessor, FALSE, TRUE); } // Build the form for auto renew. This is displayed when in credit card mode or update mode. // The reason for showing it in update mode is not that clear. if ($this->_mode || $this->_action & CRM_Core_Action::UPDATE) { if (!empty($this->_recurPaymentProcessors)) { $this->assign('allowAutoRenew', TRUE); } $autoRenewElement = $this->addElement('checkbox', 'auto_renew', ts('Membership renewed automatically'), NULL, array('onclick' => "showHideByValue('auto_renew','','send-receipt','table-row','radio',true); showHideNotice( );")); if ($this->_action & CRM_Core_Action::UPDATE) { $autoRenewElement->freeze(); } $this->assign('recurProcessor', json_encode($this->_recurPaymentProcessors)); $this->addElement('checkbox', 'auto_renew', ts('Membership renewed automatically')); $this->assignPaymentRelatedVariables(); } $this->assign('autoRenewOptions', json_encode($this->membershipTypeRenewalStatus)); if ($this->_action & CRM_Core_Action::RENEW) { $this->addButtons(array(array('type' => 'upload', 'name' => ts('Renew'), 'isDefault' => TRUE), array('type' => 'cancel', 'name' => ts('Cancel')))); } elseif ($this->_action & CRM_Core_Action::DELETE) { $this->addButtons(array(array('type' => 'next', 'name' => ts('Delete'), 'isDefault' => TRUE), array('type' => 'cancel', 'name' => ts('Cancel')))); } else { $this->addButtons(array(array('type' => 'upload', 'name' => ts('Save'), 'isDefault' => TRUE), array('type' => 'upload', 'name' => ts('Save and New'), 'subName' => 'new'), array('type' => 'cancel', 'name' => ts('Cancel')))); } }
/** * Process the form submission. */ public function postProcess() { $now = date('YmdHis'); $this->_params = $this->get('params'); if (!empty($this->_params[0]['contact_id'])) { // unclear when this would be set & whether it could be checked in getContactID. // perhaps it relates to when cid is in the url //@todo someone who knows add comments on the various contactIDs in this form $contactID = $this->_params[0]['contact_id']; } else { $contactID = $this->getContactID(); } // if a discount has been applied, lets now deduct it from the amount // and fix the fee level if (!empty($this->_params[0]['discount']) && !empty($this->_params[0]['discount']['applied'])) { foreach ($this->_params as $k => $v) { if (CRM_Utils_Array::value('amount', $this->_params[$k]) > 0 && !empty($this->_params[$k]['discountAmount'])) { $this->_params[$k]['amount'] -= $this->_params[$k]['discountAmount']; $this->_params[$k]['amount_level'] .= CRM_Utils_Array::value('discountMessage', $this->_params[$k]); } } $this->set('params', $this->_params); } // CRM-4320, lets build array of cancelled additional participant ids // those are drop or skip by primary at the time of confirmation. // get all in and then unset those we want to process. $cancelledIds = $this->_additionalParticipantIds; $params = $this->_params; if ($this->_values['event']['is_monetary']) { $this->set('finalAmount', $this->_amount); } $participantCount = array(); //unset the skip participant from params. //build the $participantCount array. //maintain record for all participants. foreach ($params as $participantNum => $record) { if ($record == 'skip') { unset($params[$participantNum]); $participantCount[$participantNum] = 'skip'; } elseif ($participantNum) { $participantCount[$participantNum] = 'participant'; } //lets get additional participant id to cancel. if ($this->_allowConfirmation && is_array($cancelledIds)) { $additonalId = CRM_Utils_Array::value('participant_id', $record); if ($additonalId && ($key = array_search($additonalId, $cancelledIds))) { unset($cancelledIds[$key]); } } } $payment = $registerByID = $primaryCurrencyID = $contribution = NULL; $paymentObjError = ts('The system did not record payment details for this payment and so could not process the transaction. Please report this error to the site administrator.'); $this->participantIDS = array(); $fields = array(); foreach ($params as $key => $value) { CRM_Event_Form_Registration_Confirm::fixLocationFields($value, $fields, $this); //unset the billing parameters if it is pay later mode //to avoid creation of billing location // @todo - the reasoning for this is unclear - elsewhere we check what fields are provided by // the form & if billing fields exist we create the address, relying on the form to collect // only information we intend to store. if ($this->_allowWaitlist || $this->_requireApproval || !empty($value['is_pay_later']) && !$this->_isBillingAddressRequiredForPayLater || empty($value['is_primary'])) { $billingFields = array("email-{$this->_bltID}", 'billing_first_name', 'billing_middle_name', 'billing_last_name', "billing_street_address-{$this->_bltID}", "billing_city-{$this->_bltID}", "billing_state_province-{$this->_bltID}", "billing_state_province_id-{$this->_bltID}", "billing_postal_code-{$this->_bltID}", "billing_country-{$this->_bltID}", "billing_country_id-{$this->_bltID}", "address_name-{$this->_bltID}"); foreach ($billingFields as $field) { unset($value[$field]); } if (!empty($value['is_pay_later'])) { $this->_values['params']['is_pay_later'] = TRUE; } } //Unset ContactID for additional participants and set RegisterBy Id. if (empty($value['is_primary'])) { $contactID = CRM_Utils_Array::value('contact_id', $value); $registerByID = $this->get('registerByID'); if ($registerByID) { $value['registered_by_id'] = $registerByID; } } else { $value['amount'] = $this->_totalAmount; } $contactID = CRM_Event_Form_Registration_Confirm::updateContactFields($contactID, $value, $fields, $this); // lets store the contactID in the session // we dont store in userID in case the user is doing multiple // transactions etc // for things like tell a friend if (!$this->getContactID() && !empty($value['is_primary'])) { $session = CRM_Core_Session::singleton(); $session->set('transaction.userID', $contactID); } $value['description'] = ts('Online Event Registration') . ': ' . $this->_values['event']['title']; $value['accountingCode'] = CRM_Utils_Array::value('accountingCode', $this->_values['event']); $pending = FALSE; if ($this->_allowWaitlist || $this->_requireApproval) { //get the participant statuses. $waitingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Waiting'"); if ($this->_allowWaitlist) { $value['participant_status_id'] = $value['participant_status'] = array_search('On waitlist', $waitingStatuses); } else { $value['participant_status_id'] = $value['participant_status'] = array_search('Awaiting approval', $waitingStatuses); } //there might be case user seleted pay later and //now becomes part of run time waiting list. $value['is_pay_later'] = FALSE; } // required only if paid event if ($this->_values['event']['is_monetary'] && !($this->_allowWaitlist || $this->_requireApproval)) { if (is_array($this->_paymentProcessor)) { $payment = $this->_paymentProcessor['object']; } if (!empty($this->_paymentProcessor) && $this->_paymentProcessor['object']->supports('preApproval')) { $preApprovalParams = $this->_paymentProcessor['object']->getPreApprovalDetails($this->get('pre_approval_parameters')); $value = array_merge($value, $preApprovalParams); } $result = NULL; if (!empty($value['is_pay_later']) || $value['amount'] == 0 || $this->_contributeMode == 'checkout' || $this->_contributeMode == 'notify') { if ($value['amount'] != 0) { $pending = TRUE; //get the participant statuses. $pendingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Pending'"); $status = !empty($value['is_pay_later']) ? 'Pending from pay later' : 'Pending from incomplete transaction'; $value['participant_status_id'] = $value['participant_status'] = array_search($status, $pendingStatuses); } } elseif (!empty($value['is_primary'])) { CRM_Core_Payment_Form::mapParams($this->_bltID, $value, $value, TRUE); // payment email param can be empty for _bltID mapping // thus provide mapping for it with a different email value if (empty($value['email'])) { $value['email'] = CRM_Utils_Array::valueByRegexKey('/^email-/', $value); } if (is_object($payment)) { try { $result = $payment->doPayment($value); $value = array_merge($value, $result); } catch (\Civi\Payment\Exception\PaymentProcessorException $e) { CRM_Core_Session::singleton()->setStatus($e->getMessage()); CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "id={$this->_eventId}")); } } else { CRM_Core_Error::fatal($paymentObjError); } } $value['receive_date'] = $now; if ($this->_allowConfirmation) { $value['participant_register_date'] = $this->_values['participant']['register_date']; } $createContrib = $value['amount'] != 0 ? TRUE : FALSE; // force to create zero amount contribution, CRM-5095 if (!$createContrib && $value['amount'] == 0 && $this->_priceSetId && $this->_lineItem) { $createContrib = TRUE; } if ($createContrib && !empty($value['is_primary']) && !$this->_allowWaitlist && !$this->_requireApproval) { // if paid event add a contribution record //if primary participant contributing additional amount //append (multiple participants) to its fee level. CRM-4196. $isAdditionalAmount = FALSE; if (count($params) > 1) { $isAdditionalAmount = TRUE; } //passing contribution id is already registered. $contribution = self::processContribution($this, $value, $result, $contactID, $pending, $isAdditionalAmount); $value['contributionID'] = $contribution->id; $value['contributionTypeID'] = $contribution->financial_type_id; $value['receive_date'] = $contribution->receive_date; $value['trxn_id'] = $contribution->trxn_id; $value['contributionID'] = $contribution->id; $value['contributionTypeID'] = $contribution->financial_type_id; } $value['contactID'] = $contactID; $value['eventID'] = $this->_eventId; $value['item_name'] = $value['description']; } if (!empty($value['contributionID'])) { $this->_values['contributionId'] = $value['contributionID']; } //CRM-4453. if (!empty($value['is_primary'])) { $primaryCurrencyID = CRM_Utils_Array::value('currencyID', $value); } if (empty($value['currencyID'])) { $value['currencyID'] = $primaryCurrencyID; } // CRM-11182 - Confirmation page might not be monetary if ($this->_values['event']['is_monetary']) { if (!$pending && !empty($value['is_primary']) && !$this->_allowWaitlist && !$this->_requireApproval) { // transactionID & receive date required while building email template $this->assign('trxn_id', $value['trxn_id']); $this->assign('receive_date', CRM_Utils_Date::mysqlToIso($value['receive_date'])); $this->set('receiveDate', CRM_Utils_Date::mysqlToIso($value['receive_date'])); $this->set('trxnId', CRM_Utils_Array::value('trxn_id', $value)); } } $value['fee_amount'] = CRM_Utils_Array::value('amount', $value); $this->set('value', $value); // handle register date CRM-4320 if ($this->_allowConfirmation) { $registerDate = CRM_Utils_Array::value('participant_register_date', $params); } elseif (!empty($params['participant_register_date']) && is_array($params['participant_register_date']) && !empty($params['participant_register_date'])) { $registerDate = CRM_Utils_Date::format($params['participant_register_date']); } else { $registerDate = date('YmdHis'); } $this->assign('register_date', $registerDate); $this->confirmPostProcess($contactID, $contribution, $payment); } //handle if no additional participant. if (!$registerByID) { $registerByID = $this->get('registerByID'); } $this->set('participantIDs', $this->_participantIDS); // create line items, CRM-5313 if ($this->_priceSetId && !empty($this->_lineItem)) { // take all processed participant ids. $allParticipantIds = $this->_participantIDS; // when participant re-walk wizard. if ($this->_allowConfirmation && !empty($this->_additionalParticipantIds)) { $allParticipantIds = array_merge(array($registerByID), $this->_additionalParticipantIds); } $entityTable = 'civicrm_participant'; $invoiceSettings = Civi::settings()->get('contribution_invoice_settings'); $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings); $totalTaxAmount = 0; $dataArray = array(); foreach ($this->_lineItem as $key => $value) { if ($value == 'skip') { continue; } if ($entityId = CRM_Utils_Array::value($key, $allParticipantIds)) { // do cleanup line items if participant re-walking wizard. if ($this->_allowConfirmation) { CRM_Price_BAO_LineItem::deleteLineItems($entityId, $entityTable); } $lineItem[$this->_priceSetId] = $value; CRM_Price_BAO_LineItem::processPriceSet($entityId, $lineItem, $contribution, $entityTable); } if ($invoicing) { foreach ($value as $line) { if (isset($line['tax_amount']) && isset($line['tax_rate'])) { $totalTaxAmount = $line['tax_amount'] + $totalTaxAmount; if (isset($dataArray[$line['tax_rate']])) { $dataArray[$line['tax_rate']] = $dataArray[$line['tax_rate']] + CRM_Utils_Array::value('tax_amount', $line); } else { $dataArray[$line['tax_rate']] = CRM_Utils_Array::value('tax_amount', $line); } } } } } if ($invoicing) { $this->assign('dataArray', $dataArray); $this->assign('totalTaxAmount', $totalTaxAmount); } } //update status and send mail to cancelled additional participants, CRM-4320 if ($this->_allowConfirmation && is_array($cancelledIds) && !empty($cancelledIds)) { $cancelledId = array_search('Cancelled', CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Negative'")); CRM_Event_BAO_Participant::transitionParticipants($cancelledIds, $cancelledId); } $isTest = FALSE; if ($this->_action & CRM_Core_Action::PREVIEW) { $isTest = TRUE; } // for Transfer checkout. // The concept of contributeMode is deprecated. if (($this->_contributeMode == 'checkout' || $this->_contributeMode == 'notify') && empty($params[0]['is_pay_later']) && !$this->_allowWaitlist && !$this->_requireApproval && $this->_totalAmount > 0) { $primaryParticipant = $this->get('primaryParticipant'); if (empty($primaryParticipant['participantID'])) { $primaryParticipant['participantID'] = $registerByID; } //build an array of custom profile and assigning it to template $customProfile = CRM_Event_BAO_Event::buildCustomProfile($registerByID, $this->_values, NULL, $isTest); if (count($customProfile)) { $this->assign('customProfile', $customProfile); $this->set('customProfile', $customProfile); } // do a transfer only if a monetary payment greater than 0 if ($this->_values['event']['is_monetary'] && $primaryParticipant) { if ($payment && is_object($payment)) { //CRM 14512 provide line items of all participants to payment gateway $primaryContactId = $this->get('primaryContactId'); //build an array of cId/pId of participants $additionalIDs = CRM_Event_BAO_Event::buildCustomProfile($registerByID, NULL, $primaryContactId, $isTest, TRUE); //need to copy, since we are unsetting on the way. $copyParticipantCountLines = $participantCount; //lets carry all participant params w/ values. foreach ($additionalIDs as $participantID => $contactId) { $participantNum = NULL; $participantNum = $participantID; if ($participantID == $registerByID) { // This is the is primary participant. $participantNum = 0; } else { if ($participantNum = array_search('participant', $copyParticipantCountLines)) { //if no participant found break. if ($participantNum === NULL) { break; } //unset current particpant so we don't check them again unset($copyParticipantCountLines[$participantNum]); } } // get values of line items if ($this->_amount) { $amount = array(); $amount[$participantNum]['label'] = preg_replace('//', '', $params[$participantNum]['amount_level']); $amount[$participantNum]['amount'] = $params[$participantNum]['amount']; $params[$participantNum]['amounts'] = $amount; } if (!empty($this->_lineItem)) { $lineItems = $this->_lineItem; $lineItem = array(); if ($lineItemValue = CRM_Utils_Array::value($participantNum, $lineItems)) { $lineItem[] = $lineItemValue; } $params[$participantNum]['lineItem'] = $lineItem; } //only add additional particpants and not the primary particpant as we already have that //added to $primaryParticipant so that this change doesn't break or require changes to //existing gateway implementations $primaryParticipant['participants_info'][$participantID] = $params[$participantNum]; } //get event custom field information $groupTree = CRM_Core_BAO_CustomGroup::getTree('Event', $this, $this->_eventId, 0, $this->_values['event']['event_type_id']); $primaryParticipant['eventCustomFields'] = $groupTree; // call postprocess hook before leaving $this->postProcessHook(); // this does not return $payment->doPayment($primaryParticipant, 'event'); } else { CRM_Core_Error::fatal($paymentObjError); } } } else { //otherwise send mail Confirmation/Receipt $primaryContactId = $this->get('primaryContactId'); //build an array of cId/pId of participants $additionalIDs = CRM_Event_BAO_Event::buildCustomProfile($registerByID, NULL, $primaryContactId, $isTest, TRUE); //lets send mails to all with meaningful text, CRM-4320. $this->assign('isOnWaitlist', $this->_allowWaitlist); $this->assign('isRequireApproval', $this->_requireApproval); //need to copy, since we are unsetting on the way. $copyParticipantCount = $participantCount; //lets carry all paticipant params w/ values. foreach ($additionalIDs as $participantID => $contactId) { $participantNum = NULL; if ($participantID == $registerByID) { $participantNum = 0; } else { if ($participantNum = array_search('participant', $copyParticipantCount)) { unset($copyParticipantCount[$participantNum]); } } if ($participantNum === NULL) { break; } //carry the participant submitted values. $this->_values['params'][$participantID] = $params[$participantNum]; } foreach ($additionalIDs as $participantID => $contactId) { $participantNum = 0; if ($participantID == $registerByID) { //set as Primary Participant $this->assign('isPrimary', 1); //build an array of custom profile and assigning it to template. $customProfile = CRM_Event_BAO_Event::buildCustomProfile($participantID, $this->_values, NULL, $isTest); if (count($customProfile)) { $this->assign('customProfile', $customProfile); $this->set('customProfile', $customProfile); } $this->_values['params']['additionalParticipant'] = FALSE; } else { //take the Additional participant number. if ($participantNum = array_search('participant', $participantCount)) { unset($participantCount[$participantNum]); } // Change $this->_values['participant'] to include additional participant values $ids = $participantValues = array(); $participantParams = array('id' => $participantID); CRM_Event_BAO_Participant::getValues($participantParams, $participantValues, $ids); $this->_values['participant'] = $participantValues[$participantID]; $this->assign('isPrimary', 0); $this->assign('customProfile', NULL); //Additional Participant should get only it's payment information if (!empty($this->_amount)) { $amount = array(); $params = $this->get('params'); $amount[$participantNum]['label'] = preg_replace('//', '', $params[$participantNum]['amount_level']); $amount[$participantNum]['amount'] = $params[$participantNum]['amount']; $this->assign('amounts', $amount); } if ($this->_lineItem) { $lineItems = $this->_lineItem; $lineItem = array(); if ($lineItemValue = CRM_Utils_Array::value($participantNum, $lineItems)) { $lineItem[] = $lineItemValue; } if ($invoicing) { $individual = $this->get('individual'); $dataArray[key($dataArray)] = $individual[$participantNum]['totalTaxAmt']; $this->assign('dataArray', $dataArray); $this->assign('totalAmount', $individual[$participantNum]['totalAmtWithTax']); $this->assign('totalTaxAmount', $individual[$participantNum]['totalTaxAmt']); $this->assign('individual', array($individual[$participantNum])); } $this->assign('lineItem', $lineItem); } $this->_values['params']['additionalParticipant'] = TRUE; $this->assign('isAdditionalParticipant', $this->_values['params']['additionalParticipant']); } //pass these variables since these are run time calculated. $this->_values['params']['isOnWaitlist'] = $this->_allowWaitlist; $this->_values['params']['isRequireApproval'] = $this->_requireApproval; //send mail to primary as well as additional participants. $this->assign('contactID', $contactId); $this->assign('participantID', $participantID); CRM_Event_BAO_Event::sendMail($contactId, $this->_values, $participantID, $isTest); } } }
/** * Set variables up before form is built. */ public function preProcess() { $this->_eventId = CRM_Utils_Request::retrieve('id', 'Positive', $this, TRUE); $this->_action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE); //CRM-4320 $this->_participantId = CRM_Utils_Request::retrieve('participantId', 'Positive', $this); // current mode $this->_mode = $this->_action == 1024 ? 'test' : 'live'; $this->_values = $this->get('values'); $this->_fields = $this->get('fields'); $this->_bltID = $this->get('bltID'); $this->_paymentProcessor = $this->get('paymentProcessor'); $this->_priceSetId = $this->get('priceSetId'); $this->_priceSet = $this->get('priceSet'); $this->_lineItem = $this->get('lineItem'); $this->_isEventFull = $this->get('isEventFull'); $this->_lineItemParticipantsCount = $this->get('lineItemParticipants'); if (!is_array($this->_lineItem)) { $this->_lineItem = array(); } if (!is_array($this->_lineItemParticipantsCount)) { $this->_lineItemParticipantsCount = array(); } $this->_availableRegistrations = $this->get('availableRegistrations'); $this->_participantIDS = $this->get('participantIDs'); //check if participant allow to walk registration wizard. $this->_allowConfirmation = $this->get('allowConfirmation'); // check for Approval $this->_requireApproval = $this->get('requireApproval'); // check for waitlisting. $this->_allowWaitlist = $this->get('allowWaitlist'); $this->_forcePayement = $this->get('forcePayement'); //get the additional participant ids. $this->_additionalParticipantIds = $this->get('additionalParticipantIds'); $config = CRM_Core_Config::singleton(); if (!$this->_values) { // create redirect URL to send folks back to event info page is registration not available $infoUrl = CRM_Utils_System::url('civicrm/event/info', "reset=1&id={$this->_eventId}", FALSE, NULL, FALSE, TRUE); // this is the first time we are hitting this, so check for permissions here if (!CRM_Core_Permission::event(CRM_Core_Permission::EDIT, $this->_eventId, 'register for events')) { CRM_Core_Error::statusBounce(ts('You do not have permission to register for this event'), $infoUrl); } // get all the values from the dao object $this->_values = $this->_fields = array(); $this->_forcePayement = FALSE; //retrieve event information $params = array('id' => $this->_eventId); CRM_Event_BAO_Event::retrieve($params, $this->_values['event']); // check for is_monetary status $isMonetary = CRM_Utils_Array::value('is_monetary', $this->_values['event']); // check for ability to add contributions of type if ($isMonetary && CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus() && !CRM_Core_Permission::check('add contributions of type ' . CRM_Contribute_PseudoConstant::financialType($this->_values['event']['financial_type_id']))) { CRM_Core_Error::fatal(ts('You do not have permission to access this page.')); } $this->checkValidEvent($infoUrl); // get the participant values, CRM-4320 $this->_allowConfirmation = FALSE; if ($this->_participantId) { $this->processFirstParticipant($this->_participantId); } //check for additional participants. if ($this->_allowConfirmation && $this->_values['event']['is_multiple_registrations']) { $additionalParticipantIds = CRM_Event_BAO_Participant::getAdditionalParticipantIds($this->_participantId); $cnt = 1; foreach ($additionalParticipantIds as $additionalParticipantId) { $this->_additionalParticipantIds[$cnt] = $additionalParticipantId; $cnt++; } $this->set('additionalParticipantIds', $this->_additionalParticipantIds); } $eventFull = CRM_Event_BAO_Participant::eventFull($this->_eventId, FALSE, CRM_Utils_Array::value('has_waitlist', $this->_values['event'])); $this->_allowWaitlist = $this->_isEventFull = FALSE; if ($eventFull && !$this->_allowConfirmation) { $this->_isEventFull = TRUE; //lets redirecting to info only when to waiting list. $this->_allowWaitlist = CRM_Utils_Array::value('has_waitlist', $this->_values['event']); if (!$this->_allowWaitlist) { CRM_Utils_System::redirect($infoUrl); } } $this->set('isEventFull', $this->_isEventFull); $this->set('allowWaitlist', $this->_allowWaitlist); //check for require requires approval. $this->_requireApproval = FALSE; if (!empty($this->_values['event']['requires_approval']) && !$this->_allowConfirmation) { $this->_requireApproval = TRUE; } $this->set('requireApproval', $this->_requireApproval); if (isset($this->_values['event']['default_role_id'])) { $participant_role = CRM_Core_OptionGroup::values('participant_role'); $this->_values['event']['participant_role'] = $participant_role["{$this->_values['event']['default_role_id']}"]; } $isPayLater = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $this->_eventId, 'is_pay_later'); //check for various combinations for paylater, payment //process with paid event. if ($isMonetary && (!$isPayLater || !empty($this->_values['event']['payment_processor']))) { $this->_paymentProcessorIDs = explode(CRM_Core_DAO::VALUE_SEPARATOR, CRM_Utils_Array::value('payment_processor', $this->_values['event'])); $this->assignPaymentProcessor($isPayLater); } //init event fee. self::initEventFee($this, $this->_eventId); // get the profile ids $ufJoinParams = array('entity_table' => 'civicrm_event', 'module' => 'CiviEvent', 'entity_id' => $this->_eventId); list($this->_values['custom_pre_id'], $this->_values['custom_post_id']) = CRM_Core_BAO_UFJoin::getUFGroupIds($ufJoinParams); // set profiles for additional participants if ($this->_values['event']['is_multiple_registrations']) { // CRM-4377: CiviEvent for the main participant, CiviEvent_Additional for additional participants $ufJoinParams['module'] = 'CiviEvent_Additional'; list($this->_values['additional_custom_pre_id'], $this->_values['additional_custom_post_id'], $preActive, $postActive) = CRM_Core_BAO_UFJoin::getUFGroupIds($ufJoinParams); // CRM-4377: we need to maintain backward compatibility, hence if there is profile for main contact // set same profile for additional contacts. if ($this->_values['custom_pre_id'] && !$this->_values['additional_custom_pre_id']) { $this->_values['additional_custom_pre_id'] = $this->_values['custom_pre_id']; } if ($this->_values['custom_post_id'] && !$this->_values['additional_custom_post_id']) { $this->_values['additional_custom_post_id'] = $this->_values['custom_post_id']; } // now check for no profile condition, in that case is_active = 0 if (isset($preActive) && !$preActive) { unset($this->_values['additional_custom_pre_id']); } if (isset($postActive) && !$postActive) { unset($this->_values['additional_custom_post_id']); } } $this->assignBillingType(); if ($this->_values['event']['is_monetary']) { CRM_Core_Payment_Form::setPaymentFieldsByProcessor($this, $this->_paymentProcessor); } $params = array('entity_id' => $this->_eventId, 'entity_table' => 'civicrm_event'); $this->_values['location'] = CRM_Core_BAO_Location::getValues($params, TRUE); $this->set('values', $this->_values); $this->set('fields', $this->_fields); $this->_availableRegistrations = CRM_Event_BAO_Participant::eventFull($this->_values['event']['id'], TRUE, CRM_Utils_Array::value('has_waitlist', $this->_values['event'])); $this->set('availableRegistrations', $this->_availableRegistrations); } $this->assign_by_ref('paymentProcessor', $this->_paymentProcessor); // check if this is a paypal auto return and redirect accordingly if (CRM_Core_Payment::paypalRedirect($this->_paymentProcessor)) { $url = CRM_Utils_System::url('civicrm/event/register', "_qf_ThankYou_display=1&qfKey={$this->controller->_key}"); CRM_Utils_System::redirect($url); } // The concept of contributeMode is deprecated. $this->_contributeMode = $this->get('contributeMode'); $this->assign('contributeMode', $this->_contributeMode); // setting CMS page title CRM_Utils_System::setTitle($this->_values['event']['title']); $this->assign('title', $this->_values['event']['title']); $this->assign('paidEvent', $this->_values['event']['is_monetary']); // we do not want to display recently viewed items on Registration pages $this->assign('displayRecent', FALSE); // Registration page values are cleared from session, so can't use normal Printer Friendly view. // Use Browser Print instead. $this->assign('browserPrint', TRUE); $isShowLocation = CRM_Utils_Array::value('is_show_location', $this->_values['event']); $this->assign('isShowLocation', $isShowLocation); // Handle PCP $pcpId = CRM_Utils_Request::retrieve('pcpId', 'Positive', $this); if ($pcpId) { $pcp = CRM_PCP_BAO_PCP::handlePcp($pcpId, 'event', $this->_values['event']); $this->_pcpId = $pcp['pcpId']; $this->_values['event']['intro_text'] = CRM_Utils_Array::value('intro_text', $pcp['pcpInfo']); } // assign all event properties so wizard templates can display event info. $this->assign('event', $this->_values['event']); $this->assign('location', $this->_values['location']); $this->assign('bltID', $this->_bltID); $isShowLocation = CRM_Utils_Array::value('is_show_location', $this->_values['event']); $this->assign('isShowLocation', $isShowLocation); //CRM-6907 $config->defaultCurrency = CRM_Utils_Array::value('currency', $this->_values['event'], $config->defaultCurrency); //lets allow user to override campaign. $campID = CRM_Utils_Request::retrieve('campID', 'Positive', $this); if ($campID && CRM_Core_DAO::getFieldValue('CRM_Campaign_DAO_Campaign', $campID)) { $this->_values['event']['campaign_id'] = $campID; } // Set the same value for is_billing_required as contribution page so code can be shared. $this->_values['is_billing_required'] = CRM_Utils_Array::value('is_billing_required', $this->_values['event']); // check if billing block is required for pay later // note that I have started removing the use of isBillingAddressRequiredForPayLater in favour of letting // the CRM_Core_Payment_Manual class handle it - but there are ~300 references to it in the code base so only // removing in very limited cases. if (CRM_Utils_Array::value('is_pay_later', $this->_values['event'])) { $this->_isBillingAddressRequiredForPayLater = CRM_Utils_Array::value('is_billing_required', $this->_values['event']); $this->assign('isBillingAddressRequiredForPayLater', $this->_isBillingAddressRequiredForPayLater); } }
/** * Process payment after confirmation. * * @param CRM_Core_Form $form * Form object. * @param array $paymentParams * Array with payment related key. * value pairs * @param int $contactID * Contact id. * @param int $contributionTypeId * Financial type id. * @param int|string $component component id * @param $isTest * * @throws CRM_Core_Exception * @throws Exception * @return array * associated array * */ public static function processConfirm(&$form, &$paymentParams, $contactID, $contributionTypeId, $component = 'contribution', $isTest) { CRM_Core_Payment_Form::mapParams($form->_bltID, $form->_params, $paymentParams, TRUE); $lineItems = $form->_lineItem; $isPaymentTransaction = self::isPaymentTransaction($form); $financialType = new CRM_Financial_DAO_FinancialType(); $financialType->id = $contributionTypeId; $financialType->find(TRUE); if ($financialType->is_deductible) { $form->assign('is_deductible', TRUE); $form->set('is_deductible', TRUE); } // add some financial type details to the params list // if folks need to use it //CRM-15297 - contributionType is obsolete - pass financial type as well so people can deprecate it $paymentParams['financialType_name'] = $paymentParams['contributionType_name'] = $form->_params['contributionType_name'] = $financialType->name; //CRM-11456 $paymentParams['financialType_accounting_code'] = $paymentParams['contributionType_accounting_code'] = $form->_params['contributionType_accounting_code'] = CRM_Financial_BAO_FinancialAccount::getAccountingCode($contributionTypeId); $paymentParams['contributionPageID'] = $form->_params['contributionPageID'] = $form->_values['id']; $paymentParams['contactID'] = $form->_params['contactID'] = $contactID; //fix for CRM-16317 $form->_params['receive_date'] = date('YmdHis'); $form->assign('receive_date', CRM_Utils_Date::mysqlToIso($form->_params['receive_date'])); if ($isPaymentTransaction) { // Fix for CRM-14354. If the membership is recurring, don't create a // civicrm_contribution_recur record for the additional contribution // (i.e., the amount NOT associated with the membership). Temporarily // cache the is_recur values so we can process the additional gift as a // one-off payment. if (!empty($form->_values['is_recur'])) { if ($form->_membershipBlock['is_separate_payment'] && !empty($form->_params['auto_renew'])) { $cachedFormValue = CRM_Utils_Array::value('is_recur', $form->_values); $cachedParamValue = CRM_Utils_Array::value('is_recur', $paymentParams); unset($form->_values['is_recur']); unset($paymentParams['is_recur']); } } $contributionParams = array('contact_id' => $contactID, 'line_item' => $lineItems, 'is_test' => $isTest, 'campaign_id' => CRM_Utils_Array::value('campaign_id', $paymentParams, CRM_Utils_Array::value('campaign_id', $form->_values)), 'contribution_page_id' => $form->_id, 'source' => CRM_Utils_Array::value('source', $paymentParams, CRM_Utils_Array::value('description', $paymentParams))); $isMonetary = !empty($form->_values['is_monetary']); if ($isMonetary) { if (empty($paymentParams['is_pay_later'])) { // @todo look up payment_instrument_id on payment processor table. $contributionParams['payment_instrument_id'] = 1; } } $contribution = CRM_Contribute_Form_Contribution_Confirm::processFormContribution($form, $paymentParams, NULL, $contributionParams, $financialType, TRUE, TRUE, $form->_bltID); $paymentParams['contributionTypeID'] = $contributionTypeId; $paymentParams['item_name'] = $form->_params['description']; if ($contribution && $form->_values['is_recur'] && $contribution->contribution_recur_id) { $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id; } $paymentParams['qfKey'] = $form->controller->_key; if ($component == 'membership') { return array('contribution' => $contribution); } // restore cached values (part of fix for CRM-14354) if (!empty($cachedFormValue)) { $form->_values['is_recur'] = $cachedFormValue; $paymentParams['is_recur'] = $cachedParamValue; } $paymentParams['contributionID'] = $contribution->id; //CRM-15297 deprecate contributionTypeID $paymentParams['financialTypeID'] = $paymentParams['contributionTypeID'] = $contribution->financial_type_id; $paymentParams['contributionPageID'] = $contribution->contribution_page_id; if (isset($paymentParams['contribution_source'])) { $paymentParams['source'] = $paymentParams['contribution_source']; } if ($form->_values['is_recur'] && $contribution->contribution_recur_id) { $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id; } if ($form->_contributeMode && $form->_amount > 0.0) { try { $payment = Civi\Payment\System::singleton()->getByProcessor($form->_paymentProcessor); if ($form->_contributeMode == 'notify') { // We want to get rid of this & make it generic - eg. by making payment processing the last thing // and always calling it first. $form->postProcessHook(); } $result = $payment->doPayment($paymentParams); $form->_params = array_merge($form->_params, $result); $form->assign('trxn_id', CRM_Utils_Array::value('trxn_id', $result)); if (!empty($result['trxn_id'])) { $contribution->trxn_id = $result['trxn_id']; } if (!empty($result['payment_status_id'])) { $contribution->payment_status_id = $result['payment_status_id']; } $result['contribution'] = $contribution; return $result; } catch (\Civi\Payment\Exception\PaymentProcessorException $e) { // Clean up DB as appropriate. if (!empty($paymentParams['contributionID'])) { CRM_Contribute_BAO_Contribution::failPayment($paymentParams['contributionID'], $paymentParams['contactID'], $e->getMessage()); } if (!empty($paymentParams['contributionRecurID'])) { CRM_Contribute_BAO_ContributionRecur::deleteRecurContribution($paymentParams['contributionRecurID']); } $result['is_payment_failure'] = TRUE; $result['error'] = $e; return $result; } } } // Only pay later or unpaid should reach this point. The theory is that paylater should get a receipt now & // processor // transaction receipts should be outcome driven. $form->set('params', $form->_params); if (isset($paymentParams['contribution_source'])) { $form->_params['source'] = $paymentParams['contribution_source']; } // get the price set values for receipt. if ($form->_priceSetId && $form->_lineItem) { $form->_values['lineItem'] = $form->_lineItem; $form->_values['priceSetID'] = $form->_priceSetId; } $form->_values['contribution_id'] = $contribution->id; $form->_values['contribution_page_id'] = $contribution->contribution_page_id; CRM_Contribute_BAO_ContributionPage::sendMail($contactID, $form->_values, $contribution->is_test); }