Merge pull request #14263 from elisseck/dev/core/966
[civicrm-core.git] / CRM / Core / Payment / Dummy.php
1 <?php
2 /*
3 * Copyright (C) 2007
4 * Licensed to CiviCRM under the Academic Free License version 3.0.
5 *
6 * Written and contributed by Ideal Solution, LLC (http://www.idealso.com)
7 *
8 */
9
10 /**
11 *
12 * @package CRM
13 * @author Marshal Newrock <marshal@idealso.com>
14 * $Id: Dummy.php 45429 2013-02-06 22:11:18Z lobo $
15 */
16
17 /**
18 * Dummy payment processor
19 */
20 class CRM_Core_Payment_Dummy extends CRM_Core_Payment {
21 const CHARSET = 'iso-8859-1';
22
23 protected $_mode = NULL;
24
25 protected $_params = [];
26 protected $_doDirectPaymentResult = [];
27
28 /**
29 * Set result from do Direct Payment for test purposes.
30 *
31 * @param array $doDirectPaymentResult
32 * Result to be returned from test.
33 */
34 public function setDoDirectPaymentResult($doDirectPaymentResult) {
35 $this->_doDirectPaymentResult = $doDirectPaymentResult;
36 if (empty($this->_doDirectPaymentResult['trxn_id'])) {
37 $this->_doDirectPaymentResult['trxn_id'] = [];
38 }
39 else {
40 $this->_doDirectPaymentResult['trxn_id'] = (array) $doDirectPaymentResult['trxn_id'];
41 }
42 }
43
44 /**
45 * We only need one instance of this object. So we use the singleton
46 * pattern and cache the instance in this variable
47 *
48 * @var object
49 */
50 static private $_singleton = NULL;
51
52 /**
53 * Constructor.
54 *
55 * @param string $mode
56 * The mode of operation: live or test.
57 *
58 * @param $paymentProcessor
59 *
60 * @return \CRM_Core_Payment_Dummy
61 */
62 public function __construct($mode, &$paymentProcessor) {
63 $this->_mode = $mode;
64 $this->_paymentProcessor = $paymentProcessor;
65 $this->_processorName = ts('Dummy Processor');
66 }
67
68 /**
69 * Submit a payment using Advanced Integration Method.
70 *
71 * @param array $params
72 * Assoc array of input parameters for this transaction.
73 *
74 * @return array
75 * the result in a nice formatted array (or an error object)
76 */
77 public function doDirectPayment(&$params) {
78 // Invoke hook_civicrm_paymentProcessor
79 // In Dummy's case, there is no translation of parameters into
80 // the back-end's canonical set of parameters. But if a processor
81 // does this, it needs to invoke this hook after it has done translation,
82 // but before it actually starts talking to its proprietary back-end.
83 if (!empty($params['is_recur'])) {
84 $throwAnENoticeIfNotSetAsTheseAreRequired = $params['frequency_interval'] . $params['frequency_unit'];
85 }
86 // no translation in Dummy processor
87 $cookedParams = $params;
88 CRM_Utils_Hook::alterPaymentProcessorParams($this,
89 $params,
90 $cookedParams
91 );
92 // This means we can test failing transactions by setting a past year in expiry. A full expiry check would
93 // be more complete.
94 if (!empty($params['credit_card_exp_date']['Y']) && date('Y') >
95 CRM_Core_Payment_Form::getCreditCardExpirationYear($params)) {
96 $error = new CRM_Core_Error(ts('transaction failed'));
97 return $error;
98 }
99 //end of hook invocation
100 if (!empty($this->_doDirectPaymentResult)) {
101 $result = $this->_doDirectPaymentResult;
102 $result['trxn_id'] = array_shift($this->_doDirectPaymentResult['trxn_id']);
103 return $result;
104 }
105 if ($this->_mode == 'test') {
106 $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'test\\_%'";
107 $p = [];
108 $trxn_id = strval(CRM_Core_Dao::singleValueQuery($query, $p));
109 $trxn_id = str_replace('test_', '', $trxn_id);
110 $trxn_id = intval($trxn_id) + 1;
111 $params['trxn_id'] = 'test_' . $trxn_id . '_' . uniqid();
112 }
113 else {
114 $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'live_%'";
115 $p = [];
116 $trxn_id = strval(CRM_Core_Dao::singleValueQuery($query, $p));
117 $trxn_id = str_replace('live_', '', $trxn_id);
118 $trxn_id = intval($trxn_id) + 1;
119 $params['trxn_id'] = 'live_' . $trxn_id . '_' . uniqid();
120 }
121 $params['gross_amount'] = $params['amount'];
122 // Add a fee_amount so we can make sure fees are handled properly in underlying classes.
123 $params['fee_amount'] = 1.50;
124 $params['net_amount'] = $params['gross_amount'] - $params['fee_amount'];
125
126 return $params;
127 }
128
129 /**
130 * Are back office payments supported.
131 *
132 * E.g paypal standard won't permit you to enter a credit card associated with someone else's login.
133 *
134 * @return bool
135 */
136 protected function supportsLiveMode() {
137 return TRUE;
138 }
139
140 /**
141 * Does this payment processor support refund?
142 *
143 * @return bool
144 */
145 public function supportsRefund() {
146 return TRUE;
147 }
148
149 /**
150 * Supports altering future start dates
151 * @return bool
152 */
153 public function supportsFutureRecurStartDate() {
154 return TRUE;
155 }
156
157 /**
158 * Submit a refund payment
159 *
160 * @throws \Civi\Payment\Exception\PaymentProcessorException
161 *
162 * @param array $params
163 * Assoc array of input parameters for this transaction.
164 */
165 public function doRefund(&$params) {}
166
167 /**
168 * Generate error object.
169 *
170 * Throwing exceptions is preferred over this.
171 *
172 * @param string $errorCode
173 * @param string $errorMessage
174 *
175 * @return CRM_Core_Error
176 * Error object.
177 */
178 public function &error($errorCode = NULL, $errorMessage = NULL) {
179 $e = CRM_Core_Error::singleton();
180 if ($errorCode) {
181 $e->push($errorCode, 0, NULL, $errorMessage);
182 }
183 else {
184 $e->push(9001, 0, NULL, 'Unknown System Error.');
185 }
186 return $e;
187 }
188
189 /**
190 * This function checks to see if we have the right config values.
191 *
192 * @return string
193 * the error message if any
194 */
195 public function checkConfig() {
196 return NULL;
197 }
198
199 /**
200 * Get an array of the fields that can be edited on the recurring contribution.
201 *
202 * Some payment processors support editing the amount and other scheduling details of recurring payments, especially
203 * those which use tokens. Others are fixed. This function allows the processor to return an array of the fields that
204 * can be updated from the contribution recur edit screen.
205 *
206 * The fields are likely to be a subset of these
207 * - 'amount',
208 * - 'installments',
209 * - 'frequency_interval',
210 * - 'frequency_unit',
211 * - 'cycle_day',
212 * - 'next_sched_contribution_date',
213 * - 'end_date',
214 * - 'failure_retry_day',
215 *
216 * The form does not restrict which fields from the contribution_recur table can be added (although if the html_type
217 * metadata is not defined in the xml for the field it will cause an error.
218 *
219 * Open question - would it make sense to return membership_id in this - which is sometimes editable and is on that
220 * form (UpdateSubscription).
221 *
222 * @return array
223 */
224 public function getEditableRecurringScheduleFields() {
225 return ['amount', 'next_sched_contribution_date'];
226 }
227
228 /**
229 * @param string $message
230 * @param array $params
231 *
232 * @return bool|object
233 */
234 public function cancelSubscription(&$message = '', $params = []) {
235 return TRUE;
236 }
237
238 }