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