Odyssey
bpCommon.i
1 <?php
2 /**
3  * File: bpCommon.i
4  *
5  * Purpose: This file is included in the hcuMobilePay.plugin.
6  * It contains the generic functions used by all bill pay vendors.
7  *
8  * Created By: Erin Robbins, 12/2018
9  */
10 
11 /**
12  * Returns eligible accounts list from the subscriber's credit union database.
13  *
14  * @param dbhandle $dbh database handle
15  * @param array $HB_ENV uses several items from environmental settings for TX_List
16  * @param array $parms (string Cu, integer Uid, string MBRACCT)
17  * @return array list of eligible accounts
18  */
19 function GetAccts($dbh, $HB_ENV, $parms) {
20  $AcctList = array();
21 
22  if (!isset($parms['Cu']) || !isset($parms['Uid']) || !isset($parms['MBRACCT'])) {
23  $AcctList['status']['response'] = 'false';
24  $AcctList['status']['code'] = '910';
25  $AcctList['status']['message'] = 'Missing Account Parameters'; # missing Cu/Uid/MBRACCT
26  return ($AcctList);
27  }
28  //calling tx_list first, to take care of most our work for us
29  $AcctList = TX_list($dbh, $HB_ENV);
30  if (!HCU_array_key_exists('acctlist', $AcctList)) {
31  throw new Exception ("Unable to load accounts.");
32  }
33  try {
34  //setting micraccount flag, only required if setup in accountspecs trusted detail
35  $micrFlg = false;
36  //pulling in vendor account specs, split by |
37  $accountspecs = explode("|", $parms['accountspecs']);
38  //trimming whitespace
39  $accountspecs = array_map('trim', $accountspecs);
40  if (in_array('micraccount', $accountspecs)){
41  $micrFlg = true;
42  }
43 
44  //extracting only the data we need into new array
45  foreach($AcctList['acctlist'] as $key=>$value){
46  $outputElem = array();
47  //checking for only deposit accounts, acctclass = D
48  //checking for available balances over $0, available: > 0
49  //checking for authorization to pay to external accounts, to_ext = Y
50  //checking if micr is required from accountspecs, if so then check
51  //that micraccount is not empty
52  // 10/22 $value['available'] was checking !=0, allowed neg. numbers to get in list
53  if ( $value['acctclass'] == 'D' && $value['available'] > 0
54  && $value['to_ext'] == 'Y' && ( !$micrFlg || ($micrFlg &&
55  $value['micraccount'] != '' && $value['micraccount'] != '0' ))) {
56  $outputElem['micraccount'] = $value['micraccount'];
57  $outputElem['suffix'] = $value['suffix'];
58  $outputElem['name'] = $value['description'];
59  $outputElem['class'] = $value['acctclass'];
60  //deposittype = Y, N, or S - Yes = Checking, N and S = Savings
61  $outputElem['type'] = ($value['deposittype'] == 'Y' ? 'Checking' : 'Savings');
62  $outputElem['balance'] = $value['available'];
63  $outputElem['toext'] = $value['to_ext'];
64  $outputElem['member'] = $value['member'];
65  //print_r($accountspecs);
66  $account = '';
67  //setting account number based on specs
68  foreach($accountspecs as $k=>$v){
69  $positions = array();
70  $start = 0;
71  $length = 0;
72  $cleanv = trim($v);
73  $fieldspec = explode("(", $cleanv);
74  $fieldname = trim($fieldspec[0]);
75  //print_r($fieldspec);
76  // $positions = explode(",", $fieldspec[1]);
77  if(isset($fieldspec[1])){
78  $positions = explode(",", rtrim($fieldspec[1], ")"));
79  }
80  if(!empty($positions)){
81  if (!empty($positions[0])){
82  $start = $positions[0];
83  }
84  if (!empty($positions[1])){
85  $length = $positions[1];
86  }
87  }
88 
89  foreach ($value as $k1=>$v1){
90  //if given a substring
91  if ($fieldname == $k1 && !empty($start) && !empty($length)){
92  $account .= substr($value[$k1], $start-1, $length);
93  //if no substring value, take whole field value
94  } elseif ($fieldname == $k1) {
95  $account .= $value[$k1];
96  }
97  }
98  }
99  //appending account type to accountid
100  if($outputElem['type'] == 'Checking'){
101  $account .= '|D';
102  }
103  else if ($outputElem['type'] == 'Savings'){
104  $account .= '|S';
105  }
106  //print_r($account);
107 
108  $acctIdEncrypted = hcu_encrypturl( $account, $HB_ENV['historyHash'] );
109 
110  $outputElem['accountid'] = $acctIdEncrypted;
111  //$outputElem['accountid'] = $account;
112  $output[] = $outputElem;
113 
114  }
115  }
116  if(empty($output)){
117  //no acceptable accounts
118  $AcctList['status']['response'] = 'false';
119  $AcctList['status']['code'] = '910';
120  $AcctList['status']['message'] = 'No elibigle pay from accounts found.';
121  return ($AcctList);
122  }
123  #normalize the name for scalability
124  $cleanlist = $output;
125  $return["status"]["response"] = 'true';
126  $return["status"]["message"] = 'Success';
127  $return["data"] = $cleanlist;
128 
129  } catch (Exception $e) {
130  $return['status']['response'] = 'false';
131  $return['status']['message'] = $e->getMessage();
132  $return['status']['code'] = $e->getCode();
133  $return['data'] = array();
134  }
135  return $return;
136 }
137 
138 /**
139  *
140  *
141  * @param $soapString
142  * @param $soapHeaders
143  * @param $soapServer
144  * @param $soapCertfile
145  * @param $soapKeyfile
146  * @param $soapCACert
147  */
148 function embcurl($soapString, $soapHeaders, $soapServer, $soapCertfile='', $soapKeyfile='', $soapCACert='') {
149  $useEmbedded = true;
150 
151  if ($useEmbedded) {
152  $curlopts = array(
153  CURLOPT_SSL_VERIFYPEER => 0,
154  CURLOPT_RETURNTRANSFER => 1,
155  CURLOPT_HEADER => 0,
156  CURLOPT_POST => 1,
157  CURLOPT_POSTFIELDS => "$soapString",
158  CURLOPT_URL => "$soapServer");
159  if (!empty($soapCertfile)) {
160  $curlopts[CURLOPT_SSLCERT] = "$soapCertfile";
161  }
162  if (!empty($soapKeyfile)) {
163  $curlopts[CURLOPT_SSLKEY] = "$soapKeyfile";
164  }
165  if (!empty($soapCACert)) {
166  $curlopts[CURLOPT_CAINFO] = "$soapCACert";
167  }
168 
169  $ch = @curl_init();
170  @curl_setopt_array($ch, $curlopts);
171  @curl_setopt($ch, CURLOPT_HTTPHEADER, $soapHeaders);
172 
173  $response = @curl_exec($ch);
174 
175 
176  if (curl_errno($ch)) {
177  $response = '';
178  }
179  @curl_close($ch);
180  } else {
181  // * Call to Command-line curl command
182 
183  // * build the command line call
184  // ** Data value
185  $clData = "--data-binary '$soapString' ";
186 
187  // * *Build Headers
188  if (is_array($soapHeaders)) {
189  foreach ($soapHeaders as $hdrLine) {
190  $clHeaders .= "-H '$hdrLine' ";
191  }
192  }
193  // * Include Cert File
194  if (!empty($soapCertfile)) {
195  $clCert = "--cert '$soapCertfile' ";
196  }
197  // * Include Key File
198  if (!empty($soapKeyfile)) {
199  $clKey= "--key '$soapKeyfile' ";
200  }
201  // * Include CA File
202  if (!empty($soapCACert)) {
203  $clCA = "--cacert $soapCACert";
204  }
205 
206  // ** Soap Action
207  $clAction = "'$soapServer'";
208 
209  $curlExec = "/usr/bin/curl $clData $clHeaders $clCert $clKey $clCA $clAction";
210 
211  $clCurl = popen($curlExec, "r");
212  $response = '';
213 
214  if (!$clCurl) {
215  $response = '';
216  } else {
217  while ($buff = fread ($clCurl, 1500)) {
218  $response .= $buff;
219  }
220  $pipe_err = pclose($clCurl);
221  }
222 
223  }
224  return $response;
225 }
226 
227 /**
228  * Returns the data response from the service calls
229  * to an array
230  *
231  * @param $object the data response passed from the service call
232  * @return array list of response messages and data
233  */
234 function objectToArray( $object ) {
235  if( !is_object( $object ) && !is_array( $object ) ) {
236  return $object;
237  }
238  if( is_object( $object ) ) {
239  $object = get_object_vars( $object );
240  }
241  return array_map( 'objectToArray', $object );
242 }
243 
244 /**
245  * Returns an array without duplicate values based
246  * on the key
247  *
248  * @param $array the array to have duplicates removed
249  * @param $key the key you want to removal based on
250  * @return array list with duplicates removed
251  */
252 function UniqueMultidimArray($array, $key){
253  $temp_array = array();
254  $i = 0;
255  $key_array = array();
256 
257  foreach($array as $val) {
258  if (!in_array($val[$key], $key_array)) {
259  $key_array[$i] = $val[$key];
260  $temp_array[$i] = $val;
261  }
262  $i++;
263  }
264  return $temp_array;
265 }
266 
267 /**
268  * Read the cache value for a given list.
269  *
270  * @param dbhandle $dbh database handle
271  * @param $user memberId
272  * @param $subscriber subscriberId
273  * @param $cu credit union
274  * @param $cacheType name of cache key
275  * @param $session session token
276  * @return array row of cached data
277  */
278 function ReadCache($dbh, $user, $subscriber, $cu, $cacheType, $session) {
279 
280  $sql = "SELECT session, entry, data
281  FROM cu_vendorcache
282  WHERE cu = '$cu'
283  AND username = '$user'
284  AND subscriber = '$subscriber'
285  AND type = '$cacheType'";
286 
287  $rs = db_query( $sql, $dbh );
288 
289  // check for mulitple ebpntries in case some error caused multiple entries to exist
290  $returnData = "";
291  $row = 0;
292  while ($cacheRow = db_fetch_array($rs, $row++)) {
293  // if already have found data, remove any more
294  if ( strlen( $returnData ) > 0 ) {
295  DeleteCache($dbh, $user, $subscriber, $cu, $cacheType, $cacheRow["session"], $cacheRow["entry"]);
296  } else if ( $cacheRow["session"] == $session ) {
297  // valid session, return the data
298  $returnData = $cacheRow["data"];
299  } else {
300  // invalid session, remove this entry
301  DeleteCache($dbh, $user, $subscriber, $cu, $cacheType, $cacheRow["session"], "");
302  }
303  }
304 
305  $returnStructure = json_decode( $returnData, true );
306 
307  return $returnStructure;
308 }
309 
310 /**
311  * Delete a given cache entry.
312  * This is how the cache is flagged as flushed.
313  * Use the $cacheType, $session, and/or $timestamp to refine how much cache to flush.
314  *
315  * @param dbhandle $dbh database handle
316  * @param $user memberId
317  * @param $subscriber subscriberId
318  * @param $cu credit union
319  * @param $cacheType name of cache key
320  * @param $session session token
321  * @param $timestamp user timestamp
322  */
323 function DeleteCache($dbh, $user, $subscriber, $cu, $cacheType, $session, $timestamp) {
324  $sql = "DELETE FROM cu_vendorcache
325  WHERE cu = '$cu'
326  AND username = '$user'
327  AND subscriber = '$subscriber'";
328 
329  if ( strlen( $cacheType ) ) {
330  $sql .= " AND type = '$cacheType'";
331  }
332 
333  if ( strlen( $session ) ) {
334  $sql .= " AND session = '$session'";
335  }
336 
337  if ( strlen( $timestamp ) ) {
338  $sql .= " AND entry = '$timestamp'";
339  }
340  db_query( $sql, $dbh );
341 }
342 
343 /**
344  * Write the cache value for a given list.
345  *
346  * @param dbhandle $dbh database handle
347  * @param $user memberId
348  * @param $subscriber subscriberId
349  * @param $cu credit union
350  * @param $cacheType name of cache key
351  * @param $session session token
352  * @param $data expected as a structure
353  * @return cached values as data structure
354  */
355 function WriteCache($dbh, $user, $subscriber, $cu, $cacheType, $session, $data) {
356  // we need every variable
357  if ( !$dbh || !$user || !$subscriber || !$cu || !$cacheType || !$session || !$data ) {
358  return;
359  }
360 
361  try {
362  // convert to a json object
363  $jsonData = json_encode( $data );
364  } catch ( Exception $e ) {
365  $jsonData = "";
366  }
367  //print "Here in Write $jsonData";
368  if ( strlen( $jsonData ) ) {
369  $jsonData = pg_escape_string($jsonData); // handle quoting, etc
370 
371  $sql = "INSERT INTO cu_vendorcache (cu, username, subscriber, session, type, data)
372  VALUES ('$cu', '$user', '$subscriber', '$session', '$cacheType', '$jsonData' )";
373  //print "About to write: $sql";
374  $result = db_query( $sql, $dbh );
375  }
376 }
377 
378 /**
379  * Inserts a log entry for each service call.
380  * Records both the request and the reply.
381  *
382  * @param array $logData (logPoint, token, txnId, request, reply, memberId
383  * userIP, SSOVendor)
384  */
385 function LogActivity( $logData ) {
386  // make sure entry isn't too long
387  $logPoint = substr( $logData["logPoint"], 0, 35 );
388  $sessionId = substr( $logData["token"], -20 ); // assuming lower characters are more significant
389  $txnId = substr( $logData["txnId"], -20 ); // assuming lower characters are more significant
390  $request = pg_escape_string(trim($logData["request"])); // handle quoting, etc
391  $reply = pg_escape_string(trim($logData["reply"])); // handle quoting, etc
392 
393 
394  // entry time is added automatically
395  $sql = "INSERT INTO cu_vendorlog (cu, user_id, service, sub_service,
396  session_id, txn_id, user_ip, request, response)
397  VALUES ('{$logData["Cu"]}', '{$logData["memberId"]}', '{$logData["SSOVendor"]}',
398  '$logPoint', '$sessionId', '$txnId',
399  '{$logData["userIP"]}', '$request', '$reply')";
400 
401  db_query($sql, $logData["dbConn"] );
402 
403 }
404 
405 /**
406  * Creates guid for use as a log tracking id
407  * in the soap message headers
408  */
409 function getGUID(){
410  mt_srand((double)microtime()*10000);//optional for php 4.2.0 and up.
411  $charid = strtoupper(md5(uniqid(rand(), true)));
412  $hyphen = chr(45);// "-"
413  $uuid = chr(123)// "{"
414  .substr($charid, 0, 8).$hyphen
415  .substr($charid, 8, 4).$hyphen
416  .substr($charid,12, 4).$hyphen
417  .substr($charid,16, 4).$hyphen
418  .substr($charid,20,12)
419  .chr(125);// "}"
420  return $uuid;
421 
422 }
423 
424 /**
425  * Return the list of states to use for a State drop-down list.
426  * NOTE: this is formatted for use with a Kendo DropdownList.
427  */
428 function GetBPStateList() {
429  $states = array(
430  [ "name"=>'Alabama', "value"=>'AL'],
431  [ "name"=>'Alaska', "value"=>'AK'],
432  [ "name"=>'Arizona', "value"=>'AZ'],
433  [ "name"=>'Arkansas', "value"=>'AR'],
434  [ "name"=>'California', "value"=>'CA'],
435  [ "name"=>'Colorado', "value"=>'CO'],
436  [ "name"=>'Connecticut', "value"=>'CT'],
437  [ "name"=>'Delaware', "value"=>'DE'],
438  [ "name"=>'Florida', "value"=>'FL'],
439  [ "name"=>'Georgia', "value"=>'GA'],
440  [ "name"=>'Hawaii', "value"=>'HI'],
441  [ "name"=>'Idaho', "value"=>'ID'],
442  [ "name"=>'Illinois', "value"=>'IL'],
443  [ "name"=>'Indiana', "value"=>'IN'],
444  [ "name"=>'Iowa', "value"=>'IA'],
445  [ "name"=>'Kansas', "value"=>'KS'],
446  [ "name"=>'Kentucky', "value"=>'KY'],
447  [ "name"=>'Louisiana', "value"=>'LA'],
448  [ "name"=>'Maine', "value"=>'ME'],
449  [ "name"=>'Maryland', "value"=>'MD'],
450  [ "name"=>'Massachusetts', "value"=>'MA'],
451  [ "name"=>'Michigan', "value"=>'MI'],
452  [ "name"=>'Minnesota', "value"=>'MN'],
453  [ "name"=>'Mississippi', "value"=>'MS'],
454  [ "name"=>'Missouri', "value"=>'MO'],
455  [ "name"=>'Montana', "value"=>'MT'],
456  [ "name"=>'Nebraska', "value"=>'NE'],
457  [ "name"=>'Nevada', "value"=>'NV'],
458  [ "name"=>'New Hampshire', "value"=>'NH'],
459  [ "name"=>'New Jersey', "value"=>'NJ'],
460  [ "name"=>'New Mexico', "value"=>'NM'],
461  [ "name"=>'New York', "value"=>'NY'],
462  [ "name"=>'North Carolina', "value"=>'NC'],
463  [ "name"=>'North Dakota', "value"=>'ND'],
464  [ "name"=>'Ohio', "value"=>'OH'],
465  [ "name"=>'Oklahoma', "value"=>'OK'],
466  [ "name"=>'Oregon', "value"=>'OR'],
467  [ "name"=>'Pennsylvania', "value"=>'PA'],
468  [ "name"=>'Rhode Island', "value"=>'RI'],
469  [ "name"=>'South Carolina', "value"=>'SC'],
470  [ "name"=>'South Dakota', "value"=>'SD'],
471  [ "name"=>'Tennessee', "value"=>'TN'],
472  [ "name"=>'Texas', "value"=>'TX'],
473  [ "name"=>'Utah', "value"=>'UT'],
474  [ "name"=>'Vermont', "value"=>'VT'],
475  [ "name"=>'Virginia', "value"=>'VA'],
476  [ "name"=>'Washington', "value"=>'WA'],
477  [ "name"=>'West Virginia', "value"=>'WV'],
478  [ "name"=>'Wisconsin', "value"=>'WI'],
479  [ "name"=>'Wyoming', "value"=>'WY']
480  );
481 
482  // $provinces = array(
483  // [ "name"=>'Alberta', "value" => 'AB' ],
484  // [ "name"=>'British Columbia', "value" => 'BC' ],
485  // [ "name"=>'Manitoba', "value" => 'MB' ],
486  // [ "name"=>'New Brunswick', "value" => 'NB' ],
487  // [ "name"=>'Newfoundland and Labrador', "value" => 'NL' ],
488  // [ "name"=>'Nova Scotia', "value" => 'NS' ],
489  // [ "name"=>'Ontario', "value" => 'ON' ],
490  // [ "name"=>'Prince Edward Island', "value" => 'PE' ],
491  // [ "name"=>'Saskatchewan', "value" => 'SK' ],
492  // [ "name"=>'Quebec', "value" => 'QC' ]
493  // );
494 
495  // $caribbean = array(
496  // [ "name"=>'US Virgin Islands', "value" => 'VI' ],
497  // [ "name"=>'Trinidad and Tobago', "value" => 'TT' ]
498  // );
499  // put them together and return them
500  // $returnData = array_merge( $states, $provinces, $caribbean );
501  $returnData = $states;
502  return $returnData;
503 }
504 
505 /**
506  * Return the list of phone types to use for a phone type drop-down list.
507  * NOTE: this is formatted for use with a Kendo DropdownList.
508  * NOTE: this is not currently used, but may be needed for future use
509  */
510 function GetPhoneTypes(){
511  $types = array(
512  [ "name"=>'Home', "code"=>'Home'],
513  [ "name"=>'Cell', "code"=>'Cell'],
514  [ "name"=>'Work', "code"=>'Work'],
515  );
516  $returnData = $types;
517  return $returnData;
518 
519 }
520 
521 /**
522  * Return the list of account types to use for a account type drop-down list.
523  * NOTE: this is formatted for use with a Kendo DropdownList.
524  */
525 function GetBPAccountTypes($MC){
526  $types = array(
527  [ "name"=>$MC->msg('Checking'), "value"=>'D'],
528  [ "name"=>$MC->msg('Savings'), "value"=>'S'],
529  );
530  $returnData = $types;
531  return $returnData;
532 
533 }
534 
535 /**
536  * Return the list of p2p types to use for a p2p type drop-down list.
537  * NOTE: this is formatted for use with a Kendo DropdownList.
538  */
539 function GetBPP2PTypes($MC){
540  $types = array(
541  [ "name"=>$MC->msg('Text'), "value"=>'SMS'],
542  [ "name"=>$MC->msg('Email'), "value"=>'Email'],
543  );
544  $returnData = $types;
545  return $returnData;
546 
547 }
548 
549 /**
550  * Return the list of billing frequencies to use for a drop-down list.
551  * Should be used for new payments and transfers
552  * NOTE: this is formatted for use with a Kendo DropdownList.
553  */
554 function GetBillingFreq($MC){
555  $types = array(
556  [ "name"=>$MC->msg('Once'), "value"=>'Once', "isDeleted"=>false],
557  [ "name"=>$MC->msg('Weekly'), "value"=>'Weekly', "isDeleted"=>false],
558  [ "name"=>$MC->msg('Monthly'), "value"=>'Monthly', "isDeleted"=>false],
559  [ "name"=>$MC->msg('Annually'), "value"=>'Annual', "isDeleted"=>false],
560  );
561  $returnData = $types;
562  return $returnData;
563 }