4 * Licensed to CiviCRM under the Academic Free License version 3.0.
6 * Written and contributed by Ideal Solution, LLC (http://www.idealso.com)
13 * @author Marshal Newrock <marshal@idealso.com>
16 use Civi\Payment\Exception\PaymentProcessorException
;
17 use Civi\Payment\PropertyBag
;
20 * Dummy payment processor
22 class CRM_Core_Payment_Dummy
extends CRM_Core_Payment
{
25 protected $_params = [];
26 protected $_doDirectPaymentResult = [];
29 * Set result from do Direct Payment for test purposes.
31 * @param array $doDirectPaymentResult
32 * Result to be returned from test.
34 public function setDoDirectPaymentResult($doDirectPaymentResult) {
35 $this->_doDirectPaymentResult
= $doDirectPaymentResult;
36 if (empty($this->_doDirectPaymentResult
['trxn_id'])) {
37 $this->_doDirectPaymentResult
['trxn_id'] = [];
40 $this->_doDirectPaymentResult
['trxn_id'] = (array) $doDirectPaymentResult['trxn_id'];
48 * The mode of operation: live or test.
50 * @param array $paymentProcessor
52 public function __construct($mode, &$paymentProcessor) {
54 $this->_paymentProcessor
= $paymentProcessor;
58 * Submit a payment using Advanced Integration Method.
60 * @param array $params
61 * Assoc array of input parameters for this transaction.
64 * the result in a nice formatted array (or an error object)
65 * @throws \Civi\Payment\Exception\PaymentProcessorException
67 public function doDirectPayment(&$params) {
68 $propertyBag = PropertyBag
::cast($params);
69 // Invoke hook_civicrm_paymentProcessor
70 // In Dummy's case, there is no translation of parameters into
71 // the back-end's canonical set of parameters. But if a processor
72 // does this, it needs to invoke this hook after it has done translation,
73 // but before it actually starts talking to its proprietary back-end.
74 if ($propertyBag->getIsRecur()) {
75 $throwAnENoticeIfNotSetAsTheseAreRequired = $propertyBag->getRecurFrequencyInterval() . $propertyBag->getRecurFrequencyUnit();
77 // no translation in Dummy processor
78 CRM_Utils_Hook
::alterPaymentProcessorParams($this,
82 // This means we can test failing transactions by setting a past year in expiry. A full expiry check would
84 if (!empty($params['credit_card_exp_date']['Y']) && date('Y') >
85 CRM_Core_Payment_Form
::getCreditCardExpirationYear($params)) {
86 throw new PaymentProcessorException(ts('Invalid expiry date'));
88 //end of hook invocation
89 if (!empty($this->_doDirectPaymentResult
)) {
90 $result = $this->_doDirectPaymentResult
;
91 if (CRM_Utils_Array
::value('payment_status_id', $result) === 'failed') {
92 throw new PaymentProcessorException($result['message'] ??
'failed');
94 $result['trxn_id'] = array_shift($this->_doDirectPaymentResult
['trxn_id']);
97 if ($this->_mode
=== 'test') {
98 $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'test\\_%'";
100 $trxn_id = (string) CRM_Core_DAO
::singleValueQuery($query, $p);
101 $trxn_id = str_replace('test_', '', $trxn_id);
102 $trxn_id = (int) $trxn_id +
1;
103 $params['trxn_id'] = 'test_' . $trxn_id . '_' . uniqid();
106 $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'live_%'";
108 $trxn_id = (string) CRM_Core_DAO
::singleValueQuery($query, $p);
109 $trxn_id = str_replace('live_', '', $trxn_id);
110 $trxn_id = (int) $trxn_id +
1;
111 $params['trxn_id'] = 'live_' . $trxn_id . '_' . uniqid();
113 $params['gross_amount'] = $propertyBag->getAmount();
114 // Add a fee_amount so we can make sure fees are handled properly in underlying classes.
115 $params['fee_amount'] = 1.50;
116 $params['description'] = $this->getPaymentDescription($params);
122 * Does this payment processor support refund?
126 public function supportsRefund() {
131 * Supports altering future start dates.
135 public function supportsFutureRecurStartDate() {
140 * Submit a refund payment
142 * @throws \Civi\Payment\Exception\PaymentProcessorException
144 * @param array $params
145 * Assoc array of input parameters for this transaction.
147 public function doRefund(&$params) {}
150 * This function checks to see if we have the right config values.
153 * the error message if any
155 public function checkConfig() {
160 * Get an array of the fields that can be edited on the recurring contribution.
162 * Some payment processors support editing the amount and other scheduling details of recurring payments, especially
163 * those which use tokens. Others are fixed. This function allows the processor to return an array of the fields that
164 * can be updated from the contribution recur edit screen.
166 * The fields are likely to be a subset of these
169 * - 'frequency_interval',
170 * - 'frequency_unit',
172 * - 'next_sched_contribution_date',
174 * - 'failure_retry_day',
176 * The form does not restrict which fields from the contribution_recur table can be added (although if the html_type
177 * metadata is not defined in the xml for the field it will cause an error.
179 * Open question - would it make sense to return membership_id in this - which is sometimes editable and is on that
180 * form (UpdateSubscription).
184 public function getEditableRecurringScheduleFields() {
185 return ['amount', 'next_sched_contribution_date'];
189 * Does this processor support cancelling recurring contributions through code.
191 * If the processor returns true it must be possible to take action from within CiviCRM
192 * that will result in no further payments being processed. In the case of token processors (e.g
193 * IATS, eWay) updating the contribution_recur table is probably sufficient.
197 protected function supportsCancelRecurring() {
202 * Cancel a recurring subscription.
204 * Payment processor classes should override this rather than implementing cancelSubscription.
206 * A PaymentProcessorException should be thrown if the update of the contribution_recur
207 * record should not proceed (in many cases this function does nothing
208 * as the payment processor does not need to take any action & this should silently
209 * proceed. Note the form layer will only call this after calling
210 * $processor->supports('cancelRecurring');
212 * @param \Civi\Payment\PropertyBag $propertyBag
216 * @throws \Civi\Payment\Exception\PaymentProcessorException
218 public function doCancelRecurring(PropertyBag
$propertyBag) {
219 return ['message' => ts('Recurring contribution cancelled')];