Odyssey
rdcVSoft.i
1 <?php
2 /*
3  * 7/15/2019
4  * Updated from Mammoth - By Erin
5  *
6  * 2/6/2019
7  * Vsoft presented new specs for Parthenon. Specs changed some. Sent this email
8  * Date: February 6, 2019 at 12:06:27 PM MST
9  * To: ishwar.viswanathan@vsoftcorp.com
10  * Cc: Jeff Mowery <jeff.mowery@vsoftcorp.com>,
11  * Rod Hamilton <rod.hamilton@vsoftcorp.com>,
12  * Buddy Heywood <buddy@homecu.com>
13  *
14  * We currently have 4 other clients using Vsoft mobile deposit, all of whom are
15  * using the older 1.5 / 1.9 version. These 4 clients are connecting to
16  * https://saas5.deposit2day.com/ValidationService.Base1/VSoftRemoteSvc.asmx for
17  * processing. In addition we have another client currently gearing up to use
18  * the product, currently in test mode. That client uses URL
19  * https://scbc1.creditunionimages.com/ValidationService/VSoftRemoteSvc.asmx
20  * which appears to be the older version as well.
21  *
22  * Our current product was originally coded for version 1.5. We updated for
23  * version 1.9, but at the time we did that 1.9 was in QA rather than full
24  * production. As a result, our product does not use the transaction history
25  * calls which were added between 1.5 and 1.9. The new specs are version 6.0.9.
26  * The version history indicates a change to the format for Amount and Account
27  * number, as well as some new calls.
28  *
29  * The change to the format for Amount concerns me. We are currently passing
30  * the dollar amount of the check formatted as currency with a decimal. The
31  * updated specs note that the amount should be stated in cents instead. While
32  * that is a reasonably easy change with regard to programming, I need to be
33  * careful not to disrupt the existing clients. Because of that, I intend to
34  * make the amount format a configurable setting so that existing clients can
35  * continue to do what they do and this new client can use the updated specs.
36  *
37  * Also, the WSDL file provided during our initial coding for versions 1.5 / 1.9
38  * included an XML tag <ReturnImage> defined as boolean in the ?Process Request?
39  * call. This tag was not in any of the printed documentation, but was marked as
40  * required in the WSDL, so we pass it along with a value of false. Will the
41  * new version tolerate the presence of this tag? Will removing it be a problem
42  * for the existing clients using the older version? I will probably tie that
43  * to the same configuration option controlling the amount format to minimize
44  * the impact for existing clients.
45  *
46  * After the email, realized:
47  * PFFCU merged w/someone and abandoned the RDC implementation, never went live
48  * DTCU, JAFCU, SONOMA hit saas5.deposit2day URL
49  * FLCCU is testing, hits scbc1.creditunionimages URL
50  * PARTH is to hit vantage-consumermobile-uat.vsoft-us.com
51  *
52  * * Coding changes today (Feb 2019) include:
53  * Don't try to recycle curdcstatus records. Just build a new one
54  * Don't save terms doc in vendor info array. Pass as localTerms
55  * Clean up logging so check images are not stuffed in db
56  *
57  * Note that following changes were backed out since VSoft indicated
58  * differences are backward-compatible
59  * Use trustedDetail parms['APIVersion'] to indicate Vsoft version.
60  * Default to version 1, mark as 6 if applicable
61  * Adjust Process call to fix XML based on APIVersion
62  */
63 
64 function RDCconfig($dbh, &$parms) {
65  $parms['pilot'] = (!isset($parms['pilot']) ? 0 : $parms['pilot']);
66  $parms['serviceurl'] = ($parms['pilot'] == 0 ? $parms['prodURL'] : $parms['pilotURL']);
67  $parms['acctttl'] = (!isset($parms['acctttl']) ? 'Select account' : $parms['acctttl']);
68  $parms['descttl'] = (!isset($parms['descttl']) ? 'Description' : $parms['descttl']);
69 }
70 
71 /**
72  * requires: $parms['Cu']
73  * $parms['rdcvendor']
74  * Additional values rdcvendor retrieved and decoded from cutrusteddetail
75  * returns:
76  */
77 function RDCauth($dbh, $HB_ENV, $MC, $parms) {
78  // assume we are going to succeed...
79  $return['status']['response'] = 'true';
80  $return['status']['code'] = '000';
81  $return['status']['message'] = 'Success';
82  $localTerms = '';
83 
84  try {
85  $parms['Fset2'] = $HB_ENV['Fset2']; // HB_ENV
86  $hculist = RDCGetAccts($dbh, $parms);
87 
88  if ($hculist['status']['response'] == 'false') {
89  throw new Exception($hculist['status']['message'], $hculist['status']['code']);
90  }
91 
92  if ($hculist['status']['response'] == 'false') {
93  // return error
94  throw new Exception($hculist['status']['message'], $hculist['status']['code']);
95  }
96 
97  // got a valid RDC account list
98  // Vsoft uses cuusers.depositlimit as vsoft profile ID
99  // if $parms['HomeCUAuth'] is set, zero means member not authorized
100  // otherwise, zero means use default profileID from trusteddetail record
101 
102  $mbr_rdc = Get_RDCSetting($dbh, $HB_ENV, $parms['rdcvendor'], $parms['MBRACCT']);
103 
104 
105  if ($mbr_rdc['status']['code'] != '000') {
106  $dl = 0;
107  } else {
108  $dl = abs(intval(HCU_array_key_value('rdcsetting', $mbr_rdc)));
109  }
110 
111  if ($parms['HomeCUAuth']) {
112  // pre-authorizing through HomeCU, retrieve the member rdc setting
113  if ($dl == 0) {
114  $HB_Notices_ary = Get_NoticeInfo($dbh, $HB_ENV, $MC, 'M', "mblNoRDC", true);
115 
116  if ($HB_Notices_ary['status']['code'] == '000' && isset($HB_Notices_ary["notice"][0])) {
117  $noticeData = $HB_Notices_ary["notice"][0]["notice_text"];
118  } else {
119  $noticeData = "";
120  }
121  if (strlen($noticeData)) {
122  $message = $noticeData;
123  $code = 111;
124  } else {
125  $message = "Account not permitted for Remote Deposit. Please contact the Credit Union for more information";
126  $code = 110;
127  }
128  throw new Exception($message, $code);
129  }
130  } else {
131 
132  // Not authorizing thru HCU, everybody swims,
133  // use default profileID if depositlimit not set
134 
135  // First, get a default profileID from $parms if there is one
136  $pro = abs(intval(HCU_array_key_value('profileID', $parms)));
137 
138  // If $dl (retrieved from member deposit limit setting) is zero, use $pro
139  $dl = ($dl == 0 ? $pro : $dl);
140  }
141 
142 
143  $parms['depositlimit'] = abs(intval($dl));
144  // Just get a new deposit record every time. Not tied
145  // to shared branching, so no cost implication for client?
146  $newrec = 1;
147  $rdcterms = array();
148  $parms['rdcstatus'] = 'S';
149 
150  if (HCU_array_key_value('HomeCUterms', $parms)) {
151  $rdcterms = hcuGetRDCterms($dbh, $HB_ENV, $MC);
152  if ($rdcterms['status']['response'] == 'false') {
153  $e = "HCU GetTerms call failed ({$rdcterms['status']['code']} {$rdcterms['status']['message']}";
154  throw new Exception($e, 301);
155  }
156  if ($rdcterms['data']['notice_popup'] == 1) {
157  $parms['rdcstatus'] = 'T';
158  } else {
159  $rdcterms = array();
160  $parms['rdcstatus'] = 'S';
161  }
162  $localTerms = HCU_array_key_value('terms', $rdcterms['data']);
163  }
164 
165  // $rdcresult = array();
166  // get account list from HomeCU
167  $return = RDCPresentAccounts($parms, $hculist, $rdcterms);
168  if ($return['status']['response'] == 'false') {
169  // error send fail
170  throw new Exception($return['status']['message'], $return['status']['code']);
171  }
172 
173  $parms['vendorinfo'] = array(
174  "Vendortime" => mktime(),
175  "userAgent" => $_SERVER['HTTP_USER_AGENT'],
176  "userIP" => $_SERVER['REMOTE_ADDR'],
177  "accounts" => $return['data']['accounts'],
178  "depositlimit" => intval($dl)
179  );
180 
181  if ($newrec) {
182  // start curdc record, return depositid as part of result
183  $depostat = curdc_start($dbh, $parms);
184  if ($depostat['status']['response'] == 'false') {
185  // error send fail
186  throw new Exception('HomeCU Start Deposit Failed', 200);
187  }
188  $parms['depositid'] = $depostat['data']['depositid'];
189  }
190  $return['data']['depositid'] = $parms['depositid'];
191  $return['data']['accounts'] = $parms['vendorinfo']['accounts'];
192  $return['data']['terms'] = $localTerms;
193 
194  $depostat = curdc_setvinfo($dbh, array(
195  'Cu' => $parms['Cu'], 'depositid' => $parms['depositid'],
196  'vendorinfo' => json_encode($parms['vendorinfo'])
197  ));
198  if ($depostat['status']['response'] == 'false') {
199  // error send fail
200  throw new Exception($depostat['status']['message'], $depostat['status']['code']);
201  }
202  } catch (Exception $e) {
203  $return['status']['response'] = 'false';
204  $return['status']['code'] = $e->getCode();
205  $return['status']['message'] = "(" . $e->getLine() . ") " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8', FALSE);
206  }
207  return $return;
208 }
209 
210 /**
211  * requires: $parms['Cu']
212  * $parms['depositid']
213  * Additional values retrieved and decoded from cutrusteddetail
214  * or from curdcstatus record using depositid as key
215  */
216 function RDCaccept($dbh, $HB_ENV, $MC, $parms) {
217  // assume we are going to succeed...
218  $return['status']['response'] = 'true';
219  $return['status']['code'] = '000';
220  $return['status']['message'] = 'Success';
221 
222  try {
223  if (!isset($parms['Cu']) || !isset($parms['depositid'])) {
224  throw new Exception('Missing Parameters', 100);
225  }
226  // look up depositid
227  // decode vendorinfo
228  $depo = curdc_read($dbh, $parms);
229  if ($depo['status']['response'] == 'false') {
230  throw new Exception('HomeCU DepositID not found', 205);
231  }
232 
233  // look up rdcTerms doc and then update to show acceptance
234  // get any notice text
235  $noticeInfo = Get_NoticeInfo($dbh, $HB_ENV, $MC, "P", "rdcTerms", false);
236  if ($noticeInfo["status"]["code"] == "000" && sizeof($noticeInfo['notice']) && intval($noticeInfo['notice'][0]['notice_id']) > 0) {
237  // action P post so set up the HCUPOST array
238  $HB_ENV['HCUPOST']['notice_id'] = $noticeInfo['notice'][0]['notice_id'];
239  $HB_ENV['HCUPOST']['notice_type'] = $noticeInfo['notice'][0]['notice_type'];
240  $HB_ENV['HCUPOST']['notice_device'] = 'P';
241  $HB_ENV["HCUPOST"]['notice_response'] = array("answer" => 1); // something non-zero but numeric
242  // not sure if the next two are needed
243  $HB_ENV["HCUPOST"]['notice_cancel'] = "0";
244  $HB_ENV['HCUPOST']['notice_msg_show'] = 1;
245  $noticeUpd = Update_NoticeInfo($dbh, $HB_ENV, $MC);
246 
247  $return['status']['message'] = 'Accept Terms OK';
248  $vendorinfo = $depo['vendorinfo'];
249  $vendorinfo['terms'] = '';
250  $vendorinfo['Vendortime'] = mktime();
251  $parms['vendorinfo'] = $vendorinfo;
252  }
253 
254  // update curdcstatus record
255  $parms['rdcstatus'] = 'O';
256  // need setvinfo to update Vendortime, let setvinfo also set new status -- only one call required
257  $depostat = curdc_setvinfo($dbh, array(
258  'Cu' => $parms['Cu'], 'depositid' => $parms['depositid'],
259  'rdcstatus' => $parms['rdcstatus'], 'vendorinfo' => json_encode($parms['vendorinfo'])
260  ));
261  if ($depostat['status']['response'] == 'false') {
262  // error send fail
263  throw new Exception($depostat['status']['message'], $depostat['status']['code']);
264  }
265  } catch (Exception $e) {
266  $return['status']['response'] = 'false';
267  $return['status']['code'] = $e->getCode();
268  $return['status']['message'] = "(" . $e->getLine() . ") " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8', FALSE);
269  }
270  return $return;
271 }
272 
273 /**
274  * requires: $parms['Cu']
275  * $parms['depositid']
276  * Additional values retrieved and decoded from cutrusteddetail
277  * or from curdcstatus record using depositid as key
278  *
279  */
280 function RDChistorylist($dbh, $parms) {
281  // assume we are going to succeed...
282  $return['status']['response'] = 'true';
283  $return['status']['code'] = '000';
284  $return['status']['message'] = 'Success';
285 
286  try {
287  if (!isset($parms['Cu']) || !isset($parms['depositid'])) {
288  throw new Exception('Missing Parameters', 100);
289  }
290  // look up depositid
291  // decode vendorinfo
292  $depo = curdc_read($dbh, $parms);
293  if ($depo['status']['response'] == 'false') {
294  throw new Exception("HomeCU DepositID not found [{$parms['depositid']}]", 205);
295  }
296 
297  $rdcresult = vsoftHistory($parms);
298  // check return values for error
299  if ($rdcresult['status']['response'] == 'false') {
300  throw new Exception('Vsoft History call failed ' . $rdcresult['status']['message'], 305);
301  }
302 
303  //pulling from our records instead of from vendor
304  // $return['response'] = $rdcresult;
305  $return['status']['message'] = 'Vsoft History List OK';
306  // $vendorinfo = $depo['vendorinfo'];
307  $vendorinfo['Vendortime'] = mktime();
308  $parms['vendorinfo'] = $vendorinfo;
309 
310  // update curdcstatus record
311 
312  $depostat = curdc_setvinfo($dbh, array(
313  'Cu' => $parms['Cu'], 'depositid' => $parms['depositid'],
314  'vendorinfo' => json_encode($parms['vendorinfo'])
315  ));
316  if ($depostat['status']['response'] == 'false') {
317  // error send fail
318  throw new Exception($depostat['status']['message'], $depostat['status']['code']);
319  }
320  $return['data']['TransactionList'] = $rdcresult['data'];
321  $return['data']['rdcvendor'] = $depo['data']['rdcvendor'];
322  } catch (Exception $e) {
323  $return['status']['response'] = 'false';
324  $return['status']['code'] = $e->getCode();
325  $return['status']['message'] = "(" . $e->getLine() . ") " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8', FALSE);
326  }
327  return $return;
328 }
329 
330 /**
331  * coded for Ensenta only?
332  * requires: $parms['Cu']
333  * $parms['transactionid']
334  * Additional values retrieved and decoded from cutrusteddetail
335  * or from curdcstatus record using depositid as key
336  */
337 function RDChistorydetl($dbh, $parms) {
338  // assume we are going to succeed...
339  $return['status']['response'] = 'true';
340  $return['status']['code'] = '000';
341  $return['status']['message'] = 'Success';
342 
343  try {
344  if (!isset($parms['Cu']) || !isset($parms['transactionid']) || !isset($parms['depositid'])) {
345  throw new Exception('Missing Parameters', 100);
346  }
347  // look up depositid
348  // decode vendorinfo
349  $depo = curdc_read($dbh, $parms);
350  if ($depo['status']['response'] == 'false') {
351  throw new Exception('HomeCU DepositID not found', 205);
352  }
353  // update curdcstatus record
354  $depostat = curdc_setvinfo($dbh, array(
355  'Cu' => $parms['Cu'], 'depositid' => $parms['depositid'],
356  'vendorinfo' => json_encode($parms['vendorinfo'])
357  ));
358  if ($depostat['status']['response'] == 'false') {
359  // error send fail
360  throw new Exception($depostat['status']['message'], $depostat['status']['code']);
361  }
362  $return['data'] = $rdcresult['data'];
363  } catch (Exception $e) {
364  $return['status']['response'] = 'false';
365  $return['status']['code'] = $e->getCode();
366  $return['status']['message'] = "(" . $e->getLine() . ") " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8', FALSE);
367  }
368  return $return;
369 }
370 
371 /**
372  * requires: $parms['Cu']
373  * $parms['depositid']
374  * $parms['amount']
375  * $parms['acctid']
376  * $parms['rdcacctid']
377  * Additional values retrieved and decoded from cutrusteddetail
378  * or from curdcstatus record using depositid as key
379  */
380 function RDCdeposit($dbh, $parms) {
381  // assume we are going to succeed...
382  $return['status']['response'] = 'true';
383  $return['status']['message'] = 'Success';
384  $return['status']['code'] = '000';
385  try {
386 
387  $parms['SessionId'] = time();
388 
389  if (
390  !isset($parms['Cu']) || !isset($parms['depositid']) ||
391  !isset($parms['amount']) || !isset($parms['acctid'])
392  ) {
393  throw new Exception('Missing Parameters', 100);
394  }
395  /*
396  * need to use $parms['acctid'] to retrieve info about receiving account
397  * get from vendorinfo[accounts] stored in deposit record, as that includes
398  * vendor-returned info
399  */
400 
401  // look up depositid
402  $depo = curdc_read($dbh, $parms);
403  if ($depo['status']['response'] == 'false') {
404  throw new Exception('HomeCU DepositID not found', 205);
405  }
406  $fail = '';
407  switch ($depo['data']['status']) {
408  case 'T':
409  $fail = 'Must accept terms of use before depositing funds';
410  break;
411  case 'R':
412  $fail = 'Deposit has been rejected';
413  break;
414  case 'C':
415  $fail = 'Deposit already completed';
416  break;
417  case 'B':
418  case 'F':
419  if (!isset($parms['POSTAWAY'])) {
420  $fail = 'Deposit requires override confirmation';
421  }
422  break;
423  }
424  if ("$fail" != '') {
425  throw new Exception($fail, 229);
426  }
427  if (is_null($depo['data']['frontpath']) || is_null($depo['data']['backpath']) || !getimagesize($depo['data']['frontpath']) || !getimagesize($depo['data']['backpath'])) {
428  throw new Exception('Check Images not found', 220);
429  }
430  $vendorinfo = $depo['data']['vendorinfo'];
431 
432  // Store amount, selected account in curdcstatus table
433  $depostat = curdc_update($dbh, array(
434  'Cu' => $parms['Cu'], 'depositid' => $parms['depositid'],
435  'amount' => $parms['amount'], 'acctid' => $parms['acctid']
436  ));
437  if ($depostat['status']['response'] == 'false') {
438  throw new Exception('HomeCU Update Deposit Amount Failed', 225);
439  }
440 
441  $acctid = $parms['acctid'];
442  $hculist = RDCGetAccts($dbh, $parms, $acctid);
443 
444  if ($hculist['status']['response'] !== 'true') {
445  throw new Exception('Invalid Deposit Account', 230);
446  }
447  $parms['depositlimit'] = $vendorinfo['depositlimit'];
448  $parms['depositAcct'] = $hculist['data'][$acctid]['suffix'];
449  switch ($hculist['data'][$acctid]['rdctype']) {
450  case 0:
451  $parms['depositType'] = 3;
452  break;
453  case 1:
454  $parms['depositType'] = 1;
455  break;
456  default:
457  $parms['depositType'] = 2;
458  break;
459  }
460 
461  /* vsoftStartTran needs these things filled in...
462  *
463  * $parms['InstID']
464  * $parms['serviceurl']
465  * $parms['Cn']
466  * $parms['depositAcct'] # suffix
467  * $parms['depositType'] #1=checking 2=gl 3=savings
468  * $parms['depositlimit']
469  *
470  */
471 
472  $vsofttran = vsoftStartTran($parms);
473 
474  if ($vsofttran['status']['response'] !== 'true') {
475  throw new Exception('Start Session failed' . $vsofttran['status']['message'], 231);
476  }
477 
478 
479  /* vsoftProcess needs these things filled in...
480  *
481  * $parms['SessionId']
482  * $parms['serviceurl']
483  * $parms['amount']
484  * $parms['FrontImage']
485  * $parms['RearImage']
486  *
487  */
488  $parms['SessionId'] = $vsofttran['data']['SessionId'];
489  $parms['FrontImage'] = base64_encode(file_get_contents($depo['data']['frontpath']));
490  $parms['RearImage'] = base64_encode(file_get_contents($depo['data']['backpath']));
491  $rdcresult = vsoftProcess($parms);
492 
493  if ($rdcresult['status']['response'] == 'false') {
494  throw new Exception('Deposit failed ' . $rdcresult['status']['message'], 243);
495  }
496 
497 
498  // check return values for error
499  if ($rdcresult['data']['ReturnValue'] !== 'true') {
500  # process was rejected - figure out why
501  $rejectfor = "{$rdcresult['data']['ErrorCode']} - {$rdcresult['data']['ErrorDesc']}";
502  $parms['rdcstatus'] = 'R';
503  $vendorinfo['Vendortime'] = mktime();
504  $vendorinfo['DepositStatus'] = $rejectfor;
505  $vendorinfo['DepositTime'] = date('YmdHis');
506  $depostat = curdc_setvinfo($dbh, array(
507  'Cu' => $parms['Cu'], 'depositid' => $parms['depositid'],
508  'rdcstatus' => $parms['rdcstatus'], 'vendorinfo' => json_encode($vendorinfo)
509  ));
510  throw new Exception("Deposit Rejected: $rejectfor", 241);
511  } else {
512  // call vsoftACK to confirm deposit & show error if it fails
513  $parms['ReturnValue'] = 1; // complete transaction
514  $rdcresult = vsoftAck($parms);
515  if ($rdcresult['status']['response'] !== 'true' || $rdcresult['data']['ReturnValue'] !== 'true') {
516  if ($rdcresult['status']['response'] !== 'true') {
517  $rejectfor = $rdcresult['status']['message'];
518  } else {
519  $rejectfor = "{$rdcresult['data']['ErrorCode']} - {$rdcresult['data']['ErrorDesc']}";
520  }
521 
522  $parms['rdcstatus'] = 'R';
523  $vendorinfo['Vendortime'] = mktime();
524  $vendorinfo['DepositStatus'] = "VsoftACK failed: $rejectfor";
525  $vendorinfo['DepositTime'] = date('YmdHis');
526  $depostat = curdc_setvinfo($dbh, array(
527  'Cu' => $parms['Cu'], 'depositid' => $parms['depositid'],
528  'rdcstatus' => $parms['rdcstatus'], 'vendorinfo' => json_encode($vendorinfo)
529  ));
530 
531  throw new Exception("{$rdcresult['data']['ErrorCode']} - {$rdcresult['data']['ErrorDesc']}", 231);
532  }
533  $parms['rdcstatus'] = 'C';
534  $vendorinfo['Vendortime'] = mktime();
535  $vendorinfo['DepositStatus'] = "Complete";
536  $vendorinfo['TransactionReceiptNumber'] = $rdcresult['data']['ConfirmationId'];
537  $vendorinfo['TransactionDateTime'] = date('c');
538  $depostat = curdc_setvinfo($dbh, array(
539  'Cu' => $parms['Cu'], 'depositid' => $parms['depositid'], 'frontaccept' => 'Y',
540  'backaccept' => 'Y', 'rdcstatus' => $parms['rdcstatus'], 'vendorinfo' => json_encode($vendorinfo)
541  ));
542  if ($depostat['status']['response'] == 'false') {
543  throw new Exception('HomeCU Update Vendorinfo Failed', 240);
544  }
545  $return['status']['response'] = 'true';
546  $return['status']['message'] = 'Vsoft Deposit Complete';
547  // this returns everything from Ensenta, but that will be a problem if we add other vendors
548  // pick a list of stuff to return and be consistent for everyone?
549  $return['data'] = $rdcresult['data'];
550  $return['data']['depositid'] = $parms['depositid'];
551  $return['data']['rdcstatus'] = $parms['rdcstatus'];
552  // use the Ensenta names for values the apps look for --
553  $return['data']['TransactionReceiptNumber'] = $rdcresult['data']['ConfirmationId'];
554  $return['data']['TransactionDateTime'] = date('c');
555  $return['data']['MaskedAccountholderNumber'] = $vendorinfo['accounts'][$acctid]['suffix'];
556 
557  $hcumessage = "Your deposit request for account {$vendorinfo['accounts'][$acctid]['suffix']} has been received";
558  $hcumessage .= ". Your confirmation number is '{$rdcresult['data']['ConfirmationId']}'. ";
559  $hcumessage .= "Please save this number and refer to it if you need to contact the credit union regarding this transaction. ";
560 
561  $return['data']['HCUReceiptMessage'] = $hcumessage;
562  }
563  } catch (Exception $e) {
564  $return['status']['response'] = 'false';
565  $return['status']['code'] = $e->getCode();
566  $return['status']['message'] = "(" . $e->getLine() . ") " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8', FALSE);
567  }
568  return $return;
569 }
570 
571 function RDCGetAccts($dbh, $parms, $Acctid = "") {
572  $AcctList = array();
573 
574  if (!isset($parms['Cu']) || !isset($parms['Cn'])) {
575  $AcctList['status']['response'] = 'false';
576  $AcctList['status']['code'] = '910';
577  $AcctList['status']['message'] = 'Missing RDC Account Parameters'; // RDCGetAccts missing Cu/Cn
578 
579  return ($AcctList);
580  }
581 
582  $Cu = $parms['Cu'];
583  // $Cn = $parms['Cn'];
584  $Cn = $parms['MBRACCT'];
585  $Fset2 = $parms['Fset2'];
586  $balwhere = $parms['balwhere'];
587  $lnwhere = $parms['lnwhere'];
588 
589  // default allow deposit, loan pmt, credit card pmt
590  $rtxn = (sizeof($parms['rtxn']) == 0 ?
591  array('AT' => 1, 'LP' => 1, 'CP' => 1) : json_decode($parms['rtxn'], TRUE));
592  $savingsql = (!isset($parms['savingsql']) ?
593  "trim(accounttype)" : $parms['savingsql']);
594  $draftsql = (!isset($parms['draftsql']) ?
595  "trim(accounttype)" : $parms['draftsql']);
596  $loansql = (!isset($parms['loansql']) ?
597  "trim(loannumber)" : $parms['loansql']);
598  $mbrsql = (!isset($parms['mbrsql']) ?
599  "trim(accountnumber)" : $parms['mbrsql']);
600 
601  // fetch transactions types
602  $sql = "select ht.trancode, trim(t.trandesc), trim(ht.cudesc), t.specialproc
603  from cutrans t, cuhavetrans ht
604  where ht.cu='$Cu'
605  and ht.trancode = t.trancode\n";
606 
607  $sth = db_query($sql, $dbh);
608  //
609  // Return a line for each allowed transaction type.
610  //
611  $txncodes = array();
612  for ($row = 0; list($code, $desc, $cudesc, $spec) = db_fetch_array($sth, $row); $row++) {
613  $txncodes{
614  $code} = array($desc, $spec, $cudesc);
615  }
616  db_free_result($sth);
617 
618  $sql = "";
619  $verb = "";
620 
621  // 1/23/2018
622  // The *_rdctype parms don't appear to be used by VSoft at this time. (VSoft
623  // TrustedMaster doesn't define these parms.) Changed to uppercase leading letter
624  // to be consistent with Bluepoint, TranzCap, and Digiliti. Ensenta is an oddball
625  $sv_rdctype = (!isset($parms['Sv_rdctype']) ? '0' : $parms['Sv_rdctype']);
626  $ck_rdctype = (!isset($parms['Ck_rdctype']) ? '1' : $parms['Ck_rdctype']);
627  $ln_rdctype = (!isset($parms['Ln_rdctype']) ? '128' : $parms['Ln_rdctype']);
628  // str_word_count code was trying to:
629  // if the rdctype is all digits, leave it plain else wrap in single quotes for Postgres
630  // but didn't work as expected. VSoft doesn't even use the *_rdctype parameters
631  // probably should remove this, but will need testing to make sure nothing breaks.
632  $sv_rdctype = (str_word_count($sv_rdctype, 0, '0123456789') > 1 ? $sv_rdctype : "'$sv_rdctype'");
633  $ck_rdctype = (str_word_count($ck_rdctype, 0, '0123456789') > 1 ? $ck_rdctype : "'$ck_rdctype'");
634  $ln_rdctype = (str_word_count($ln_rdctype, 0, '0123456789') > 1 ? $ln_rdctype : "'$ln_rdctype'");
635 
636  // find out how many valid accounts the member has:
637 
638  if (HCU_array_key_exists('AT', $txncodes) && HCU_array_key_exists('AT', $rtxn)) {
639  // $txncodes is configured list @HCU - $rtxn is allowed list for RDC
640  // rdctype 0 Savings, 1 Checking, 128 Installment Loan, 64 Credit Card
641  // NOTE: using 128 as no way to distinguish 32 Line-of-Credit or 256 Mortgage
642 
643  $sql = "SELECT 'D' as tbl,
644  $mbrsql as rdcmember, trim(description) as desc,
645  trim(accounttype) as accounttype, $savingsql as suffix, certnumber as cert,
646  $sv_rdctype as rdctype, 'SAVINGS ACCOUNT' as rdcdesc
647  FROM ${Cu}accountbalance
648  WHERE accountnumber = '$Cn' $balwhere
649  AND upper(deposittype) in ('S','N')
650  UNION
651  SELECT 'D', $mbrsql as rdcmember,
652  trim(description), trim(accounttype), $draftsql,
653  certnumber, $ck_rdctype, 'CHECKING ACCOUNT'
654  FROM ${Cu}accountbalance
655  WHERE accountnumber = '$Cn' $balwhere
656  AND upper(deposittype) = 'Y' ";
657 
658  $verb = " UNION ";
659  }
660 
661  if (HCU_array_key_exists('LP', $txncodes) && HCU_array_key_exists('LP', $rtxn)) {
662 
663  $sql .= "$verb
664  SELECT 'L', $mbrsql as rdcmember, trim(description),
665  trim(loannumber), $loansql,'0', $ln_rdctype, 'LOAN'
666  FROM ${Cu}loanbalance
667  WHERE accountnumber = '$Cn' $lnwhere
668  AND currentbalance >0 ";
669  if (($Fset2 & $CU2_SPEC18) == $CU2_SPEC18) {
670  $sql .= " and (type <> '18' or type is null) ";
671  if ($rtxn{"CP"}) {
672  $sql .= "UNION
673  SELECT 'C', $mbrsql as rdcmember, trim(description),
674  trim(loannumber), $loansql, '0', $ln_rdctype, 'CREDIT CARD'
675  FROM ${Cu}loanbalance
676  WHERE accountnumber = '$Cn' $lnwhere
677  AND type = '18' ";
678  if (($Fset2 & $CU2_CC18SHOWZERO) != $CU2_CC18SHOWZERO) {
679  $sql .= " and currentbalance > 0 ";
680  }
681  }
682  }
683  }
684  $sql .= " order by 5,2,3";
685  $acct_rs = db_query($sql, $dbh);
686 
687  if (db_num_rows($acct_rs) == 0) {
688  $AcctList['status']['response'] = 'false';
689  $AcctList['status']['code'] = '920';
690  $AcctList['status']['message'] = htmlspecialchars('No Eligible RDC <test>Accounts', ENT_QUOTES, 'UTF-8', FALSE); // RDCGetAccts no valid accounts
691  $AcctList['status']['sql'] = $sql;
692  } else {
693 
694  $AcctList['status']['response'] = 'true';
695  $AcctList['status']['code'] = '000';
696  $AcctList['status']['message'] = 'Success';
697  for ($row = 0; $drow = db_fetch_array($acct_rs, $row); $row++) {
698  $tbl = $drow['tbl'];
699  $desc = $drow['desc'];
700  $accounttype = $drow['accounttype'];
701  $suffix = $drow['suffix'];
702  $cert = $drow['cert'];
703  $rdctype = $drow['rdctype'];
704  switch ($rdctype) {
705  case '0':
706  $rdcdesc = 'Savings';
707  break;
708  case '1':
709  $rdcdesc = 'Checking';
710  break;
711  case '64':
712  $rdcdesc = 'CreditCard';
713  break;
714  case '128':
715  $rdcdesc = 'Loan';
716  break;
717  default:
718  $rdcdesc = 'Savings';
719  break;
720  }
721  $rdcmember = $drow['rdcmember'];
722  if (strpos($accounttype, "@")) {
723  list($jtype, $jacct) = explode("@", $accounttype);
724  $trust = 'joint';
725  } else {
726  $jtype = $accounttype;
727  $jacct = $Cn;
728  $trust = 'primary';
729  }
730  $tokn = sha1("${Cn}${accounttype}${Cu}${rdctype}obl1vi0u5");
731 
732  //$AcctList['data']["$tbl|$Cn|$accounttype|$cert"][micraccount]=$drow['micraccount'];
733 
734  $desc = ($desc == '' ? '_' : "$desc - $accounttype");
735  $desc = htmlspecialchars($desc, ENT_QUOTES, 'UTF-8', FALSE);
736  $displaydesc = ($cert == 0 ? "{$drow['desc']} - $accounttype" : "{$drow['desc']} # $cert - $accounttype");
737  $displaydesc = htmlspecialchars($displaydesc, ENT_QUOTES, 'UTF-8', FALSE);
738 
739  $Accts["$tbl|$jacct|$jtype|$cert"]['accounttype'] = $accounttype;
740  $Accts["$tbl|$jacct|$jtype|$cert"]['suffix'] = $suffix;
741  $Accts["$tbl|$jacct|$jtype|$cert"]['certnumber'] = $cert;
742  $Accts["$tbl|$jacct|$jtype|$cert"]['acctclass'] = $tbl;
743  $Accts["$tbl|$jacct|$jtype|$cert"]['description'] = $desc;
744  $Accts["$tbl|$jacct|$jtype|$cert"]['tokn'] = "$tokn";
745  $Accts["$tbl|$jacct|$jtype|$cert"]['member'] = "$Cn";
746  $Accts["$tbl|$jacct|$jtype|$cert"]['tomember'] = "$Cn";
747  $Accts["$tbl|$jacct|$jtype|$cert"]['trust'] = "$trust";
748  $Accts["$tbl|$jacct|$jtype|$cert"]['displaydesc'] = "$displaydesc";
749  $Accts["$tbl|$jacct|$jtype|$cert"]['rdctype'] = $rdctype;
750  $Accts["$tbl|$jacct|$jtype|$cert"]['rdcdesc'] = $rdcdesc;
751  $Accts["$tbl|$jacct|$jtype|$cert"]['rdcmember'] = $rdcmember;
752  }
753  }
754  if (!empty($Acctid)) {
755  // got an account identifier - return one only
756  $AcctList['data'][$Acctid] = $Accts[$Acctid];
757  } else {
758  $AcctList['data'] = $Accts;
759  }
760 
761  return ($AcctList);
762 }
763 
764 /**
765  *
766  * @param array $parms
767  * @param array $hculist
768  * valid RDC accounts on record at HomeCU
769  * @param type $rdcsent
770  * valid RDC accounts returned from vendor
771  * @param type $rdcterms
772  * terms of use returned from vendor
773  * @return array
774  * ['data'][accounts] list of valid accounts
775  * each entry looks like this:
776  * [D|666665|50|0] => Array
777  (
778  ['suffix'] => 50
779  ['certnumber'] => 0
780  ['acctclass'] => D
781  ['description'] => REGULAR SHARES - 50
782  ['tokn'] => a9a525ac33035b7c3845809443c5eed626297e0f
783  ['member'] => 666665
784  ['tomember'] => 666665
785  ['trust'] => primary
786  ['displaydesc'] => REGULAR SHARES - 50
787  ['rdctype'] => 0
788  ['rdcdesc'] =>
789  ['RDCAcctId'] => 1
790  )
791  * Note that for Ensenta we pass a list of accounts on the 'start session' call
792  * if the client uses shared branching, Ensenta returns list of shared branching
793  * accounts, or if batch they return the same list we sent.
794  * We need to parse through the list they send to record the account identifier
795  * they will recognize & which we are required to use when making the deposit.
796  *
797  * ['data'][terms] terms of use (if any) returned from rdc vendor
798  * ['data'] array also contains any values returned from rdc vendor on
799  * start session call. For Ensenta, these include:
800  * [ResponseCode] => 00
801  * [SessionStateId] => 55121227-e3ea-4524-8e34-dec9b199a3f3
802  * [IsTermsAcceptanceRequired] => false
803  * [IsBlackListed] => false
804  * [ReceiptEmail] =>
805  * [accounts] => Array
806  *
807  */
808 function RDCPresentAccounts($parms, $hculist, $rdcterms) {
809  // build array list to send to app
810  // include depositid
811  // include terms to be accepted if they are provided
812  // include labels acctttl, descttl
813  // $pass_along = $rdcsent; # GetReviewLimits result
814  $pass_along['data']['accounts'] = $hculist['data'];
815  // Vsoft doesn't filter accounts, just pass what we got from DB
816  // Vsoft doesn't serve terms 12/5/2014 but in case HCU can server them...
817  if (sizeof($rdcterms) > 0)
818  $pass_along['data']['terms'] = $rdcterms['data']['terms'];
819  $pass_along['status']['response'] = 'true';
820  $pass_along['status']['code'] = '000';
821  $pass_along['status']['message'] = 'Success';
822  return $pass_along;
823 }
824 
825 function vsoftStartTran($parms) {
826  /**
827  * uses: $parms['InstID']
828  * $parms['Cn']
829  * $parms['Ml'] # optional - if empty no ereceipt is sent
830  * $parms['depositAcct'] passed to vsoft as AccountNumber. Defined as string, but must be digits only
831  * $parms['depositType'] 1=DDA, 2=GL, 3=Savings, 4=Money Market.
832  * $parms['depositlimit'] specifies profileId, defaults to 0
833  * $parms['serviceurl']
834  *
835  * ApplicationId is always 6 for RDC Mobile
836  * ImagefFormat =1, jpeg
837  * ImageView =0, both sides
838  * ReturnImage=false, don't return the corrected image
839  * */
840 
841  try {
842  $parms['SessionId'] = time();
843  if (!isset($parms['InstID']) || !isset($parms['serviceurl']) ||
844  !isset($parms['Cn']) ||
845  !isset($parms['depositAcct']) ||
846  !isset($parms['depositType']) ||
847  !isset($parms['depositlimit'])) {
848  throw new Exception("Missing Parameters " . print_r($parms, true));
849  }
850 
851  $soapString = '<?xml version="1.0" encoding="utf-8"?>';
852 
853  $soapString .= '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:val="http://validationservice.vsoftcorp.com/">';
854  $soapString .= "<soapenv:Header/>
855  <soapenv:Body>
856  <val:StartTran>
857  <val:request>
858  <val:InstId>{$parms['InstID']}</val:InstId>
859  <val:ApplicationId>6</val:ApplicationId>
860  <val:UserId>{$parms['Cn']}</val:UserId>
861  <val:Email>" . urldecode($parms['Ml']) . "</val:Email>
862  <val:AccountNumber>{$parms['depositAcct']}</val:AccountNumber>
863  <val:AccountType>{$parms['depositType']}</val:AccountType>
864  <val:ImageFormat>1</val:ImageFormat>
865  <val:ImageView>0</val:ImageView>
866  <val:ProfileId>{$parms['depositlimit']}</val:ProfileId>
867  <val:ReturnImage>0</val:ReturnImage>
868  </val:request>
869  </val:StartTran>
870  </soapenv:Body>
871 </soapenv:Envelope>\n";
872 
873  $cmd = "/usr/bin/curl --silent --cacert /etc/ssl/certs/ValiCert.crt --data-binary '$soapString' -H 'Content-Type: text/xml; charset=utf-8'";
874  $cmd .= " -H 'SOAPAction: \"http://validationservice.vsoftcorp.com/StartTran\"'";
875  $cmd .= " {$parms['serviceurl']}";
876 
877  $soapHeaders = array();
878  $soapHeaders[] = "Content-Type: text/xml; charset=utf-8";
879  $soapHeaders[] = 'SOAPAction: "http://validationservice.vsoftcorp.com/StartTran"';
880  $response = embcurl($soapString, $soapHeaders, $parms['serviceurl']);
881 
882  if ($parms["logging"] == "enabled") {
883  $logParms = $parms["environment"]; // get the environment info passed in
884  $logParms["SSOVendor"] = $parms['rdcvendor'];
885  $logParms["token"] = $parms['SessionId']; // the id used across all communications in session
886  $logParms["txnId"] = time(); // the id for this transaction
887  $logParms["logPoint"] = "StartTran"; // this action in a readable form
888  $logParms["request"] = $cmd; // the request
889  $logParms["reply"] = $response; // the response
890  LogSSOActivity($logParms);
891  }
892 
893  $pos = strpos($response, 'HCUERROR: ');
894  if ($pos !== false) {
895  throw new Exception(substr($response, $pos));
896  }
897  if (empty($response)) {
898  throw new Exception("Empty Response");
899  }
900  // call parse function to format response array
901  $xmlreturn = vsoftGetXMLResponse($response, 'StartTranResult', 'http://validationservice.vsoftcorp.com/');
902  if (!is_array($xmlreturn)) {
903  throw new Exception("RDC Invalid XML Response");
904  }
905 
906  if (!$xmlreturn[0]['ReturnValue']) {
907  throw new Exception("{$xmlreturn[0]['ErrorDesc']} - {$xmlreturn[0]['ErrorCode']}");
908  } else {
909  $return['status']['response'] = 'true';
910  $return['status']['message'] = 'Success';
911  $return['data'] = $xmlreturn[0];
912  }
913  } catch (Exception $e) {
914  $return['status']['response'] = 'false';
915  $return['status']['message'] = $e->getMessage();
916  $return['status']['raw'] = "$response";
917  }
918  return $return;
919 }
920 
921 /**
922  * uses: $parms['SessionId']
923  * $parms['amount']
924  * $parms['FrontImage']
925  * $parms['RearImage']
926  * $parms['serviceurl']
927  */
928 function vsoftProcess($parms) {
929 
930  try {
931  if (!isset($parms['SessionId']) || !isset($parms['serviceurl']) ||
932  !isset($parms['amount']) ||
933  !isset($parms['FrontImage']) ||
934  !isset($parms['RearImage'])) {
935  $str = '';
936  if (!isset($parms['SessionId']))
937  $str .= "SessionId ";
938  if (!isset($parms['serviceurl']))
939  $str .= "serviceurl ";
940  if (!isset($parms['amount']))
941  $str .= "amount ";
942  if (!isset($parms['FrontImage']))
943  $str .= "FrontImage ";
944  if (!isset($parms['RearImage']))
945  $str .= "RearImage ";
946 
947  throw new Exception("Missing Parameters ($str)");
948  }
949 
950  $soapString = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:val="http://validationservice.vsoftcorp.com/">';
951  $soapString .= "<soapenv:Header/>
952  <soapenv:Body>
953  <val:Process>
954  <val:request>
955  <val:SessionId>{$parms['SessionId']}</val:SessionId>
956  <val:Amount>";
957  $soapString .= sprintf('%.2f', $parms['amount'] * .01);
958  $soapString .= "</val:Amount>
959  <val:FrontImage>{$parms['FrontImage']}</val:FrontImage>
960  <val:RearImage>{$parms['RearImage']}</val:RearImage>
961  </val:request>
962  </val:Process>
963  </soapenv:Body>
964  </soapenv:Envelope>\n";
965 
966  $cmd = "/usr/bin/curl --silent --cacert /etc/ssl/certs/ValiCert.crt --data-binary '$soapString' -H 'Content-Type: text/xml; charset=utf-8'";
967  $cmd .= " -H 'SOAPAction: \"http://validationservice.vsoftcorp.com/Process\"'";
968  $cmd .= " {$parms['serviceurl']}";
969 
970  $soapHeaders = array();
971  $soapHeaders[] = "Content-Type: text/xml; charset=utf-8";
972  $soapHeaders[] = 'SOAPAction: "http://validationservice.vsoftcorp.com/Process"';
973  $response = embcurl($soapString, $soapHeaders, $parms['serviceurl']);
974 
975  // no need to log the images - so strip them out
976  $logRequest = $soapString;
977  $startpos = strpos($logRequest, ':FrontImage>') + 12;
978  $endpos = strrpos($logRequest, '</val:FrontImage>');
979  $logRequest = substr_replace($logRequest, " Base64-encode parms['CheckFront'] ", $startpos, $endpos - $startpos);
980  $startpos = strpos($logRequest, '<val:RearImage>') + 15;
981  $endpos = strrpos($logRequest, '</val:RearImage>');
982  $logRequest = substr_replace($logRequest, " Base64-encode parms['CheckBack'] ", $startpos, $endpos - $startpos);
983 
984  // Vsoft v1 sent a <ReturnImages>false XML tag so not an issue
985  // but Vsoft v6 may return the images in a success response
986  // strip those out if we find them. Note that if Vsoft response
987  // includes namesapce as ns:FrontImage this code will need to change
988  // see CheckAlt for method that works with namespace
989 
990  // According to Vsoft, leaving out the <ReturnImages> tag defaults false, no images.
991  // So probably don't need this block.
992  // but leaving it in until testing confirms not neeed.
993 
994  if ($parms["logging"] == "enabled") {
995  $logParms = $parms["environment"];
996  $logParms["SSOVendor"] = $parms['rdcvendor'];
997  $logParms["token"] = $parms['SessionId'];
998  $logParms["txnId"] = time();
999  $logParms["logPoint"] = "Process";
1000  $logParms["request"] = "Request HDRs: " . print_r($soapHeaders, true);
1001  $logParms["request"] .= "Request URL: {$parms['serviceurl']}\n";
1002  $logParms["request"] .= "Request String: $logRequest\n";
1003  $logParms["reply"] = $response;
1004  LogSSOActivity($logParms);
1005  }
1006 
1007  $pos = strpos($response, 'HCUERROR: ');
1008  if ($pos !== false) {
1009  throw new Exception(substr($response, $pos));
1010  }
1011  if (empty($response)) {
1012  throw new Exception("Empty Response");
1013  }
1014 
1015  $xmlreturn = vsoftGetXMLResponse($response, 'ProcessResult', 'http://validationservice.vsoftcorp.com/');
1016 
1017  if (!is_array($xmlreturn)) {
1018  throw new Exception("RDC Invalid XML Response");
1019  }
1020 
1021  if (!$xmlreturn[0]['ReturnValue']) {
1022  throw new Exception("{$xmlreturn[0]['ErrorDesc']} - {$xmlreturn[0]['ErrorCode']}");
1023  } else {
1024  $return['status']['response'] = 'true';
1025  $return['status']['message'] = 'Success';
1026  $return['data'] = $xmlreturn[0];
1027  }
1028  } catch (Exception $e) {
1029  $return['status']['response'] = 'false';
1030  $return['status']['message'] = $e->getMessage();
1031  // $return['status']['raw'] = "$xmlreturn";
1032  $return['data'] = $xmlreturn[0];
1033  }
1034  return $return;
1035 }
1036 
1037 /**
1038  * uses: $parms['SessionId']
1039  * $parms['ReturnValue']
1040  * $parms['serviceurl']
1041  */
1042 function vsoftAck($parms) {
1043 
1044  try {
1045  if (!isset($parms['SessionId']) || !isset($parms['serviceurl']) ||
1046  !isset($parms['ReturnValue'])) {
1047  throw new Exception("Missing Parameters");
1048  }
1049  $soapString = '<?xml version="1.0" encoding="utf-8"?>';
1050 
1051  $soapString .= '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:val="http://validationservice.vsoftcorp.com/">
1052  <soapenv:Header/>';
1053  $soapString .= "<soapenv:Body>
1054  <val:Acknowledgment>
1055  <val:request>
1056  <val:SessionId>{$parms['SessionId']}</val:SessionId>
1057  <val:ReturnValue>{$parms['ReturnValue']}</val:ReturnValue>
1058  </val:request>
1059  </val:Acknowledgment>
1060  </soapenv:Body>
1061 </soapenv:Envelope>\n";
1062 
1063  $cmd = "/usr/bin/curl --silent --cacert /etc/ssl/certs/ValiCert.crt --data-binary '$soapString' -H 'Content-Type: text/xml; charset=utf-8'";
1064  $cmd .= " -H 'SOAPAction: \"http://validationservice.vsoftcorp.com/Acknowledgment\"'";
1065  $cmd .= " {$parms['serviceurl']}";
1066 
1067  $soapHeaders = array();
1068  $soapHeaders[] = "Content-Type: text/xml; charset=utf-8";
1069  $soapHeaders[] = 'SOAPAction: "http://validationservice.vsoftcorp.com/Acknowledgment"';
1070  $response = embcurl($soapString, $soapHeaders, $parms['serviceurl']);
1071 
1072  if ($parms["logging"] == "enabled") {
1073  $logParms = $parms["environment"]; // get the environment info passed in
1074  $logParms["SSOVendor"] = $parms['rdcvendor'];
1075  $logParms["token"] = $parms['SessionId']; // the id used across all communications in session
1076  $logParms["txnId"] = time(); // the id for this transaction
1077  $logParms["logPoint"] = "Ack"; // this action in a readable form
1078  $logParms["request"] = $cmd; // the request
1079  $logParms["reply"] = $response; // the response
1080  LogSSOActivity($logParms);
1081  }
1082 
1083  $pos = strpos($response, 'HCUERROR: ');
1084  if ($pos !== false) {
1085  throw new Exception(substr($response, $pos));
1086  }
1087  if (empty($response)) {
1088  throw new Exception("Empty Response");
1089  }
1090  // call parse function to format response array
1091  $xmlreturn = vsoftGetXMLResponse($response, 'AcknowledgmentResult', 'http://validationservice.vsoftcorp.com/');
1092  if (!is_array($xmlreturn)) {
1093  throw new Exception("RDC Invalid XML Response");
1094  }
1095 
1096  if (!$xmlreturn[0]['ReturnValue']) {
1097  throw new Exception("{$xmlreturn[0]['ErrorDesc']} - {$xmlreturn[0]['ErrorCode']}");
1098  } else {
1099  $return['status']['response'] = 'true';
1100  $return['status']['message'] = 'Success';
1101  $return['data'] = $xmlreturn[0];
1102  }
1103  } catch (Exception $e) {
1104  $return['status']['response'] = 'false';
1105  $return['status']['message'] = $e->getMessage();
1106  }
1107  return $return;
1108 }
1109 
1110 /**
1111  * uses: $parms['InstID']
1112  * $parms['Cn']
1113  *
1114  * history call is not implemented until v1.9, which is not yet available
1115  * so for now, just return successful/empty
1116  * note that vsoft also wants depositAcct / depositType to get history
1117  * if I read the WSDL right, depositAcct is optional, depositType required
1118  * depositType 1=DDA, 2=GL, 3=Savings, 4=Money Market.
1119  * not sure yet how to implement this...without re-writing app calls.
1120  * perhaps make the call & append to result array for ea account in hculist?
1121  */
1122 function vsoftHistory($parms) {
1123 
1124  //8-29-19 still not using, does not support our current framework
1125  //we want all user history, this is based on a selected account
1126  //so returning a success here and will show history from our table
1127  $return = array();
1128  $return['status']['response'] = 'true';
1129  $return['status']['message'] = 'Success';
1130  $return['callparms'] = $parms;
1131  $return['data'] = array();
1132  return $return;
1133 
1134  try {
1135  $parms['SessionId'] = time();
1136  if (!isset($parms['InstID']) || !isset($parms['serviceurl']) ||
1137  !isset($parms['Cn']) || !isset($parms['depositAcct']) ||
1138  !isset($parms['depositType'])) {
1139  throw new Exception("Missing Parameters " . print_r($parms, true));
1140  }
1141 
1142  $soapString = '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1143  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
1144  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
1145  <soap:Body>
1146  <AccountTransactionHistory xmlns="http://validationservice.vsoftcorp.com/">';
1147 
1148  $soapString .= "<AcctTransHistoryRequest>
1149  <InstId>{$parms['InstID']}</InstId>
1150  <AccountNumber>{$parms['depositAcct']}</AccountNumber>
1151  <UserId>{$parms['Cn']}</UserId>
1152  <AccountType>{$parms['depositType']}</AccountType>
1153  </AcctTransHistoryRequest>
1154  </AccountTransactionHistory>
1155  </soap:Body>
1156  </soapenv:Envelope>\n";
1157 
1158  $cmd = "/usr/bin/curl --silent --cacert /etc/ssl/certs/ValiCert.crt --data-binary '$soapString' -H 'Content-Type: text/xml; charset=utf-8'";
1159  $cmd .= " -H 'SOAPAction: \"http://validationservice.vsoftcorp.com/AccountTransactionHistory\"'";
1160  $cmd .= " {$parms['serviceurl']}";
1161 
1162  $soapHeaders = array();
1163  $soapHeaders[] = "Content-Type: text/xml; charset=utf-8";
1164  $soapHeaders[] = 'SOAPAction: "http://validationservice.vsoftcorp.com/AccountTransactionHistory"';
1165  $response = embcurl($soapString, $soapHeaders, $parms['serviceurl']);
1166 
1167  if ($parms["logging"] == "enabled") {
1168  $logParms = $parms["environment"]; // get the environment info passed in
1169  $logParms["SSOVendor"] = $parms['rdcvendor'];
1170  $logParms["token"] = $parms['SessionId']; // the id used across all communications in session
1171  $logParms["txnId"] = time(); // the id for this transaction
1172  $logParms["logPoint"] = "TransactionHistory"; // this action in a readable form
1173  $logParms["request"] = $cmd; // the request
1174  $logParms["reply"] = $response; // the response
1175  LogSSOActivity($logParms);
1176  }
1177 
1178  $pos = strpos($response, 'HCUERROR: ');
1179  if ($pos !== false) {
1180  throw new Exception(substr($response, $pos));
1181  }
1182  if (empty($response)) {
1183  throw new Exception("Empty Response");
1184  }
1185  // call parse function to format response array
1186  $xmlreturn = vsoftGetXMLResponse($response, 'AccountTransactionHistoryResult', 'http://validationservice.vsoftcorp.com/');
1187  if (!is_array($xmlreturn)) {
1188  throw new Exception("RDC Invalid XML Response");
1189  }
1190 
1191  if (!$xmlreturn[0]['ReturnValue']) {
1192  throw new Exception("{$xmlreturn[0]['ErrorDesc']} - {$xmlreturn[0]['ErrorCode']}");
1193  } else {
1194  $return['status']['response'] = 'true';
1195  $return['status']['message'] = 'Success';
1196  $return['data'] = $xmlreturn[0];
1197  }
1198  } catch (Exception $e) {
1199  $return['status']['response'] = 'false';
1200  $return['status']['message'] = $e->getMessage();
1201  $return['data'] = $response;
1202  }
1203  return $return;
1204 }
1205 
1206 function vsoftGetXMLResponse($rdcXML, $rdcCONT, $rdcNS) {
1207  try {
1208  $xml = simplexml_load_string($rdcXML, "SimpleXMLElement", LIBXML_NOWARNING);
1209  if (!is_object($xml)) {
1210  throw new Exception("Invalid XML not object");
1211  }
1212  $xml->registerXPathNamespace('s', "http://schemas.xmlsoap.org/soap/envelope/");
1213  $errorresponse = $xml->xpath("//s:Fault");
1214  if (is_array($errorresponse) && count($errorresponse)) {
1215  $resp_arr = array(
1216  'faultcode' => $errorresponse[0]->faultcode,
1217  'faultstring' => $errorresponse[0]->faultstring
1218  );
1219  } else {
1220  $xml->registerXPathNamespace('rdc', $rdcNS);
1221  $dataresponse = $xml->xpath("//rdc:$rdcCONT");
1222  $resp_arr = objectToArray($dataresponse);
1223  }
1224  } catch (Exception $e) {
1225  $resp_arr = false;
1226  }
1227  return $resp_arr;
1228 }