Odyssey
hcuACH.data
1 <?php
2 /*
3  * File: hcuACH.data
4  * Purpose: Handle the CRUD portion of the ACH. This includes ACH Payments and Collections,
5  * single and batch, and also Payroll. When returning the requested data
6  * do it in a JSON format, for the client to display accordingly.
7  *
8  *
9  * Call this script with the following parameters
10  * action - what the client side is requesting.
11  *
12  * Returns JSON OBJECT.
13  */
14 try {
15  // ** SET HOMECU FLAGS
16  $serviceShowInfo = false;
17  $serviceLoadMenu = false;
18  $serviceShowMenu = false;
19 
20 
21  // ** INCLUDE MAIN GLOBAL SCRIPT -- Handles security / global variable values
22  // hcuService will be returning a status object: e.g. ["homecuErrors":{[{"message":"message1"}...{"message":"messageN"}}]
23  require_once(dirname(__FILE__) . '/../library/hcuService.i');
24 
25  require_once(dirname(__FILE__) . '/../library/permissions.i');
26  require_once(dirname(__FILE__) . '/../library/hcuACH.i');
27  require_once(dirname(__FILE__) . '/../library/hcuTransfer.i');
28  require_once(dirname(__FILE__) . '/../library/hcuTransferScheduled.i');
29 
30  // ** IMPORT FORM VALUES
31  $inputVars = array();
32  $varOk = array(
33  "action" => array('filter' => FILTER_SANITIZE_STRING),
34  "ach_name" => array('filter' => FILTER_SANITIZE_STRING),
35  "display_name" => array("filter" => FILTER_SANITIZE_STRING, 'options' => array('flags' => FILTER_FLAG_NO_ENCODE_QUOTES)),
36  "email" => array('filter' => FILTER_SANITIZE_EMAIL),
37  "email_notify" => array('filter' => FILTER_SANITIZE_NUMBER_INT),
38  "address1" => array('filter' => FILTER_SANITIZE_STRING),
39  "address2" => array('filter' => FILTER_SANITIZE_STRING),
40  "city" => array('filter' => FILTER_SANITIZE_STRING),
41  "state" => array('filter' => FILTER_SANITIZE_STRING),
42  "zip" => array('filter' => FILTER_SANITIZE_STRING),
43  "country" => array('filter' => FILTER_SANITIZE_STRING),
44  "update_partner" => array('filter' => FILTER_SANITIZE_NUMBER_INT),
45  "dfi_routing" => array('filter' => FILTER_SANITIZE_STRING),
46  "dfi_account" => array('filter' => FILTER_SANITIZE_STRING),
47  "dfi_account_type" => array('filter' => FILTER_SANITIZE_STRING),
48  "addenda" => array('filter' => FILTER_SANITIZE_STRING),
49  "internal_acct" => array('filter' => FILTER_SANITIZE_STRING),
50  "internal_sub_acct" => array('filter' => FILTER_SANITIZE_STRING),
51  "eff_date" => array('filter' => FILTER_SANITIZE_STRING),
52  "end_date" => array('filter' => FILTER_SANITIZE_STRING),
53  "frequency" => array('filter' => FILTER_SANITIZE_STRING),
54  "continue" => array('filter' => FILTER_SANITIZE_STRING),
55  "amount" => array('filter' => FILTER_SANITIZE_NUMBER_INT),
56  "ach_type" => array('filter' => FILTER_SANITIZE_STRING),
57  "memo" => array('filter' => FILTER_SANITIZE_STRING),
58  "batch_data" => array('filter' => FILTER_UNSAFE_RAW),
59  "partner_id" => array('filter' => FILTER_SANITIZE_NUMBER_INT),
60  "partner_type" => array('filter' => FILTER_SANITIZE_STRING),
61  "template_id" => array('filter' => FILTER_SANITIZE_NUMBER_INT),
62  "template_name" => array('filter' => FILTER_SANITIZE_STRING),
63  "update_template" => array('filter' => FILTER_SANITIZE_NUMBER_INT),
64  );
65 
66  HCU_ImportVars( $inputVars, "", $varOk );
67  header('Content-Type: application/json');
68 
69  if (!$dbh) {
70  // The connection was not made to the database
71  // unresolved: return an error??
72  }
73 
74  $aryReply = array();
75  $aryResult = array();
76 
77  $aryInfo = array();
78 
79  /*
80  * Returned Errors Structure
81  *
82  * homecuInfo => An informational message to report to the user.
83  *
84  * The existence of Errors is proof of an error, if homecuErrors is NOT found or
85  * empty then success is assumed
86  *
87  * 'homecuErrors' element will contain an array of the following object
88  * 'id' => the element id of the error, this is useful so the client side can
89  * highlight the affected element
90  * 'message' => the error message to be displayed back to the member. For
91  * summary only information, leave the 'id' field blank and
92  * enter the message here
93  *
94  * 'homecuData' element will return information to display for the member.
95  */
96 
97  // ** First check the refer script -- This will be used to ensure proper usage later
98  $parseRefer = parse_url($_SERVER['HTTP_REFERER']);
99  $referScript = basename($parseRefer['path']);
100 
101  if (!in_array($referScript, array('hcuACHSingle.prg', 'hcuACHBatch.prg', 'hcuACHPartners.prg'))) {
102  // ** Wrong script calling this data routine
103  $aryErrors[] = $MC->msg('Feature Unavailable', HCU_DISPLAY_AS_RAW);
104  throw new Exception (HCU_JsonEncode($aryErrors));
105  }
106 
107  // don't worry about checking if ACH Enabled because they wouldn't get the feature if it wasn't
108  $aryErrors = array();
109 
110  // do the requested operation
111  switch ( $inputVars["action"] ) {
112  case "submit_payment":
113  case "submit_collection":// update has an id
114 
115  // ** Verify the user can access this feature.
116  $permissionInputs = array();
117  if ( $inputVars["action"] === "submit_payment" ) {
118  $permissionInputs["feature"] = FEATURE_ACH_PAYMENTS;
119  } else {
120  $permissionInputs["feature"] = FEATURE_ACH_COLLECTIONS;
121  }
122  $return = Perm_AccessRights( $dbh, $HB_ENV, $permissionInputs );
123  if ( !$return ) {
124  // * Rights NOT set up for user access
125  $aryErrors[] = $MC->msg('Rights not set', HCU_DISPLAY_AS_HTML);
126  throw new Exception (HCU_JsonEncode($aryErrors));
127  }
128 
129  // the amount came in as an integer so need to shift decimal back
130  // NOTE: This only affects the single transaction because the batch comes in as a json stringified array.
131  $inputVars["amount"] = round( $inputVars["amount"] / 100, 2 );
132 
133  // validate the inputs
134  $aryValidate = ACH_ValidateInputs( $HB_ENV, $dbh, $inputVars, $MC );
135  if ( !$aryValidate || ($aryValidate["code"] !== "000") ) {
136  // an error occurred
137  if ( is_array( $aryValidate["errors"] ) ) {
138  for ( $e = 0; $e < count( $aryValidate["errors"] ); $e++ ) {
139  $aryErrors[] = $aryValidate["errors"][$e];
140  }
141  } else {
142  $aryErrors[] = $aryValidate["errors"];
143  }
144 
145  throw new Exception (HCU_JsonEncode($aryErrors));
146  }
147 
148  // see if partner should be updated/added (first, because it might be needed for the notification)
149  $partnerAddResult = false;
150  if ( intval( $inputVars["update_partner"] ) === 1 ) {
151  $partnerAddResult = ACH_UpdatePartner( $dbh, $HB_ENV, $inputVars, $MC );
152  if ( $partnerAddResult["code"] !== "000" ) {
153  // throw an error since the ACH submission may depend on the address
154  // if we got here we were successful with the ach partner update
155  $aryErrors[] = $MC->msg('ACH Partner update failed', HCU_DISPLAY_AS_RAW);
156 
157  if ( is_array( $partnerAddResult["errors"] ) ) {
158  for ( $e = 0; $e < count( $partnerAddResult["errors"] ); $e++ ) {
159  $aryErrors[] = $partnerAddResult["errors"][$e];
160  }
161  } else {
162  $aryErrors[] = $partnerAddResult["errors"];
163  }
164 
165  throw new Exception (HCU_JsonEncode($aryErrors));
166  } else {
167  // if we got here we were successful with the ach partner update
168  $aryInfo[] = $MC->msg('ACH Partner updated', HCU_DISPLAY_AS_RAW);
169  }
170  }
171 
172  // decode the account info
173  $decryptedAccountInfo = hcu_decrypturl( $inputVars["internal_sub_acct"], $HB_ENV['historyHash'] );
174 
175  // validate the amount is within limits (inputs set up previously)
176  $accountParts = explode( "|", $decryptedAccountInfo );
177  $permissionInputs["account"] = $accountParts[1];
178  $permissionInputs["accounttype"] = $accountParts[2];
179  $permissionInputs["amount"] = $inputVars["amount"];
180 
181  $return = Perm_CheckLimits( $dbh, $HB_ENV, $permissionInputs );
182  if ( !$return || ($return["status"]["code"] !== "000") ) {
183  $aryErrors[] = $MC->msg('ACH Exceeded Permissions', HCU_DISPLAY_AS_RAW);
184  // add the returned message
185  $aryErrors[] = Perm_GetLimitErrDesc($MC, $return["status"]["code"]);
186 
187  throw new Exception (HCU_JsonEncode($aryErrors));
188  }
189 
190  // clean up any user-supplied data - convert any UTF-8 characters to encoded html entities
191  // NOTE: data was sanitized on input
192  $inputVars["addenda"] = ConvertFromUTF8( $inputVars["addenda"] );
193  $inputVars["memo"] = ConvertFromUTF8( $inputVars["memo"] );
194  $inputVars["needs_confirmation"] = Perm_CheckConfirmReq( $dbh, $HB_ENV, $permissionInputs );
195 
196  // Because ACH transactions have an effectve date, one time
197  // future dated transfers are still considered non-scheduled
198  // so we only base non-scheduled on frequency = OneTime.
199  $immdTransfer = $inputVars['frequency'] == "OneTime";
200 
201  if ( $immdTransfer ) {
202  $return = ACH_Submit( $dbh, $HB_ENV, $inputVars, $MC );
203  if ( $return["code"] !== "000" ) {
204  if ( is_array( $return["errors"] ) ) {
205  for ( $e = 0; $e < count( $return["errors"] ); $e++ ) {
206  $aryErrors[] = $return["errors"][$e];
207  }
208  } else {
209  $aryErrors[] = $return["errors"];
210  }
211 
212  throw new Exception (HCU_JsonEncode($aryErrors));
213  }
214 
215  // Send transaction data and confirmation code to user
216  $aryResult['txn'] = Array(
217  Array("label" => $MC->msg('Date', HCU_DISPLAY_AS_RAW), 'caption' => $return['data']["data_date"]),
218  Array("label" => $MC->msg('Action', HCU_DISPLAY_AS_RAW), 'caption' => $return['data']["data_action"]),
219  Array("label" => $MC->msg('ACH Company Name Label', HCU_DISPLAY_AS_RAW), 'caption' => $return['data']["data_company"]),
220  Array("label" => $MC->msg('Account', HCU_DISPLAY_AS_RAW), 'caption' => $return['data']["data_account"]),
221  Array("label" => $MC->msg('Amount', HCU_DISPLAY_AS_RAW), 'caption' => "$" . mobile_formatnumber($return['data']["data_amount"]), ","),
222  Array("label" => $MC->msg('Confirmation', HCU_DISPLAY_AS_RAW), 'caption' => $return['data']["data_confirm"])
223  );
224 
225  // if we got here we were successful with the ach submission
226  if ( $inputVars["action"] === "submit_payment" ) {
227  $aryInfo[] = $MC->msg('ACH Payment Submitted', HCU_DISPLAY_AS_RAW);
228  } else {
229  $aryInfo[] = $MC->msg('ACH Collection Submitted', HCU_DISPLAY_AS_RAW);
230  }
231  }
232 
233  if ( !$immdTransfer ) {
234  // ValidateTransfer in hcuTransfer.i sets the frequency count for scheduled
235  // transfers to 0 when creating a new scheduled transfer, the ach validation
236  // does no such thing so we must do it here to avoid php warnings.
237  $inputVars['frequency_count'] = 0;
238  // need to have a partner id to schedule an ACH transaction
239  $partnerId = $inputVars["partner_id"] > 0 ? $inputVars["partner_id"] : $partnerAddResult["data"]["partner_id"];
240 
241  if ( $partnerId > 0 ) {
242  //check if end date is valid for interval
243  $nextIntervalDate = TxNextInterval($inputVars['eff_date'], $inputVars['frequency'], 0);
244  if ($nextIntervalDate == null) {
245  $aryErrors[] = $MC->msg('Continue Until greater than next', HCU_DISPLAY_AS_RAW);
246  throw new Exception (HCU_JsonEncode($aryErrors));
247  }
248  // setup a schedule transaction for ACH
249  $txScheduleData = array(
250  "txAmount" => floatval($inputVars['amount']),
251  "txLocalAccount" => $decryptedAccountInfo,
252  "txLocalMember" => $inputVars['internal_acct'],
253  "txPartnerId" => $partnerId,
254  "txCode" => ACH_GetTransCode( $permissionInputs['feature'], $inputVars['ach_type'] ),
255  "txMemo" => prep_save($inputVars['memo']),
256  "txAddenda" => prep_save($inputVars['addenda']),
257  "txType" => ($permissionInputs['feature'] == FEATURE_ACH_PAYMENTS ? "L2R" : "R2L")
258  );
259  $txScheduleParameters = array(
260  "txFrequency" => prep_save($inputVars['frequency'], 50)
261  );
262  $txScheduleValues = array(
263  "txDateStart" => $inputVars['eff_date'],
264  "txDateEnd" => $inputVars['end_date'],
265  "txFrequency" => $inputVars['frequency'],
266  "txFrequencyCount" => $inputVars['frequency_count'],
267  "txFeature" => $permissionInputs['feature'],
268  "txParameters" => TxnSchedParameters($txScheduleParameters),
269  "txData" => TxnSchedDataACH($txScheduleData)
270  );
271 
272  // schedule the transfer with the create function
273  $txScheduleCreate = TxnSchedCreate($HB_ENV, $dbh, $MC, $txScheduleValues);
274 
275  // ** check errors
276  if ($txScheduleCreate['status']['code'] !== "000") {
277 
278  // display errors
279  $aryErrors[] = $txScheduleCreate['status']['errors'];
280  }
281 
282  // if we got here we were successful with the ach submission
283  if ( $inputVars["action"] === "submit_payment" ) {
284  $aryInfo[] = $MC->msg("ACH Scheduled A Payment", HCU_DISPLAY_AS_RAW);
285  } else {
286  $aryInfo[] = $MC->msg("ACH Scheduled A Collection", HCU_DISPLAY_AS_RAW);
287  }
288  } else {
289  $aryErrors[] = $MC->msg("ACH Scheduled partner error", HCU_DISPLAY_AS_RAW);
290  throw new Exception (HCU_JsonEncode($aryErrors));
291  }
292  }
293 
294  // if successful, return the partner list, if it was updated
295  if ( $partnerAddResult !== false ) {
296  // figure out the type of internal accounts to show (ones to pay from vs ones to deposit to)
297  $fromTo = ( $inputVars["action"] === "submit_payment" ) ? "withdrawl" : "deposit";
298 
299  $return = ACH_GetPartners( $dbh, $HB_ENV );
300  if ( $return["code"] !== "000" ) {
301  if ( is_array( $return["errors"] ) ) {
302  for ( $e = 0; $e < count( $return["errors"] ); $e++ ) {
303  $aryErrors[] = $return["errors"][$e];
304  }
305  } else {
306  $aryErrors[] = $return["errors"];
307  }
308 
309  throw new Exception (HCU_JsonEncode($aryErrors));
310  }
311 
312  // return the partner list
313  $aryResult["partners"] = $return["data"];
314 
315  $return = ACH_GetAccounts( $dbh, $HB_ENV, $fromTo );
316  if ( $return["code"] !== "000" ) {
317  if ( is_array( $return["errors"] ) ) {
318  for ( $e = 0; $e < count( $return["errors"] ); $e++ ) {
319  $aryErrors[] = $return["errors"][$e];
320  }
321  } else {
322  $aryErrors[] = $return["errors"];
323  }
324 
325  throw new Exception (HCU_JsonEncode($aryErrors));
326  }
327 
328  // return the account lists
329  $aryResult["accounts"] = $return["data"];
330  }
331 
332  break;
333  case "get_ach_partners":
334  // get the partners for the current user's group
335  $partners = ACH_GetPartners( $dbh, $HB_ENV, $MC );
336  if ( $partners["code"] !== "000" ) {
337  $aryErrors[] = $MC->msg('ACH Error getting partners', HCU_DISPLAY_AS_RAW);
338 
339  if ( is_array( $partners["errors"] ) ) {
340  for ( $e = 0; $e < count( $partners["errors"] ); $e++ ) {
341  $aryErrors[] = $partners["errors"][$e];
342  }
343  } else {
344  $aryErrors[] = $partners["errors"];
345  }
346 
347  throw new Exception (HCU_JsonEncode($aryErrors));
348  }
349 
350  // return the requested list
351  $aryResult["partners"] = $partners["data"];
352  break;
353  case "collections_list":
354  case "payments_list":
355  // figure out the type of internal accounts to show (ones to pay from vs ones to deposit to)
356  // If payments, coming out of accounts; if collection, going into accounts.
357  $fromTo = ( $inputVars["action"] === "payments_list" ) ? "withdrawl" : "deposit";
358 
359  $return = ACH_GetAccounts( $dbh, $HB_ENV, $fromTo );
360  if ( $return["code"] !== "000" ) {
361  $aryErrors[] = $MC->msg('ACH Error getting lists', HCU_DISPLAY_AS_RAW);
362 
363  if ( is_array( $return["errors"] ) ) {
364  for ( $e = 0; $e < count( $return["errors"] ); $e++ ) {
365  $aryErrors[] = $return["errors"][$e];
366  }
367  } else {
368  $aryErrors[] = $return["errors"];
369  }
370 
371  throw new Exception (HCU_JsonEncode($aryErrors));
372  }
373 
374  // return the requested list
375  $aryResult["accounts"] = $return["data"];
376  break;
377  case "read_templates":
378  // get the template information to show the user
379  $return = ACH_GetTemplates( $dbh, $HB_ENV, $inputVars["action"], $MC );
380 
381  if ($return['code'] != '000') {
382  // an error occurred
383  if ( is_array( $return["errors"] ) ) {
384  for ( $e = 0; $e < count( $return["errors"] ); $e++ ) {
385  $aryErrors[] = $return["errors"][$e];
386  }
387  } else {
388  $aryErrors[] = $return["errors"];
389  }
390 
391  throw new Exception (HCU_JsonEncode($aryErrors));
392  }
393 
394  $aryResult["templates"] = $return["data"];
395  break;
396  case "update_template":
397  case "delete_template":
398  // pass straight to the function
399  $return = ACH_UpdateTemplate( $dbh, $HB_ENV, $inputVars, $MC );
400 
401  if ($return['code'] != '000') {
402  // an error occurred
403  if ( is_array( $return["errors"] ) ) {
404  for ( $e = 0; $e < count( $return["errors"] ); $e++ ) {
405  $aryErrors[] = $return["errors"][$e];
406  }
407  } else {
408  $aryErrors[] = $return["errors"];
409  }
410 
411  throw new Exception (HCU_JsonEncode($aryErrors));
412  }
413 
414  // re-get the template information to show the user
415  $return = ACH_GetTemplates( $dbh, $HB_ENV, $inputVars["action"], $MC );
416 
417  if ($return['code'] != '000') {
418  // an error occurred
419  if ( is_array( $return["errors"] ) ) {
420  for ( $e = 0; $e < count( $return["errors"] ); $e++ ) {
421  $aryErrors[] = $return["errors"][$e];
422  }
423  } else {
424  $aryErrors[] = $return["errors"];
425  }
426 
427  throw new Exception (HCU_JsonEncode($aryErrors));
428  }
429 
430  $aryResult["templates"] = $return["data"];
431  break;
432  case "ach_partner":
433  $return = ACH_GetSinglePartner( $dbh, $HB_ENV, $inputVars["partner_id"] );
434 
435  if ($return['code'] != '000') {
436  $aryErrors[] = $MC->msg('ACH Error getting partner info', HCU_DISPLAY_AS_RAW);
437  throw new Exception (HCU_JsonEncode($aryErrors));
438  }
439 
440  $aryResult["one_partner"] = $return["data"];
441 
442  break;
443  case "add_ach_partner":
444  case "update_ach_partner":
445  // the inputs were validated by the filtering above
446  $partnerUpdateAddResult = ACH_UpdatePartner( $dbh, $HB_ENV, $inputVars, $MC );
447  if ( $partnerUpdateAddResult["code"] !== "000" ) {
448  $aryErrors[] = $MC->msg('ACH Error Partner update failed', HCU_DISPLAY_AS_RAW);
449 
450  if ( is_array( $partnerUpdateAddResult["errors"] ) ) {
451  for ( $e = 0; $e < count( $partnerUpdateAddResult["errors"] ); $e++ ) {
452  $aryErrors[] = $partnerUpdateAddResult["errors"][$e];
453  }
454  } else {
455  $aryErrors[] = $partnerUpdateAddResult["errors"];
456  }
457 
458  throw new Exception (HCU_JsonEncode($aryErrors));
459  }
460 
461  // if we got here we were successful with the ach partner update
462  $aryInfo[] = $MC->msg('ACH Partner updated', HCU_DISPLAY_AS_RAW);
463 
464  // return the updated information (it might be a new partner id, if an add)
465  $partnerId = $partnerUpdateAddResult["data"]["partner_id"];
466  $partnerRead = ACH_GetSinglePartner( $dbh, $HB_ENV, $partnerId );
467 
468  if ($partnerRead['code'] != '000') {
469  $aryErrors[] = $MC->msg('ACH Error getting partner info', HCU_DISPLAY_AS_RAW);
470  throw new Exception (HCU_JsonEncode($aryErrors));
471  }
472 
473  $aryResult["partner_data"] = $partnerRead["data"];
474  $aryResult["update_partner"] = $partnerUpdateAddResult["data"];
475 
476  break;
477  case "delete_ach_partner":
478  $partnerDeleteResult = ACH_DeletePartner( $dbh, $HB_ENV, $inputVars, $MC);
479  if ( $partnerDeleteResult["code"] !== "000" ) {
480 
481  if ( is_array( $partnerDeleteResult["errors"] ) ) {
482  for ( $e = 0; $e < count( $partnerDeleteResult["errors"] ); $e++ ) {
483  $aryErrors[] = $partnerDeleteResult["errors"][$e];
484  }
485  } else {
486  $aryErrors[] = $partnerDeleteResult["errors"];
487  }
488 
489  throw new Exception (HCU_JsonEncode($aryErrors));
490  }
491 
492  // if we got here we were successful with the ach partner update
493  $aryInfo[] = $MC->msg('ACH Partner deleted', HCU_DISPLAY_AS_RAW);
494  $aryResult["update_partner"] = $partnerDeleteResult["data"];
495 
496  break;
497  case "read_template_partners":
498  // get the template information to show the user
499  $return = ACH_GetTemplatePartners( $dbh, $HB_ENV, $inputVars["template_id"], $MC );
500 
501  if ($return['code'] != '000') {
502  // an error occurred
503  if ( is_array( $return["errors"] ) ) {
504  for ( $e = 0; $e < count( $return["errors"] ); $e++ ) {
505  $aryErrors[] = $return["errors"][$e];
506  }
507  } else {
508  $aryErrors[] = $return["errors"];
509  }
510 
511  throw new Exception (HCU_JsonEncode($aryErrors));
512  }
513 
514  $aryResult["read_template_partners"] = $return["data"];
515  break;
516  case "add_template_partner":
517  // add the partner to the template's list
518  $return = ACH_AddPartnerToTemplate( $dbh, $HB_ENV, $inputVars["template_id"], $inputVars["partner_id"], $MC );
519  if ($return['code'] != '000') {
520  $aryErrors[] = $MC->msg('ACH Error Adding Template Partner', HCU_DISPLAY_AS_RAW);
521  throw new Exception (HCU_JsonEncode($aryErrors));
522  }
523 
524  // return partner information for client to use
525  $return = ACH_GetSinglePartner( $dbh, $HB_ENV, $inputVars["partner_id"] );
526 
527  if ($return['code'] != '000') {
528  $aryErrors[] = $MC->msg('ACH Error getting partner info', HCU_DISPLAY_AS_RAW);
529  throw new Exception (HCU_JsonEncode($aryErrors));
530  }
531 
532  $aryResult["one_partner"] = $return["data"];
533 
534  break;
535  case "remove_template_partner":
536  // remove the partner from the template's list
537  $return = ACH_RemovePartnerFromTemplate( $dbh, $HB_ENV, $inputVars["template_id"], $inputVars["partner_id"], $MC );
538  if ($return['code'] != '000') {
539  $aryErrors[] = $MC->msg('ACH Error removing partner template', HCU_DISPLAY_AS_RAW);
540  throw new Exception (HCU_JsonEncode($aryErrors));
541  }
542 
543  $aryResult["partner_removed"] = $inputVars["partner_id"];
544 
545  break;
546  case "submit_batch_payment":
547  case "submit_batch_collection":
548  // ** Verify the user can access this feature.
549  $permissionInputs = array();
550  if ( $inputVars["action"] === "submit_batch_payment" ) {
551  $permissionInputs["feature"] = FEATURE_ACH_PAYMENTS;
552  } else {
553  $permissionInputs["feature"] = FEATURE_ACH_COLLECTIONS;
554  }
555  $return = Perm_AccessRights( $dbh, $HB_ENV, $permissionInputs );
556  if ( !$return ) {
557  // * Rights NOT set up for user access
558  $aryErrors[] = $MC->msg('Rights not set', HCU_DISPLAY_AS_HTML);
559  throw new Exception (HCU_JsonEncode($aryErrors));
560  }
561 
562  // validate the inputs
563  $aryValidate = ACH_ValidateInputs( $HB_ENV, $dbh, $inputVars, $MC );
564  if ( !$aryValidate || ($aryValidate["code"] !== "000") ) {
565  // an error occurred
566  if ( is_array( $aryValidate["errors"] ) ) {
567  for ( $e = 0; $e < count( $aryValidate["errors"] ); $e++ ) {
568  $aryErrors[] = $aryValidate["errors"][$e];
569  }
570  } else {
571  $aryErrors[] = $aryValidate["errors"];
572  }
573 
574  throw new Exception (HCU_JsonEncode($aryErrors));
575  }
576 
577  // decode the account info
578  $decryptedAccountInfo = hcu_decrypturl( $inputVars["internal_sub_acct"], $HB_ENV['historyHash'] );
579 
580  // validate the amount is within limits (inputs set up previously)
581  $accountParts = explode( "|", $decryptedAccountInfo );
582  $permissionInputs["account"] = $accountParts[1];
583  $permissionInputs["accounttype"] = $accountParts[2];
584 
585  // add up the amounts from the batch data
586  $batchInfo = HCU_JsonDecode( $inputVars["batch_data"]);
587 
588  $batchAmount = 0;
589  for ( $i = 0; $i < count( $batchInfo ); $i++ ) {
590  $batchAmount += $batchInfo[$i]["amount"];
591 
592  // clean up the input while we are at it
593  $batchInfo[$i]["addenda"] = ConvertFromUTF8( $batchInfo[$i]["addenda"] );
594  }
595 
596  $permissionInputs["amount"] = $batchAmount;
597 
598 
599  $return = Perm_CheckLimits( $dbh, $HB_ENV, $permissionInputs );
600  if ( !$return || ($return["status"]["code"] !== "000") ) {
601  $aryErrors[] = $MC->msg('ACH Exceeded Permissions', HCU_DISPLAY_AS_RAW);
602  // add the returned message
603  $aryErrors[] = Perm_GetLimitErrDesc($MC, $return["status"]["code"]);
604 
605  throw new Exception (HCU_JsonEncode($aryErrors));
606  }
607 
608  // clean up any user-supplied data - convert any UTF-8 characters to encoded html entities
609  // NOTE: data was sanitized on input
610  $inputVars["memo"] = ConvertFromUTF8( $inputVars["memo"] );
611  $inputVars["needs_confirmation"] = Perm_CheckConfirmReq( $dbh, $HB_ENV, $permissionInputs );
612 
613  // submit the ach
614  $return = ACH_SubmitBatch( $dbh, $HB_ENV, $inputVars, $batchInfo, $MC );
615  if ( $return["code"] !== "000" ) {
616  if ( is_array( $return["errors"] ) ) {
617  for ( $e = 0; $e < count( $return["errors"] ); $e++ ) {
618  $aryErrors[] = $return["errors"][$e];
619  }
620  } else {
621  $aryErrors[] = $return["errors"];
622  }
623 
624  throw new Exception (HCU_JsonEncode($aryErrors));
625  }
626 
627  // Send transaction data and confirmation code to user
628  $aryResult['txn'] = Array(
629  Array("label" => $MC->msg('Date', HCU_DISPLAY_AS_RAW), 'caption' => $return['data']["data_date"]),
630  Array("label" => $MC->msg('Action', HCU_DISPLAY_AS_RAW), 'caption' => $return['data']["data_action"]),
631  Array("label" => $MC->msg('ACH Company Name Label', HCU_DISPLAY_AS_RAW), 'caption' => $return['data']["data_company"]),
632  Array("label" => $MC->msg('Account', HCU_DISPLAY_AS_RAW), 'caption' => $return['data']["data_account"]),
633  Array("label" => $MC->msg('Amount', HCU_DISPLAY_AS_RAW), 'caption' => "$" . mobile_formatnumber($return['data']["data_amount"]), ","),
634  Array("label" => $MC->msg('Confirmation', HCU_DISPLAY_AS_RAW), 'caption' => $return['data']["data_confirm"])
635  );
636 
637  // if we got here we were successful with the ach submission
638  if ( $inputVars["action"] === "submit_batch_payment" ) {
639  $aryInfo[] = $MC->msg('ACH Payment Submitted', HCU_DISPLAY_AS_RAW);
640  } else {
641  $aryInfo[] = $MC->msg('ACH Collection Submitted', HCU_DISPLAY_AS_RAW);
642  }
643 
644  // see if partner should be updated/added
645  if ( intval( $inputVars["update_template"] ) === 1 ) {
646  $partnerAddResult = ACH_UpdateTemplatePartners( $dbh, $HB_ENV, $inputVars["template_id"], $batchInfo, $MC );
647  if ( $partnerAddResult["code"] !== "000" ) {
648  // don't throw an error since the ACH submission happened - just let the user know the partner update failed
649  // if we got here we were successful with the ach partner update
650  $aryInfo[] = $MC->msg('ACH Error Template partner update failed', HCU_DISPLAY_AS_RAW);
651 
652  for ( $i = 0 ; $i < count( $partnerAddResult["errors"] ); $i++ ) {
653  $aryInfo[] = $partnerAddResult["errors"][$i];
654  }
655  } else {
656  // if we got here we were successful with the ach partner update
657  $aryInfo[] = $MC->msg('ACH Template Updated', HCU_DISPLAY_AS_RAW);
658  }
659  }
660 
661  $aryResult["submit_batch"] = "Success";
662  break;
663  case "approve":
664 
665  break;
666  case "csv":
667  $uploadFile = $_FILES["csvFile"];
668  if ( $uploadFile["error"] !== 0 || $uploadFile["type"] != "text/csv" ) {
669  $aryErrors[] = $MC->msg('Upload file error', HCU_DISPLAY_AS_RAW) . " 1000";
670  throw new Exception (HCU_JsonEncode($aryErrors));
671  }
672 
673  $tmpName = $uploadFile["tmp_name"];
674 
675  if ( !is_uploaded_file( $tmpName ) ) {
676  $aryErrors[] = $MC->msg('Upload file error', HCU_DISPLAY_AS_RAW) . " 1001";
677  throw new Exception (HCU_JsonEncode($aryErrors));
678  }
679 
680  // open the file and check it for correctness
681  $contents = file( $tmpName, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
682 
683  // delete the uploaded file
684  unlink( $tmpName );
685 
686  $csvResult = ACH_ProcessCSV( $HB_ENV, $inputVars["template_id"], $contents, $MC );
687  if ( $csvResult["code"] !== "000" ) {
688  $aryErrors[] = $csvResult["errors"];
689  throw new Exception (HCU_JsonEncode($aryErrors));
690  }
691 
692  // these partners were found and are id, amount, addenda, notify
693  $aryResult["csv"]["found"] = $csvResult["data"]["found"];
694  // these were in csv and not found in partners and are a list of names
695  $aryResult["csv"]["not_found"] = $csvResult["data"]["not_found"];
696  // these were template partners that weren't in the csv and are a list of names
697  $aryResult["csv"]["missed"] = $csvResult["data"]["missed"];
698  break;
699  default:
700  $aryErrors[] = "Unexpected action: {$inputVars["action"]}";
701  throw new Exception (HCU_JsonEncode($aryErrors));
702  }
703 }
704 catch(Exception $ex)
705 {
706  //Return error message
707  $aryReply["homecuErrors"] = HCU_JsonDecode( $ex->getMessage() );
708 
709  // if returning error, not replying with data
710  $aryResult = array();
711 
712  // if returning error, not returning status
713  $aryInfo = array();
714 }
715 
716  if ( count( $aryInfo ) ) {
717  $aryReply["homecuInfo"] = $aryInfo;
718  }
719 
720  if ( count( $aryResult ) ) {
721  $aryReply["homecuData"] = $aryResult;
722  }
723 
724  print HCU_JsonEncode(Array("Results" => $aryReply));
725 
726 // Do the actual entity conversion for a single element (one dimentional associative array).
727 function FixOneElement( $pInputList ) {
728  $outputArray = array();
729 
730  $keys = HCU_array_keys( $pInputList );
731 
732  foreach ( $keys as $key ) {
733  $outputArray[$key] = html_entity_decode( $pInputList[$key] );
734  }
735 
736  return $outputArray;
737 } // end FixOneElement
738 
739 /*
740  * Go through and change any html entities into the correct html character.
741  * Returns an array with the same keys as came in but the fields are converted.
742  */
743 function FixEntities( $pHBEnv, $pInputArray ) {
744 
745  $retArray = array();
746 
747  try {
748  if ( !is_array( $pInputArray ) ) {
749  throw new Exception ("Parameter must be an array.");
750  }
751 
752  for ( $i = 0; $i < count( $pInputArray ); $i++ ) {
753  $element = $pInputArray[$i];
754 
755  // add to output array
756  $retArray[] = FixOneElement( $element );
757  }
758 
759  } catch (Exception $ex) {
760  $reason = $ex->getMessage();
761  $pHBEnv["SYSENV"]["logger"]->info( __FILE__ . " FixEntities error: " . $reason );
762 
763  // return what we got
764  $retArray = $pInputArray;
765  }
766 
767  return $retArray;
768 } // end FixEntities