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