$balanceTrxnParams['status_id'] = $statusId;
$balanceTrxnParams['payment_instrument_id'] = $params['contribution']->payment_instrument_id;
$balanceTrxnParams['check_number'] = CRM_Utils_Array::value('check_number', $params);
+ $balanceTrxnParams['pan_truncation'] = CRM_Utils_Array::value('pan_truncation', $params);
+ $balanceTrxnParams['card_type_id'] = CRM_Utils_Array::value('card_type_id', $params);
if (!empty($balanceTrxnParams['from_financial_account_id']) &&
($statusId == array_search('Completed', $contributionStatuses) || $statusId == array_search('Partially paid', $contributionStatuses))
) {
'status_id' => $statusId,
'payment_instrument_id' => CRM_Utils_Array::value('payment_instrument_id', $params, $params['contribution']->payment_instrument_id),
'check_number' => CRM_Utils_Array::value('check_number', $params),
+ 'pan_truncation' => CRM_Utils_Array::value('pan_truncation', $params),
+ 'card_type_id' => CRM_Utils_Array::value('card_type_id', $params),
);
if ($contributionStatus == 'Refunded' || $contributionStatus == 'Chargeback' || $contributionStatus == 'Cancelled') {
$trxnParams['trxn_date'] = !empty($params['contribution']->cancel_date) ? $params['contribution']->cancel_date : date('YmdHis');
return;
}
}
+
$trxn = CRM_Core_BAO_FinancialTrxn::create($params['trxnParams']);
$params['entity_id'] = $trxn->id;
if ($context != 'changePaymentInstrument') {
'receive_date',
'receipt_date',
'contribution_status_id',
+ 'card_type_id',
+ 'pan_truncation',
);
if (self::isSingleLineItem($primaryContributionID)) {
$inputContributionWhiteList[] = 'financial_type_id';
CRM_Core_Resources::singleton()->addVars('coreForm', array('contact_id' => (int) $this->_contactID));
$this->_action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, 'add');
$this->_mode = empty($this->_mode) ? CRM_Utils_Request::retrieve('mode', 'String', $this) : $this->_mode;
+ $this->assign('isBackOffice', $this->isBackOffice);
$this->assignPaymentRelatedVariables();
}
$this->assign('credit_card_type', CRM_Utils_Array::value('credit_card_type', $this->_params));
}
$this->_params['ip_address'] = CRM_Utils_System::ipAddress();
- if (in_array('credit_card_type', array_keys($this->_params))) {
- $this->_params['card_type_id'] = CRM_Core_PseudoConstant::getKey('CRM_Core_BAO_FinancialTrxn', 'card_type_id', $this->_params['credit_card_type']);
- }
- if (!empty($this->_params['credit_card_number']) && empty($this->_params['pan_truncation'])) {
- $this->_params['pan_truncation'] = substr($this->_params['credit_card_number'], -4);
- }
+ self::formatCreditCardDetails($this->_params);
}
+ /**
+ * Format credit card details like:
+ * 1. Retrieve last 4 digit from credit card number as pan_truncation
+ * 2. Retrieve credit card type id from name
+ *
+ * @param array $params
+ *
+ * @return void
+ */
+ public static function formatCreditCardDetails(&$params) {
+ if (in_array('credit_card_type', array_keys($params))) {
+ $params['card_type_id'] = CRM_Core_PseudoConstant::getKey('CRM_Core_BAO_FinancialTrxn', 'card_type_id', $params['credit_card_type']);
+ }
+ if (!empty($params['credit_card_number']) && empty($params['pan_truncation'])) {
+ $params['pan_truncation'] = substr($params['credit_card_number'], -4);
+ }
+ }
/**
* Add the billing address to the contact who paid.
'payment_processor_id' => $this->_paymentProcessor['id'],
'is_transactional' => FALSE,
'fee_amount' => CRM_Utils_Array::value('fee_amount', $result),
+ 'card_type_id' => CRM_Utils_Array::value('card_type_id', $paymentParams),
+ 'pan_truncation' => CRM_Utils_Array::value('pan_truncation', $paymentParams),
));
// This has now been set to 1 in the DB - declare it here also
$contribution->contribution_status_id = 1;
* @throws \Exception
*/
protected function submit($submittedValues, $action, $pledgePaymentID) {
-
$pId = $contribution = $isRelatedId = FALSE;
$this->_params = $submittedValues;
$this->beginPostProcess();
+ // reassign submitted form values if the any information is formatted via beginPostProcess
+ $submittedValues = $this->_params;
if (!empty($submittedValues['price_set_id']) && $action & CRM_Core_Action::UPDATE) {
$line = CRM_Price_BAO_LineItem::getLineItems($this->_id, 'contribution');
'cancel_reason',
'source',
'check_number',
+ 'card_type_id',
+ 'pan_truncation',
);
foreach ($fields as $f) {
$params[$f] = CRM_Utils_Array::value($f, $formValues);
// fix currency ID
$this->_params['currencyID'] = CRM_Core_Config::singleton()->defaultCurrency;
+ CRM_Contribute_Form_AbstractEditPayment::formatCreditCardDetails($this->_params);
+
// CRM-18854
if (CRM_Utils_Array::value('is_pledge', $this->_params) && !CRM_Utils_Array::value('pledge_id', $this->_values) && CRM_Utils_Array::value('adjust_recur_start_date', $this->_values)) {
$pledgeBlock = CRM_Pledge_BAO_PledgeBlock::getPledgeBlock($this->_id);
if (CRM_Utils_Array::value('payment_status_id', $result) == 1) {
try {
civicrm_api3('contribution', 'completetransaction', array(
- 'id' => $contributionID,
- 'trxn_id' => CRM_Utils_Array::value('trxn_id', $result),
- 'payment_processor_id' => $this->_paymentProcessor['id'],
- 'is_transactional' => FALSE,
- 'fee_amount' => CRM_Utils_Array::value('fee_amount', $result),
- 'receive_date' => CRM_Utils_Array::value('receive_date', $result),
- )
- );
+ 'id' => $contributionID,
+ 'trxn_id' => CRM_Utils_Array::value('trxn_id', $result),
+ 'payment_processor_id' => $this->_paymentProcessor['id'],
+ 'is_transactional' => FALSE,
+ 'fee_amount' => CRM_Utils_Array::value('fee_amount', $result),
+ 'receive_date' => CRM_Utils_Array::value('receive_date', $result),
+ 'card_type_id' => CRM_Utils_Array::value('card_type_id', $result),
+ 'pan_truncation' => CRM_Utils_Array::value('pan_truncation', $result),
+ ));
}
catch (CiviCRM_API3_Exception $e) {
if ($e->getErrorCode() != 'contribution_completed') {
BILLING_MODE_BUTTON = 2,
BILLING_MODE_NOTIFY = 4;
+ /**
+ * Which payment type(s) are we using?
+ *
+ * credit card
+ * direct debit
+ * or both
+ * @todo create option group - nb omnipay uses a 3rd type - transparent redirect cc
+ */
+ const
+ PAYMENT_TYPE_CREDIT_CARD = 1,
+ PAYMENT_TYPE_DIRECT_DEBIT = 2;
+
/**
* Subscription / Recurring payment Status
* START, END
'maxlength' => 4,
'autocomplete' => 'off',
),
+ 'rules' => array(
+ array(
+ 'rule_message' => ts('Please enter valid last 4 digit card number.'),
+ 'rule_name' => 'numeric',
+ 'rule_parameters' => NULL,
+ ),
+ ),
),
);
}
$processor['object']->setBackOffice($isBackOffice);
$processor['object']->setPaymentInstrumentID($paymentInstrumentID);
$paymentTypeName = self::getPaymentTypeName($processor);
- $paymentTypeLabel = self::getPaymentTypeLabel($processor);
$form->assign('paymentTypeName', $paymentTypeName);
+ $paymentTypeLabel = self::getPaymentTypeLabel($processor);
$form->assign('paymentTypeLabel', $paymentTypeLabel);
$form->assign('isBackOffice', $isBackOffice);
$form->_paymentFields = $form->billingFieldSets[$paymentTypeName]['fields'] = self::getPaymentFieldMetadata($processor);
// However there is an ambiguity as that field is an integer & should hence be called
// credit_card_type_id, or it should store 'visa' It probably makes sense to fix that before going much
// further as the code I've seen makes it clear that it will require work arounds.
- return array('pan_truncation');
+ return array('credit_card_type', 'pan_truncation');
}
elseif ($paymentInstrument === 'Check') {
// Really we should render check_number here, but we need to review how we edit
*/
protected $_paymentProcessorID;
protected $currency;
+
public $_values = array();
/**
'tax_amount',
'skipLineItem',
'contribution_recur_id',
+ 'pan_truncation',
+ 'card_type_id',
);
foreach ($recordContribution as $f) {
$contributionParams[$f] = CRM_Utils_Array::value($f, $params);
'check_number',
'campaign_id',
'receive_date',
+ 'card_type_id',
+ 'pan_truncation',
);
foreach ($recordContribution as $f) {
'type' => CRM_Utils_Type::T_STRING,
'description' => 'Transaction ID specific to the refund taking place',
);
+ $params['card_type_id'] = array(
+ 'title' => 'Card Type ID',
+ 'description' => 'Providing Credit Card Type ID',
+ 'type' => CRM_Utils_Type::T_INT,
+ 'pseudoconstant' => array(
+ 'optionGroupName' => 'accept_creditcard',
+ ),
+ );
}
/**
* @throws \Exception
*/
function civicrm_api3_contribution_completetransaction(&$params) {
-
$input = $ids = array();
if (isset($params['payment_processor_id'])) {
$input['payment_processor_id'] = $params['payment_processor_id'];
'description' => 'Date this transaction occurred',
'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
);
+ $params['card_type_id'] = array(
+ 'title' => 'Card Type ID',
+ 'description' => 'Providing Credit Card Type ID',
+ 'type' => CRM_Utils_Type::T_INT,
+ 'pseudoconstant' => array(
+ 'optionGroupName' => 'accept_creditcard',
+ ),
+ );
}
/**
$input['receipt_from_name'] = CRM_Utils_Array::value('receipt_from_name', $params, $domainFromName);
$input['receipt_from_email'] = CRM_Utils_Array::value('receipt_from_email', $params, $domainFromEmail);
}
+ $input['card_type_id'] = CRM_Utils_Array::value('card_type_id', $params);
+ $input['pan_truncation'] = CRM_Utils_Array::value('pan_truncation', $params);
$transaction = new CRM_Core_Transaction();
return CRM_Contribute_BAO_Contribution::completeOrder($input, $ids, $objects, $transaction, !empty
($contribution->contribution_recur_id), $contribution,
</table>
{if !$contributionMode}
+ <fieldset class="payment-details_group">
+ <legend>
+ {ts}Payment Details{/ts}
+ </legend>
<table class="form-layout-compressed" >
<tr class="crm-contribution-form-block-receive_date">
<td class="label">{$form.receive_date.label}</td>
<td>{$form.from_email_address.html}</td>
</tr>
</table>
+ </fieldset>
{/if}
{include file='CRM/Core/BillingBlockWrapper.tpl'}
{* Payment processors sometimes need to append something to the end of the billing block. We create a region for
clarity - the plan is to move to assigning this through the payment processor to this region *}
{/crmRegion}
-
field_type ="radio"
invert = 0
}
- {include file="CRM/common/showHideByFieldValue.tpl"
- trigger_field_id ="payment_instrument_id"
- trigger_value = '4'
- target_element_id ="checkNumber"
- target_element_type ="table-row"
- field_type ="select"
- invert = 0
- }
{/if}
{literal}
</table>
</td>
</tr>
- <tr class="crm-membership-form-block-billing">
- <td colspan="2">
- {include file='CRM/Core/BillingBlockWrapper.tpl'}
- </td>
- </tr>
<div class="spacer"></div>
{/if}
+
+<tr class="crm-membership-form-block-billing">
+ <td colspan="2">
+ {include file='CRM/Core/BillingBlockWrapper.tpl'}
+ </td>
+</tr>
$this->callAPISuccessGetCount('FinancialItem', array(), 2);
}
+ /**
+ * function to test card_type and pan truncation.
+ */
+ public function testCardTypeAndPanTruncation() {
+ $form = new CRM_Contribute_Form_Contribution();
+ $form->testSubmit(
+ array(
+ 'total_amount' => 100,
+ 'financial_type_id' => 3,
+ 'receive_date' => '04/21/2015',
+ 'receive_date_time' => '11:27PM',
+ 'contact_id' => $this->_individualId,
+ 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments),
+ 'contribution_status_id' => 1,
+ 'credit_card_type' => 'Visa',
+ 'pan_truncation' => 4567,
+ 'price_set_id' => 0,
+ ),
+ CRM_Core_Action::ADD
+ );
+ $contribution = $this->callAPISuccessGetSingle('Contribution',
+ array(
+ 'contact_id' => $this->_individualId,
+ 'return' => array('id'),
+ )
+ );
+ $lastFinancialTrxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contribution['id'], 'DESC');
+ $financialTrxn = $this->callAPISuccessGetSingle(
+ 'FinancialTrxn',
+ array(
+ 'id' => $lastFinancialTrxnId['financialTrxnId'],
+ 'return' => array('card_type_id.label', 'pan_truncation'),
+ )
+ );
+ $this->assertEquals(CRM_Utils_Array::value('card_type_id.label', $financialTrxn), 'Visa');
+ $this->assertEquals(CRM_Utils_Array::value('pan_truncation', $financialTrxn), 4567);
+ }
+
+ /**
+ * function to test card_type and pan truncation.
+ */
+ public function testCardTypeAndPanTruncationLiveMode() {
+ $visaID = CRM_Core_PseudoConstant::getKey('CRM_Core_BAO_FinancialTrxn', 'card_type_id', 'Visa');
+ $form = new CRM_Contribute_Form_Contribution();
+ $form->_mode = 'Live';
+ $error = FALSE;
+ $form->testSubmit(
+ array(
+ 'total_amount' => 50,
+ 'financial_type_id' => 1,
+ 'receive_date' => '04/21/2015',
+ 'receive_date_time' => '11:27PM',
+ 'contact_id' => $this->_individualId,
+ 'credit_card_number' => 4444333322221111,
+ 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments),
+ 'cvv2' => 123,
+ 'credit_card_exp_date' => array(
+ 'M' => 9,
+ 'Y' => date('Y', strtotime('+5 years')),
+ ),
+ 'credit_card_type' => 'Visa',
+ 'billing_first_name' => 'Junko',
+ 'billing_middle_name' => '',
+ 'billing_last_name' => 'Adams',
+ 'billing_street_address-5' => '790L Lincoln St S',
+ 'billing_city-5' => 'Maryknoll',
+ 'billing_state_province_id-5' => 1031,
+ 'billing_postal_code-5' => 10545,
+ 'billing_country_id-5' => 1228,
+ 'frequency_interval' => 1,
+ 'frequency_unit' => 'month',
+ 'installments' => '',
+ 'hidden_AdditionalDetail' => 1,
+ 'hidden_Premium' => 1,
+ 'from_email_address' => '"civi45" <civi45@civicrm.com>',
+ 'receipt_date' => '',
+ 'receipt_date_time' => '',
+ 'payment_processor_id' => $this->paymentProcessorID,
+ 'currency' => 'USD',
+ 'source' => 'bob sled race',
+ ),
+ CRM_Core_Action::ADD
+ );
+ $contribution = $this->callAPISuccessGetSingle('Contribution', array('contact_id' => $this->_individualId));
+ $lastFinancialTrxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contribution['id'], 'DESC');
+ $financialTrxn = $this->callAPISuccessGetSingle(
+ 'FinancialTrxn',
+ array(
+ 'id' => $lastFinancialTrxnId['financialTrxnId'],
+ 'return' => array('card_type_id', 'pan_truncation'),
+ )
+ );
+ // @todo in test environment FinancialTrxn.getsingle doesn't fetch card_type_id value
+ //$this->assertEquals(CRM_Utils_Array::value('card_type_id', $financialTrxn), $visaID);
+ $this->assertEquals(CRM_Utils_Array::value('pan_truncation', $financialTrxn), 1111);
+ }
+
}