addMinutes(config('onewaysms.minutes')); $created_at = $currentDateTime->toDateTimeString(); $voter = Voter::where('no_kp', $request->no_kp)->firstOrFail(); if ($voter) { $expiration = $this->checkExpirationTAC($request->no_kp); if ($expiration['notexpired'] == true) { throw new \Exception('Expired TAC : ' . $expiration['remaining']); } $sms_token = $this->getTokenSMS($voter->telefon, $currentDateTime); if ($sms_token == 'error') { throw new \Exception('error in getting the data from SMSToken'); } $user_otp = new UserOTP(); $user_otp->nokp = $voter->no_kp; $user_otp->telefon = $voter->telefon; $user_otp->token = $sms_token; $user_otp->created_at = $created_at; $user_otp->expired_at = $expired_at; $user_otp->save(); activity() ->performedOn($voter) ->withProperties([ 'election_id' => Util::getCurrentElection(), 'voter_id' => $voter->id, 'voter_name' => $voter->name, 'no_kp' => $voter->no_kp, 'telefon' => $voter->telefon, 'otp_expires_at' => $expired_at->toDateTimeString(), 'ip' => $request->ip(), 'user_agent' => $request->userAgent(), ]) ->log('voter request tac'); $response = [ 'status' => 'success', 'message' => 'generated SMS Token', 'notel' => $voter->telefon, 'nokp' => $voter->no_kp, ]; if (app()->environment(['local', 'development'])) { $response['debug_otp'] = $sms_token; } return response()->json($response); } return response()->json([ 'status' => 'failed', 'message' => 'Does not found NO KP.', ]); } catch (Exception $e) { activity() ->withProperties([ 'no_kp' => (string) $request->input('no_kp'), 'ip' => $request->ip(), 'user_agent' => $request->userAgent(), 'error' => $e->getMessage(), ]) ->log('voter request tac failed'); return response()->json([ 'status' => 'failed', 'message' => 'Error: ' . $e->getMessage(), ]); } } public function checkExpirationTAC($nokp): array { $currentDateTime = Carbon::now(); $expiretac = UserOTP::where('nokp', $nokp) ->whereDate('created_at', '=', $currentDateTime) ->whereDate('expired_at', '=', $currentDateTime) ->whereTime('expired_at', '>=', $currentDateTime->toTimeString()) ->whereTime('created_at', '<=', $currentDateTime->toTimeString()) ->latest() ->first(); if ($expiretac) { $remaining = $this->getRemainingTime($expiretac->expired_at); return ['notexpired' => true, 'remaining' => $remaining]; } return ['notexpired' => false]; } public function verifyTAC(Request $request) { $authenticateOTP = $this->getTACModel($request->no_kp, $request->token); if (! $authenticateOTP['condition']) { activity() ->withProperties([ 'no_kp' => (string) $request->input('no_kp'), 'ip' => $request->ip(), 'user_agent' => $request->userAgent(), 'reason' => $authenticateOTP['message'] ?? 'invalid', ]) ->log('voter verify tac failed'); return response()->json([ 'status' => 'failed', 'message' => $authenticateOTP['message'], ]); } if (Auth::guard('voter')->attempt(['no_kp' => $request->no_kp, 'password' => 'admin', 'election_id' => Util::getCurrentElection()])) { $user = Auth::guard('voter')->user(); activity() ->performedOn($user) ->withProperties([ 'election_id' => Util::getCurrentElection(), 'voter_id' => $user->id, 'voter_name' => $user->name, 'no_kp' => $user->no_kp, 'ip' => $request->ip(), 'user_agent' => $request->userAgent(), ]) ->log("voter login: {$user->name}"); return response()->json([ 'status' => 'success', 'message' => 'Login successfully.', 'user' => Auth::guard('voter')->user(), 'election_status' => Util::getElectionStatus(), 'token' => Auth::guard('voter')->user()->createToken('My Token', ['vote'])->accessToken, ]); } activity() ->withProperties([ 'no_kp' => (string) $request->input('no_kp'), 'ip' => $request->ip(), 'user_agent' => $request->userAgent(), ]) ->log('voter login failed'); return response()->json([ 'status' => 'failed', 'message' => 'No. KP tidak wujud. Atau sesi mengundi telah tamat', ]); } private function getTACModel($no_kp, $token) { $currentDateTime = Carbon::now(); $result = UserOTP::where('nokp', $no_kp) ->whereDate('created_at', '=', $currentDateTime) ->whereDate('expired_at', '=', $currentDateTime) ->whereTime('expired_at', '>=', $currentDateTime->toTimeString()) ->whereTime('created_at', '<=', $currentDateTime->toTimeString()) ->latest() ->first(); if (! $result) { return ['condition' => false, 'message' => 'Token Expired']; } if ($result['token'] == $token) { return ['condition' => true]; } return ['condition' => false, 'message' => 'Invalid Token']; } private function getTokenSMS($tele, $date) { $tac_token = $this->randum_number(6, 2, false); if (env('APP_ENV') == 'production') { $mobileno = '6' . $tele; $messages = sprintf(config('onewaysms.message'), $tac_token, $date); $parameter = [ 'apiusername' => env('ONEWAY_SMS_USERNAME'), 'apipassword' => env('ONEWAY_SMS_PASSWORD'), 'senderid' => env('ONEWAY_SMS_SENDERID', 'INFO'), 'mobileno' => $mobileno, 'message' => $messages, 'languagetype' => env('ONEWAY_SMS_LANG', 1), ]; $client = new Client(['verify' => false]); $status = $client->get('http://gateway.onewaysms.com.my:10001/api.aspx', [ 'query' => $parameter, ]); if ($status) { return $tac_token; } return 'error'; } return $tac_token; } private function randum_number($len = 6, $dup = 1, $sort = false) { if ($dup < 1) { throw new \InvalidArgumentException('Second argument is < 1'); } $num = range(0, 9); shuffle($num); $num = array_slice($num, 0, ($len - $dup) + 1); if ($dup > 0) { $k = array_rand($num, 1); for ($i = 0; $i < ($dup - 1); $i++) { $num[] = $num[$k]; } } if ($sort) { sort($num); } return implode('', $num); } private function getRemainingTime($expired_at) { $currentDateTime = Carbon::now(); $expiredAt = Carbon::parse($expired_at); $remainingSeconds = $currentDateTime->diffInSeconds($expiredAt); return gmdate('H:i:s', $remainingSeconds); } }