تایید شماره موبایل با SMS در PHP (احراز هویت پیامکی)
تایید شماره موبایل PHP – در این آموزش با استفاده از api پیامکی که آموزش دادیم می خواهیم که سیستم ثبت نام پیامکی را در php بسازیم .
تا زمانی که کد ارسال شده به شماره را در فیلد خواسته شده وارد نکند امکان ثبت نام وجود نخواهد داشت و البته هر کد یکبار مصرف تنها 2 دقیقه اعتبار دارد و بعد از آن منقضی خواهد شد .
همچنین اگر برای هر کد تنها 3 بار امکان وارد سازی کد تایید وجود دارد و بیش از آن کد منقضی خواهد شد و حتی اگر برای بار 4 درست هم وارد شود باز هم کاربر نامعتبر دریافت می کند .
دموی پروژه :
در این سیستم فایل هایی شامل :
- sign.up.php : صفحه ثبت نام کاربر با شماره همراه
- sign.up.verify.php : صفحه وارد کردن کد تایید ارسال شده
- sign.up.complete.php : صفحه ای پس از دریافت کد تایید صحیح از کاربر خواسته می شود تا پروفایل خود را کامل نماید ( نام کاربری ، نام کامل )
- view.php : صفحه ای که پس از فعال شدن حساب کاربر هدایت می شود که اطلاعات فردی خود را مشاهده نماید .
- فایل توابع functions.php : اکثر تابع های کاربردی را در این اسکریپت داریم که از جمله ( ساخت توکن برای اعتبار سنجی ، handle کردن فرم ها )
- فایل توابع misc.php : توابع متفرقه از جمله ( بررسی Regex ، ارسال post ، ارسال پیامک ، دریافت اطلاعات کاربر از طریق کوکی )
- فایل توابع db.php : توابع مربوط به دیتابیس ( اتصال ، ساخت ، دریافت ، بروزرسانی )
1- اسکریپت sign.up.php
<?php require_once "parts/header.php"; ?> <h1 class="text-center">ثبت نام</h1> <?php if (!@$handler_result || isset($handler_result['status']) && !$handler_result['status']) : ?> <form method="POST" class="col-6 m-auto"> <label class="mb-2" for="phone_number">شماره همراه</label> <input type="text" name="phone_number" id="phone_number" class="form-control" dir="ltr" placeholder="09*********"> <input type="hidden" name="handler" value="handler_post_sign_up"> <div class="text-center mt-4"> <input type="submit" class="btn btn-outline-success" value="ارسال"> </div> </form> <?php elseif (@$handler_result['status'] == 1 || @$handler_result['status'] == -1) : ?> <form method="POST" class="col-6 m-auto"> <p class="bg-<?= $handler_result['status'] == 1 ? "success text-white" : "warning text-dark" ?> p-2 rounded text-center"><?= $handler_result['message'] ?></p> <label class="mb-2" for="verify_code">کد تایید</label> <input type="number" name="verify_code" id="verify_code" class="form-control" dir="ltr" placeholder="* * * *"> <input type="hidden" name="handler" value="handler_post_sign_up_verify"> <input type="hidden" name="id" value="<?= $handler_result['data'] ?>"> <div class="text-center mt-4"> <input type="submit" class="btn btn-outline-success" value="ارسال"> </div> </form> <?php endif; ?> <?php ?> <?php require_once "parts/footer.php"; ?>
2- اسکریپت sign.up.verify.php
<?php require_once "parts/header.php"; ?> <h1 class="text-center">تکمیل پروفایل</h1> <form method="POST" class="col-6 m-auto"> <label class="mb-2" for="phone_number">شماره همراه</label> <input type="number" name="phone_number" id="phone_number" class="form-control" dir="ltr" placeholder="09*********"> <input type="hidden" name="handler" value="handler_post_sign_up"> <div class="text-center mt-4"> <input type="submit" class="btn btn-outline-success" value="ارسال"> </div> </form> <?php require_once "parts/footer.php"; ?>
3- اسکریپت sign.up.complete.php
<?php require_once "parts/header.php"; ?> <h1 class="text-center">تکمیل پروفایل</h1> <form method="POST" class="col-6 m-auto"> <label class="mb-2" for="username">نام کاربری ( کاراکتر های مجاز (a-z .) )</label> <input type="text" name="username" id="username" class="form-control" dir="ltr" placeholder="senior.x"> <div class="w-100 mt-3"></div> <label class="mb-2" for="fullname">نام کامل</label> <input type="text" name="fullname" id="fullname" class="form-control" dir="rtl" placeholder="حسین باقری"> <input type="hidden" name="handler" value="handler_post_sign_up_complete"> <div class="text-center mt-4"> <input type="submit" class="btn btn-outline-success" value="ارسال"> </div> </form> <?php require_once "parts/footer.php"; ?>
4- اسکریپت view.php
<?php require_once "parts/header.php"; ?> <h1 class="text-center">پروفایل <?= $GLOBALS['user_data']['fullname'] ?></h1> <form method="POST" class="col-6 m-auto"> <label class="mb-2" for="username">نام کاربری</label> <input type="text" disabled name="username" id="username" class="form-control" dir="ltr" placeholder="senior.x" value="<?= $GLOBALS['user_data']['username'] ?>"> <div class="w-100 mt-3"></div> <label class="mb-2" for="fullname">نام کامل</label> <input type="text" disabled name="fullname" id="fullname" class="form-control" dir="rtl" placeholder="حسین باقری" value="<?= $GLOBALS['user_data']['fullname'] ?>"> <input type="hidden" name="handler" value="handler_post_sign_up_complete"> </form> <?php require_once "parts/footer.php"; ?>
5- اسکریپت توابع functions.php
<?php require_once "misc.php"; require_once "db.php"; function generate_rand_int($from = 1000, $to = 9999) { return random_int($from, $to); } function generate_otp_code($phone_number) { $id = insertRow([ "phone_number" => $phone_number, "code" => generate_rand_int(), ], "otp"); $row = selectRow("otp", [$id], "id=?"); $row = $row[0]; return $row; } function getMessageOtpSent($otp) { return "کد تایید : {$otp['code']}\nرپید کد"; } function get_session_epxire_seconds() { return 86400 * 30; } function generate_token($type, $user_id, $phone_number) { $token = generate_password_hash(time() . uniqid("rpd_salt")); $id = insertRow([ "user_id" => $user_id, "type" => $type, "token" => $token, "phone_number" => $phone_number ], "session_token"); return [ "id" => $id, "token" => $token ]; } function getPostHandlers() { return [ "handler_post_sign_up", "handler_post_sign_up_verify", "handler_post_sign_up_complete" ]; } function handler_post($post) { $handler = $post['handler'] ?? ""; $post_handlers = getPostHandlers(); if (in_array($handler, $post_handlers)) { return $handler($post); } else { die("invalid handler {$handler}"); } } function get_seconds_expire_otp() { return 120; } function getResponseHtml() { return [ "status" => 0, // 0 -> fail , 1 -> success , -1 -> try again "message" => "", "data" => "", "redirect" => "", ]; } function handler_post_sign_up($post) { $phone_number = $post['phone_number'] ?? ""; $seconds_expire = get_seconds_expire_otp(); $res = getResponseHtml(); if (regexCheck($phone_number, '/\d{11}/m')) { $old_phone_number = isRowExists("users", [$phone_number], "phone_number=?"); if ($old_phone_number) { $res['message'] = "شماره {$phone_number} قبلا وارد شده"; } else { $limit_message_cbk = function () use (&$limit_seconds, &$res) { $limit_seconds = get_seconds_expire_otp(); $res['message'] = "از قبل کد فعالسازی برای شما فرستاده شده لطفا از زمان ارسال تا {$limit_seconds} ثانیه بعد اقدام کنید"; }; // check for sms limitation $can_send = limit_send_message(["restrict" => true, "column" => "phone_number", "data" => []], $post['phone_number']); if ($can_send) { $otp = generate_otp_code($post['phone_number']); $sms_res = send_message(getMessageOtpSent($otp), $post['phone_number'], ["column" => "phone_number", "data" => $otp]); if (is_int($sms_res)) { $res['status'] = 1; $res['message'] = "کد تایید به شماره {$post['phone_number']} ارسال گردید و در <span data-action=\"lesser\" data-on-end=\"reload\" class=\"timer\">{$seconds_expire}</span> ثانیه دیگر منقضی می گردد"; $res['data'] = $otp['id']; } else { $limit_message_cbk(); } } else { $limit_message_cbk(); } } } else { $res['message'] = "شماره همراه نا معتبر"; } return $res; } function handler_post_sign_up_verify($post) { $res = getResponseHtml(); $verify_code = $post['verify_code']; $id = $post['id']; $row = selectRow("otp", [$id], "id=?"); if (!empty($row[0])) { $row = $row[0]; } if (!$row) { $res['message'] = "موردی با این مشخصات یافت نشد"; } else { $datetime = getDatetime(); if (($row['expired_at'] < $datetime)) { $res['message'] = "کد وارد شده منقضی شده"; } else { $attempted = $row["attempt"] + 1; $dataUpdate = ["attempt" => ($attempted)]; $expire_otp = function () use (&$dataUpdate) { $dataUpdate['expired_at'] = getDatetime((time() - 10)); }; if ($row['code'] != $verify_code) { $res['message'] = "کاراکتر وارد شده مطابقت ندارد"; $res['status'] = -1; $res['data'] = $id; if ($attempted == 3) { $expire_otp(); } $affectedRows = updateRow($dataUpdate, "otp", ["keys" => "id=?", "values" => [$id]]); } else if ($row['code'] == $verify_code) { $expire_otp(); $dataUpdate['checked'] = true; updateRow($dataUpdate, "otp", ["keys" => "id=?", "values" => [$id]]); $token_data = generate_token("auth", -1, $row['phone_number']); setcookie("auth", $token_data['token'], (time() + get_session_epxire_seconds())); $res['status'] = 1; $res['message'] = "موفق , اکنون به صفحه پروفایل وارد می شید"; $res['redirect'] = "sign.up.complete.php"; } } } return $res; } function handler_post_sign_up_complete($post) { $res = getResponseHtml(); if (!@$post['username'] || !@$post['fullname']) { $res['message'] = "نام کاربری یا نام کامل وارد نشده"; } else { $post['fullname'] = trim(strtolower($post['fullname'])); $post['fullname'] = preg_replace('/\s{2,}/m' , " " , $post['fullname']); if (100 < mb_strlen($post['username']) || 100 < mb_strlen($post['fullname'])) { $res['message'] = "نام کاربری یا نام کامل بیشتر از 100 کاراکتر می باشد"; } else { if (!regexCheck($post['username'], '/^[a-zA-Z.]{1,}$/m')) { $res['message'] = "نام کاربری معتبر نیست لطفا طبق الگو انتخاب کنید"; } else { $row = isRowExists("users", [$post['username']], "username=?"); if ($row) { $res['message'] = "نام کاربری {$post['username']} از قبل انتخاب شده نام کاربری دیگری در نظر بگیرید"; } else { $user_id = insertRow(["username" => $post['username'], "fullname" => $post['fullname'], "status" => "active", "phone_number" => $GLOBALS['user_data']['phone_number']], "users"); updateRow(["user_id" => $user_id], "session_token", ["keys" => "token = ?", "values" => [$_COOKIE['auth']]]); header("Location: view.php"); } } } } return $res; }
6- اسکریپت توابع misc.php
<?php function regexCheck($str, $regex) { $str = preg_replace($regex,"", $str); return $str == ""; } function limit_send_message($limit, $to) { $can_send = 1; if ($limit) { $row = selectRow("otp", [$to, getDatetime()], "{$limit['column']}=? AND ? <= expired_at"); if (isset($row[0])) { $row = $row[0]; if (isset($limit['data']['id']) && $row['id'] != $limit['data']['id']) { $can_send = 0; } else if (!isset($limit['data']['id']) && !empty($limit['restrict'])) { $can_send = 0; } } } return $can_send; } function send_message($message, $to, $limit = ["column" => "", "data" => [], "restrict" => false]) { if (!empty($limit['column'])) { $status_limit = limit_send_message($limit, $to); if (!$status_limit) return $limit['column']; } $status = 0; $body = ["username" => 'USERNAME', "password" => 'PASSWORD', "to" => $to, "from" => 'FROM', "text" => $message, "isflash" => 'true',]; $response = postRequest('http://api.payamak-panel.com/post/send.asmx/SendSimpleSMS', $body); $response = (array)new SimpleXMLElement($response); $response = trim($response['string']); if (100 < $response) $status = 1; else $status = 0; return $status; } function postRequest($url, $data) { $params = http_build_query($data); $options = array( CURLOPT_URL => $url, CURLOPT_HTTPHEADER => ["Content-Type: application/x-www-form-urlencoded"], CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => $params, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_RETURNTRANSFER => true ); $ch = curl_init(); curl_setopt_array($ch, $options); $response = curl_exec($ch); curl_close($ch); return $response; } function getDatetime($timestamp = null) { $timestamp = $timestamp ?: time(); return date("Y-m-d H:i:s", $timestamp); } function generate_password_hash($password, $option = ["cost" => "10"]) { return password_hash($password, PASSWORD_BCRYPT, $option); } function check_hashed_password($password, $hashed_password) { return password_verify($password, $hashed_password); } function get_current_user_data() { if (!isset($GLOBALS['user_data'])) $GLOBALS['user_data'] = []; $status = false; if (isset($_COOKIE['auth'])) { $token_data = isRowExists("session_token", [$_COOKIE['auth']], "token=?"); $invalid_cookie_cbk = function() use ($status){ setcookie("auth" , "" , time() - 15); return $status; }; if (!$token_data){ return $invalid_cookie_cbk(); } if ($token_data['expired_at'] < getDatetime()) { return $invalid_cookie_cbk(); } $GLOBALS['user_data']['phone_number'] = $token_data['phone_number']; if ($token_data['user_id'] < 0) { $GLOBALS['user_data']['need_complete_profile'] = true; } else { $user = isRowExists("users", [$token_data['user_id']], "id=?"); if ($user) { $GLOBALS['user_data']['need_complete_profile'] = false; $GLOBALS['user_data']['username'] = $user['username']; $GLOBALS['user_data']['fullname'] = $user['fullname']; $GLOBALS['user_data']['token'] = $token_data['token']; $status = 1; } } } return $status; } function get_current_user_authorize() { $isUserLoggedInNeedCompleteProfile = !empty($GLOBALS['user_data']['need_complete_profile']); $isUserLoggedIn = isset($GLOBALS['user_data']['username']); $redirect = ""; $php_script_name = basename($_SERVER['PHP_SELF']); if ($isUserLoggedInNeedCompleteProfile && $php_script_name != "sign.up.complete.php") { $redirect = "sign.up.complete.php"; } else if (!$isUserLoggedIn && !$isUserLoggedInNeedCompleteProfile && $php_script_name != "sign.up.php") { $redirect = "sign.up.php"; } else if($isUserLoggedIn && $php_script_name != "view.php"){ $redirect = "view.php"; } if ($redirect) { header("Location: {$redirect}"); } }
7- اسکریپت توابع db.php
<?php function startMysql() { $GLOBALS['mysqli'] = new mysqli("localhost", "root", "", "auth_users"); if ($GLOBALS['mysqli']->connect_error) { die("MYSQL ISSUE : " . $GLOBALS['mysqli']->connect_error); } $GLOBALS['mysqli']->set_charset("utf8"); $GLOBALS['stmt'] = $GLOBALS['mysqli']->stmt_init(); } function endMysql() { $GLOBALS['stmt']->close(); $GLOBALS['mysqli']->close(); } function insertRow($data, $table, $interface = null, $where = ["keys" => "", "values" => []]) { startMysql(); $keys = array_keys($data); $keysStr = join(",", $keys); $values = array_values($data); if ($interface == "update") { $keysStr = ""; foreach ($data as $theKey => $theValue) { $keysStr .= "{$theKey}=?, "; } $keysStr = substr($keysStr, 0, strlen($keysStr) - 2); if (count($where['values'])) { $values = array_merge($values, $where['values']); $where['keys'] = " WHERE " . $where['keys']; } $query = "UPDATE `{$table}` SET {$keysStr}" . $where['keys']; } else if ($interface === null) { $valuesStrQuestion = str_repeat("? , ", count($values)); if (1 < count($values)) { $valuesStrQuestion = substr($valuesStrQuestion, 0, strlen($valuesStrQuestion) - 3); } $query = "INSERT INTO `{$table}` ({$keysStr}) VALUES ({$valuesStrQuestion})"; } $inserted_id = 0; $GLOBALS['stmt']->prepare($query); $GLOBALS['stmt']->bind_param(str_repeat("s", count($values)), ...$values); if ($GLOBALS['stmt']->execute()) { $inserted_id = $GLOBALS['stmt']->affected_rows; if ($interface === null) { $inserted_id = $GLOBALS['stmt']->insert_id; } } endMysql(); return $inserted_id; } function selectRow($table, $data = [], $concat_query = "1=1") { startMysql(); $query = "SELECT * FROM `{$table}` WHERE {$concat_query}"; $rows = []; $GLOBALS['stmt']->prepare($query); if ($data) { $GLOBALS['stmt']->bind_param(str_repeat("s", count($data)), ...$data); } if ($GLOBALS['stmt']->execute() && $res = $GLOBALS['stmt']->get_result()) { if ($GLOBALS['stmt']->affected_rows || $res->num_rows) { while ($row = $res->fetch_assoc()) { $rows[] = $row; } } } endMysql(); return $rows; } function updateRow($data, $table, $where = ["keys" => "", "values" => []]) { $affectefRows = insertRow($data, $table, "update", $where); return $affectefRows; } function isRowExists($table, $data, $concat_query) { $rows = selectRow($table, $data, $concat_query); if (!$rows) return false; else { return $rows[0]; } }
قبل از استفاده از سورس :
- وارد پوشه to import شوید و دیتابیس را وارد کنید .
- اطلاعات ورود سامانه پیامکی در تابع send_message در اسکریپت misc.php را وارد نمایید
لیست نظرات
سلام وقت بخیر ، برای استفاده از دیگر سامانه های پیامکی باید چیکار کرد لطفا یکی دو تا مثال بزنید مثلا رایگان اس ام اس یا فراز اس ام اس
درود ، معمولا نحوه استفاده در بخش api یا با عنوان راهنما برنامه نویسان وجود داره می تونید پیدا کنید .
سلام ممنون از کد عالیتون فقط api پنل رو دقیقا باید کجا وارد کنم ممنون میشم جواب بدید
اطلاعات ورود سامانه پیامکی در تابع send_message در اسکریپت misc.php را وارد نمایید
امکان ارتباط با شما از طریق ایمیل یا تلگرام مقدور هستش تا بصورت خصوصی با شما صحبت کنم ایمیل در اختیارتون هست اگر پاسخ بدید
اطلاعات تماس
کد های مربوط به دیتابیس را هم قرار بدین هر چند از داخل فیلم میشه فهمید بازم خواستین کامل بشه قرار بدین ممنون
در پوشه to import از قبل قرار داده شده .
من به خطا خوردم زیاد
دقیقا خطا تون چی هست متن ش رو بفرستید ( این رو هم در نظر داشته باشید که پنل ملی پیامک رو بایستی خریداری کرده باشید و اطلاعات ورود رو تابع send_message وارد کنید
چجوری میشه این پروژه رو در قالب وردپرس استفاده کرد؟
باید دانش برنامه نویسی قالب یا افزونه وردپرس رو داشته باشید تا بتونید پیاده سازی کنید .