/** * Submit a payment using Advanced Integration Method * * @param array $params assoc array of input parameters for this transaction * @return array the result in a nice formatted array (or an error object) * @public */ function doDirectPayment(&$params) { // Invoke hook_civicrm_paymentProcessor // In Dummy's case, there is no translation of parameters into // the back-end's canonical set of parameters. But if a processor // does this, it needs to invoke this hook after it has done translation, // but before it actually starts talking to its proprietary back-end. $cookedParams = $params; // no translation in Dummy processor CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $cookedParams); //end of hook invokation if ($this->_mode == 'test') { $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'test\\_%'"; $p = array(); $trxn_id = strval(CRM_Core_Dao::singleValueQuery($query, $p)); $trxn_id = str_replace('test_', '', $trxn_id); $trxn_id = intval($trxn_id) + 1; $params['trxn_id'] = sprintf('test_%08d', $trxn_id); } else { $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'live_%'"; $p = array(); $trxn_id = strval(CRM_Core_Dao::singleValueQuery($query, $p)); $trxn_id = str_replace('live_', '', $trxn_id); $trxn_id = intval($trxn_id) + 1; $params['trxn_id'] = sprintf('live_%08d', $trxn_id); } $params['gross_amount'] = $params['amount']; return $params; }
/** * This function sends request and receives response from * the processor * @param array $params * @return array|object * @throws Exception */ public function doDirectPayment(&$params) { if (isset($params['is_recur']) && $params['is_recur'] == TRUE) { CRM_Core_Error::fatal(ts('Elavon - recurring payments not implemented')); } if (!defined('CURLOPT_SSLCERT')) { CRM_Core_Error::fatal(ts('Elavon / Nova Virtual Merchant Gateway requires curl with SSL support')); } //Create the array of variables to be sent to the processor from the $params array // passed into this function $requestFields = self::mapProcessorFieldstoParams($params); // define variables for connecting with the gateway $requestFields['ssl_merchant_id'] = $this->_paymentProcessor['user_name']; $requestFields['ssl_user_id'] = $this->_paymentProcessor['password']; $requestFields['ssl_pin'] = $this->_paymentProcessor['signature']; $host = $this->_paymentProcessor['url_site']; if ($this->_mode == "test") { $requestFields['ssl_test_mode'] = "TRUE"; } // Allow further manipulation of the arguments via custom hooks .. CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $requestFields); // Check to see if we have a duplicate before we send if ($this->checkDupe($params['invoiceID'], CRM_Utils_Array::value('contributionID', $params))) { return self::errorExit(9003, 'It appears that this transaction is a duplicate. Have you already submitted the form once? If so there may have been a connection problem. Check your email for a receipt. If you do not receive a receipt within 2 hours you can try your transaction again. If you continue to have problems please contact the site administrator.'); } // Convert to XML using function below $xml = self::buildXML($requestFields); // Send to the payment processor using cURL $chHost = $host . '?xmldata=' . $xml; $ch = curl_init($chHost); if (!$ch) { return self::errorExit(9004, 'Could not initiate connection to payment gateway'); } curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, Civi::settings()->get('verifySSL') ? 2 : 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, Civi::settings()->get('verifySSL')); // return the result on success, FALSE on failure curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 36000); // set this for debugging -look for output in apache error log //curl_setopt ($ch,CURLOPT_VERBOSE,1 ); // ensures any Location headers are followed if (ini_get('open_basedir') == '' && ini_get('safe_mode') == 'Off') { curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); } // Send the data out over the wire $responseData = curl_exec($ch); // See if we had a curl error - if so tell 'em and bail out // NOTE: curl_error does not return a logical value (see its documentation), but // a string, which is empty when there was no error. if (curl_errno($ch) > 0 || strlen(curl_error($ch)) > 0) { curl_close($ch); $errorNum = curl_errno($ch); $errorDesc = curl_error($ch); // Paranoia - in the unlikley event that 'curl' errno fails if ($errorNum == 0) { $errorNum = 9005; } // Paranoia - in the unlikley event that 'curl' error fails if (strlen($errorDesc) == 0) { $errorDesc = "Connection to payment gateway failed"; } if ($errorNum = 60) { return self::errorExit($errorNum, "Curl error - " . $errorDesc . " Try this link for more information http://curl.haxx.se/docs/sslcerts.html"); } return self::errorExit($errorNum, "Curl error - " . $errorDesc . " your key is located at " . $key . " the url is " . $host . " xml is " . $requestxml . " processor response = " . $processorResponse); } // If null data returned - tell 'em and bail out // NOTE: You will not necessarily get a string back, if the request failed for // any reason, the return value will be the boolean false. if ($responseData === FALSE || strlen($responseData) == 0) { curl_close($ch); return self::errorExit(9006, "Error: Connection to payment gateway failed - no data returned."); } // If gateway returned no data - tell 'em and bail out if (empty($responseData)) { curl_close($ch); return self::errorExit(9007, "Error: No data returned from payment gateway."); } // Success so far - close the curl and check the data curl_close($ch); // Payment successfully sent to gateway - process the response now $processorResponse = self::decodeXMLResponse($responseData); // success in test mode returns response "APPROVED" // test mode always returns trxn_id = 0 // fix for CRM-2566 if ($processorResponse['errorCode']) { return self::errorExit(9010, "Error: [" . $processorResponse['errorCode'] . " " . $processorResponse['errorName'] . " " . $processorResponse['errorMessage'] . "] - from payment processor"); } if ($processorResponse['ssl_result_message'] == "APPROVED") { if ($this->_mode == 'test') { $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'test%'"; $p = array(); $trxn_id = strval(CRM_Core_Dao::singleValueQuery($query, $p)); $trxn_id = str_replace('test', '', $trxn_id); $trxn_id = intval($trxn_id) + 1; $params['trxn_id'] = sprintf('test%08d', $trxn_id); return $params; } else { return self::errorExit(9099, "Error: [approval code related to test transaction but mode was " . $this->_mode); } } // transaction failed, print the reason if ($processorResponse['ssl_result_message'] != "APPROVAL") { return self::errorExit(9009, "Error: [" . $processorResponse['ssl_result_message'] . " " . $processorResponse['ssl_result'] . "] - from payment processor"); } else { // Success ! if ($this->_mode != 'test') { // 'trxn_id' is varchar(255) field. returned value is length 37 $params['trxn_id'] = $processorResponse['ssl_txn_id']; } $params['trxn_result_code'] = $processorResponse['ssl_approval_code'] . "-Cvv2:" . $processorResponse['ssl_cvv2_response'] . "-avs:" . $processorResponse['ssl_avs_response']; return $params; } }
/** * Submit a payment using Advanced Integration Method. * * @param array $params * Assoc array of input parameters for this transaction. * * @return array * the result in a nice formatted array (or an error object) */ public function doDirectPayment(&$params) { // Invoke hook_civicrm_paymentProcessor // In Dummy's case, there is no translation of parameters into // the back-end's canonical set of parameters. But if a processor // does this, it needs to invoke this hook after it has done translation, // but before it actually starts talking to its proprietary back-end. // no translation in Dummy processor $cookedParams = $params; CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $cookedParams); //end of hook invocation if (!empty($this->_doDirectPaymentResult)) { $result = $this->_doDirectPaymentResult; $result['trxn_id'] = array_shift($this->_doDirectPaymentResult['trxn_id']); return $result; } if ($this->_mode == 'test') { $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'test\\_%'"; $p = array(); $trxn_id = strval(CRM_Core_Dao::singleValueQuery($query, $p)); $trxn_id = str_replace('test_', '', $trxn_id); $trxn_id = intval($trxn_id) + 1; $params['trxn_id'] = sprintf('test_%08d', $trxn_id); } else { $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'live_%'"; $p = array(); $trxn_id = strval(CRM_Core_Dao::singleValueQuery($query, $p)); $trxn_id = str_replace('live_', '', $trxn_id); $trxn_id = intval($trxn_id) + 1; $params['trxn_id'] = sprintf('live_%08d', $trxn_id); } $params['gross_amount'] = $params['amount']; // Add a fee_amount so we can make sure fees are handled properly in underlying classes. $params['fee_amount'] = 1.5; $params['net_amount'] = $params['gross_amount'] - $params['fee_amount']; return $params; }
/** * Lookup the admin page at which a field's option list can be edited * @param $fieldSpec * @return string|null */ static function getOptionEditUrl($fieldSpec) { // If it's an option group, that's easy if (!empty($fieldSpec['pseudoconstant']['optionGroupName'])) { return 'civicrm/admin/options/' . $fieldSpec['pseudoconstant']['optionGroupName']; } elseif (!empty($fieldSpec['pseudoconstant']['table'])) { $daoName = CRM_Core_DAO_AllCoreTables::getClassForTable($fieldSpec['pseudoconstant']['table']); if (!$daoName) { return NULL; } // We don't have good mapping so have to do a bit of guesswork from the menu list(, $parent, , $child) = explode('_', $daoName); $sql = "SELECT path FROM civicrm_menu\n WHERE page_callback LIKE '%CRM_Admin_Page_{$child}%' OR page_callback LIKE '%CRM_{$parent}_Page_{$child}%'\n ORDER BY page_callback\n LIMIT 1"; return CRM_Core_Dao::singleValueQuery($sql); } return NULL; }
/** * Submit a payment using Advanced Integration Method. * * @param array $params * Assoc array of input parameters for this transaction. * * @return array * the result in a nice formatted array (or an error object) */ public function doDirectPayment(&$params) { // Invoke hook_civicrm_paymentProcessor // In Dummy's case, there is no translation of parameters into // the back-end's canonical set of parameters. But if a processor // does this, it needs to invoke this hook after it has done translation, // but before it actually starts talking to its proprietary back-end. // no translation in Dummy processor $cookedParams = $params; CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $cookedParams); // This means we can test failing transactions by setting a past year in expiry. A full expiry check would // be more complete. if (!empty($params['credit_card_exp_date']['Y']) && date('Y') > CRM_Core_Payment_Form::getCreditCardExpirationYear($params)) { $error = new CRM_Core_Error(ts('transaction failed')); return $error; } //end of hook invocation if (!empty($this->_doDirectPaymentResult)) { $result = $this->_doDirectPaymentResult; $result['trxn_id'] = array_shift($this->_doDirectPaymentResult['trxn_id']); return $result; } if ($this->_mode == 'test') { $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'test\\_%'"; $p = array(); $trxn_id = strval(CRM_Core_Dao::singleValueQuery($query, $p)); $trxn_id = str_replace('test_', '', $trxn_id); $trxn_id = intval($trxn_id) + 1; $params['trxn_id'] = 'test_' . $trxn_id . '_' . uniqid(); } else { $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'live_%'"; $p = array(); $trxn_id = strval(CRM_Core_Dao::singleValueQuery($query, $p)); $trxn_id = str_replace('live_', '', $trxn_id); $trxn_id = intval($trxn_id) + 1; $params['trxn_id'] = 'live_' . $trxn_id . '_' . uniqid(); } $params['gross_amount'] = $params['amount']; // Add a fee_amount so we can make sure fees are handled properly in underlying classes. $params['fee_amount'] = 1.5; $params['net_amount'] = $params['gross_amount'] - $params['fee_amount']; return $params; }
/** * Submit a payment using Advanced Integration Method * * @param array $params assoc array of input parameters for this transaction * * @return array the result in a nice formatted array (or an error object) * @public */ function doDirectPayment(&$params) { if (!defined('CURLOPT_SSLCERT')) { return self::error(9001, 'Authorize.Net requires curl with SSL support'); } /* * recurpayment function does not compile an array & then proces it - * - the tpl does the transformation so adding call to hook here * & giving it a change to act on the params array */ $newParams = $params; if (CRM_Utils_Array::value('is_recur', $params) && $params['contributionRecurID']) { CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $newParams); } foreach ($newParams as $field => $value) { $this->_setParam($field, $value); } if (CRM_Utils_Array::value('is_recur', $params) && $params['contributionRecurID']) { $result = $this->doRecurPayment(); if (is_a($result, 'CRM_Core_Error')) { return $result; } return $params; } $postFields = array(); $authorizeNetFields = $this->_getAuthorizeNetFields(); // Set up our call for hook_civicrm_paymentProcessor, // since we now have our parameters as assigned for the AIM back end. CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $authorizeNetFields); foreach ($authorizeNetFields as $field => $value) { // CRM-7419, since double quote is used as enclosure while doing csv parsing $value = $field == 'x_description' ? str_replace('"', "'", $value) : $value; $postFields[] = $field . '=' . urlencode($value); } // Authorize.Net will not refuse duplicates, so we should check if the user already submitted this transaction if ($this->_checkDupe($authorizeNetFields['x_invoice_num'])) { return self::error(9004, 'It appears that this transaction is a duplicate. Have you already submitted the form once? If so there may have been a connection problem. Check your email for a receipt from Authorize.net. If you do not receive a receipt within 2 hours you can try your transaction again. If you continue to have problems please contact the site administrator.'); } $submit = curl_init($this->_paymentProcessor['url_site']); if (!$submit) { return self::error(9002, 'Could not initiate connection to payment gateway'); } curl_setopt($submit, CURLOPT_POST, TRUE); curl_setopt($submit, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($submit, CURLOPT_POSTFIELDS, implode('&', $postFields)); curl_setopt($submit, CURLOPT_SSL_VERIFYPEER, CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'verifySSL')); $response = curl_exec($submit); if (!$response) { return self::error(curl_errno($submit), curl_error($submit)); } curl_close($submit); $response_fields = $this->explode_csv($response); // check gateway MD5 response if (!$this->checkMD5($response_fields[37], $response_fields[6], $response_fields[9])) { return self::error(9003, 'MD5 Verification failed'); } // check for application errors // TODO: // AVS, CVV2, CAVV, and other verification results if ($response_fields[0] != self::AUTH_APPROVED) { $errormsg = $response_fields[2] . ' ' . $response_fields[3]; return self::error($response_fields[1], $errormsg); } // Success // test mode always returns trxn_id = 0 // also live mode in CiviCRM with test mode set in // Authorize.Net return $response_fields[6] = 0 // hence treat that also as test mode transaction // fix for CRM-2566 if ($this->_mode == 'test' || $response_fields[6] == 0) { $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'test%'"; $p = array(); $trxn_id = strval(CRM_Core_Dao::singleValueQuery($query, $p)); $trxn_id = str_replace('test', '', $trxn_id); $trxn_id = intval($trxn_id) + 1; $params['trxn_id'] = sprintf('test%08d', $trxn_id); } else { $params['trxn_id'] = $response_fields[6]; } $params['gross_amount'] = $response_fields[9]; // TODO: include authorization code? return $params; }
static function hasPermission($pcpId = NULL, $contactId = NULL, $action = CRM_Core_Permission::EDIT, $teamPcpId = NULL) { if (empty($pcpId)) { if ($contactId) { if ($action == CRM_Core_Permission::VIEW) { // since get api is open now, we allow viewing member details return TRUE; } else { return $contactId == CRM_Pcpteams_Utils::getloggedInUserId() ? true : CRM_Contact_BAO_Contact_Permission::allow($contactId, $action); } } return FALSE; } $pcpOwnerContactId = CRM_Core_DAO::getFieldValue('CRM_PCP_DAO_PCP', $pcpId, 'contact_id'); $hasPermission = FALSE; if (empty($contactId)) { $contactId = CRM_Pcpteams_Utils::getloggedInUserId(); } // Check the pcp page which he is looking is the owner of pcp, then allow 'edit' permission if ($pcpOwnerContactId == $contactId) { return TRUE; } else { if ($action == CRM_Core_Permission::VIEW) { // Since PCP get api is opened, as long as pcpId is available then allow view permission if ($pcpId) { return TRUE; } //CASE 1: IF logged in user is trying to view team member's pcp page //CASE 1A: get all team pcps for logged in user $getUserTeamQuery = "\n SELECT cps.team_pcp_id FROM civicrm_value_pcp_custom_set cps \n INNER JOIN civicrm_pcp cp ON (cp.id = cps.entity_id)\n WHERE cp.contact_id = %1 AND cps.team_pcp_id IS NOT NULL\n "; $getUserTeamPcpDAO = CRM_Core_DAO::executeQuery($getUserTeamQuery, array(1 => array($contactId, 'Integer'))); $userTeamPcps = array(); while ($getUserTeamPcpDAO->fetch()) { //CASE 2: IF logged in user is admin OR member of pcp being viewed if ($getUserTeamPcpDAO->team_pcp_id == $pcpId) { return TRUE; } $userTeamPcps[] = $getUserTeamPcpDAO->team_pcp_id; } //CASE 1B: IF pcp being viewed is related to team-pcp via custom teamp-pcp-id OR under approval relationship if (!empty($userTeamPcps)) { $userTeamPcpIds = implode(', ', $userTeamPcps); $memberQuery = "\n SELECT cp.id\n FROM civicrm_pcp cp\n LEFT JOIN civicrm_value_pcp_custom_set cpcs ON (cp.id = cpcs.entity_id)\n LEFT JOIN civicrm_value_pcp_relationship_set crcs ON (cp.id = crcs.pcp_a_b)\n WHERE (cpcs.entity_id = %1 AND cpcs.team_pcp_id IN ({$userTeamPcpIds})) OR ( crcs.pcp_a_b = %1 AND crcs.pcp_b_a IN ({$userTeamPcpIds}))\n "; $memberPcp = CRM_Core_DAO::singleValueQuery($memberQuery, array(1 => array($pcpId, 'Integer'))); if ($memberPcp) { return TRUE; } } //CASE 3: IF pcp being viewed has been requested to be joined by logged in user (under approval) $relQuery = "\n SELECT cr.id \n FROM civicrm_relationship cr\n INNER JOIN civicrm_value_pcp_relationship_set crcs ON (cr.id = crcs.entity_id) \n WHERE cr.contact_id_a = %1 AND cr.contact_id_b = %2 AND cr.relationship_type_id = %3 AND crcs.pcp_b_a = %4\n "; $relTypeId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', CRM_Pcpteams_Constant::C_TEAM_RELATIONSHIP_TYPE, 'id', 'name_a_b'); $relQueryParams = array(1 => array($contactId, 'Integer'), 2 => array($pcpOwnerContactId, 'Integer'), 3 => array($relTypeId, 'Integer'), 4 => array($pcpId, 'Integer')); if (CRM_Core_DAO::singleValueQuery($relQuery, $relQueryParams)) { return TRUE; } //CASE 4: if admin is trying to view the pcp if (CRM_Contact_BAO_Contact_Permission::allow($pcpOwnerContactId, CRM_Core_Permission::VIEW)) { return TRUE; } } else { if ($action == CRM_Pcpteams_Constant::C_PERMISSION_MEMBER) { if ($pcpId && $teamPcpId) { //check pcp custom set $queryParams = array(1 => array($pcpId, 'Integer'), 2 => array($teamPcpId, 'Integer')); $query = "\n SELECT id FROM civicrm_value_pcp_custom_set \n WHERE entity_id = %1 AND team_pcp_id = %2\n "; $teamMemberExists = CRM_Core_Dao::singleValueQuery($query, $queryParams); if ($teamMemberExists) { return TRUE; } //check pcp relationship custom set $query = "\n SELECT id FROM civicrm_value_pcp_relationship_set\n WHERE pcp_a_b = %1 AND pcp_b_a = %2\n "; $teamMemberExists = CRM_Core_Dao::singleValueQuery($query, $queryParams); if ($teamMemberExists) { return TRUE; } } else { if ($pcpId && $contactId) { $query = "\n SELECT cs.id FROM civicrm_value_pcp_custom_set cs\n INNER JOIN civicrm_pcp cp ON cp.id = cs.entity_id \n INNER JOIN civicrm_contact cc ON cc.id = cp.contact_id\n WHERE cs.team_pcp_id = %1 AND cc.id = %2\n "; $queryParams = array(1 => array($pcpId, 'Integer'), 2 => array($contactId, 'Integer')); $teamMemberExists = CRM_Core_Dao::executeQuery($query, $queryParams); if ($teamMemberExists->fetch()) { return TRUE; } } } return FALSE; } else { if ($action == CRM_Pcpteams_Constant::C_PERMISSION_TEAM_ADMIN) { if ($pcpId && $contactId) { $query = "\n SELECT cs.id FROM civicrm_value_pcp_custom_set cs\n INNER JOIN civicrm_pcp mp ON mp.id = cs.entity_id\n INNER JOIN civicrm_pcp tp ON tp.id = cs.team_pcp_id\n INNER JOIN civicrm_contact tc ON tc.id = tp.contact_id\n INNER JOIN civicrm_relationship cr ON cr.contact_id_b = tc.id\n INNER JOIN civicrm_relationship_type crt on crt.id = cr.relationship_type_id\n WHERE cs.entity_id = %1 AND cr.contact_id_a = %2 AND crt.name_a_b = %3"; $queryParams = array(1 => array($pcpId, 'Integer'), 2 => array($contactId, 'Integer'), 3 => array(CRM_Pcpteams_Constant::C_TEAM_ADMIN_REL_TYPE, 'String')); if (CRM_Core_DAO::singleValueQuery($query, $queryParams)) { return TRUE; } if (CRM_Contact_BAO_Contact_Permission::allow($contactId, CRM_Core_Permission::EDIT)) { return TRUE; } } } else { if ($action == CRM_Core_Permission::EDIT) { // A. if logged in user ($contactId) is owner of pcp ($pcpId) it should have returned true in the beginning. // B. at this point we checking if logged in user ($contactId) is admin for team-contact ($pcpOwnerContactId) of pcp ($pcpId) $query = "\n SELECT cr.id FROM civicrm_relationship cr\n INNER JOIN civicrm_relationship_type crt ON (crt.id = cr.relationship_type_id)\n WHERE cr.contact_id_a = %1 AND cr.contact_id_b = %2 AND cr.is_active = %3 AND crt.name_a_b = %4"; $queryParams = array(1 => array($contactId, 'Integer'), 2 => array($pcpOwnerContactId, 'Integer'), 3 => array(1, 'Integer'), 4 => array(CRM_Pcpteams_Constant::C_TEAM_ADMIN_REL_TYPE, 'String')); if (CRM_Core_DAO::singleValueQuery($query, $queryParams)) { return TRUE; } if (CRM_Contact_BAO_Contact_Permission::allow($pcpOwnerContactId, CRM_Core_Permission::EDIT)) { return TRUE; } } } } } } return FALSE; }