commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-old / civicrm / packages / PaymentExpress / pxaccess.inc.php
1 <?php
2
3 #******************************************************************************
4 #* Name : PxAccess.inc
5 #* Description : The objects for PX Payment page
6 #* Copyright (c) : 2004 Direct Payment solutions
7 #* Date : 2003-12-24
8 #* Modifications : 2003-12-24 MifMessage class
9 #* : 2004-09-01 PxAccess, PxPayRequest, PxPayResponse classes
10 #* which encapsulate 3-DES to handle payment requests and
11 #* response.
12 #* 2004-10-14 Implements complete transactions
13 #* 2005-03-14 change unpack("H*", $enc); to unpack("H$enclen", $enc);
14 #* due to the version 4.3.10 Php unpack function bugs
15 #*Version : 2.01.08
16 #******************************************************************************
17
18 # MifMessage.
19 # Use this class to parse a DPS PX MifMessage in XML form,
20 # and access the content.
21 class MifMessage
22 {
23 var $xml_;
24 var $xml_index_;
25 var $xml_value_;
26
27 # Constructor:
28 # Create a MifMessage with the specified XML text.
29 # The constructor returns a null object if there is a parsing error.
30 function MifMessage($xml)
31 {
32 $p = xml_parser_create();
33 xml_parser_set_option($p,XML_OPTION_CASE_FOLDING,0);
34 $ok = xml_parse_into_struct($p, $xml, $value, $index);
35 xml_parser_free($p);
36 if ($ok)
37 {
38 $this->xml_ = $xml;
39 $this->xml_value_ = $value;
40 $this->xml_index_ = $index;
41 }
42 #print_r($this->xml_value_); # JH_DEBUG
43 }
44
45 # Return the value of the specified top-level attribute.
46 # This method can only return attributes of the root element.
47 # If the attribute is not found, return "".
48 function get_attribute($attribute)
49 {
50 #$attribute = strtoupper($attribute);
51 $attributes = $this->xml_value_[0]["attributes"];
52 return $attributes[$attribute];
53 }
54
55 # Return the text of the specified element.
56 # The element is given as a simplified XPath-like name.
57 # For example, "Link/ServerOk" refers to the ServerOk element
58 # nested in the Link element (nested in the root element).
59 # If the element is not found, return "".
60 function get_element_text($element)
61 {
62 #print_r($this->xml_value_); # JH_DEBUG
63 $index = $this->get_element_index($element, 0);
64 if ($index == 0)
65 {
66 return "";
67 }
68 else
69 {
70 ## TW2004-09-24: Fixed bug when elemnt existent but empty
71 #
72 $elementObj = $this->xml_value_[$index];
73 if (! array_key_exists("value", $elementObj))
74 return "";
75
76 return $this->xml_value_[$index]["value"];
77 }
78 }
79
80 # (internal method)
81 # Return the index of the specified element,
82 # relative to some given root element index.
83 #
84 function get_element_index($element, $rootindex = 0)
85 {
86 #$element = strtoupper($element);
87 $pos = strpos($element, "/");
88 if ($pos !== false)
89 {
90 # element contains '/': find first part
91 $start_path = substr($element,0,$pos);
92 $remain_path = substr($element,$pos+1);
93 $index = $this->get_element_index($start_path, $rootindex);
94 if ($index == 0)
95 {
96 # couldn't find first part; give up.
97 return 0;
98 }
99 # recursively find rest
100 return $this->get_element_index($remain_path, $index);
101 }
102 else
103 {
104 # search from the parent across all its children
105 # i.e. until we get the parent's close tag.
106 $level = $this->xml_value_[$rootindex]["level"];
107 if ($this->xml_value_[$rootindex]["type"] == "complete")
108 {
109 return 0; # no children
110 }
111 $index = $rootindex+1;
112 while ($index<count($this->xml_value_) &&
113 !($this->xml_value_[$index]["level"]==$level &&
114 $this->xml_value_[$index]["type"]=="close"))
115 {
116 # if one below parent and tag matches, bingo
117 if ($this->xml_value_[$index]["level"] == $level+1 &&
118 # $this->xml_value_[$index]["type"] == "complete" &&
119 $this->xml_value_[$index]["tag"] == $element)
120 {
121 return $index;
122 }
123 $index++;
124 }
125 return 0;
126 }
127 }
128 }
129
130 class PxAccess
131 {
132 var $Mac_Key, $Des_Key;
133 var $PxAccess_Url;
134 var $PxAccess_Userid;
135 function PxAccess($Url, $UserId, $Des_Key, $Mac_Key){
136 error_reporting(E_ERROR);
137 $this->Mac_Key = pack("H*",$Mac_Key);
138 $this->Des_Key = pack("H*", $Des_Key);
139 $this->PxAccess_Url = $Url;
140 $this->PxAccess_Userid = $UserId;
141 }
142 function makeRequest($request)
143 {
144 #Validate the REquest
145 if($request->validData() == false) return "" ;
146
147 #$txnId=rand(1,100000);
148 $txnId = uniqid("MI"); #You need to generate you own unqiue reference. JZ:2004-08-12
149 $request->setTxnId($txnId);
150 $request->setTs($this->getCurrentTS());
151 $request->setSwVersion("2.01.01");
152 $request->setAppletType("PHPPxAccess");
153
154
155 $xml = $request->toXml();
156
157 if (strlen($xml)%8 != 0)
158 {
159 $xml = str_pad($xml, strlen($xml) + 8-strlen($xml)%8); # pad to multiple of 8
160 }
161 #add MAC code JZ2004-8-16
162 $mac = $this->makeMAC($xml,$this->Mac_Key );
163 $msg = $xml.$mac;
164 #$msg = $xml;
165 $enc = $this->encrypt_tripledes($msg, $this->Des_Key); #JZ2004-08-16: Include the MAC code
166
167 $enclen = strlen($enc) * 2;
168
169 $enc_hex = unpack("H$enclen", $enc); #JZ2005-03-14: there is a bug in the new version php unpack function
170 #$enc_hex = @unpack("H*", $enc); #JZ2005-03-14: there is a bug in the new version php unpack function
171
172 #$enc_hex = $enc_hex[""]; #use this function if PHP version before 4.3.4
173 #$enc_hex = $enc_hex[1]; #use this function if PHP version after 4.3.4
174 $enc_hex = (version_compare(PHP_VERSION, "4.3.4", ">=")) ? $enc_hex[1] :$enc_hex[""];
175
176 $PxAccess_Redirect = "$this->PxAccess_Url?userid=$this->PxAccess_Userid&request=$enc_hex";
177
178 return $PxAccess_Redirect;
179
180 }
181
182 #******************************************************************************
183 # This function ecrypts data using 3DES via libmcrypt
184 #******************************************************************************
185 function encrypt_tripledes($data, $key)
186 {
187 # deprecated libmcrypt 2.2 encryption: use this if you have libmcrypt 2.2.x
188 # $result = mcrypt_ecb(MCRYPT_DES, $key, $data, MCRYPT_ENCRYPT);
189 # return $result;
190 #
191 # otherwise use this for libmcrypt 2.4.x and above:
192 $td = mcrypt_module_open('tripledes', '', 'ecb', '');
193 $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
194 mcrypt_generic_init($td, $key, $iv);
195 $result = mcrypt_generic($td, $data);
196 #mcrypt_generic_deinit($td); #Might cause problem in some PHP version
197 return $result;
198 }
199
200
201 #******************************************************************************
202 # This function decrypts data using 3DES via libmcrypt
203 #******************************************************************************
204 function decrypt_tripledes($data, $key)
205 {
206 # deprecated libmcrypt 2.2 encryption: use this if you have libmcrypt 2.2.x
207 # $result = mcrypt_ecb(MCRYPT_DES, $key, $data, MCRYPT_DECRYPT);
208 # return $result;
209 #
210 # otherwise use this for libmcrypt 2.4.x and above:
211 $td = mcrypt_module_open('tripledes', '', 'ecb', '');
212 $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
213 mcrypt_generic_init($td, $key, $iv);
214 $result = mdecrypt_generic($td, $data);
215 #mcrypt_generic_deinit($td); #Might cause problem in some PHP version
216 return $result;
217 }
218
219 #JZ2004-08-16
220
221 #******************************************************************************
222 # Generate and return a message authentication code (MAC) for a string.
223 # (Uses ANSI X9.9 procedure.)
224 #******************************************************************************
225 function makeMAC($msg,$Mackey){
226
227 if (strlen($msg)%8 != 0)
228 {
229 $extra = 8 - strlen($msg)%8;
230 $msg .= str_repeat(" ", $extra); # pad to multiple of 8
231 }
232 $mac = pack("C*", 0, 0, 0, 0, 0, 0, 0, 0); # start with all zeros
233 #$mac_result = unpack("C*", $mac);
234
235 for ( $i=0; $i<strlen($msg)/8; $i++)
236 {
237 $msg8 = substr($msg, 8*$i, 8);
238
239 $mac ^= $msg8;
240 $mac = $this->encrypt_des($mac,$Mackey);
241
242 }
243 #$mac = pack("C*", $mac);
244 #$mac_result= encrypt_des($mac, $Mackey);
245
246 $mac_result = unpack("H8", $mac);
247 #$mac_result = $mac_result[""]; #use this function if PHP version before 4.3.4
248 #$mac_result = $mac_result[1]; #use this function if PHP version after 4.3.4
249 $mac_result = (version_compare(PHP_VERSION, "4.3.4", ">=")) ? $mac_result[1]: $mac_result[""];
250
251 return $mac_result;
252
253
254 }
255
256 #******************************************************************************
257 # This function ecrypts data using DES via libmcrypt
258 # JZ2004-08-16
259 #******************************************************************************
260 function encrypt_des($data, $key)
261 {
262 # deprecated libmcrypt 2.2 encryption: use this if you have libmcrypt 2.2.x
263 # $result = mcrypt_ecb(MCRYPT_3DES, $key, $data, MCRYPT_ENCRYPT);
264 # return $result;
265 #
266 # otherwise use this for libmcrypt 2.4.x and above:
267 $td = mcrypt_module_open('des', '', 'ecb', '');
268 $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
269 mcrypt_generic_init($td, $key, $iv);
270 $result = mcrypt_generic($td, $data);
271 #mcrypt_generic_deinit($td); #Might cause problem in some PHP version
272 mcrypt_module_close($td);
273
274 return $result;
275 }
276
277
278 #JZ2004-08-16
279 function getResponse($resp_enc){
280 #global $Mac_Key;
281 $enc = pack("H*", $resp_enc);
282 $resp = trim($this->decrypt_tripledes($enc, $this->Des_Key));
283 $xml = substr($resp, 0, strlen($resp)-8);
284 $mac = substr($resp, -8);
285 $checkmac = $this->makeMac($xml, $this->Mac_Key);
286 if($mac != $checkmac){
287 $xml = "<success>0</success><ResponseText>Response MAC Invalid</ResponseText>";
288 }
289
290 $pxresp = new PxPayResponse($xml);
291 return $pxresp;
292
293 }
294
295
296
297 #******************************************************************************
298 # Return the current time (GMT/UTC).The return time formatted YYYYMMDDHHMMSS.
299 #JZ2004-08-30
300 #******************************************************************************
301 function getCurrentTS()
302 {
303
304 return gmstrftime("%Y%m%d%H%M%S", time());
305 }
306
307
308
309 }
310
311 #******************************************************************************
312 # Class for PxPay request messages.
313 #******************************************************************************
314 class PxPayRequest extends PxPayMessage
315 {
316 var $TxnId,$UrlFail,$UrlSuccess;
317 var $AmountInput, $AppletVersion, $InputCurrency;
318 var $EnableAddBillCard;
319 var $TS;
320
321 var $AppletType;
322
323 #Constructor
324 function PxPayRequest(){
325 $this->PxPayMessage();
326
327 }
328
329 function setAppletType($AppletType){
330 $this->AppletType = $AppletType;
331 }
332
333 function getAppletType(){
334 return $this->AppletType;
335 }
336
337
338
339 function setTs($Ts){
340 $this->TS = $Ts;
341 }
342 function setEnableAddBillCard($EnableBillAddCard){
343 $this->EnableAddBillCard = $EnableBillAddCard;
344 }
345
346 function getEnableAddBillCard(){
347 return $this->EnableAddBillCard;
348 }
349 function setInputCurrency($InputCurrency){
350 $this->InputCurrency = $InputCurrency;
351 }
352 function getInputCurrency(){
353 return $this->InputCurrency;
354 }
355 function setTxnId( $TxnId)
356 {
357 $this->TxnId = $TxnId;
358 }
359 function getTxnId(){
360 return $this->TxnId;
361 }
362
363 function setUrlFail($UrlFail){
364 $this->UrlFail = $UrlFail;
365 }
366 function getUrlFail(){
367 return $this->UrlFail;
368 }
369 function setUrlSuccess($UrlSuccess){
370 $this->UrlSuccess = $UrlSuccess;
371 }
372 function setAmountInput($AmountInput){
373 $this->AmountInput = sprintf("%9.2f",$AmountInput);
374 }
375
376 function getAmountInput(){
377 return $this->AmountInput;
378 }
379 function setSwVersion($SwVersion){
380 $this->AppletVersion = $SwVersion;
381 }
382
383 function getSwVersion(){
384 return $this->AppletVersion;
385 }
386 #******************************************************************
387 #Data validation
388 #******************************************************************
389 function validData(){
390 $msg = "";
391 if($this->TxnType != "Purchase")
392 if($this->TxnType != "Auth")
393 if($this->TxnType != "GetCurrRate")
394 if($this->TxnType != "Refund")
395 if($this->TxnType != "Complete")
396 if($this->TxnType != "Order1")
397 $msg = "Invalid TxnType[$this->TxnType]<br>";
398
399 if(strlen($this->MerchantReference) > 64)
400 $msg = "Invalid MerchantReference [$this->MerchantReference]<br>";
401
402 if(strlen($this->TxnId) > 16)
403 $msg = "Invalid TxnId [$this->TxnId]<br>";
404 if(strlen($this->TxnData1) > 255)
405 $msg = "Invalid TxnData1 [$this->TxnData1]<br>";
406 if(strlen($this->TxnData2) > 255)
407 $msg = "Invalid TxnData2 [$this->TxnData2]<br>";
408 if(strlen($this->TxnData3) > 255)
409 $msg = "Invalid TxnData3 [$this->TxnData3]<br>";
410
411 if(strlen($this->EmailAddress) > 255)
412 $msg = "Invalid EmailAddress [$this->EmailAddress]<br>";
413
414 if(strlen($this->UrlFail) > 255)
415 $msg = "Invalid UrlFail [$this->UrlFail]<br>";
416 if(strlen($this->UrlSuccess) > 255)
417 $msg = "Invalid UrlSuccess [$this->UrlSuccess]<br>";
418 if(strlen($this->BillingId) > 32)
419 $msg = "Invalid BillingId [$this->BillingId]<br>";
420 if(strlen($this->DpsBillingId) > 16)
421 $msg = "Invalid DpsBillingId [$this->DpsBillingId]<br>";
422
423 if ($msg != "") {
424 trigger_error($msg,E_USER_ERROR);
425 return false;
426 }
427 return true;
428 }
429
430 }
431
432 #******************************************************************************
433 # Abstract base class for PxPay messages.
434 # These are messages with certain defined elements, which can be serialized to XML.
435
436 #******************************************************************************
437 class PxPayMessage {
438 var $TxnType;
439 var $TxnData1;
440 var $TxnData2;
441 var $TxnData3;
442 var $MerchantReference;
443 var $EmailAddress;
444 var $BillingId;
445 var $DpsBillingId;
446 var $DpsTxnRef;
447
448 function PxPayMessage(){
449
450 }
451 function setDpsTxnRef($DpsTxnRef){
452 $this->DpsTxnRef = $DpsTxnRef;
453 }
454
455 function getDpsTxnRef(){
456 return $this->DpsTxnRef;
457 }
458
459 function setDpsBillingId($DpsBillingId){
460 $this->DpsBillingId = $DpsBillingId;
461 }
462
463 function getDpsBillingId(){
464 return $this->DpsBillingId;
465 }
466 function setBillingId($BillingId){
467 $this->BillingId = $BillingId;
468 }
469
470 function getBillingId(){
471 return $this->BillingId;
472 }
473 function setTxnType($TxnType){
474 $this->TxnType = $TxnType;
475 }
476 function getTxnType(){
477 return $this->TxnType;
478 }
479 function setMerchantReference($MerchantReference){
480 $this->MerchantReference = $MerchantReference;
481 }
482
483 function getMerchantReference(){
484 return $this->MerchantReference;
485 }
486 function setEmailAddress($EmailAddress){
487 $this->EmailAddress = $EmailAddress;
488
489 }
490
491 function getEmailAddress(){
492 return $this->EmailAddress;
493 }
494
495 function setTxnData1($TxnData1){
496 $this->TxnData1 = $TxnData1;
497
498 }
499 function getTxnData1(){
500 return $this->TxnData1;
501 }
502 function setTxnData2($TxnData2){
503 $this->TxnData2 = $TxnData2;
504
505 }
506 function getTxnData2(){
507 return $this->TxnData2;
508 }
509
510 function getTxnData3(){
511 return $this->TxnData3;
512 }
513 function setTxnData3($TxnData3){
514 $this->TxnData3 = $TxnData3;
515
516 }
517 function toXml(){
518 $arr = get_object_vars($this);
519 $root = get_class($this);
520 if($root == "PxPayRequest")
521 $root = "Request";
522 elseif ($root == "PxPayResponse")
523 $root = "Response";
524 else
525 $root ="Request";
526
527 $xml = "<$root>";
528 while (list($prop, $val) = each($arr))
529 $xml .= "<$prop>$val</$prop>" ;
530
531 $xml .= "</$root>";
532 return $xml;
533 }
534
535
536 }
537
538 #******************************************************************************
539 # Class for PxPay response messages.
540 #******************************************************************************
541
542 class PxPayResponse extends PxPayMessage
543 {
544 var $Success;
545 var $StatusRequired;
546 var $Retry;
547 var $AuthCode;
548 var $AmountSettlement;
549 var $CurrencySettlement;
550 var $CardName;
551 var $CurrencyInput;
552 var $UserId;
553 var $ResponseText;
554 #var $DpsTxnRef;
555 var $MerchantTxnId;
556 var $TS;
557
558 function PxPayResponse($xml){
559 $msg = new MifMessage($xml);
560 $this->PxPayMessage();
561
562 $TS = $msg->get_element_text("TS");
563 $expiryTS = $this->getExpiredTS();
564 if(strcmp($TS, $expiryTS) < 0 ){
565 $this->Success = "0";
566 $this->ResponseText = "Response TS out of range";
567 return;
568 }
569
570 $this->setBillingId($msg->get_element_text("BillingId"));
571 $this->setDpsBillingId($msg->get_element_text("DpsBillingId"));
572 $this->setEmailAddress($msg->get_element_text("EmailAddress"));
573 $this->setMerchantReference($msg->get_element_text("MerchantReference"));
574 $this->setTxnData1($msg->get_element_text("TxnData1"));
575 $this->setTxnData2($msg->get_element_text("TxnData2"));
576 $this->setTxnData3($msg->get_element_text("TxnData3"));
577 $this->setTxnType($msg->get_element_text("TxnType"));
578
579 $this->Success = $msg->get_element_text("Success");
580 $this->StatusRequired = $msg->get_element_text("StatusRequired");
581 $this->Retry = $msg->get_element_text("Retry");
582 $this->AuthCode = $msg->get_element_text("AuthCode");
583 $this->AmountSettlement = $msg->get_element_text("AmountSettlement");
584 $this->CurrencySettlement = $msg->get_element_text("CurrencySettlement");
585 $this->CardName = $msg->get_element_text("CardName");
586 $this->CurrencyInput = $msg->get_element_text("CurrencyInput");
587 $this->UserId = $msg->get_element_text("UserId");
588 $this->ResponseText = $msg->get_element_text("ResponseText");
589 $this->DpsTxnRef = $msg->get_element_text("DpsTxnRef");
590 $this->MerchantTxnId = $msg->get_element_text("MerchantTxnId");
591 $this->TS = $msg->get_element_text("TS");
592 }
593 function getTS(){
594 return $this->TS;
595 }
596 function getMerchantTxnId(){
597 return $this->MerchantTxnId;
598 }
599
600 function getResponseText(){
601 return $this->ResponseText;
602 }
603 function getUserId(){
604 return $this->UserId;
605 }
606 function getCurrencyInput(){
607 return $this->CurrencyInput;
608 }
609 function getCardName(){
610 return $this->CardName;
611 }
612 function getCurrencySettlement(){
613 $this->CurrencySettlement;
614 }
615 function getAmountSettlement(){
616 return $this->AmountSettlement;
617 }
618 function getSuccess(){
619 return $this->Success;
620 }
621 function getStatusRequired(){
622 return $this->StatusRequired;
623 }
624 function getRetry(){
625 return $this->Retry;
626 }
627 function getAuthCode(){
628 return $this->AuthCode;
629 }
630 #******************************************************************************
631 # Return the expired time, i.e. 2 days ago (GMT/UTC).
632 #JZ2004-08-30
633 #******************************************************************************
634 function getExpiredTS()
635 {
636
637 return gmstrftime("%Y%m%d%H%M%S", time()- 2 * 24 * 60 * 60);
638 }
639
640 }
641
642 ?>