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