/** * @param CRM_Core_Form $form * @param null $type * @param null $mode * * @throws Exception */ public static function preProcess(&$form, $type = NULL, $mode = NULL) { if ($type) { $form->_type = $type; } else { $form->_type = CRM_Utils_Request::retrieve('type', 'String', $form); } if ($form->_type) { $form->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($form->_type, $form->_mode); } $form->set('paymentProcessor', $form->_paymentProcessor); // also set cancel subscription url if (!empty($form->_paymentProcessor['is_recur']) && !empty($form->_values['is_recur'])) { $form->_paymentObject = CRM_Core_Payment::singleton($mode, $form->_paymentProcessor, $form); $form->_values['cancelSubscriptionUrl'] = $form->_paymentObject->subscriptionURL(); } //checks after setting $form->_paymentProcessor // we do this outside of the above conditional to avoid // saving the country/state list in the session (which could be huge) CRM_Core_Payment_Form::setPaymentFieldsByProcessor($form, $form->_paymentProcessor); $form->assign_by_ref('paymentProcessor', $form->_paymentProcessor); // check if this is a paypal auto return and redirect accordingly //@todo - determine if this is legacy and remove if (CRM_Core_Payment::paypalRedirect($form->_paymentProcessor)) { $url = CRM_Utils_System::url('civicrm/contribute/transact', "_qf_ThankYou_display=1&qfKey={$form->controller->_key}"); CRM_Utils_System::redirect($url); } // make sure we have a valid payment class, else abort if (!empty($form->_values['is_monetary']) && !$form->_paymentProcessor['class_name'] && empty($form->_values['is_pay_later'])) { CRM_Core_Error::fatal(ts('Payment processor is not set for this page')); } if (!empty($form->_membershipBlock) && !empty($form->_membershipBlock['is_separate_payment']) && (!empty($form->_paymentProcessor['class_name']) && !(CRM_Utils_Array::value('billing_mode', $form->_paymentProcessor) & CRM_Core_Payment::BILLING_MODE_FORM))) { CRM_Core_Error::fatal(ts('This contribution page is configured to support separate contribution and membership payments. This %1 plugin does not currently support multiple simultaneous payments, or the option to "Execute real-time monetary transactions" is disabled. Please contact the site administrator and notify them of this error', array(1 => $form->_paymentProcessor['payment_processor_type']))); } }
/** * Set variables up before form is built. * * @return void */ public function preProcess() { parent::preProcess(); $this->_paymentProcessorID = CRM_Utils_Request::retrieve('processor_id', 'Integer', CRM_Core_DAO::$_nullObject, TRUE); $this->assignBillingType(); // @todo - round about way to load it - just load as an object using civi\payment\system::getByProcessor $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($this->_paymentProcessorID, 'unused'); CRM_Core_Payment_ProcessorForm::preProcess($this); self::addCreditCardJs(); $this->assign('paymentProcessorID', $this->_paymentProcessorID); }
/** * Set variables up before form is built. */ public function preProcess() { parent::preProcess(); $this->_paymentProcessorID = CRM_Utils_Request::retrieve('processor_id', 'Integer', CRM_Core_DAO::$_nullObject, TRUE); $this->assignBillingType(); $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($this->_paymentProcessorID); CRM_Core_Payment_ProcessorForm::preProcess($this); self::addCreditCardJs(); $this->assign('paymentProcessorID', $this->_paymentProcessorID); $this->assign('suppressForm', TRUE); }
/** * @param CRM_Contribute_Form_Contribution_Main|CRM_Event_Form_Registration_Register|CRM_Financial_Form_Payment $form * @param null $type * @param null $mode * * @throws Exception */ public static function preProcess(&$form, $type = NULL, $mode = NULL) { if ($type) { $form->_type = $type; } else { $form->_type = CRM_Utils_Request::retrieve('type', 'String', $form); } if ($form->_type) { $form->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($form->_type, $form->_mode); } if (empty($form->_paymentProcessor)) { // This would happen when hitting the back-button on a multi-page form with a $0 selection in play. return; } $form->set('paymentProcessor', $form->_paymentProcessor); $form->_paymentObject = System::singleton()->getByProcessor($form->_paymentProcessor); $form->assign('suppressSubmitButton', $form->_paymentObject->isSuppressSubmitButtons()); $form->assign('currency', CRM_Utils_Array::value('currency', $form->_values)); // also set cancel subscription url if (!empty($form->_paymentProcessor['is_recur']) && !empty($form->_values['is_recur'])) { $form->_values['cancelSubscriptionUrl'] = $form->_paymentObject->subscriptionURL(NULL, NULL, 'cancel'); } if (!empty($form->_values['custom_pre_id'])) { $profileAddressFields = array(); $fields = CRM_Core_BAO_UFGroup::getFields($form->_values['custom_pre_id'], FALSE, CRM_Core_Action::ADD, NULL, NULL, FALSE, NULL, FALSE, NULL, CRM_Core_Permission::CREATE, NULL); foreach ((array) $fields as $key => $value) { CRM_Core_BAO_UFField::assignAddressField($key, $profileAddressFields, array('uf_group_id' => $form->_values['custom_pre_id'])); } if (count($profileAddressFields)) { $form->set('profileAddressFields', $profileAddressFields); } } //checks after setting $form->_paymentProcessor // we do this outside of the above conditional to avoid // saving the country/state list in the session (which could be huge) CRM_Core_Payment_Form::setPaymentFieldsByProcessor($form, $form->_paymentProcessor, CRM_Utils_Request::retrieve('billing_profile_id', 'String')); $form->assign_by_ref('paymentProcessor', $form->_paymentProcessor); // check if this is a paypal auto return and redirect accordingly //@todo - determine if this is legacy and remove if (CRM_Core_Payment::paypalRedirect($form->_paymentProcessor)) { $url = CRM_Utils_System::url('civicrm/contribute/transact', "_qf_ThankYou_display=1&qfKey={$form->controller->_key}"); CRM_Utils_System::redirect($url); } // make sure we have a valid payment class, else abort if (!empty($form->_values['is_monetary']) && !$form->_paymentProcessor['class_name'] && empty($form->_values['is_pay_later'])) { CRM_Core_Error::fatal(ts('Payment processor is not set for this page')); } if (!empty($form->_membershipBlock) && !empty($form->_membershipBlock['is_separate_payment']) && (!empty($form->_paymentProcessor['class_name']) && !$form->_paymentObject->supports('MultipleConcurrentPayments'))) { CRM_Core_Error::fatal(ts('This contribution page is configured to support separate contribution and membership payments. This %1 plugin does not currently support multiple simultaneous payments, or the option to "Execute real-time monetary transactions" is disabled. Please contact the site administrator and notify them of this error', array(1 => $form->_paymentProcessor['payment_processor_type']))); } }
/** * Set variables up before form is built. */ public function preProcess() { parent::preProcess(); $this->_values['custom_pre_id'] = CRM_Utils_Request::retrieve('pre_profile_id', 'Integer', $this); $this->_paymentProcessorID = CRM_Utils_Request::retrieve('processor_id', 'Integer', CRM_Core_DAO::$_nullObject, TRUE); $this->currency = CRM_Utils_Request::retrieve('currency', 'String', CRM_Core_DAO::$_nullObject, TRUE); $this->assignBillingType(); $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($this->_paymentProcessorID); CRM_Core_Payment_ProcessorForm::preProcess($this); self::addCreditCardJs(); $this->assign('paymentProcessorID', $this->_paymentProcessorID); $this->assign('currency', $this->currency); $this->assign('suppressForm', TRUE); $this->controller->_generateQFKey = FALSE; }
/** * 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 int $billing_profile_id * Display billing fields even for pay later. * @param bool $isBackOffice * Is this a back office function? If so the option to suppress the cvn needs to be evaluated. */ public static function setPaymentFieldsByProcessor(&$form, $processor, $billing_profile_id = NULL, $isBackOffice = FALSE) { $form->billingFieldSets = array(); // Load the pay-later processor // @todo load this right up where the other processors are loaded initially. if (empty($processor)) { $processor = CRM_Financial_BAO_PaymentProcessor::getPayment(0); } $processor['object']->setBillingProfile($billing_profile_id); $paymentTypeName = self::getPaymentTypeName($processor); $paymentTypeLabel = self::getPaymentTypeLabel($processor); $form->assign('paymentTypeName', $paymentTypeName); $form->assign('paymentTypeLabel', $paymentTypeLabel); $form->_paymentFields = $form->billingFieldSets[$paymentTypeName]['fields'] = self::getPaymentFieldMetadata($processor); $form->_paymentFields = array_merge($form->_paymentFields, self::getBillingAddressMetadata($processor, $form->_bltID)); $form->assign('paymentFields', self::getPaymentFields($processor)); self::setBillingAddressFields($form, $processor); // @todo - this may be obsolete - although potentially it could be used to re-order things in the form. $form->billingFieldSets['billing_name_address-group']['fields'] = array(); }
/** * Process a transaction and record it against the contact. * * @param array $params * Input parameters. * * @return array * contribution of created or updated record (or a civicrm error) */ function civicrm_api3_contribution_transact($params) { // Set some params specific to payment processing // @todo - fix this function - none of the results checked by civicrm_error would ever be an array with // 'is_error' set // also trxn_id is not saved. // but since there is no test it's not desirable to jump in & make the obvious changes. $params['payment_processor_mode'] = empty($params['is_test']) ? 'live' : 'test'; $params['amount'] = $params['total_amount']; if (!isset($params['net_amount'])) { $params['net_amount'] = $params['amount']; } if (!isset($params['invoiceID']) && isset($params['invoice_id'])) { $params['invoiceID'] = $params['invoice_id']; } // Some payment processors expect a unique invoice_id - generate one if not supplied $params['invoice_id'] = CRM_Utils_Array::value('invoice_id', $params, md5(uniqid(rand(), TRUE))); $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($params['payment_processor'], $params['payment_processor_mode']); $paymentProcessor['object']->doPayment($params); $params['payment_instrument_id'] = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessorType', $paymentProcessor['payment_processor_type_id'], 'payment_type') == 1 ? 'Credit Card' : 'Debit Card'; return civicrm_api('Contribution', 'create', $params); }
/** * Set variables up before form is built. * * @return void */ public function preProcess() { $session = CRM_Core_Session::singleton(); $this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this, TRUE); $contributionParams = $requestParams = $_REQUEST; $contactID = $session->get('userID'); if ($contactID && empty($contributionParams['email'])) { $emailDetails = CRM_Contact_BAO_Contact_Location::getEmailDetails($contactID); if (!empty($emailDetails)) { $contributionParams['email'] = $emailDetails[1]; // for email to be prefilled $this->assign('email', $emailDetails[1]); } } $pageConfig = civicrm_api3('ContributionPage', 'getsingle', array('id' => $this->_id)); if (is_array($pageConfig['payment_processor'])) { CRM_Core_Error::fatal(ts('Multiple payment processors not supported with quick donate.')); } $processorDetails = CRM_Financial_BAO_PaymentProcessor::getPayment($pageConfig['payment_processor'], 'live'); //MV: get amount details if other amount enabled for contribution page. if ($pageConfig['amount_block_is_active']) { $sql = "SELECT cpfv.amount, cpfv.is_default, cpfv.weight \n FROM civicrm_price_field_value cpfv \n INNER JOIN civicrm_price_field cpf ON (cpf.id = cpfv.price_field_id)\n INNER JOIN civicrm_price_set_entity cpse ON (cpse.price_set_id = cpf.price_set_id)\n WHERE cpse.entity_id = %1 AND cpf.name = 'contribution_amount'\n "; $dao = CRM_Core_DAO::executeQuery($sql, array(1 => array($pageConfig['id'], 'Integer'))); $amount = 0; while ($dao->fetch()) { if ($dao->weight == 1 || $dao->is_default == 1) { $amount = $dao->amount; } } } $pageConfig['default_amount'] = $amount ? $amount : $pageConfig['min_amount']; $pageConfig['currency_symbol'] = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_Currency', $pageConfig['currency'], 'symbol', 'name'); $this->assign('pageConfig', $pageConfig); $this->assign('key', $processorDetails['password']); $this->assign('currency', strtolower($pageConfig['currency'])); if (!empty($requestParams['stripe_token'])) { //FIXME: could go in post process if (!$contributionParams['email']) { CRM_Core_Error::fatal(ts('Email address is required')); } $contributionParams['financial_type_id'] = $pageConfig['financial_type_id']; if (!$contactID) { $contactParams = array('email' => $contributionParams['email'], 'contact_type' => 'Individual'); $dedupeParams = CRM_Dedupe_Finder::formatParams($contactParams, '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); if (!$contactID) { $cont = civicrm_api3('Contact', 'create', $contactParams); $contactID = $cont['id']; } } $contributionParams['contact_id'] = $contactID; $contributionParams['payment_processor_id'] = $pageConfig['payment_processor']; $contributionParams['currencyID'] = $pageConfig['currency']; //gift aid //get gift aid custom field id $sqlCF = "SELECT cf.id \n FROM civicrm_custom_field cf \n INNER JOIN civicrm_custom_group cg ON (cg.id = cf.custom_group_id) \n WHERE cg.name = %1 AND cf.name = %2"; $sqlCFParams = array(1 => array(self::C_CUSTOM_GROUP_GIFT_AID, 'String'), 2 => array(self::C_CUSTOM_FIELD_GIFT_AID, 'String')); $cfId = CRM_Core_DAO::singleValueQuery($sqlCF, $sqlCFParams); if ($cfId && $contributionParams['donation_form']['gift_aid']) { $contributionParams["custom_{$cfId}"] = 1; } //gift aid end //campaign if ($pageConfig['campaign_id']) { $contributionParams['campaign_id'] = $pageConfig['campaign_id']; } try { $result = civicrm_api3('Contribution', 'transact', $contributionParams); } catch (CiviCRM_API3_Exception $e) { $error = $e->getMessage(); $this->assign('error', $error); CRM_Utils_System::setTitle(ts('Oops! There was a problem')); } if (!empty($result['error'])) { $this->assign('error', $result['error']); CRM_Utils_System::setTitle(ts('Oops! There was a problem')); } else { if ($result) { $contributionID = $result['id']; $contactID = $result['values'][$contributionID]['contact_id']; // Send receipt civicrm_api3('contribution', 'sendconfirmation', array('id' => $contributionID) + $pageConfig); CRM_Utils_System::setTitle(ts('Thank you')); $this->assign('status', 'thankyou'); $profileID = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', 'Supporter Profile', 'id', 'title'); // Link (button) for users to create their own Personal Campaign page if ($profileID && !$session->get('userID')) { $ufId = CRM_Core_BAO_UFMatch::getUFId($contactID); if ($ufId) { $config = CRM_Core_Config::singleton(); $loginURL = $config->userSystem->getLoginURL(); $this->assign('loginURL', $loginURL); } else { $linkTextUrl = CRM_Utils_System::url('civicrm/profile/create', "gid={$profileID}&reset=1", FALSE, NULL, TRUE); $this->assign('linkTextUrl', $linkTextUrl); } } //redirect if the logged in user if ($session->get('userID')) { $urlParams = array('pageId' => $this->_id, 'component' => 'contribute', 'reset' => 1); $sql = "SELECT pcp.id FROM civicrm_pcp pcp \n INNER JOIN civicrm_pcp_block cpb ON (cpb.id = pcp.pcp_block_id)\n WHERE cpb.entity_id = %1 AND pcp.contact_id = %2\n "; $sqlparams = array(1 => array($pageConfig['id'], 'Integer'), 2 => array($contactID, 'Integer')); $pcpId = CRM_Core_DAO::singleValueQuery($sql, $sqlparams); if ($pcpId) { $urlParams['id'] = $pcpId; } $url = CRM_Utils_System::url('civicrm/pcp/setup', $urlParams); CRM_Utils_System::redirect($url); } } } } else { if (!empty($requestParams['_qf_Main_display'])) { //$this->assign('error', $error); CRM_Utils_System::setTitle(ts('Oops! There was a problem')); } else { $this->assign('status', 'quickdonate'); CRM_Core_Resources::singleton()->addStyleFile('uk.co.vedaconsulting.quickdonate', 'css/quickdonatebox.css'); } } }
/** * This method is handles the response that will be invoked (from extern/googleNotify) every time * a notification or request is sent by the Google Server. * */ static function main($xml_response) { require_once 'Google/library/googleresponse.php'; require_once 'Google/library/googlerequest.php'; require_once 'Google/library/googlemerchantcalculations.php'; require_once 'Google/library/googleresult.php'; require_once 'Google/library/xml-processing/gc_xmlparser.php'; $config = CRM_Core_Config::singleton(); // Retrieve the XML sent in the HTTP POST request to the ResponseHandler if (get_magic_quotes_gpc()) { $xml_response = stripslashes($xml_response); } $headers = CRM_Utils_System::getAllHeaders(); if (GOOGLE_DEBUG_PP) { CRM_Core_Error::debug_var('RESPONSE', $xml_response, TRUE, TRUE, 'Google'); } // Retrieve the root and data from the xml response $response = new GoogleResponse(); list($root, $data) = $response->GetParsedXML($xml_response); // lets retrieve the private-data & order-no $privateData = NULL; if (array_key_exists('shopping-cart', $data[$root])) { $privateData = $data[$root]['shopping-cart']['merchant-private-data']['VALUE']; } if (empty($privateData) && array_key_exists('order-summary', $data[$root]) && array_key_exists('shopping-cart', $data[$root]['order-summary'])) { $privateData = $data[$root]['order-summary']['shopping-cart']['merchant-private-data']['VALUE']; } $privateData = $privateData ? self::stringToArray($privateData) : ''; $orderNo = $data[$root]['google-order-number']['VALUE']; $serial = $data[$root]['serial-number']; // a dummy object to call get context and a parent function inside it. $ipn = new CRM_Core_Payment_GoogleIPN('live', $dummyProcessor); list($mode, $module, $paymentProcessorID) = $ipn->getContext($privateData, $orderNo, $root, $response, $serial); $mode = $mode ? 'test' : 'live'; $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($paymentProcessorID, $mode); $merchant_id = $paymentProcessor['user_name']; $merchant_key = $paymentProcessor['password']; $response->SetMerchantAuthentication($merchant_id, $merchant_key); $server_type = $mode == 'test' ? 'sandbox' : 'production'; $request = new GoogleRequest($merchant_id, $merchant_key, $server_type); $ipn = self::singleton($mode, $module, $paymentProcessor); if (GOOGLE_DEBUG_PP) { CRM_Core_Error::debug_var('RESPONSE-ROOT', $response->root, TRUE, TRUE, 'Google'); } //Check status and take appropriate action $status = $response->HttpAuthentication($headers); switch ($root) { case "request-received": case "error": case "diagnosis": case "checkout-redirect": case "merchant-calculation-callback": break; case "new-order-notification": $response->SendAck($serial, FALSE); $ipn->newOrderNotify($data[$root], $privateData, $module); break; case "order-state-change-notification": $response->SendAck($serial, FALSE); $new_financial_state = $data[$root]['new-financial-order-state']['VALUE']; $new_fulfillment_order = $data[$root]['new-fulfillment-order-state']['VALUE']; switch ($new_financial_state) { case 'CHARGEABLE': break; case 'CHARGED': case 'PAYMENT_DECLINED': case 'CANCELLED': case 'CANCELLED_BY_GOOGLE': $ipn->orderStateChange($new_financial_state, $data[$root], $privateData, $module); break; case 'REVIEWING': case 'CHARGING': break; default: break; } break; case "authorization-amount-notification": $response->SendAck($serial, FALSE); $new_financial_state = $data[$root]['order-summary']['financial-order-state']['VALUE']; $new_fulfillment_order = $data[$root]['order-summary']['fulfillment-order-state']['VALUE']; switch ($new_financial_state) { case 'CHARGEABLE': // For google-handled subscriptions chargeorder needn't be initiated, // assuming auto-charging is turned on. //$request->SendProcessOrder($data[$root]['google-order-number']['VALUE']); //$request->SendChargeOrder($data[$root]['google-order-number']['VALUE'],''); break; case 'CHARGED': case 'PAYMENT_DECLINED': case 'CANCELLED': break; case 'REVIEWING': case 'CHARGING': case 'CANCELLED_BY_GOOGLE': break; default: break; } break; case "charge-amount-notification": case "chargeback-amount-notification": case "refund-amount-notification": case "risk-information-notification": $response->SendAck($serial); break; default: break; } }
/** * 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}")); } }
/** * Process form submission. * * This function is also accessed by a unit test. */ protected function submit() { $this->storeContactFields($this->_params); $now = CRM_Utils_Date::getToday(NULL, 'YmdHis'); $this->convertDateFieldsToMySQL($this->_params); $this->assign('receive_date', $this->_params['receive_date']); $this->processBillingAddress($now); 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'); } $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->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($this->_params['payment_processor_id']); $this->_params['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($this->_params); $this->_params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($this->_params); $this->assign('credit_card_exp_date', CRM_Utils_Date::mysqlToIso(CRM_Utils_Date::format($this->_params['credit_card_exp_date']))); $this->assign('credit_card_number', CRM_Utils_System::mungeCreditCard($this->_params['credit_card_number'])); $this->assign('credit_card_type', $this->_params['credit_card_type']); $this->_params['description'] = ts("Contribution submitted by a staff person using member's credit card for renewal"); $this->_params['ip_address'] = CRM_Utils_System::ipAddress(); $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); $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. $contributionRecurID = isset($this->_params['contributionRecurID']) ? $this->_params['contributionRecurID'] : NULL; $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(); $priceSetId = CRM_Member_BAO_Membership::createLineItems($this, $this->_params['membership_type_id']); CRM_Price_BAO_PriceSet::processAmount($this->_priceSet['fields'], $this->_params, $lineItem[$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[$priceSetId] as &$li) { $li['financial_type_id'] = $submittedFinancialType; } } $this->_params['total_amount'] = CRM_Utils_Array::value('amount', $this->_params); 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')); } }
/** * This method is handles the response that will be invoked (from extern/googleNotify) every time * a notification or request is sent by the Google Server. * */ static function main($xml_response) { require_once 'Google/library/googleresponse.php'; require_once 'Google/library/googlemerchantcalculations.php'; require_once 'Google/library/googleresult.php'; require_once 'Google/library/xml-processing/xmlparser.php'; $config = CRM_Core_Config::singleton(); // Retrieve the XML sent in the HTTP POST request to the ResponseHandler if (get_magic_quotes_gpc()) { $xml_response = stripslashes($xml_response); } require_once 'CRM/Utils/System.php'; $headers = CRM_Utils_System::getAllHeaders(); if (GOOGLE_DEBUG_PP) { CRM_Core_Error::debug_var('RESPONSE', $xml_response, TRUE, TRUE, 'Google'); } // Retrieve the root and data from the xml response $xmlParser = new XmlParser($xml_response); $root = $xmlParser->GetRoot(); $data = $xmlParser->GetData(); $orderNo = $data[$root]['google-order-number']['VALUE']; // lets retrieve the private-data $privateData = $data[$root]['shopping-cart']['merchant-private-data']['VALUE']; $privateData = $privateData ? self::stringToArray($privateData) : ''; list($mode, $module, $paymentProcessorID) = self::getContext($xml_response, $privateData, $orderNo, $root); $mode = $mode ? 'test' : 'live'; require_once 'CRM/Financial/BAO/PaymentProcessor.php'; $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($paymentProcessorID, $mode); $ipn =& self::singleton($mode, $module, $paymentProcessor); // Create new response object $merchant_id = $paymentProcessor['user_name']; $merchant_key = $paymentProcessor['password']; $server_type = $mode == 'test' ? "sandbox" : ''; $response = new GoogleResponse($merchant_id, $merchant_key, $xml_response, $server_type); if (GOOGLE_DEBUG_PP) { CRM_Core_Error::debug_var('RESPONSE-ROOT', $response->root, TRUE, TRUE, 'Google'); } //Check status and take appropriate action $status = $response->HttpAuthentication($headers); switch ($root) { case "request-received": case "error": case "diagnosis": case "checkout-redirect": case "merchant-calculation-callback": break; case "new-order-notification": $response->SendAck(); $ipn->newOrderNotify($data[$root], $privateData, $module); break; case "order-state-change-notification": $response->SendAck(); $new_financial_state = $data[$root]['new-financial-order-state']['VALUE']; $new_fulfillment_order = $data[$root]['new-fulfillment-order-state']['VALUE']; switch ($new_financial_state) { case 'CHARGEABLE': $amount = $ipn->getAmount($orderNo); if ($amount) { $response->SendChargeOrder($data[$root]['google-order-number']['VALUE'], $amount, $message_log); $response->SendProcessOrder($data[$root]['google-order-number']['VALUE'], $message_log); } break; case 'CHARGED': case 'PAYMENT_DECLINED': case 'CANCELLED': $ipn->orderStateChange($new_financial_state, $data[$root], $module); break; case 'REVIEWING': case 'CHARGING': case 'CANCELLED_BY_GOOGLE': break; default: break; } case "charge-amount-notification": case "chargeback-amount-notification": case "refund-amount-notification": case "risk-information-notification": $response->SendAck(); break; default: break; } }
/** * 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}")); } }
/** * Payment callback handler. The processor_name or processor_id is passed in. * Note that processor_id is more reliable as one site may have more than one instance of a * processor & ideally the processor will be validating the results * Load requested payment processor and call that processor's handle<$method> method * * @public * @param $method * @param array $params */ static function handlePaymentMethod($method, $params = array()) { if (!isset($params['processor_id']) && !isset($params['processor_name'])) { CRM_Core_Error::fatal("Either 'processor_id' or 'processor_name' param is required for payment callback"); } self::logPaymentNotification($params); // Query db for processor .. $mode = @$params['mode']; $sql = "SELECT ppt.class_name, ppt.name as processor_name, pp.id AS processor_id\n FROM civicrm_payment_processor_type ppt\n INNER JOIN civicrm_payment_processor pp\n ON pp.payment_processor_type_id = ppt.id\n AND pp.is_active\n AND pp.is_test = %1"; $args[1] = array($mode == 'test' ? 1 : 0, 'Integer'); if (isset($params['processor_id'])) { $sql .= " WHERE pp.id = %2"; $args[2] = array($params['processor_id'], 'Integer'); $notfound = "No active instances of payment processor ID#'{$params['processor_id']}' were found."; } else { $sql .= " WHERE ppt.name = %2"; $args[2] = array($params['processor_name'], 'String'); $notfound = "No active instances of the '{$params['processor_name']}' payment processor were found."; } $dao = CRM_Core_DAO::executeQuery($sql, $args); // Check whether we found anything at all .. if (!$dao->N) { CRM_Core_Error::fatal($notfound); } $method = 'handle' . $method; $extension_instance_found = FALSE; // In all likelihood, we'll just end up with the one instance returned here. But it's // possible we may get more. Hence, iterate through all instances .. while ($dao->fetch()) { // Check pp is extension $ext = CRM_Extension_System::singleton()->getMapper(); if ($ext->isExtensionKey($dao->class_name)) { $paymentClass = $ext->keyToClass($dao->class_name, 'payment'); require_once $ext->classToPath($paymentClass); } else { // Legacy or extension as module instance if (empty($paymentClass)) { $paymentClass = 'CRM_Core_' . $dao->class_name; } } $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($dao->processor_id, $mode); // Should never be empty - we already established this processor_id exists and is active. if (empty($paymentProcessor)) { continue; } // Instantiate PP $processorInstance = $paymentClass::singleton($mode, $paymentProcessor); // Does PP implement this method, and can we call it? if (!method_exists($processorInstance, $method) || !is_callable(array($processorInstance, $method))) { // on the off chance there is a double implementation of this processor we should keep looking for another // note that passing processor_id is more reliable & we should work to deprecate processor_name continue; } // Everything, it seems, is ok - execute pp callback handler $processorInstance->{$method}(); $extension_instance_found = TRUE; } if (!$extension_instance_found) { CRM_Core_Error::fatal("No extension instances of the '{$params['processor_name']}' payment processor were found.<br />" . "{$method} method is unsupported in legacy payment processors."); } // Exit here on web requests, allowing just the plain text response to be echoed if ($method == 'handlePaymentNotification') { CRM_Utils_System::civiExit(); } }
/** * Load objects relations to contribution object. * Objects are stored in the $_relatedObjects property * In the first instance we are just moving functionality from BASEIpn - * @see http://issues.civicrm.org/jira/browse/CRM-9996 * * Note that the unit test for the BaseIPN class tests this function * * @param array $input * Input as delivered from Payment Processor. * @param array $ids * Ids as Loaded by Payment Processor. * @param bool $loadAll * Load all related objects - even where id not passed in? (allows API to call this). * * @return bool * @throws Exception */ public function loadRelatedObjects(&$input, &$ids, $loadAll = FALSE) { if ($loadAll) { $ids = array_merge($this->getComponentDetails($this->id), $ids); if (empty($ids['contact']) && isset($this->contact_id)) { $ids['contact'] = $this->contact_id; } } if (empty($this->_component)) { if (!empty($ids['event'])) { $this->_component = 'event'; } else { $this->_component = strtolower(CRM_Utils_Array::value('component', $input, 'contribute')); } } // If the object is not fully populated then make sure it is - this is a more about legacy paths & cautious // refactoring than anything else, and has unit test coverage. if (empty($this->financial_type_id)) { $this->find(TRUE); } $paymentProcessorID = CRM_Utils_Array::value('payment_processor_id', $input, CRM_Utils_Array::value('paymentProcessor', $ids)); if (!$paymentProcessorID && $this->contribution_page_id) { $paymentProcessorID = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionPage', $this->contribution_page_id, 'payment_processor'); if ($paymentProcessorID) { $intentionalEnotice = $CRM16923AnUnreliableMethodHasBeenUserToDeterminePaymentProcessorFromContributionPage; } } $ids['contributionType'] = $this->financial_type_id; $ids['financialType'] = $this->financial_type_id; $entities = array('contact' => 'CRM_Contact_BAO_Contact', 'contributionRecur' => 'CRM_Contribute_BAO_ContributionRecur', 'contributionType' => 'CRM_Financial_BAO_FinancialType', 'financialType' => 'CRM_Financial_BAO_FinancialType'); foreach ($entities as $entity => $bao) { if (!empty($ids[$entity])) { $this->_relatedObjects[$entity] = new $bao(); $this->_relatedObjects[$entity]->id = $ids[$entity]; if (!$this->_relatedObjects[$entity]->find(TRUE)) { throw new CRM_Core_Exception($entity . ' could not be loaded'); } } } if (!empty($ids['contributionRecur']) && !$paymentProcessorID) { $paymentProcessorID = $this->_relatedObjects['contributionRecur']->payment_processor_id; } if (!empty($ids['pledge_payment'])) { foreach ($ids['pledge_payment'] as $key => $paymentID) { if (empty($paymentID)) { continue; } $payment = new CRM_Pledge_BAO_PledgePayment(); $payment->id = $paymentID; if (!$payment->find(TRUE)) { throw new Exception("Could not find pledge payment record: " . $paymentID); } $this->_relatedObjects['pledge_payment'][] = $payment; } } $this->loadRelatedMembershipObjects($ids); if ($this->_component != 'contribute') { // we are in event mode // make sure event exists and is valid $event = new CRM_Event_BAO_Event(); $event->id = $ids['event']; if ($ids['event'] && !$event->find(TRUE)) { throw new Exception("Could not find event: " . $ids['event']); } $this->_relatedObjects['event'] =& $event; $participant = new CRM_Event_BAO_Participant(); $participant->id = $ids['participant']; if ($ids['participant'] && !$participant->find(TRUE)) { throw new Exception("Could not find participant: " . $ids['participant']); } $participant->register_date = CRM_Utils_Date::isoToMysql($participant->register_date); $this->_relatedObjects['participant'] =& $participant; // get the payment processor id from event - this is inaccurate see CRM-16923 // in future we should look at throwing an exception here rather than an dubious guess. if (!$paymentProcessorID) { $paymentProcessorID = $this->_relatedObjects['event']->payment_processor; if ($paymentProcessorID) { $intentionalEnotice = $CRM16923AnUnreliableMethodHasBeenUserToDeterminePaymentProcessorFromEvent; } } } if ($paymentProcessorID) { $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($paymentProcessorID, $this->is_test ? 'test' : 'live'); $ids['paymentProcessor'] = $paymentProcessorID; $this->_relatedObjects['paymentProcessor'] = $paymentProcessor; } return TRUE; }
function simpledonate_civicrm_pageRun(&$page) { $pageName = $page->getVar('_name'); if ($pageName == 'Civi\\Angular\\Page\\Main' && $page->urlPath[1] == 'simple') { //Get all contribution page detils and session details to be used in js $settingVal = simpledonate_getSimpleDonateSetting(); $session = CRM_Core_Session::singleton(); $contactID = $session->get('userID'); if ($settingVal['donatePageID']) { $extends = CRM_Core_Component::getComponentID('CiviContribute'); $priceSetID = CRM_Price_BAO_PriceSet::getFor('civicrm_contribution_page', $settingVal['donatePageID'], $extends); $priceField = civicrm_api3('PriceField', 'get', array("price_set_id" => $priceSetID)); //Check for is_quick_config $isQuickConfig = civicrm_api3('PriceSet', 'getvalue', array('id' => $priceSetID, 'return' => "is_quick_config")); //Check for Other amount $otherAmount = FALSE; foreach ($priceField['values'] as $key => $value) { if ($value['name'] == 'other_amount') { $otherAmount = TRUE; } else { $priceFieldVal = civicrm_api3('PriceFieldValue', 'get', array('return' => "amount, title, name, is_default", "price_field_id" => $value['id'])); $priceList = $priceFieldVal['values']; $htmlPriceList[$value['html_type']] = $priceFieldVal['values']; } } //Get donation page details $donateConfig = $donatePage = civicrm_api3('ContributionPage', 'getsingle', array('id' => $settingVal['donatePageID'])); CRM_Utils_System::setTitle($donateConfig['title']); // Set the page title $currencySymbol = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_Currency', $donatePage['currency'], 'symbol', 'name'); $test = !empty($_GET['test']) ? 'test' : 'live'; // Check for test or live donation //Get payment processor details if (is_array($donatePage['payment_processor'])) { $paymentProcessors = CRM_Financial_BAO_PaymentProcessor::getPayments($donatePage['payment_processor'], $test); } else { $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($donatePage['payment_processor'], $test); $paymentProcessors[$paymentProcessor['id']] = $paymentProcessor; $paymentProcessors[$paymentProcessor['id']]['hide'] = $donateConfig['is_pay_later'] ? FALSE : TRUE; } //set Country and State value $config = CRM_Core_Config::singleton(); $defaultContactCountry = $config->defaultContactCountry; $stateProvince = array_flip(CRM_Core_PseudoConstant::stateProvinceForCountry($defaultContactCountry)); $countryList = CRM_Core_PseudoConstant::country(); $stateList = array(); foreach ($countryList as $key => $val) { $stateList[$key] = CRM_Core_PseudoConstant::stateProvinceForCountry($key); } CRM_Core_Resources::singleton()->addSetting(array('simpledonate' => array('sessionContact' => $contactID, 'priceSetID' => $priceSetID, 'ziptasticEnable' => $settingVal['ziptasticEnable'], 'countryList' => CRM_Core_PseudoConstant::country(), 'stateList' => $stateList, 'country' => $defaultContactCountry, 'allStates' => $stateProvince, 'currency' => $currencySymbol, 'config' => $donateConfig, 'paymentProcessor' => $paymentProcessors, 'priceList' => $priceList, 'otherAmount' => $otherAmount, 'isTest' => $test == 'test' ? 1 : 0, 'htmlPriceList' => $htmlPriceList, 'isQuickConfig' => $isQuickConfig))); //Include bootstrap and custom css files to affect this angular page only CRM_Core_Resources::singleton()->addStyleFile('com.webaccessglobal.simpledonate', 'css/bootstrap.min.css', 103, 'page-header'); CRM_Core_Resources::singleton()->addStyleFile('com.webaccessglobal.simpledonate', 'css/simpledonate.css', 100, 'page-body'); } if ($contactID) { $id = array('id' => $contactID); $result = civicrm_api3('Contact', 'getSingle', $id); CRM_Core_Resources::singleton()->addSetting(array('simpledonateVal' => $result)); } } }
/** * Check that the MDs is valid. * * Note that this only checks if it is provided. * * @param array $ids * @param array $input * * @throws CRM_Core_Exception */ public function checkMD5($ids, $input) { if (empty($input['trxn_id'])) { // For decline we have nothing to check against. return; } $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($ids['paymentProcessor'], $input['is_test'] ? 'test' : 'live'); $paymentObject = CRM_Core_Payment::singleton($input['is_test'] ? 'test' : 'live', $paymentProcessor); if (!$paymentObject->checkMD5($input['MD5_Hash'], $input['trxn_id'], $input['amount'], TRUE)) { $message = "Failure: Security verification failed"; $log = new CRM_Utils_SystemLogger(); $log->error('payment_notification', array('message' => $message, 'ids' => $ids, 'input' => $input)); throw new CRM_Core_Exception($message); } }
/** * This method is handles the response that will be invoked by the * notification or request sent by the payment processor. * hex string from paymentexpress is passed to this function as hex string. Code based on googleIPN * mac_key is only passed if the processor is pxaccess as it is used for decryption * $dps_method is either pxaccess or pxpay */ public static function main($dps_method, $rawPostData, $dps_url, $dps_user, $dps_key, $mac_key) { $config = CRM_Core_Config::singleton(); define('RESPONSE_HANDLER_LOG_FILE', $config->uploadDir . 'CiviCRM.PaymentExpress.log'); //Setup the log file if (!($message_log = fopen(RESPONSE_HANDLER_LOG_FILE, "a"))) { error_func("Cannot open " . RESPONSE_HANDLER_LOG_FILE . " file.\n", 0); exit(1); } if ($dps_method == "pxpay") { $processResponse = CRM_Core_Payment_PaymentExpressUtils::_valueXml(array('PxPayUserId' => $dps_user, 'PxPayKey' => $dps_key, 'Response' => $_GET['result'])); $processResponse = CRM_Core_Payment_PaymentExpressUtils::_valueXml('ProcessResponse', $processResponse); fwrite($message_log, sprintf("\n\r%s:- %s\n", date("D M j G:i:s T Y"), $processResponse)); // Send the XML-formatted validation request to DPS so that we can receive a decrypted XML response which contains the transaction results $curl = CRM_Core_Payment_PaymentExpressUtils::_initCURL($processResponse, $dps_url); fwrite($message_log, sprintf("\n\r%s:- %s\n", date("D M j G:i:s T Y"), $curl)); $success = FALSE; if ($response = curl_exec($curl)) { fwrite($message_log, sprintf("\n\r%s:- %s\n", date("D M j G:i:s T Y"), $response)); curl_close($curl); // Assign the returned XML values to variables $valid = CRM_Core_Payment_PaymentExpressUtils::_xmlAttribute($response, 'valid'); $success = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, 'Success'); $txnId = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, 'TxnId'); $responseText = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, 'ResponseText'); $authCode = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, 'AuthCode'); $DPStxnRef = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, 'DpsTxnRef'); $qfKey = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, "TxnData1"); $privateData = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, "TxnData2"); list($component, $paymentProcessorID, ) = explode(',', CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, "TxnData3")); $amount = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, "AmountSettlement"); $merchantReference = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, "MerchantReference"); } else { // calling DPS failed CRM_Core_Error::fatal(ts('Unable to establish connection to the payment gateway to verify transaction response.')); exit; } } elseif ($dps_method == "pxaccess") { require_once 'PaymentExpress/pxaccess.inc.php'; global $pxaccess; $pxaccess = new PxAccess($dps_url, $dps_user, $dps_key, $mac_key); #getResponse method in PxAccess object returns PxPayResponse object #which encapsulates all the response data $rsp = $pxaccess->getResponse($rawPostData); $qfKey = $rsp->getTxnData1(); $privateData = $rsp->getTxnData2(); list($component, $paymentProcessorID) = explode(',', $rsp->getTxnData3()); $success = $rsp->getSuccess(); $authCode = $rsp->getAuthCode(); $DPStxnRef = $rsp->getDpsTxnRef(); $amount = $rsp->getAmountSettlement(); $MerchantReference = $rsp->getMerchantReference(); } $privateData = $privateData ? self::stringToArray($privateData) : ''; // Record the current count in array, before we start adding things (for later checks) $countPrivateData = count($privateData); // Private Data consists of : a=contactID, b=contributionID,c=contributionTypeID,d=invoiceID,e=membershipID,f=participantID,g=eventID $privateData['contactID'] = $privateData['a']; $privateData['contributionID'] = $privateData['b']; $privateData['contributionTypeID'] = $privateData['c']; $privateData['invoiceID'] = $privateData['d']; if ($component == "event") { $privateData['participantID'] = $privateData['f']; $privateData['eventID'] = $privateData['g']; } elseif ($component == "contribute") { if ($countPrivateData == 5) { $privateData["membershipID"] = $privateData['e']; } } $transactionReference = $authCode . "-" . $DPStxnRef; list($mode, $component, $duplicateTransaction) = self::getContext($privateData, $transactionReference); $mode = $mode ? 'test' : 'live'; $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($paymentProcessorID, $mode); $ipn = self::singleton($mode, $component, $paymentProcessor); //Check status and take appropriate action if ($success == 1) { if ($duplicateTransaction == 0) { $ipn->newOrderNotify($success, $privateData, $component, $amount, $transactionReference); } if ($component == "event") { $finalURL = CRM_Utils_System::url('civicrm/event/register', "_qf_ThankYou_display=1&qfKey={$qfKey}", FALSE, NULL, FALSE); } elseif ($component == "contribute") { $finalURL = CRM_Utils_System::url('civicrm/contribute/transact', "_qf_ThankYou_display=1&qfKey={$qfKey}", FALSE, NULL, FALSE); } CRM_Utils_System::redirect($finalURL); } else { if ($component == "event") { $finalURL = CRM_Utils_System::url('civicrm/event/confirm', "reset=1&cc=fail&participantId={$privateData['participantID']}", FALSE, NULL, FALSE); } elseif ($component == "contribute") { $finalURL = CRM_Utils_System::url('civicrm/contribute/transact', "_qf_Main_display=1&cancel=1&qfKey={$qfKey}", FALSE, NULL, FALSE); } CRM_Utils_System::redirect($finalURL); } }
function checkMD5($ids, $input) { $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($ids['paymentProcessor'], $input['is_test'] ? 'test' : 'live'); $paymentObject = CRM_Core_Payment::singleton($input['is_test'] ? 'test' : 'live', $paymentProcessor); if (!$paymentObject->checkMD5($input['MD5_Hash'], $input['trxn_id'], $input['amount'], TRUE)) { CRM_Core_Error::debug_log_message("MD5 Verification failed."); echo "Failure: Security verification failed<p>"; exit; } return TRUE; }
/** * 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; }
/** * Load objects relations to contribution object. * Objects are stored in the $_relatedObjects property * In the first instance we are just moving functionality from BASEIpn - * @see http://issues.civicrm.org/jira/browse/CRM-9996 * * Note that the unit test for the BaseIPN class tests this function * * @param array $input * Input as delivered from Payment Processor. * @param array $ids * Ids as Loaded by Payment Processor. * @param bool $loadAll * Load all related objects - even where id not passed in? (allows API to call this). * * @return bool * @throws Exception */ public function loadRelatedObjects(&$input, &$ids, $loadAll = FALSE) { if ($loadAll) { $ids = array_merge($this->getComponentDetails($this->id), $ids); if (empty($ids['contact']) && isset($this->contact_id)) { $ids['contact'] = $this->contact_id; } } if (empty($this->_component)) { if (!empty($ids['event'])) { $this->_component = 'event'; } else { $this->_component = strtolower(CRM_Utils_Array::value('component', $input, 'contribute')); } } // If the object is not fully populated then make sure it is - this is a more about legacy paths & cautious // refactoring than anything else, and has unit test coverage. if (empty($this->financial_type_id)) { $this->find(TRUE); } $paymentProcessorID = CRM_Utils_Array::value('payment_processor_id', $input, CRM_Utils_Array::value('paymentProcessor', $ids)); if (!$paymentProcessorID && $this->contribution_page_id) { $paymentProcessorID = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionPage', $this->contribution_page_id, 'payment_processor'); if ($paymentProcessorID) { $intentionalEnotice = $CRM16923AnUnreliableMethodHasBeenUserToDeterminePaymentProcessorFromContributionPage; } } $ids['contributionType'] = $this->financial_type_id; $ids['financialType'] = $this->financial_type_id; $entities = array('contact' => 'CRM_Contact_BAO_Contact', 'contributionRecur' => 'CRM_Contribute_BAO_ContributionRecur', 'contributionType' => 'CRM_Financial_BAO_FinancialType', 'financialType' => 'CRM_Financial_BAO_FinancialType'); foreach ($entities as $entity => $bao) { if (!empty($ids[$entity])) { $this->_relatedObjects[$entity] = new $bao(); $this->_relatedObjects[$entity]->id = $ids[$entity]; if (!$this->_relatedObjects[$entity]->find(TRUE)) { throw new CRM_Core_Exception($entity . ' could not be loaded'); } } } if (!empty($ids['contributionRecur']) && !$paymentProcessorID) { $paymentProcessorID = $this->_relatedObjects['contributionRecur']->payment_processor_id; } if (!empty($ids['pledge_payment'])) { foreach ($ids['pledge_payment'] as $key => $paymentID) { if (empty($paymentID)) { continue; } $payment = new CRM_Pledge_BAO_PledgePayment(); $payment->id = $paymentID; if (!$payment->find(TRUE)) { throw new Exception("Could not find pledge payment record: " . $paymentID); } $this->_relatedObjects['pledge_payment'][] = $payment; } } if ($this->_component == 'contribute') { // retrieve the other optional objects first so // stuff down the line can use this info and do things // CRM-6056 //in any case get the memberships associated with the contribution //because we now support multiple memberships w/ price set // see if there are any other memberships to be considered for same contribution. $query = "\n SELECT membership_id\n FROM civicrm_membership_payment\nWHERE contribution_id = %1 "; $params = array(1 => array($this->id, 'Integer')); $dao = CRM_Core_DAO::executeQuery($query, $params); while ($dao->fetch()) { if ($dao->membership_id) { if (!is_array($ids['membership'])) { $ids['membership'] = array(); } $ids['membership'][] = $dao->membership_id; } } if (array_key_exists('membership', $ids) && is_array($ids['membership'])) { foreach ($ids['membership'] as $id) { if (!empty($id)) { $membership = new CRM_Member_BAO_Membership(); $membership->id = $id; if (!$membership->find(TRUE)) { throw new Exception("Could not find membership record: {$id}"); } $membership->join_date = CRM_Utils_Date::isoToMysql($membership->join_date); $membership->start_date = CRM_Utils_Date::isoToMysql($membership->start_date); $membership->end_date = CRM_Utils_Date::isoToMysql($membership->end_date); $this->_relatedObjects['membership'][$membership->membership_type_id] = $membership; $membership->free(); } } } } else { // we are in event mode // make sure event exists and is valid $event = new CRM_Event_BAO_Event(); $event->id = $ids['event']; if ($ids['event'] && !$event->find(TRUE)) { throw new Exception("Could not find event: " . $ids['event']); } $this->_relatedObjects['event'] =& $event; $participant = new CRM_Event_BAO_Participant(); $participant->id = $ids['participant']; if ($ids['participant'] && !$participant->find(TRUE)) { throw new Exception("Could not find participant: " . $ids['participant']); } $participant->register_date = CRM_Utils_Date::isoToMysql($participant->register_date); $this->_relatedObjects['participant'] =& $participant; // get the payment processor id from event - this is inaccurate see CRM-16923 // in future we should look at throwing an exception here rather than an dubious guess. if (!$paymentProcessorID) { $paymentProcessorID = $this->_relatedObjects['event']->payment_processor; if ($paymentProcessorID) { $intentionalEnotice = $CRM16923AnUnreliableMethodHasBeenUserToDeterminePaymentProcessorFromEvent; } } } if ($paymentProcessorID) { $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($paymentProcessorID, $this->is_test ? 'test' : 'live'); $ids['paymentProcessor'] = $paymentProcessorID; $this->_relatedObjects['paymentProcessor'] = $paymentProcessor; } return TRUE; }
/** * @return array (0 => array(int $ppId => string $label), 1 => array(...payproc details...)) */ public function getValidProcessorsAndAssignFutureStartDate() { $validProcessors = array(); $processors = CRM_Core_PseudoConstant::paymentProcessor(FALSE, FALSE, "billing_mode IN ( 1, 3 )"); foreach ($processors as $ppID => $label) { $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($ppID, $this->_mode); // at this stage only Authorize.net has been tested to support future start dates so if it's enabled let the template know // to show receive date $processorsSupportingFutureStartDate = array('AuthNet'); if (in_array($paymentProcessor['payment_processor_type'], $processorsSupportingFutureStartDate)) { $this->assign('processorSupportsFutureStartDate', TRUE); } if ($paymentProcessor['payment_processor_type'] == 'PayPal' && !$paymentProcessor['user_name']) { continue; } elseif ($paymentProcessor['payment_processor_type'] == 'Dummy' && $this->_mode == 'live') { continue; } else { $paymentObject = CRM_Core_Payment::singleton($this->_mode, $paymentProcessor, $this); $error = $paymentObject->checkConfig(); if (empty($error)) { $validProcessors[$ppID] = $label; } $paymentObject = NULL; } } if (empty($validProcessors)) { CRM_Core_Error::fatal(ts('You will need to configure the %1 settings for your Payment Processor before you can submit credit card transactions.', array(1 => $this->_mode))); } else { return array($validProcessors, $paymentProcessor); } }
/** * Get the payment processor (array) for a recurring processor. * * @param int $id * @param string $mode * - Test or NULL - all other variants are ignored. * * @return array|null */ public static function getPaymentProcessor($id, $mode = NULL) { $sql = "\nSELECT r.payment_processor_id\n FROM civicrm_contribution_recur r\n WHERE r.id = %1"; $params = array(1 => array($id, 'Integer')); $paymentProcessorID = CRM_Core_DAO::singleValueQuery($sql, $params); if (!$paymentProcessorID) { return NULL; } return CRM_Financial_BAO_PaymentProcessor::getPayment($paymentProcessorID, $mode); }
/** * Load objects relations to contribution object. * Objects are stored in the $_relatedObjects property * In the first instance we are just moving functionality from BASEIpn - * @see http://issues.civicrm.org/jira/browse/CRM-9996 * * Note that the unit test for the BaseIPN class tests this function * * @param array $input * Input as delivered from Payment Processor. * @param array $ids * Ids as Loaded by Payment Processor. * @param bool $required * Is Payment processor / contribution page required. * @param bool $loadAll * Load all related objects - even where id not passed in? (allows API to call this). * * @return bool * @throws Exception */ public function loadRelatedObjects(&$input, &$ids, $required = FALSE, $loadAll = FALSE) { if ($loadAll) { $ids = array_merge($this->getComponentDetails($this->id), $ids); if (empty($ids['contact']) && isset($this->contact_id)) { $ids['contact'] = $this->contact_id; } } if (empty($this->_component)) { if (!empty($ids['event'])) { $this->_component = 'event'; } else { $this->_component = strtolower(CRM_Utils_Array::value('component', $input, 'contribute')); } } $paymentProcessorID = CRM_Utils_Array::value('paymentProcessor', $ids); $contributionType = new CRM_Financial_BAO_FinancialType(); $contributionType->id = $this->financial_type_id; $contributionType->find(TRUE); if (!empty($ids['contact'])) { $this->_relatedObjects['contact'] = new CRM_Contact_BAO_Contact(); $this->_relatedObjects['contact']->id = $ids['contact']; $this->_relatedObjects['contact']->find(TRUE); } $this->_relatedObjects['contributionType'] = $contributionType; if ($this->_component == 'contribute') { // retrieve the other optional objects first so // stuff down the line can use this info and do things // CRM-6056 //in any case get the memberships associated with the contribution //because we now support multiple memberships w/ price set // see if there are any other memberships to be considered for same contribution. $query = "\n SELECT membership_id\n FROM civicrm_membership_payment\nWHERE contribution_id = %1 "; $params = array(1 => array($this->id, 'Integer')); $dao = CRM_Core_DAO::executeQuery($query, $params); while ($dao->fetch()) { if ($dao->membership_id) { if (!is_array($ids['membership'])) { $ids['membership'] = array(); } $ids['membership'][] = $dao->membership_id; } } if (array_key_exists('membership', $ids) && is_array($ids['membership'])) { foreach ($ids['membership'] as $id) { if (!empty($id)) { $membership = new CRM_Member_BAO_Membership(); $membership->id = $id; if (!$membership->find(TRUE)) { throw new Exception("Could not find membership record: {$id}"); } $membership->join_date = CRM_Utils_Date::isoToMysql($membership->join_date); $membership->start_date = CRM_Utils_Date::isoToMysql($membership->start_date); $membership->end_date = CRM_Utils_Date::isoToMysql($membership->end_date); $this->_relatedObjects['membership'][$membership->membership_type_id] = $membership; $membership->free(); } } } if (!empty($ids['pledge_payment'])) { foreach ($ids['pledge_payment'] as $key => $paymentID) { if (empty($paymentID)) { continue; } $payment = new CRM_Pledge_BAO_PledgePayment(); $payment->id = $paymentID; if (!$payment->find(TRUE)) { throw new Exception("Could not find pledge payment record: " . $paymentID); } $this->_relatedObjects['pledge_payment'][] = $payment; } } if (!empty($ids['contributionRecur'])) { $recur = new CRM_Contribute_BAO_ContributionRecur(); $recur->id = $ids['contributionRecur']; if (!$recur->find(TRUE)) { throw new Exception("Could not find recur record: " . $ids['contributionRecur']); } $this->_relatedObjects['contributionRecur'] =& $recur; //get payment processor id from recur object. $paymentProcessorID = $recur->payment_processor_id; } //for normal contribution get the payment processor id. if (!$paymentProcessorID) { if ($this->contribution_page_id) { // get the payment processor id from contribution page $paymentProcessorID = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionPage', $this->contribution_page_id, 'payment_processor'); } elseif (empty($ids['pledge_payment'])) { $loadObjectSuccess = TRUE; if ($required) { throw new Exception("Could not find contribution page for contribution record: " . $this->id); } return $loadObjectSuccess; } } } else { // we are in event mode // make sure event exists and is valid $event = new CRM_Event_BAO_Event(); $event->id = $ids['event']; if ($ids['event'] && !$event->find(TRUE)) { throw new Exception("Could not find event: " . $ids['event']); } $this->_relatedObjects['event'] =& $event; $participant = new CRM_Event_BAO_Participant(); $participant->id = $ids['participant']; if ($ids['participant'] && !$participant->find(TRUE)) { throw new Exception("Could not find participant: " . $ids['participant']); } $participant->register_date = CRM_Utils_Date::isoToMysql($participant->register_date); $this->_relatedObjects['participant'] =& $participant; if (!$paymentProcessorID) { $paymentProcessorID = $this->_relatedObjects['event']->payment_processor; } } if ($paymentProcessorID) { $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($paymentProcessorID, $this->is_test ? 'test' : 'live'); $ids['paymentProcessor'] = $paymentProcessorID; $this->_relatedObjects['paymentProcessor'] = $paymentProcessor; } elseif ($required) { throw new Exception("Could not find payment processor for contribution record: " . $this->id); } return TRUE; }
/** * Set variables up before form is built. * * @return void */ 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']); $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']}"]; } // check for is_monetary status $isMonetary = CRM_Utils_Array::value('is_monetary', $this->_values['event']); $isPayLater = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $this->_eventId, 'is_pay_later'); //check for variour combination for paylater, payment //process with paid event. if ($isMonetary && (!$isPayLater || !empty($this->_values['event']['payment_processor']))) { $ppID = CRM_Utils_Array::value('payment_processor', $this->_values['event']); if (!$ppID) { CRM_Core_Error::statusBounce(ts('A payment processor must be selected for this event registration page, or the event must be configured to give users the option to pay later (contact the site administrator for assistance).'), $infoUrl); } $ppIds = explode(CRM_Core_DAO::VALUE_SEPARATOR, $ppID); $this->_paymentProcessors = CRM_Financial_BAO_PaymentProcessor::getPayments($ppIds, $this->_mode); $this->set('paymentProcessors', $this->_paymentProcessors); //set default payment processor if (!empty($this->_paymentProcessors) && empty($this->_paymentProcessor)) { foreach ($this->_paymentProcessors as $ppId => $values) { if ($values['is_default'] == 1 || count($this->_paymentProcessors) == 1) { $defaultProcessorId = $ppId; break; } } } if (isset($defaultProcessorId)) { $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($defaultProcessorId, $this->_mode); } // make sure we have a valid payment class, else abort if ($this->_values['event']['is_monetary']) { if (!CRM_Utils_System::isNull($this->_paymentProcessors)) { foreach ($this->_paymentProcessors as $eachPaymentProcessor) { // check selected payment processor is active if (!$eachPaymentProcessor) { CRM_Core_Error::fatal(ts('The site administrator must set a Payment Processor for this event in order to use online registration.')); } // ensure that processor has a valid config $payment = CRM_Core_Payment::singleton($this->_mode, $eachPaymentProcessor, $this); $error = $payment->checkConfig(); if (!empty($error)) { CRM_Core_Error::fatal($error); } } } } } //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']); } } // get the billing location type $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id', array(), 'validate'); // CRM-8108 remove ts from Billing as the location type can not be translated in CiviCRM! //$this->_bltID = array_search( ts('Billing'), $locationTypes ); $this->_bltID = array_search('Billing', $locationTypes); if (!$this->_bltID) { CRM_Core_Error::fatal(ts('Please set a location type of %1', array(1 => 'Billing'))); } $this->set('bltID', $this->_bltID); 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); } $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; } // check if billing block is required for pay later 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); } }
/** * Function to run hooks in the payment processor class * Load requested payment processor and call the method specified. * * @param string $method - the method to call in the payment processor class * @private */ private function _runPaymentHook(CRM_Extension_Info $info, $method) { // Not concerned about performance at this stage, as these are seldomly performed tasks // (payment processor enable/disable/install/uninstall). May wish to implement some // kind of registry/caching system if more hooks are added. try { $paymentClass = $this->mapper->keyToClass($info->key, 'payment'); $file = $this->mapper->classToPath($paymentClass); if (!file_exists($file)) { CRM_Core_Session::setStatus(ts('Failed to load file (%3) for payment processor (%1) while running "%2"', array(1 => $info->key, 2 => $method, 3 => $file)), '', 'error'); return; } else { require_once $file; } } catch (CRM_Extension_Exception $e) { CRM_Core_Session::setStatus(ts('Failed to determine file path for payment processor (%1) while running "%2"', array(1 => $info->key, 2 => $method)), '', 'error'); return; } // See if we have any instances of this PP defined .. if ($processor_id = CRM_Core_DAO::singleValueQuery("\n SELECT pp.id\n FROM civicrm_extension ext\n INNER JOIN civicrm_payment_processor_type ppt\n ON ext.name = ppt.name\n INNER JOIN civicrm_payment_processor pp\n ON ppt.id = pp.payment_processor_type_id\n WHERE ext.type = 'payment'\n AND ext.full_name = %1\n ", array(1 => array($info->key, 'String')))) { // If so, load params in the usual way .. $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($processor_id, NULL); } else { // Otherwise, do the best we can to construct some .. $dao = CRM_Core_DAO::executeQuery("\n SELECT ppt.*\n FROM civicrm_extension ext\n INNER JOIN civicrm_payment_processor_type ppt\n ON ppt.name = ext.name\n WHERE ext.name = %1\n AND ext.type = 'payment'\n ", array(1 => array($info->name, 'String'))); if ($dao->fetch()) { $paymentProcessor = array('id' => -1, 'name' => $dao->title, 'payment_processor_type_id' => $dao->id, 'user_name' => 'nothing', 'password' => 'nothing', 'signature' => '', 'url_site' => $dao->url_site_default, 'url_api' => $dao->url_api_default, 'url_recur' => $dao->url_recur_default, 'url_button' => $dao->url_button_default, 'subject' => '', 'class_name' => $dao->class_name, 'is_recur' => $dao->is_recur, 'billing_mode' => $dao->billing_mode, 'payment_type' => $dao->payment_type); } else { CRM_Core_Error::fatal("Unable to find payment processor in " . __CLASS__ . '::' . __METHOD__); } } // In the case of uninstall, check for instances of PP first. // Don't run hook if any are found. if ($method == 'uninstall' && $paymentProcessor['id'] > 0) { return; } switch ($method) { case 'install': case 'uninstall': case 'enable': case 'disable': // Instantiate PP $processorInstance = $paymentClass::singleton(NULL, $paymentProcessor); // Does PP implement this method, and can we call it? if (method_exists($processorInstance, $method) && is_callable(array($processorInstance, $method))) { // If so, call it ... $processorInstance->{$method}(); } break; default: CRM_Core_Session::setStatus(ts("Unrecognized payment hook (%1) in %2::%3", array(1 => $method, 2 => __CLASS__, 3 => __METHOD__)), '', 'error'); } }
/** * Function to set variables up before form is built * * @return void * @access public */ public function preProcess() { $config = CRM_Core_Config::singleton(); $session = CRM_Core_Session::singleton(); // current contribution page id $this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this); if (!$this->_id) { // seems like the session is corrupted and/or we lost the id trail // lets just bump this to a regular session error and redirect user to main page $this->controller->invalidKeyRedirect(); } // this was used prior to the cleverer this_>getContactID - unsure now $this->_userID = $session->get('userID'); $this->_contactID = $this->_membershipContactID = $this->getContactID(); $this->_mid = NULL; if ($this->_contactID) { $this->_mid = CRM_Utils_Request::retrieve('mid', 'Positive', $this); if ($this->_mid) { $membership = new CRM_Member_DAO_Membership(); $membership->id = $this->_mid; if ($membership->find(TRUE)) { $this->_defaultMemTypeId = $membership->membership_type_id; if ($membership->contact_id != $this->_contactID) { $validMembership = FALSE; $employers = CRM_Contact_BAO_Relationship::getPermissionedEmployer($this->_userID); if (!empty($employers) && array_key_exists($membership->contact_id, $employers)) { $this->_membershipContactID = $membership->contact_id; $this->assign('membershipContactID', $this->_membershipContactID); $this->assign('membershipContactName', $employers[$this->_membershipContactID]['name']); $validMembership = TRUE; } else { $membershipType = new CRM_Member_BAO_MembershipType(); $membershipType->id = $membership->membership_type_id; if ($membershipType->find(TRUE)) { // CRM-14051 - membership_type.relationship_type_id is a CTRL-A padded string w one or more ID values. // Convert to commma separated list. $inheritedRelTypes = implode(CRM_Utils_Array::explodePadded($membershipType->relationship_type_id), ','); $permContacts = CRM_Contact_BAO_Relationship::getPermissionedContacts($this->_userID, $membershipType->relationship_type_id); if (array_key_exists($membership->contact_id, $permContacts)) { $this->_membershipContactID = $membership->contact_id; $validMembership = TRUE; } } } if (!$validMembership) { CRM_Core_Session::setStatus(ts("Oops. The membership you're trying to renew appears to be invalid. Contact your site administrator if you need assistance. If you continue, you will be issued a new membership."), ts('Membership Invalid'), 'alert'); } } } else { CRM_Core_Session::setStatus(ts("Oops. The membership you're trying to renew appears to be invalid. Contact your site administrator if you need assistance. If you continue, you will be issued a new membership."), ts('Membership Invalid'), 'alert'); } unset($membership); } } // we do not want to display recently viewed items, so turn off $this->assign('displayRecent', FALSE); // Contribution page values are cleared from session, so can't use normal Printer Friendly view. // Use Browser Print instead. $this->assign('browserPrint', TRUE); // action $this->_action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, 'add'); $this->assign('action', $this->_action); // 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'); if (!$this->_values) { // get all the values from the dao object $this->_values = array(); $this->_fields = array(); CRM_Contribute_BAO_ContributionPage::setValues($this->_id, $this->_values); // check if form is active if (!CRM_Utils_Array::value('is_active', $this->_values)) { // form is inactive, die a fatal death CRM_Core_Error::fatal(ts('The page you requested is currently unavailable.')); } // also check for billing informatin // get the billing location type $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id', array(), 'validate'); // CRM-8108 remove ts around Billing location type //$this->_bltID = array_search( ts('Billing'), $locationTypes ); $this->_bltID = array_search('Billing', $locationTypes); if (!$this->_bltID) { CRM_Core_Error::fatal(ts('Please set a location type of %1', array(1 => 'Billing'))); } $this->set('bltID', $this->_bltID); // check for is_monetary status $isMonetary = CRM_Utils_Array::value('is_monetary', $this->_values); $isPayLater = CRM_Utils_Array::value('is_pay_later', $this->_values); //FIXME: to support multiple payment processors if ($isMonetary && (!$isPayLater || CRM_Utils_Array::value('payment_processor', $this->_values))) { $ppID = CRM_Utils_Array::value('payment_processor', $this->_values); if (!$ppID) { CRM_Core_Error::fatal(ts('A payment processor must be selected for this contribution page (contact the site administrator for assistance).')); } $ppIds = explode(CRM_Core_DAO::VALUE_SEPARATOR, $ppID); $this->_paymentProcessors = CRM_Financial_BAO_PaymentProcessor::getPayments($ppIds, $this->_mode); $this->set('paymentProcessors', $this->_paymentProcessors); //set default payment processor if (!empty($this->_paymentProcessors) && empty($this->_paymentProcessor)) { foreach ($this->_paymentProcessors as $ppId => $values) { if ($values['is_default'] == 1 || count($this->_paymentProcessors) == 1) { $defaultProcessorId = $ppId; break; } } } if (isset($defaultProcessorId)) { $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($defaultProcessorId, $this->_mode); $this->assign_by_ref('paymentProcessor', $this->_paymentProcessor); } if (!CRM_Utils_System::isNull($this->_paymentProcessors)) { foreach ($this->_paymentProcessors as $eachPaymentProcessor) { // check selected payment processor is active if (empty($eachPaymentProcessor)) { CRM_Core_Error::fatal(ts('A payment processor configured for this page might be disabled (contact the site administrator for assistance).')); } // ensure that processor has a valid config $this->_paymentObject =& CRM_Core_Payment::singleton($this->_mode, $eachPaymentProcessor, $this); $error = $this->_paymentObject->checkConfig(); if (!empty($error)) { CRM_Core_Error::fatal($error); } } } } // get price info // CRM-5095 CRM_Price_BAO_PriceSet::initSet($this, $this->_id, 'civicrm_contribution_page'); // this avoids getting E_NOTICE errors in php $setNullFields = array('amount_block_is_active', 'honor_block_is_active', 'is_allow_other_amount', 'footer_text'); foreach ($setNullFields as $f) { if (!isset($this->_values[$f])) { $this->_values[$f] = NULL; } } //check if Membership Block is enabled, if Membership Fields are included in profile //get membership section for this contribution page $this->_membershipBlock = CRM_Member_BAO_Membership::getMembershipBlock($this->_id); $this->set('membershipBlock', $this->_membershipBlock); if ($this->_values['custom_pre_id']) { $preProfileType = CRM_Core_BAO_UFField::getProfileType($this->_values['custom_pre_id']); } if ($this->_values['custom_post_id']) { $postProfileType = CRM_Core_BAO_UFField::getProfileType($this->_values['custom_post_id']); } if ((isset($postProfileType) && $postProfileType == 'Membership' || isset($preProfileType) && $preProfileType == 'Membership') && !$this->_membershipBlock['is_active']) { CRM_Core_Error::fatal(ts('This page includes a Profile with Membership fields - but the Membership Block is NOT enabled. Please notify the site administrator.')); } $pledgeBlock = CRM_Pledge_BAO_PledgeBlock::getPledgeBlock($this->_id); if ($pledgeBlock) { $this->_values['pledge_block_id'] = CRM_Utils_Array::value('id', $pledgeBlock); $this->_values['max_reminders'] = CRM_Utils_Array::value('max_reminders', $pledgeBlock); $this->_values['initial_reminder_day'] = CRM_Utils_Array::value('initial_reminder_day', $pledgeBlock); $this->_values['additional_reminder_day'] = CRM_Utils_Array::value('additional_reminder_day', $pledgeBlock); //set pledge id in values $pledgeId = CRM_Utils_Request::retrieve('pledgeId', 'Positive', $this); //authenticate pledge user for pledge payment. if ($pledgeId) { $this->_values['pledge_id'] = $pledgeId; //lets override w/ pledge campaign. $this->_values['campaign_id'] = CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_Pledge', $pledgeId, 'campaign_id'); self::authenticatePledgeUser(); } } $this->set('values', $this->_values); $this->set('fields', $this->_fields); } // Handle PCP $pcpId = CRM_Utils_Request::retrieve('pcpId', 'Positive', $this); if ($pcpId) { $pcp = CRM_PCP_BAO_PCP::handlePcp($pcpId, 'contribute', $this->_values); $this->_pcpId = $pcp['pcpId']; $this->_pcpBlock = $pcp['pcpBlock']; $this->_pcpInfo = $pcp['pcpInfo']; } // Link (button) for users to create their own Personal Campaign page if ($linkText = CRM_PCP_BAO_PCP::getPcpBlockStatus($this->_id, 'contribute')) { $linkTextUrl = CRM_Utils_System::url('civicrm/contribute/campaign', "action=add&reset=1&pageId={$this->_id}&component=contribute", FALSE, NULL, TRUE); $this->assign('linkTextUrl', $linkTextUrl); $this->assign('linkText', $linkText); } //set pledge block if block id is set if (CRM_Utils_Array::value('pledge_block_id', $this->_values)) { $this->assign('pledgeBlock', TRUE); } // check if one of the (amount , membership) bloks is active or not $this->_membershipBlock = $this->get('membershipBlock'); if (!$this->_values['amount_block_is_active'] && !$this->_membershipBlock['is_active'] && !$this->_priceSetId) { CRM_Core_Error::fatal(ts('The requested online contribution page is missing a required Contribution Amount section or Membership section or Price Set. Please check with the site administrator for assistance.')); } if ($this->_values['amount_block_is_active']) { $this->set('amount_block_is_active', $this->_values['amount_block_is_active']); } $this->_contributeMode = $this->get('contributeMode'); $this->assign('contributeMode', $this->_contributeMode); //assigning is_monetary and is_email_receipt to template $this->assign('is_monetary', $this->_values['is_monetary']); $this->assign('is_email_receipt', $this->_values['is_email_receipt']); $this->assign('bltID', $this->_bltID); //assign cancelSubscription URL to templates $this->assign('cancelSubscriptionUrl', CRM_Utils_Array::value('cancelSubscriptionUrl', $this->_values)); // assigning title to template in case someone wants to use it, also setting CMS page title if ($this->_pcpId) { $this->assign('title', $this->_pcpInfo['title']); CRM_Utils_System::setTitle($this->_pcpInfo['title']); } else { $this->assign('title', $this->_values['title']); CRM_Utils_System::setTitle($this->_values['title']); } $this->_defaults = array(); $this->_amount = $this->get('amount'); //CRM-6907 $config = CRM_Core_Config::singleton(); $config->defaultCurrency = CRM_Utils_Array::value('currency', $this->_values, $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['campaign_id'] = $campID; } //do check for cancel recurring and clean db, CRM-7696 if (CRM_Utils_Request::retrieve('cancel', 'Boolean', CRM_Core_DAO::$_nullObject)) { self::cancelRecurring(); } }
/** * Validate the payment instrument values before passing it to the payment processor * We want this to be overrideable by the payment processor, and default to using * this object's validCreditCard for credit cards (implemented as the default in the Payment class). */ public static function validatePaymentInstrument($payment_processor_id, $values, &$errors, $form) { // ignore if we don't have a payment instrument to validate (e.g. backend payments) if ($payment_processor_id > 0) { $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($payment_processor_id, 'live'); $payment = CRM_Core_Payment::singleton('live', $paymentProcessor, $form); $payment->validatePaymentInstrument($values, $errors); } }
/** * 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'); } }
public static function process() { require_once 'CRM/Utils/Request.php'; $type = CRM_Utils_Request::retrieve('type', 'String', CRM_Core_DAO::$_nullObject, FALSE, 'csv', 'REQUEST'); $type = strtolower($type); switch ($type) { case 'paypal': $start = CRM_Utils_Request::retrieve('start', 'String', CRM_Core_DAO::$_nullObject, FALSE, 31, 'REQUEST'); $end = CRM_Utils_Request::retrieve('end', 'String', CRM_Core_DAO::$_nullObject, FALSE, 0, 'REQUEST'); if ($start < $end) { CRM_Core_Error::fatal("Start offset can't be less than End offset."); } $start = date('Y-m-d', time() - $start * 24 * 60 * 60) . 'T00:00:00.00Z'; $end = date('Y-m-d', time() - $end * 24 * 60 * 60) . 'T23:59:00.00Z'; $ppID = CRM_Utils_Request::retrieve('ppID', 'Integer', CRM_Core_DAO::$_nullObject, TRUE, NULL, 'REQUEST'); $mode = CRM_Utils_Request::retrieve('ppMode', 'String', CRM_Core_DAO::$_nullObject, FALSE, 'live', 'REQUEST'); $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($ppID, $mode); CRM_Core_Error::debug_log_message("Start Date={$start}, End Date={$end}, ppID={$ppID}, mode={$mode} <p>", TRUE); return self::$type($paymentProcessor, $mode, $start, $end); case 'csv': return self::csv(); } }