Merge pull request #9606 from yashodha/CRM-19783
[civicrm-core.git] / CRM / Core / Payment / PayflowPro.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +----------------------------------------------------------------------------+
7e9e8871 4 | PayflowPro Core Payment Module for CiviCRM version 4.7 |
6a488035
TO
5 +----------------------------------------------------------------------------+
6 | Licensed to CiviCRM under the Academic Free License version 3.0 |
7 | |
8 | Written & Contributed by Eileen McNaughton - 2009 |
9 +---------------------------------------------------------------------------+
10 */
28518c90
EM
11
12/**
0b014509 13 * Class CRM_Core_Payment_PayflowPro.
28518c90 14 */
6a488035
TO
15class CRM_Core_Payment_PayflowPro extends CRM_Core_Payment {
16 // (not used, implicit in the API, might need to convert?)
7da04cde 17 const
353ffa53 18 CHARSET = 'UFT-8';
6a488035
TO
19
20 /**
21 * We only need one instance of this object. So we use the singleton
22 * pattern and cache the instance in this variable
23 *
24 * @var object
6a488035
TO
25 */
26 static private $_singleton = NULL;
27
3ecad08a 28 /**
6a488035
TO
29 * Constructor
30 *
6a0b768e
TO
31 * @param string $mode
32 * The mode of operation: live or test.
6c786a9b
EM
33 * @param $paymentProcessor
34 */
00be9182 35 public function __construct($mode, &$paymentProcessor) {
6a488035
TO
36 // live or test
37 $this->_mode = $mode;
38 $this->_paymentProcessor = $paymentProcessor;
39 $this->_processorName = ts('Payflow Pro');
40 }
ceb10dc7 41
6a488035
TO
42 /*
43 * This function sends request and receives response from
44 * the processor. It is the main function for processing on-server
45 * credit card transactions
46 */
b5c2afd0
EM
47 /**
48 * This function collects all the information from a web/api form and invokes
49 * the relevant payment processor specific functions to perform the transaction
50 *
6a0b768e
TO
51 * @param array $params
52 * Assoc array of input parameters for this transaction.
b5c2afd0 53 *
a6c01b45
CW
54 * @return array
55 * the result in an nice formatted array (or an error object)
b5c2afd0
EM
56 * @abstract
57 */
00be9182 58 public function doDirectPayment(&$params) {
6a488035
TO
59 if (!defined('CURLOPT_SSLCERT')) {
60 CRM_Core_Error::fatal(ts('PayFlowPro requires curl with SSL support'));
61 }
62
63 /*
64 * define variables for connecting with the gateway
65 */
ceb10dc7 66
6a488035
TO
67 // Are you using the Payflow Fraud Protection Service?
68 // Default is YES, change to NO or blank if not.
69 //This has not been investigated as part of writing this payment processor
70 $fraud = 'NO';
71 //if you have not set up a separate user account the vendor name is used as the username
72 if (!$this->_paymentProcessor['subject']) {
73 $user = $this->_paymentProcessor['user_name'];
74 }
75 else {
76 $user = $this->_paymentProcessor['subject'];
77 }
78
79 // ideally this id would be passed through into this class as
80 // part of the paymentProcessor
81 //object with the other variables. It seems inefficient to re-query to get it.
82 //$params['processor_id'] = CRM_Core_DAO::getFieldValue(
83 // 'CRM_Contribute_DAO_ContributionP
84 //age',$params['contributionPageID'], 'payment_processor_id' );
85
86 /*
87 *Create the array of variables to be sent to the processor from the $params array
88 * passed into this function
89 *
90 */
91
92 $payflow_query_array = array(
93 'USER' => $user,
94 'VENDOR' => $this->_paymentProcessor['user_name'],
95 'PARTNER' => $this->_paymentProcessor['signature'],
96 'PWD' => $this->_paymentProcessor['password'],
97 // C - Direct Payment using credit card
98 'TENDER' => 'C',
99 // A - Authorization, S - Sale
100 'TRXTYPE' => 'S',
101 'ACCT' => urlencode($params['credit_card_number']),
102 'CVV2' => $params['cvv2'],
103 'EXPDATE' => urlencode(sprintf('%02d', (int) $params['month']) . substr($params['year'], 2, 2)),
104 'ACCTTYPE' => urlencode($params['credit_card_type']),
105 'AMT' => urlencode($params['amount']),
106 'CURRENCY' => urlencode($params['currency']),
107 'FIRSTNAME' => $params['billing_first_name'],
108 //credit card name
109 'LASTNAME' => $params['billing_last_name'],
110 //credit card name
111 'STREET' => $params['street_address'],
112 'CITY' => urlencode($params['city']),
113 'STATE' => urlencode($params['state_province']),
114 'ZIP' => urlencode($params['postal_code']),
115 'COUNTRY' => urlencode($params['country']),
116 'EMAIL' => $params['email'],
117 'CUSTIP' => urlencode($params['ip_address']),
118 'COMMENT1' => urlencode($params['contributionType_accounting_code']),
119 'COMMENT2' => $mode,
120 'INVNUM' => urlencode($params['invoiceID']),
121 'ORDERDESC' => urlencode($params['description']),
122 'VERBOSITY' => 'MEDIUM',
123 'BILLTOCOUNTRY' => urlencode($params['country']),
124 );
125
126 if ($params['installments'] == 1) {
0f76c95a 127 $params['is_recur'] = FALSE;
6a488035
TO
128 }
129
130 if ($params['is_recur'] == TRUE) {
131
132 $payflow_query_array['TRXTYPE'] = 'R';
133 $payflow_query_array['OPTIONALTRX'] = 'S';
134 $payflow_query_array['OPTIONALTRXAMT'] = $params['amount'];
135 //Amount of the initial Transaction. Required
136 $payflow_query_array['ACTION'] = 'A';
137 //A for add recurring (M-modify,C-cancel,R-reactivate,I-inquiry,P-payment
138 $payflow_query_array['PROFILENAME'] = urlencode('RegularContribution');
139 //A for add recurring (M-modify,C-cancel,R-reactivate,I-inquiry,P-payment
140 if ($params['installments'] > 0) {
141 $payflow_query_array['TERM'] = $params['installments'] - 1;
142 //ie. in addition to the one happening with this transaction
143 }
144 // $payflow_query_array['COMPANYNAME']
145 // $payflow_query_array['DESC'] = not set yet Optional
146 // description of the goods or
147 //services being purchased.
148 //This parameter applies only for ACH_CCD accounts.
149 // The
150 // $payflow_query_array['MAXFAILPAYMENTS'] = 0;
151 // number of payment periods (as s
152 //pecified by PAYPERIOD) for which the transaction is allowed
153 //to fail before PayPal cancels a profile. the default
154 // value of 0 (zero) specifies no
155 //limit. Retry
156 //attempts occur until the term is complete.
157 // $payflow_query_array['RETRYNUMDAYS'] = (not set as can't assume business rule
158
159 switch ($params['frequency_unit']) {
160 case '1 week':
797b807e 161 $params['next_sched_contribution_date'] = mktime(0, 0, 0, date("m"), date("d") + 7,
6a488035
TO
162 date("Y")
163 );
164 $params['end_date'] = mktime(0, 0, 0, date("m"), date("d") + (7 * $payflow_query_array['TERM']),
165 date("Y")
166 );
797b807e 167 $payflow_query_array['START'] = date('mdY', $params['next_sched_contribution_date']);
6a488035
TO
168 $payflow_query_array['PAYPERIOD'] = "WEEK";
169 $params['frequency_unit'] = "week";
170 $params['frequency_interval'] = 1;
171 break;
172
173 case '2 weeks':
797b807e 174 $params['next_sched_contribution_date'] = mktime(0, 0, 0, date("m"), date("d") + 14, date("Y"));
2aa397bc 175 $params['end_date'] = mktime(0, 0, 0, date("m"), date("d") + (14 * $payflow_query_array['TERM']), date("Y ")
6a488035 176 );
797b807e 177 $payflow_query_array['START'] = date('mdY', $params['next_sched_contribution_date']);
6a488035
TO
178 $payflow_query_array['PAYPERIOD'] = "BIWK";
179 $params['frequency_unit'] = "week";
180 $params['frequency_interval'] = 2;
181 break;
182
183 case '4 weeks':
797b807e 184 $params['next_sched_contribution_date'] = mktime(0, 0, 0, date("m"), date("d") + 28, date("Y")
6a488035 185 );
2aa397bc 186 $params['end_date'] = mktime(0, 0, 0, date("m"), date("d") + (28 * $payflow_query_array['TERM']), date("Y")
6a488035 187 );
797b807e 188 $payflow_query_array['START'] = date('mdY', $params['next_sched_contribution_date']);
6a488035
TO
189 $payflow_query_array['PAYPERIOD'] = "FRWK";
190 $params['frequency_unit'] = "week";
191 $params['frequency_interval'] = 4;
192 break;
193
194 case '1 month':
797b807e 195 $params['next_sched_contribution_date'] = mktime(0, 0, 0, date("m") + 1,
6a488035
TO
196 date("d"), date("Y")
197 );
198 $params['end_date'] = mktime(0, 0, 0, date("m") +
199 (1 * $payflow_query_array['TERM']),
200 date("d"), date("Y")
201 );
797b807e 202 $payflow_query_array['START'] = date('mdY', $params['next_sched_contribution_date']);
6a488035
TO
203 $payflow_query_array['PAYPERIOD'] = "MONT";
204 $params['frequency_unit'] = "month";
205 $params['frequency_interval'] = 1;
206 break;
207
208 case '3 months':
2aa397bc 209 $params['next_sched_contribution_date'] = mktime(0, 0, 0, date("m") + 3, date("d"), date("Y")
6a488035
TO
210 );
211 $params['end_date'] = mktime(0, 0, 0, date("m") +
212 (3 * $payflow_query_array['TERM']),
213 date("d"), date("Y")
214 );
797b807e 215 $payflow_query_array['START'] = date('mdY', $params['next_sched_contribution_date']);
6a488035
TO
216 $payflow_query_array['PAYPERIOD'] = "QTER";
217 $params['frequency_unit'] = "month";
218 $params['frequency_interval'] = 3;
219 break;
220
221 case '6 months':
797b807e 222 $params['next_sched_contribution_date'] = mktime(0, 0, 0, date("m") + 6, date("d"),
6a488035
TO
223 date("Y")
224 );
225 $params['end_date'] = mktime(0, 0, 0, date("m") +
226 (6 * $payflow_query_array['TERM']),
227 date("d"), date("Y")
228 );
2aa397bc 229 $payflow_query_array['START'] = date('mdY', $params['next_sched_contribution_date']
6a488035
TO
230 );
231 $payflow_query_array['PAYPERIOD'] = "SMYR";
232 $params['frequency_unit'] = "month";
233 $params['frequency_interval'] = 6;
234 break;
235
236 case '1 year':
797b807e 237 $params['next_sched_contribution_date'] = mktime(0, 0, 0, date("m"), date("d"),
6a488035
TO
238 date("Y") + 1
239 );
240 $params['end_date'] = mktime(0, 0, 0, date("m"), date("d"),
241 date("Y") +
242 (1 * $payflow_query_array['TEM'])
243 );
797b807e 244 $payflow_query_array['START'] = date('mdY', $params['next_sched_contribution_date']);
6a488035
TO
245 $payflow_query_array['PAYPERIOD'] = "YEAR";
246 $params['frequency_unit'] = "year";
247 $params['frequency_interval'] = 1;
248 break;
249 }
250 }
251
252 CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $payflow_query_array);
253 $payflow_query = $this->convert_to_nvp($payflow_query_array);
254
255 /*
256 * Check to see if we have a duplicate before we send
257 */
d253aeb8 258 if ($this->checkDupe($params['invoiceID'], CRM_Utils_Array::value('contributionID', $params))) {
6a488035
TO
259 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.');
260 }
261
262 // ie. url at payment processor to submit to.
263 $submiturl = $this->_paymentProcessor['url_site'];
264
265 $responseData = self::submit_transaction($submiturl, $payflow_query);
266
267 /*
ceb10dc7 268 * Payment successfully sent to gateway - process the response now
6a488035
TO
269 */
270 $result = strstr($responseData, "RESULT");
271 $nvpArray = array();
272 while (strlen($result)) {
273 // name
274 $keypos = strpos($result, '=');
275 $keyval = substr($result, 0, $keypos);
276 // value
277 $valuepos = strpos($result, '&') ? strpos($result, '&') : strlen($result);
278 $valval = substr($result, $keypos + 1, $valuepos - $keypos - 1);
279 // decoding the respose
280 $nvpArray[$keyval] = $valval;
281 $result = substr($result, $valuepos + 1, strlen($result));
282 }
283 // get the result code to validate.
284 $result_code = $nvpArray['RESULT'];
285 /*debug
e70a7fc0
TO
286 echo "<p>Params array</p><br>";
287 print_r($params);
288 echo "<p></p><br>";
289 echo "<p>Values to Payment Processor</p><br>";
290 print_r($payflow_query_array);
291 echo "<p></p><br>";
292 echo "<p>Results from Payment Processor</p><br>";
293 print_r($nvpArray);
294 echo "<p></p><br>";
295 */
6a488035
TO
296
297 switch ($result_code) {
298 case 0:
299
300 /*******************************************************
301 * Success !
302 * This is a successful transaction. PayFlow Pro does return further information
303 * about transactions to help you identify fraud including whether they pass
304 * the cvv check, the avs check. This is stored in
305 * CiviCRM as part of the transact
306 * but not further processing is done. Business rules would need to be defined
6a488035
TO
307 *******************************************************/
308 $params['trxn_id'] = $nvpArray['PNREF'] . $nvpArray['TRXPNREF'];
309 //'trxn_id' is varchar(255) field. returned value is length 12
310 $params['trxn_result_code'] = $nvpArray['AUTHCODE'] . "-Cvv2:" . $nvpArray['CVV2MATCH'] . "-avs:" . $nvpArray['AVSADDR'];
311
312 if ($params['is_recur'] == TRUE) {
313 $params['recur_trxn_id'] = $nvpArray['PROFILEID'];
314 //'trxn_id' is varchar(255) field. returned value is length 12
315 }
316 return $params;
317
318 case 1:
319 return self::errorExit(9008, "There is a payment processor configuration problem. This is usually due to invalid account information or ip restrictions on the account. You can verify ip restriction by logging // into Manager. See Service Settings >> Allowed IP Addresses. ");
320
321 case 12:
322 // Hard decline from bank.
323 return self::errorExit(9009, "Your transaction was declined ");
324
325 case 13:
326 // Voice authorization required.
327 return self::errorExit(9010, "Your Transaction is pending. Contact Customer Service to complete your order.");
328
329 case 23:
330 // Issue with credit card number or expiration date.
331 return self::errorExit(9011, "Invalid credit card information. Please re-enter.");
332
333 case 26:
334 return self::errorExit(9012, "You have not configured your payment processor with the correct credentials. Make sure you have provided both the <vendor> and the <user> variables ");
335
336 default:
337 return self::errorExit(9013, "Error - from payment processor: [" . $result_code . " " . $nvpArray['RESPMSG'] . "] ");
338 }
339
340 return self::errorExit(9014, "Check the code - all transactions should have been headed off before they got here. Something slipped through the net");
341 }
342
6a488035
TO
343 /*
344 * Produces error message and returns from class
345 */
6c786a9b
EM
346 /**
347 * @param null $errorCode
348 * @param null $errorMessage
349 *
350 * @return object
351 */
00be9182 352 public function &errorExit($errorCode = NULL, $errorMessage = NULL) {
6a488035
TO
353 $e = CRM_Core_Error::singleton();
354 if ($errorCode) {
355 $e->push($errorCode, 0, NULL, $errorMessage);
356 }
357 else {
358 $e->push(9000, 0, NULL, 'Unknown System Error.');
359 }
360 return $e;
361 }
362
363
364 /*
365 * NOTE: 'doTransferCheckout' not implemented
366 */
6c786a9b 367 /**
c490a46a 368 * @param array $params
6c786a9b
EM
369 * @param $component
370 *
371 * @throws Exception
372 */
00be9182 373 public function doTransferCheckout(&$params, $component) {
6a488035
TO
374 CRM_Core_Error::fatal(ts('This function is not implemented'));
375 }
376
377 /*
378 * This public function checks to see if we have the right processor config values set
379 *
380 * NOTE: Called by Events and Contribute to check config params are set prior to trying
381 * register any credit card details
382 *
6a0b768e
TO
383 * @param string $mode
384 * The mode we are operating in (live or test) - not used.
6a488035
TO
385 *
386 * returns string $errorMsg if any errors found - null if OK
6a488035 387 */
ceb10dc7 388
6a488035
TO
389 // function checkConfig( $mode ) // CiviCRM V1.9 Declaration
390
b5c2afd0 391 /**
4f1f1f2a 392 * CiviCRM V2.0 Declaration
b5c2afd0
EM
393 * This function checks to see if we have the right config values
394 *
395 * @internal param string $mode the mode we are operating in (live or test)
396 *
a6c01b45
CW
397 * @return string
398 * the error message if any
b5c2afd0 399 */
00be9182 400 public function checkConfig() {
6a488035
TO
401 $errorMsg = array();
402 if (empty($this->_paymentProcessor['user_name'])) {
403 $errorMsg[] = ' ' . ts('ssl_merchant_id is not set for this payment processor');
404 }
405
406 if (empty($this->_paymentProcessor['url_site'])) {
407 $errorMsg[] = ' ' . ts('URL is not set for %1', array(1 => $this->_paymentProcessor['name']));
408 }
409
410 if (!empty($errorMsg)) {
411 return implode('<p>', $errorMsg);
412 }
413 else {
414 return NULL;
415 }
416 }
417 //end check config
418
419 /*
420 * convert to a name/value pair (nvp) string
421 */
6c786a9b
EM
422 /**
423 * @param $payflow_query_array
424 *
425 * @return array|string
426 */
00be9182 427 public function convert_to_nvp($payflow_query_array) {
6a488035
TO
428 foreach ($payflow_query_array as $key => $value) {
429 $payflow_query[] = $key . '[' . strlen($value) . ']=' . $value;
430 }
431 $payflow_query = implode('&', $payflow_query);
432
433 return $payflow_query;
434 }
435
436 /*
437 * Submit transaction using CuRL
438 * @submiturl string Url to direct HTTPS GET to
439 * @payflow_query value string to be posted
6a488035 440 */
6c786a9b
EM
441 /**
442 * @param $submiturl
443 * @param $payflow_query
444 *
445 * @return mixed|object
446 */
00be9182 447 public function submit_transaction($submiturl, $payflow_query) {
6a488035
TO
448 /*
449 * Submit transaction using CuRL
450 */
ceb10dc7 451
6a488035
TO
452 // get data ready for API
453 $user_agent = $_SERVER['HTTP_USER_AGENT'];
454 // Here's your custom headers; adjust appropriately for your setup:
455 $headers[] = "Content-Type: text/namevalue";
456 //or text/xml if using XMLPay.
457 $headers[] = "Content-Length : " . strlen($data);
458 // Length of data to be passed
459 // Here the server timeout value is set to 45, but notice
460 // below in the cURL section, the timeout
461 // for cURL is 90 seconds. You want to make sure the server
462 // timeout is less, then the connection.
463 $headers[] = "X-VPS-Timeout: 45";
464 //random unique number - the transaction is retried using this transaction ID
465 // in this function but if that doesn't work and it is re- submitted
466 // it is treated as a new attempt. PayflowPro doesn't allow
467 // you to change details (e.g. card no) when you re-submit
468 // you can only try the same details
469 $headers[] = "X-VPS-Request-ID: " . rand(1, 1000000000);
470 // optional header field
471 $headers[] = "X-VPS-VIT-Integration-Product: CiviCRM";
472 // other Optional Headers. If used adjust as necessary.
473 // Name of your OS
474 //$headers[] = "X-VPS-VIT-OS-Name: Linux";
475 // OS Version
476 //$headers[] = "X-VPS-VIT-OS-Version: RHEL 4";
477 // What you are using
478 //$headers[] = "X-VPS-VIT-Client-Type: PHP/cURL";
479 // For your info
480 //$headers[] = "X-VPS-VIT-Client-Version: 0.01";
481 // For your info
482 //$headers[] = "X-VPS-VIT-Client-Architecture: x86";
483 // Application version
484 //$headers[] = "X-VPS-VIT-Integration-Version: 0.01";
485 $ch = curl_init();
486 curl_setopt($ch, CURLOPT_URL, $submiturl);
487 curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
488 curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
489 curl_setopt($ch, CURLOPT_HEADER, 1);
490 // tells curl to include headers in response
491 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
492 // return into a variable
493 curl_setopt($ch, CURLOPT_TIMEOUT, 90);
494 // times out after 90 secs
439b9688
LS
495 if (ini_get('open_basedir') == '' && ini_get('safe_mode') == 'Off') {
496 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
497 }
aaffa79f 498 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, Civi::settings()->get('verifySSL'));
6a488035
TO
499 // this line makes it work under https
500 curl_setopt($ch, CURLOPT_POSTFIELDS, $payflow_query);
501 //adding POST data
aaffa79f 502 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, Civi::settings()->get('verifySSL') ? 2 : 0);
6a488035
TO
503 //verifies ssl certificate
504 curl_setopt($ch, CURLOPT_FORBID_REUSE, TRUE);
505 //forces closure of connection when done
506 curl_setopt($ch, CURLOPT_POST, 1);
507 //data sent as POST
508
509 // Try to submit the transaction up to 3 times with 5 second delay. This can be used
510 // in case of network issues. The idea here is since you are posting via HTTPS there
511 // could be general network issues, so try a few times before you tell customer there
512 // is an issue.
513
514 $i = 1;
515 while ($i++ <= 3) {
516 $responseData = curl_exec($ch);
517 $responseHeaders = curl_getinfo($ch);
518 if ($responseHeaders['http_code'] != 200) {
519 // Let's wait 5 seconds to see if its a temporary network issue.
520 sleep(5);
521 }
522 elseif ($responseHeaders['http_code'] == 200) {
523 // we got a good response, drop out of loop.
524 break;
525 }
526 }
527
528 /*
529 * Transaction submitted -
530 * See if we had a curl error - if so tell 'em and bail out
531 *
532 * NOTE: curl_error does not return a logical value (see its documentation), but
533 * a string, which is empty when there was no error.
534 */
535 if ((curl_errno($ch) > 0) || (strlen(curl_error($ch)) > 0)) {
536 curl_close($ch);
537 $errorNum = curl_errno($ch);
538 $errorDesc = curl_error($ch);
539
540 //Paranoia - in the unlikley event that 'curl' errno fails
2aa397bc
TO
541 if ($errorNum == 0) {
542 $errorNum = 9005;
543 }
6a488035
TO
544
545 // Paranoia - in the unlikley event that 'curl' error fails
2aa397bc
TO
546 if (strlen($errorDesc) == 0) {
547 $errorDesc = "Connection to payment gateway failed";
548 }
6a488035
TO
549 if ($errorNum = 60) {
550 return self::errorExit($errorNum, "Curl error - " . $errorDesc .
551 " Try this link for more information http://curl.haxx.se/d
552 ocs/sslcerts.html"
553 );
554 }
555
556 return self::errorExit($errorNum, "Curl error - " . $errorDesc .
557 " processor response = " . $processorResponse
558 );
559 }
560
561 /*
562 * If null data returned - tell 'em and bail out
563 *
564 * NOTE: You will not necessarily get a string back, if the request failed for
565 * any reason, the return value will be the boolean false.
566 */
567 if (($responseData === FALSE) || (strlen($responseData) == 0)) {
568 curl_close($ch);
569 return self::errorExit(9006, "Error: Connection to payment gateway failed - no data
570 returned. Gateway url set to $submiturl");
571 }
572
573 /*
574 * If gateway returned no data - tell 'em and bail out
575 */
576 if (empty($responseData)) {
577 curl_close($ch);
578 return self::errorExit(9007, "Error: No data returned from payment gateway.");
579 }
580
581 /*
582 * Success so far - close the curl and check the data
583 */
584 curl_close($ch);
585 return $responseData;
586 }
587 //end submit_transaction
588
6c786a9b 589 /**
100fef9d
CW
590 * @param int $recurringProfileID
591 * @param int $processorID
6c786a9b
EM
592 *
593 * @throws Exception
594 */
00be9182 595 public function getRecurringTransactionStatus($recurringProfileID, $processorID) {
6a488035
TO
596 if (!defined('CURLOPT_SSLCERT')) {
597 CRM_Core_Error::fatal(ts('PayFlowPro requires curl with SSL support'));
598 }
599
600 /*
601 * define variables for connecting with the gateway
602 */
ceb10dc7 603
6a488035
TO
604 //if you have not set up a separate user account the vendor name is used as the username
605 if (!$this->_paymentProcessor['subject']) {
606 $user = $this->_paymentProcessor['user_name'];
607 }
608 else {
609 $user = $this->_paymentProcessor['subject'];
610 }
611 //$recurringProfileID = "RT0000000001";
612 // c $trythis = $this->getRecurringTransactionStatus($recurringProfileID,17);
613
6a488035
TO
614 /*
615 *Create the array of variables to be sent to the processor from the $params array
616 * passed into this function
617 *
618 */
619
620 $payflow_query_array = array(
621 'USER' => $user,
622 'VENDOR' => $this->_paymentProcessor['user_name'],
623 'PARTNER' => $this->_paymentProcessor['signature'],
624 'PWD' => $this->_paymentProcessor['password'],
625 // C - Direct Payment using credit card
626 'TENDER' => 'C',
627 // A - Authorization, S - Sale
628 'TRXTYPE' => 'R',
629 'ACTION' => 'I',
630 //A for add recurring
631 //(M-modify,C-cancel,R-reactivate,
632 //I-inquiry,P-payment
633 'ORIGPROFILEID' => $recurringProfileID,
634 'PAYMENTHISTORY' => 'Y',
635 );
636
637 $payflow_query = $this->convert_to_nvp($payflow_query_array);
638 echo $payflow_query;
639 $submiturl = $this->_paymentProcessor['url_site'];
640 //ie. url at payment processor to submit to.
641 $responseData = self::submit_transaction($submiturl, $payflow_query);
642 /*
ceb10dc7 643 * Payment successfully sent to gateway - process the response now
6a488035 644 */
ceb10dc7 645
6a488035
TO
646 $result = strstr($responseData, "RESULT");
647 $nvpArray = array();
648 while (strlen($result)) {
649 // name
650 $keypos = strpos($result, '=');
651 $keyval = substr($result, 0, $keypos);
652 // value
653 $valuepos = strpos($result, '&') ? strpos($result, '&') : strlen($result);
654 $valval = substr($result, $keypos + 1, $valuepos - $keypos - 1);
655 // decoding the respose
656 $nvpArray[$keyval] = $valval;
657 $result = substr($result, $valuepos + 1, strlen($result));
658 }
659 // get the result code to validate.
660 $result_code = $nvpArray['RESULT'];
661 print_r($responseData);
662
663 //RESPMSG=Invalid Profile ID: Invalid recurring profile ID
664 //RT0000000001
665 }
96025800 666
6a488035 667}