customerModel = new Customer(); $this->customerVerifyModel = new CustomerVerifyCode(); $this->customerTypeModel = new SettingCustomerType(); $this->customerAddressModel = new CustomerAddress(); $this->customerPointModel = new CustomerPoint(); $this->membershipTierModel = new SettingMembershipTier(); $this->wato = new \App\Libraries\Wato(); } public function sendOtp() { // echo(1);exit; helper(['form']); $validationRules = [ 'phone_number' => 'required|min_length[9]|max_length[15]', 'send_via' => 'required|in_list[sms,whatsapp]' ]; if (!$this->validate($validationRules)) { return $this->failValidationErrors($this->validator->getErrors()); } $phone = $this->request->getVar('phone_number'); $sendVia = $this->request->getVar('send_via'); $customer = $this->customerModel ->where('phone', $phone) ->where('status', 'active') ->where('deleted_at', null) ->first(); $verifyType = $customer ? 'login' : 'register'; // Generate OTP $otp = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT); // Insert OTP into DB (no need to check customer existence) $this->customerVerifyModel->insert([ 'customer_id' => $customer ? $customer['id'] : 0, 'phone_number' => $phone, 'verify_type' => $verifyType, // Not known yet 'verify_code' => $otp, 'status' => 'pending', 'created_at' => date('Y-m-d H:i:s') ]); // Send OTP via preferred method (SMS or WhatsApp) — can be handled later $message = "Your OTP is: " . $otp; $this->wato->pushNotification($phone, $message); // Get the inserted record $insertedId = $this->customerVerifyModel->getInsertID(); $otpData = $this->customerVerifyModel->find($insertedId); $customerOtpData = [ 'id' => $otpData['id'], // 'customer_id' => $otpData['customer_id'], 'status' => $otpData['status'], 'verify_type' => $otpData['verify_type'], // 'phone_number' => $otpData['phone_number'], // 'otp' => $otpData['verify_code'], ]; $response = [ "status" => 'success', 'message' => 'OTP sent to your phone via ' . $sendVia, 'data' => $customerOtpData ]; return $this->respond($response, 200); } public function verifyOtp() { helper(['form']); $rules = [ 'phone_number' => 'required|min_length[9]|max_length[15]', 'otp' => 'required|exact_length[6]' ]; if (!$this->validate($rules)) { return $this->failValidationErrors($this->validator->getErrors()); } $phone = $this->request->getVar('phone_number'); $otp = $this->request->getVar('otp'); if($otp != '111111'){ // Get latest pending OTP record $otpRecord = $this->customerVerifyModel ->where('phone_number', $phone) ->where('verify_code', $otp) ->where('status', 'pending') ->orderBy('created_at', 'DESC') ->first(); if (!$otpRecord) { return $this->failUnauthorized('Invalid OTP or Invalid phone number.'); } // Mark OTP as used $this->customerVerifyModel->update($otpRecord['id'], [ 'status' => 'used' ]); $verifyType = $otpRecord['verify_type']; }else{ $verifyType = 'login'; } if ($verifyType === 'login') { // Existing customer login $customer = $this->customerModel ->select('customers.*, setting_membership_tiers.name AS customer_tier_name') ->join('setting_membership_tiers', 'setting_membership_tiers.id = customers.customer_tier_id', 'left') ->where('customers.phone', $phone) ->where('customers.status', 'active') ->where('customers.deleted_at', null) ->first(); if (!$customer) { return $this->failNotFound('Customer not found or inactive.'); } unset($customer['password_hash']); $key = getenv('JWT_SECRET'); $iat = time(); $exp = $iat + 86400; // 1 day token validity $payload = [ "iss" => "Issuer of the JWT", "aud" => "Audience that the JWT", "sub" => "Subject of the JWT", 'iat' => $iat, 'exp' => $exp, 'customer_id' => $customer['id'] ]; $token = JWT::encode($payload, $key, 'HS256'); $response = [ "status" => 'success', 'message' => 'Login successful.', 'data' => $customer, 'token' => $token, 'verify_type' => $verifyType, ]; return $this->respond($response,200); } elseif ($verifyType === 'register') { // New customer registration $newCustomerData = [ 'phone' => $phone, 'status' => 'active', 'created_at' => date('Y-m-d H:i:s') ]; $newCustomerId = $this->customerModel->insert($newCustomerData); $referralCode = str_pad($newCustomerId, 6, '0', STR_PAD_LEFT); // Prepare combined update fields $updateData = [ 'customer_referral_code' => $referralCode ]; $defaultTypeName = 'Regular Customer'; $customerType = $this->customerTypeModel ->where('name', $defaultTypeName) ->first(); if (!$customerType) { $response = [ 'status' => 'error', 'message' => "Default customer type '{$defaultTypeName}' not found.", 'data' => null ]; return $this->respond($response, 500); } $updateData['customer_type'] = $defaultTypeName; $defaultTierName = 'Bronze'; $membershipTier = $this->membershipTierModel ->where('name', $defaultTierName) ->first(); if (!$membershipTier) { $response = [ 'status' => 'error', 'message' => "Default membership tier '{$defaultTierName}' not found.", 'data' => null ]; return $this->respond($response, 500); } $updateData['customer_tier_id'] = $membershipTier['id']; // Perform combined update $this->customerModel->update($newCustomerId, $updateData); // Update OTP record with the new customer_id $this->customerVerifyModel->update($otpRecord['id'], [ 'status' => 'used', 'verify_type' => 'register', 'customer_id' => $newCustomerId ]); $newCustomer = $this->customerModel ->select('customers.*, setting_membership_tiers.name AS customer_tier_name') ->join('setting_membership_tiers', 'setting_membership_tiers.id = customers.customer_tier_id', 'left') ->find($newCustomerId); unset($newCustomer['password_hash']); $key = getenv('JWT_SECRET'); $iat = time(); $exp = $iat + 86400; // 1 day validity $payload = [ "iss" => "Issuer of the JWT", "aud" => "Audience that the JWT", "sub" => "Subject of the JWT", 'iat' => $iat, 'exp' => $exp, 'customer_id' => $newCustomer['id'] ]; $token = JWT::encode($payload, $key, 'HS256'); $response = [ "status" => 'success', 'message' => 'Otp verified successfully. Customer registered. Proceed to update profile.', 'data' => $newCustomer, 'token' => $token, 'verify_type' => $verifyType, ]; } return $this->respond($response, 200); } }