Odyssey
MDesk_API.i
1 <?php
2 function mdesk_readMember($mxURL, $mxKey, $orgid, $member, $parms) {
3 // curl -i https://int-live.moneydesktop.com/:client_id/users/:user_id/members/:member_id \
4 // -H "Content-Type:application/vnd.moneydesktop.mdx.v5+xml" \
5 // -H "Accept:application/vnd.moneydesktop.mdx.v5+xml" \
6 // -H "MD-API-KEY: :api_key"
7 
8  $request = "{$mxURL}/{$orgid}/users/{$orgid}-{$member}/members/M-{$orgid}-{$member}.json";
9  $reqHeaders = array("Content-Type:application/json",
10  "MD-API-Key: $mxKey",
11  "Accept: application/vnd.moneydesktop.mdx.v5+json");
12 
13  $parms["environment"]["logPoint"] = "readMember"; // this action in a readable form
14  $MXsaid = mdesk_embcurl($parms, $request,'GET',$mxKey, $reqHeaders);
15 
16  return $MXsaid;
17 }
18 
19 function mdesk_createMember($mxURL, $mxKey, $orgid, $member, $token, $parms) {
20 // curl -i -X POST https://int-live.moneydesktop.com/:client_id/users/:user_id/members \
21 // -d '<member><user_id>:user_id</user_id><id>:id</id><userkey>:userkey</userkey></member>' \
22 // -H "Content-Type:application/vnd.moneydesktop.mdx.v5+xml" \
23 // -H "Accept:application/vnd.moneydesktop.mdx.v5+xml" \
24 // -H "MD-API-KEY: :api_key"
25 
26  $request = "{$mxURL}/{$orgid}/users/{$orgid}-{$member}/members.json";
27 
28  $reqData = json_encode(array("member" => array("id" => "M-{$orgid}-{$member}", "userkey" => "$token")));
29 
30  $reqHeaders = array("Content-Type:application/json",
31  "MD-API-Key: $mxKey",
32  "Accept: application/vnd.moneydesktop.mdx.v5+json");
33 
34  $parms["environment"]["logPoint"] = "createMember"; // this action in a readable form
35  $MXsaid = mdesk_embcurl($parms, $request,'POST',$mxKey, $reqHeaders, $reqData);
36 
37  return $MXsaid;
38 }
39 
40 function mdesk_updateMember($mxURL, $mxKey, $orgid, $member, $token, $parms) {
41 // curl -i -X PUT https://int-live.moneydesktop.com/:client_id/users/:user_id/members/:member_id \
42 // -H "Content-Type:application/vnd.moneydesktop.mdx.v5+xml" \
43 // -H "Accept:application/vnd.moneydesktop.mdx.v5+xml" \
44 // -H "MD-API-KEY: :api_key"
45 
46  $request = "{$mxURL}/{$orgid}/users/{$orgid}-{$member}/members/M-{$orgid}-{$member}.json";
47  $reqData = json_encode(array("member" => array(
48  "user_id" => "{$orgid}-{$member}", "id" => "M-{$orgid}-{$member}",
49  "userkey" => "$token")));
50 
51  $reqHeaders = array("Content-Type:application/json",
52  "MD-API-Key: $mxKey",
53  "Accept: application/vnd.moneydesktop.mdx.v5+json");
54 
55  $parms["environment"]["logPoint"] = "updateMember"; // this action in a readable form
56  $MXsaid = mdesk_embcurl($parms, $request,'PUT',$mxKey, $reqHeaders, $reqData);
57 
58  return $MXsaid;
59 }
60 
61 function mdesk_readUser($mxURL, $mxKey, $orgid, $member, $parms) {
62 // curl -i https://int-live.moneydesktop.com/:client_id/users/:user_id \
63 // -H "Content-Type: application/vnd.moneydesktop.mdx.v5+xml" \
64 // -H "Accept: application/vnd.moneydesktop.mdx.v5+xml" \
65 // -H "MD-API-KEY: :api_key"
66 
67  $request = "{$mxURL}/{$orgid}/users/{$orgid}-{$member}.json";
68  $reqHeaders = array("Content-Type:application/json",
69  "MD-API-Key: $mxKey",
70  "Accept: application/vnd.moneydesktop.mdx.v5+json");
71 
72  $parms["environment"]["logPoint"] = "readUser"; // this action in a readable form
73  $MXsaid = mdesk_embcurl($parms, $request,'GET',$mxKey, $reqHeaders);
74 
75  return $MXsaid;
76 }
77 
78 function mdesk_createUser($mxURL, $mxKey, $orgid, $member, $email, $parms) {
79 // curl -i -X POST https://int-live.moneydesktop.com/:client_id/users \
80 // -d '<user><id>:user_id</id></user>' \
81 // -H "Content-Type: application/vnd.moneydesktop.mdx.v5+xml" \
82 // -H "Accept: application/vnd.moneydesktop.mdx.v5+xml" \
83 // -H "MD-API-KEY: :api_key"
84  $request = "{$mxURL}/{$orgid}/users.json";
85  $reqArr = array("user" => array("id" => "{$orgid}-{$member}"));
86  if (!empty($email) && validateEmail($email) ) {
87  $reqArr["user"]["email"] = $email;
88  }
89  $reqData = json_encode($reqArr);
90 
91  $reqHeaders = array("Content-Type:application/json",
92  "MD-API-Key: $mxKey",
93  "Accept: application/vnd.moneydesktop.mdx.v5+json");
94 
95  $parms["environment"]["logPoint"] = "createUser"; // this action in a readable form
96  $MXsaid = mdesk_embcurl($parms, $request,'POST', $mxKey, $reqHeaders, $reqData);
97 
98  return $MXsaid;
99 }
100 
101 function mdesk_getURL($mxURL, $mxKey, $orgid, $Uid, $widget, $parms) {
102 // $request = "{$mxURL}/{$orgid}/users/" . urlencode("{$orgid}-{$member}") . "/urls/{$widget}.json";
103  $request = "{$mxURL}/{$orgid}/users/{$orgid}-{$Uid}/urls/{$widget}.json";
104  $reqHeaders = array("Content-Type:application/json",
105  "MD-API-Key: $mxKey",
106  "Accept: application/vnd.moneydesktop.sso.v3+json");
107 
108  $parms["environment"]["logPoint"] = "getURL"; // this action in a readable form
109  $MXsaid = mdesk_embcurl($parms, $request,'GET',$mxKey, $reqHeaders);
110 
111  return $MXsaid;
112 }
113 
114 function mdesk_embcurl($parms, $reqURL, $reqMethod, $reqAPIkey, $reqHeaders, $reqData='') {
115  # reqURL is the service url
116  # reqOpts is an array of curlopts
117  # reqHeaders is an array of headers to be sent
118 
119  $curlopts = array(
120  CURLOPT_RETURNTRANSFER => 1,
121  CURLOPT_SSL_VERIFYPEER => 0,
122  CURLOPT_SSL_VERIFYHOST => 0,
123  CURLOPT_HEADER => FALSE,
124  CURLOPT_URL => "$reqURL");
125 
126  $ch = @curl_init();
127  @curl_setopt_array($ch, $curlopts);
128 // if (isset($reqOpts) && count($reqOpts)) {
129 // @curl_setopt_array($ch, $reqOpts);
130 // }
131  if ($reqMethod != 'GET') {
132  @curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $reqMethod);
133  }
134  if (strlen($reqData) > 0) {
135  @curl_setopt($ch, CURLOPT_POSTFIELDS, $reqData);
136  }
137  @curl_setopt($ch, CURLOPT_HTTPHEADER, $reqHeaders);
138 
139  $response = @curl_exec($ch);
140  if ($parms["logging"] == "enabled") {
141  $logParms = $parms["environment"]; // get the environment info passed in
142  $logParms["token"] = ''; // the id used across all communications in session
143  $logParms["txnId"] = time(); // the id for this transaction
144 // $logParms["logPoint"] = "MDesk"; // this action in a readable form
145  $logParms["request"] = "curl "; // the request
146  if ($reqMethod != 'GET') {
147  $logParms["request"] .= "-X $reqMethod ";
148  }
149  $logParms["request"] .= "'$reqURL' "; // the request
150  if (is_array($reqHeaders)) {
151  foreach($reqHeaders as $hdr) {
152  $logParms["request"] .= "-H $hdr ";
153  }
154  }
155  if (strlen($reqData) > 0) {
156  $logParms["request"] .= "-d '$reqData' "; // the request
157  }
158  $logParms["reply"] = $response; // the response
159  LogSSOActivity($logParms);
160  }
161  $respHTTP = curl_getinfo($ch,CURLINFO_HTTP_CODE);
162  if ($respHTTP > 400 && $respHTTP < 600 ) {
163  # HTTP Response 4xx client error or 5xx server error
164  $respArr = array("error"=>array("status" => "hcuH" . $respHTTP,"message" => "Connection Failed HTTP Error"));
165  } elseif (curl_errno($ch)) {
166  $respArr = array("error"=>array("status" => "hcuC" . curl_errno($ch),"message" => "Curl Error"));
167  } elseif (!isset($response) || $response == '') {
168  $respArr = array("error"=>array("status" => "hcuE" . curl_errno($ch),"message" => "Empty Response"));
169  } else {
170  $respArr = json_decode($response, TRUE);
171  }
172 
173  @curl_close($ch);
174  return $respArr;
175 }
176 
177 /**
178  *
179  * @param string $data_URL
180  * @param string $API_key
181  * @param string $Cu
182  * @param integer $Uid # Odyssey Uid
183  * @param string $Cn # Odyssey user_name
184  * @param string $Ml # email
185  * @param string $mxtoken
186  * @param array $parms # used for SSO logging
187  * @return array(Status, Code)
188  * @throws Exception
189  */
190 function mdesk_sync($data_URL, $API_key, $Cu, $Uid, $Cn, $Ml, $mxtoken, $parms) {
191  try {
192 // first try to use an existing member entry in the Mx database
193  # member read (GET)
194 // $resparr = mdesk_readMember($data_URL, $API_key, $Cu, $Cn, $parms); #Mammoth w/Cn
195  $resparr = mdesk_readMember($data_URL, $API_key, $Cu, $Uid, $parms); #Odyssey w/Uid
196 
197  if (isset($resparr['error']) && ($resparr['error']['status'] == 'hcuC' || $resparr['error']['status'] == 'hcuE')) {
198  throw new Exception("Error ({$resparr['error']['message']}). Unable to connect to MoneyDesktop. Please contact the credit union");
199  }
200  if (isset($resparr['member'])) {
201  # if member found, update it with the new token
202 // $resparr = mdesk_updateMember($data_URL, $API_key, $Cu, $Cn, $mxtoken, $parms); #Mammoth w/Cn
203  $resparr = mdesk_updateMember($data_URL, $API_key, $Cu, $Uid, $mxtoken, $parms); #Mammoth w/Cn
204  if (isset($resparr['error'])) {
205  throw new Exception("Error ({$resparr['error']['message']}). Unable to set security token for MoneyDesktop. Please contact the credit union");
206  }
207  } else {
208  # member read did not get a member
209  # try a user read
210 // $resparr = mdesk_readUser($data_URL, $API_key, $Cu, $Cn, $parms); #Mammoth w/Cn
211  $resparr = mdesk_readUser($data_URL, $API_key, $Cu, $Uid, $parms); #Odyssey w/Uid
212  if (isset($resparr['error']) && ($resparr['error']['status'] == 'hcuC' || $resparr['error']['status'] == 'hcuE')) {
213  throw new Exception("Error ({$resparr['error']['message']}). Unable to connect to MoneyDesktop. Please contact the credit union");
214  }
215  if (!isset($resparr['user'])) {
216  # no user, try to create one
217 // $resparr = mdesk_createUser($data_URL, $API_key, $Cu, $Cn, $parms); #Mammoth w/Cn
218  $resparr = mdesk_createUser($data_URL, $API_key, $Cu, $Uid, $Ml, $parms); #Odyssey w/Uid & added Ml
219  if (isset($resparr['error'])) {
220  if ($resparr['error']['status'] == 'hcuC' || $resparr['error']['status'] == 'hcuE') {
221  throw new Exception("Error ({$resparr['error']['message']}). Unable to connect to MoneyDesktop. Please contact the credit union");
222  } else {
223  throw new Exception("Error ({$resparr['error']['message']}). Unable to create user for MoneyDesktop. Please contact the credit union");
224  }
225  }
226  }
227  # user exists, or we made one. Now make the member
228 // $resparr = mdesk_createMember($data_URL, $API_key, $Cu, $Cn, $mxtoken, $parms); #Mammoth w/Cn
229  $resparr = mdesk_createMember($data_URL, $API_key, $Cu, $Uid, $mxtoken, $parms); #Odyssey w/Uid
230  if (isset($resparr['error'])) {
231  if ($resparr['error']['status'] == 'hcuC' || $resparr['error']['status'] == 'hcuE') {
232  throw new Exception("Error ({$resparr['error']['message']}). Unable to connect to MoneyDesktop. Please contact the credit union");
233  } else {
234  throw new Exception("Error ({$resparr['error']['message']}). Unable to create member for MoneyDesktop. Please contact the credit union");
235  }
236  }
237  }
238  # set result success
239  $result = array('status' => 'Success', 'code' => 0);
240  } catch (Exception $e) {
241  # set result error
242 
243 
244  $result = array('status' => $e->getMessage(), 'code' => $e->getCode());
245  }
246  return $result;
247 }
248 
249 function mxValidRequest($headers, $mxHMACKey, $mxRestOpt, $mxSessionData) {
250  try {
251  $statusresult = 0;
252  $statusreason = 'Success';
253  if (empty($mxHMACKey)) {
254  throw new Exception("Missing key");
255  }
256  if (empty($mxSessionData)) {
257  $mxSessionData = ''; # in case it is null, force empty string
258  }
259  $mxContentMD5 = HCU_array_key_value('Content-MD5', $headers);
260  $digest = md5($mxSessionData);
261  if ($digest !== $mxContentMD5) {
262  throw new Exception("Precondition failed Session Data ");
263  }
264 
265  $mxVerb = $_SERVER['REQUEST_METHOD'];
266  $mxHMAC = HCU_array_key_value('MDX-HMAC', $headers);
267  $mxContentType = HCU_array_key_value('Content-Type', $headers);
268  $mxEpoch = HCU_array_key_value('Date', $headers);
269  $mxAccept = HCU_array_key_value('Accept', $headers);
270  $mxSessionKey = HCU_array_key_value('MDX-Session-Key', $headers);
271  if (empty($mxSessionKey)) {
272  $mxSessionKey = ''; # in case it is null, force empty string
273  }
274 //POST /sessions "<?xml version=\"1.0\"?>\n<mdx version=\"5.0\">\n <session>\n <userkey><![CDATA[the-userkey]]></userkey>\n </session>\n</mdx>\n"
275 //Content-Type: application/vnd.moneydesktop.mdx.v5+xml
276 //Date: 1382975431
277 //Accept: application/vnd.moneydesktop.mdx.v5+xml
278 //MDX-Session-Key:
279  #HTTP VERB + "\n" + # $mxVerb
280  #Content-MD5 Header + "\n" + # $mxContentMD5
281  #Content-Type Header + "\n" + # $mxContentType
282  #UNIX Epoch Date Time + "\n" + # $mxEpoch
283  #Accept Header + "\n" + # $mxAccept
284  #MDX-Session-Key + "\n" + # $mxSessionKey
285  #REST Resource of Request # $mxRestOpt
286 
287 # $mxHMACKey = "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo3ODkwMTI=";
288 
289 // $sigStr = "POST\ne9a179f879165fd64bdeaa57032d342f\napplication/vnd.moneydesktop.mdx.v5+xml\n1382975431\napplication/vnd.moneydesktop.mdx.v5+xml\n\n/sessions";
290  $sigStr = "{$mxVerb}\n{$mxContentMD5}\n{$mxContentType}\n{$mxEpoch}\n{$mxAccept}\n{$mxSessionKey}\n/{$mxRestOpt}";
291  # calculate SHA1 using key mxHMACKey above as test
292  $sigHash = hash_hmac("SHA1", $sigStr, base64_decode($mxHMACKey));
293  if ($sigHash !== $mxHMAC) {
294  throw new Exception("Precondition Failed Signature");
295  }
296  } catch (Exception $e) {
297  $statusresult = 999;
298  $statusreason = $e -> getMessage();
299 // $statusreason .= " " . json_encode(array(
300 // 'mxHMACKey' => $mxHMACKey,
301 // 'sigStr' => $sigStr,
302 // 'sigHash' => $sigHash));
303  }
304 // return $statusresult;
305  return array('status' => $statusresult, 'message' => $statusreason);
306 }
307 function CheckMxKey($CU, $USERKEY, $MXKEY, $HMETHOD) {
308  try {
309  $result = array('Status' => array('Code' => 0, 'Message' => 'Success'));
310 
311  $apptokarr = array();
312  # decrypt key first
313 
314  parse_str(urldecode($USERKEY), $apptokarr);
315 
316  if (!HCU_array_key_value('E',$apptokarr) || !HCU_array_key_value('A',$apptokarr) || !HCU_array_key_value('H',$apptokarr) ) {
317  throw new Exception("Invalid Credentials (Partial Token) " . __LINE__, 15510);
318  }
319 
320  if ($apptokarr['E'] < time()) {
321  throw new Exception("Invalid Credentials (Expired Token) " . __LINE__, 15510);
322  }
323 
324  $MEMBER = $apptokarr['A'];
325  $EXPIRES = $apptokarr['E'];
326 
327  if (HCU_array_key_exists('P',$apptokarr) ) {
328  $PWCHANGE = HCU_array_key_value('P',$apptokarr);
329  } else {
330  $PWCHANGE = 0;
331  }
332  if ($HMETHOD == 'S') {
333  $hash = hash_hmac('sha384', MD5(join(':', array($MXKEY, $EXPIRES, $CU, $MEMBER, $PWCHANGE))), $MXKEY);
334  } else {
335  $hash = MD5($MXKEY . MD5(join(':', array($MXKEY, $EXPIRES, $CU, $MEMBER, $MEMBER))));
336  }
337  if ($apptokarr['H'] != $hash) {
338  throw new Exception("Invalid Credentials (Corrupted Token) " . __LINE__, 15510);
339  }
340 
341  $result['data'] = $apptokarr;
342  } catch (Exception $e) {
343  $result = array('Status' => array('Code' => $e->getCode(), 'Message' => 'Failed ' . $e->getMessage()));
344  }
345  return $result;
346 }
347 /**
348  *
349  * @param string $CU HomeCU client code
350  * @param string $USER HomeCU UID
351  * @param integer $TTL time-to-live of hash in seconds 8121600 = 94days
352  * @param string $KEY hash key to use
353  * @param string $KEYTYPE (A)authenticated or (P) MFA-in-progress
354  * @param string $HMETHOD hash method to use S=sha384 M=md5
355  * @param integer $PWCHANGE timestamp of last password change
356  * @return string new USERKEY
357  */
358 function MakeMxKey($CU, $USER, $TTL, $KEY, $KEYTYPE, $HMETHOD, $PWCHANGE=0) {
359  $appexpires = time() + $TTL; # 94 days
360  if ($HMETHOD == 'S') {
361  $apphash = hash_hmac('sha384',MD5(join(':', array($KEY, $appexpires, $CU, $MEMBER, $PWCHANGE))),$KEY);
362  $apptoken = urlencode("H=$apphash&E=$appexpires&A=$MEMBER&P=$PWCHANGE");
363  } else {
364  $apphash = MD5($KEY . MD5(join(':', array($KEY, $appexpires, $CU, $MEMBER, $MEMBER))));
365  $apptoken = urlencode("H=$apphash&E=$appexpires&A=$MEMBER&C=$MEMBER");
366  }
367  return $apptoken;
368 }
369 function createMxKey($Cu, $mxBundle) {
370  try {
371  $mxBundle = HCU_PayloadEncode($Cu,$mxBundle);
372  $mxBundle = str_replace(array("+", "/", "="), array("-", "_", "."), $mxBundle);
373  } catch (Exception $e) {
374  $mxBundle='';
375  }
376 
377  return $mxBundle;
378 }
379 function openMxKey($Cu, $mxBundle) {
380  try {
381 
382  $mxBundle = str_replace(array("-", "_", "."), array("+", "/", "="), $mxBundle);
383  $mxBundle = HCU_PayloadDecode($Cu, $mxBundle);
384 
385  } catch (Exception $e) {
386  $mxBundle=array();
387  }
388  return $mxBundle;
389 }
390 function mdesk_setLogging($dbh, $Cu, $username, &$parms) {
391  # set up logging here
392  $loggingFlag = trim($parms["hcuLogging"]);
393  if (strlen($loggingFlag) > 0) {
394 
395  $enable = $loggingFlag == -1;
396 
397  if (!$enable) {
398  $loggingFlag = str_replace(" ", "", strtolower($loggingFlag));
399  $testArray = explode(",", $loggingFlag);
400  $enable = in_array(strtolower($username), $testArray);
401  }
402 
403  if ($enable) {
404  // these are used inside the plugin to test if logging and info to log.
405  $parms["logging"] = "enabled";
406  $parms["environment"] = array("Cu" => $Cu, // credit union
407  "memberId" => $username, // member id
408  "SSOVendor" => 'MDX',
409  "userIP" => $_SERVER['REMOTE_ADDR'], // user's ip address
410  "dbConn" => $dbh); // database connection
411  }
412  }
413 }