/** * Sets payment information and saves to database (unless dontSaveToDatabase option is set) * * @param array $ps_payment_info * @param array $pa_options Options array: * dontSaveToDatabase = * dontChargeCreditCard = */ public function setPaymentInfo($pa_payment_info, $pa_options = null) { $o_config = caGetClientServicesConfiguration(); $vs_currency = $o_config->get('currency'); $va_payment_info = array('order_id' => $this->getPrimaryKey(), 'created_on' => (int) $this->get('created_on', array('GET_DIRECT_DATE' => true))); $vb_dont_save_to_database = isset($pa_options['dontSaveToDatabase']) && $pa_options['dontSaveToDatabase'] ? true : false; $vb_dont_charge_credit_card = isset($pa_options['dontChargeCreditCard']) && $pa_options['dontChargeCreditCard'] ? true : false; $this->clearErrors(); switch ($vs_payment_method = $this->get('payment_method')) { case 'CREDIT': foreach (array('credit_card_type', 'credit_card_number', 'credit_card_ccv', 'credit_card_exp_mon', 'credit_card_exp_yr') as $vs_fld) { $vs_val = isset($pa_payment_info[$vs_fld]) ? $pa_payment_info[$vs_fld] : null; switch ($vs_fld) { case 'credit_card_type': $va_cc_types = $o_config->getAssoc('credit_card_types'); if (!is_array($va_cc_types)) { $va_cc_types = array(); } if (array_search($vs_val, $va_cc_types) === false) { $this->postError(1101, _t('Credit card type is invalid'), 'ca_commerce_orders->setPaymentInfo()'); } break; case 'credit_card_ccv': switch ($pa_payment_info['credit_card_type']) { case 'AMEX': if (strlen($vs_val) != 4) { $this->postError(1101, _t('Credit card CCV is invalid'), 'ca_commerce_orders->setPaymentInfo()'); } break; default: if (strlen($vs_val) != 3) { $this->postError(1101, _t('Credit card CCV is invalid'), 'ca_commerce_orders->setPaymentInfo()'); } break; } break; case 'credit_card_number': $vs_val = preg_replace('![^\\d]+!', '', $vs_val); if (!caValidateCreditCardNumber($vs_val)) { $this->postError(1101, _t('Credit card number is invalid'), 'ca_commerce_orders->setPaymentInfo()'); } break; case 'credit_card_exp_mon': if ((int) $vs_val < 1 || (int) $vs_val > 12) { $this->postError(1101, _t('Credit card month is invalid'), 'ca_commerce_orders->setPaymentInfo()'); } break; case 'credit_card_exp_yr': $vn_current_year = (int) date("Y"); $vn_current_month = (int) date("m"); if ((int) $vs_val < $vn_current_year || (int) $vs_val == $vn_current_year && $pa_payment_info['credit_card_exp_mon'] < $vn_current_month) { $this->postError(1101, _t('Credit card is expired'), 'ca_commerce_orders->setPaymentInfo()'); } if ((int) $vs_val > $vn_current_year + 12) { $this->postError(1101, _t('Credit card year is invalid'), 'ca_commerce_orders->setPaymentInfo()'); } break; } $va_payment_info[$vs_fld] = $vs_val; } break; case 'CHECK': foreach (array('check_payee', 'check_bank', 'check_date', 'check_number') as $vs_fld) { $vs_val = isset($pa_payment_info[$vs_fld]) ? $pa_payment_info[$vs_fld] : null; if ($this->get('payment_received_on')) { switch ($vs_fld) { case 'check_payee': if (!strlen($vs_val)) { $this->postError(1101, _t('Payee name must be set'), 'ca_commerce_orders->setPaymentInfo()'); } break; case 'check_bank': if (!strlen($vs_val)) { $this->postError(1101, _t('Bank name must be set'), 'ca_commerce_orders->setPaymentInfo()'); } break; case 'check_date': if (!caDateToUnixTimestamp($vs_val)) { $this->postError(1101, _t('Check date is invalid'), 'ca_commerce_orders->setPaymentInfo()'); } break; case 'check_number': if (!strlen($vs_val)) { $this->postError(1101, _t('Check number must be set'), 'ca_commerce_orders->setPaymentInfo()'); } break; } } $va_payment_info[$vs_fld] = $vs_val; } break; case 'PO': foreach (array('purchase_order_date', 'purchase_order_number') as $vs_fld) { $vs_val = isset($pa_payment_info[$vs_fld]) ? $pa_payment_info[$vs_fld] : null; if ($this->get('payment_received_on')) { switch ($vs_fld) { case 'purchase_order_date': if (!caDateToUnixTimestamp($vs_val)) { $this->postError(1101, _t('Purchase order date is invalid'), 'ca_commerce_orders->setPaymentInfo()'); } break; case 'purchase_order_number': if (!strlen($vs_val)) { $this->postError(1101, _t('Purchase order number must be set'), 'ca_commerce_orders->setPaymentInfo()'); } break; } } $va_payment_info[$vs_fld] = $vs_val; } break; case 'NONE': case 'CASH': default: // noop break; } if ($vb_ret = $this->numErrors() > 0 ? false : true) { if ($vs_payment_method === 'CREDIT' && !$vb_dont_charge_credit_card && !$this->get('payment_received_on')) { // if it's a credit card try to actually charge the card if (!($o_payment = Payment::getProcessor())) { return null; } // couldn't load processor if ($va_payment_response = $o_payment->DoPayment($this->getTotal(), $va_payment_info, $this->getBillingInfo(), array('currency' => $vs_currency, 'note' => $o_config->get('payment_note')))) { if ($va_payment_response['success'] === true) { $this->set('payment_status', 'RECEIVED'); $this->set('payment_response', $va_payment_response); $this->set('payment_received_on', date('c')); $this->sendEmailPaymentNotification(true, $o_payment->getGatewayName(), $va_payment_response); } else { $this->postError(1101, _t('Credit card charge failed: %1', $va_payment_response['error']), 'ca_commerce_orders->setPaymentInfo()'); $this->sendEmailPaymentNotification(false, $o_payment->getGatewayName(), $va_payment_response); return false; } } } if ($vs_payment_method === 'CREDIT') { // obscure credit card # and CCV $vs_len = strlen($va_payment_info['credit_card_number']); $va_payment_info['credit_card_number'] = 'xxxx-xxxxxxx-x' . substr($va_payment_info['credit_card_number'], $vs_len - 5, 5); //$va_payment_info['credit_card_ccv'] = str_repeat("x", strlen($va_payment_info['credit_card_ccv'])); } $this->set('payment_details', $va_payment_info); } else { // Errors in payment info return $vb_ret; } if (!$vb_dont_save_to_database) { $this->setMode(ACCESS_WRITE); $_REQUEST['form_timestamp'] = time(); // disable form collision checking since this update will trigger it return $this->update(); } return $vb_ret; }
/** * Checkout an object for a user. Will throw an exception if the item is currently out or object or user_id are invalid; * * @param int $pn_object_id * @param int $pn_user_id * @param string $ps_note Optional checkin notes * @param string $ps_due_date A valid date time expression for the date item is due to be returned. If omitted the default date as configured will be used. * @param array $pa_options * * @return bool True on success, false on failure */ public function checkout($pn_object_id, $pn_user_id, $ps_note = null, $ps_due_date = null, $pa_options = null) { global $g_ui_locale_id; $vb_we_set_transaction = false; if ($this->inTransaction()) { $o_trans = $this->getTransaction(); } else { $vb_we_set_transaction = true; $this->setTransaction($o_trans = new Transaction()); } $o_request = caGetOption('request', $pa_options, null); $t_object = new ca_objects($pn_object_id); $t_object->setTransaction($o_trans); if (!$t_object->getPrimaryKey()) { throw new Exception(_t('Object_id is not valid')); } if ($o_request && !$t_object->isReadable($o_request)) { throw new Exception(_t('Object_id is not accessible')); } $t_user = new ca_users($pn_user_id); if (!$t_user->getPrimaryKey()) { throw new Exception(_t('User_id is not valid')); } // is object available? if (!in_array($t_object->getCheckoutStatus(), array(__CA_OBJECTS_CHECKOUT_STATUS_AVAILABLE__, __CA_OBJECTS_CHECKOUT_STATUS_RESERVED__))) { throw new Exception(_t('Item is already out')); } // is there a reservation for this user? $o_db = $o_trans->getDb(); $qr_res = $o_db->query("\n\t\t\tSELECT *\n\t\t\tFROM ca_object_checkouts\n\t\t\tWHERE\n\t\t\t\tuser_id = ? AND object_id = ? AND checkout_date IS NULL AND return_date IS NULL\n\t\t\tORDER BY \n\t\t\t\tcreated_on\n\t\t", array($pn_user_id, $pn_object_id)); $vb_update = false; if ($qr_res->nextRow()) { $vs_uuid = $qr_res->get('group_uuid'); if ($this->load($qr_res->get('checkout_id'))) { $vb_update = true; } } else { $vs_uuid = $this->getTransactionUUID(); } $va_checkout_config = ca_object_checkouts::getObjectCheckoutConfigForType($t_object->getTypeCode()); if (!($va_checkout_config['allow_override_of_due_dates'] && $ps_due_date && caDateToUnixTimestamp($ps_due_date))) { // calculate default return date $ps_due_date = isset($va_checkout_config['default_checkout_date']) ? $va_checkout_config['default_checkout_date'] : null; } $this->setMode(ACCESS_WRITE); $this->set(array('group_uuid' => $vs_uuid, 'object_id' => $pn_object_id, 'user_id' => $pn_user_id, 'checkout_notes' => $ps_note, 'checkout_date' => _t('today'), 'due_date' => $ps_due_date)); // Do we need to set values? if (is_array($va_checkout_config['set_values']) && sizeof($va_checkout_config['set_values'])) { $t_object->setMode(ACCESS_WRITE); foreach ($va_checkout_config['set_values'] as $vs_attr => $va_attr_values_by_event) { if (!is_array($va_attr_values_by_event['checkout'])) { if ($t_object->hasField($vs_attr)) { // Intrinsic $t_object->set($vs_attr, $va_attr_values_by_event['checkout']); } } else { $va_attr_values['locale_id'] = $g_ui_locale_id; $t_object->replaceAttribute($va_attr_values_by_event['checkout'], $vs_attr); } $t_object->update(); if ($t_object->numErrors()) { $this->errors = $t_object->errors; if ($vb_we_set_transaction) { $o_trans->rollback(); } return false; } } } $vn_rc = $vb_update ? $this->update() : $this->insert(); if ($vb_we_set_transaction) { $vn_rc ? $o_trans->commit() : $o_trans->rollback(); } return $vn_rc; }