WordPress-user-roles--wolfactive-949x475
21/12/2020

[WordPress] Hướng dẫn xử lí đăng ký user WordPress

Chào các bạn, hôm nay Wolfactive tụi mình sẽ chia sẽ cho các bạn về cách đăng kí user trên WP khi người dùng đăng kí tài khoản khi người dùng đăng ký tài khoản. Bên cạnh đó tụi mình cũng sẽ hướng dẫn các bạn làm sao cho bảo mật và hiểu quả nhất. Giờ chúng ta bắt đầu tìm hiểu nhé.

Hướng dẫn đăng kí người dùng với REST API

1/ Tạo form đăng kí

Đầu tiên để các bạn có thể đăng ký user thì các bạn cần phải tạo form đăng kí trước!

<div class="form-create-account">
    <div class="form-field">
      <label for="first-name">First Name</label>
      <input type="text" name="firstName" id="first-name" class="form-field-item">
    </div>
    <div class="form-field">
      <label for="last-name">Last Name</label>
      <input type="text" name="lastName" id="last-name" class="form-field-item">
    </div>
    <div class="form-field">
      <label for="email">Your Email Address *</label>
      <input type="text" name="email" id="email" class="form-field-item">
    </div>
    <div class="form-field">
      <label for="password">Your Password *</label>
      <input type="password" name="password" id="password" class="form-field-item">
    </div>
    <div class="form-field">
      <a href="javascript:void(0)" class="btn btn-submit-create-account">Create Account</a>
    </div>
</div>

Sau khi tạo form xong thì các bạn cần phải tạo REST API để đưa dữ liệu người dùng lên và lưu lại trong db website các bạn có thể đọc kỹ hơn ở bài Custom Api Endpoint Post Request. Nên ở bài này mình sẽ ko đi chi tiết về api nữa.

2/ Tạo Custom Api Endpoint Post Request

2.1/ Tạo API và callback function thực thi

Trước hết tụi mình sẽ tạo đường dẫn api bằng register_rest_route:

add_action('rest_api_init','submitCreateAccount');
function WAsubmitCreateAccount(){
   register_rest_route('user-api/v1','/save-data',array(
      'methods' => "POST",
      'callback' => 'WAsubmitDataToDb',
      'permission_callback' => '__return_true',
   ));
}
function WAsubmitDataToDb($request){
   $submit = WAprefix_userSubmitDB();
   return rest_ensure_response($submit);
}

Như các bạn thấy ở đây mình tạo hai function. WAsubmitCreateAccount để tạo đường dẫn api và callback hàm WAsubmitDataToDb để thực thi. Bên trong WAsubmitDataToDb thì mình sẽ gọi tiếp một hàm để xử lí chương trình.

2.2/ Tạo function thực thi

Ở trên mục 2.1, ở function thứ 2 mình có gọi hàm WAprefix_userSubmitDB() vào $submit. Nên bây giờ tụi mình sẽ bắt đầu tạo hàm này nhé:

function WAprefix_userSubmitDB(){
        $contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : '';
        if ($contentType === "application/json") {
            //Receive the RAW post data.
            $content = trim(file_get_contents("php://input"));
            $decoded = json_decode($content, true);
            // setup default result data
            $result = array(            
              'status' => 0,
              'message' => array(),
              'error'=>'',           
            );
            if (wp_verify_nonce( $decoded['wp_rest'], 'wp_rest' )) {
              $firstName = $decoded['firstName'];
              $lastName = $decoded['lastName'];
              $username = $firstName.$lastName;
              $email = $decoded['email'];
              $password = $decoded['password'];
              $checkUserName = username_exists( $username );
              $checkEmail = email_exists( $email );
              if(!$checkEmail===false && $checkUserName){
                $result['error']='error';
                array_push($result['message'],"Username already exists, please you need change it");
                array_push($result['message'],"Email already exists, please you need change it");
              }
              else if($checkUserName){
                $result['error']='error';
                array_push($result['message'],"Username already exists, please you need change it");
              } else if(!$checkEmail===false){
                $result['error']='error';
                array_push($result['message'],"Email already exists, please you need change it");
              } 
              else if(!$checkUserName &&  $checkEmail===false){
                $user_data = [
                    'user_login' => $username,
                    'user_pass'  => $password,
                    'user_email' => $email,
                    'first_name' => $firstName,
                    'last_name' => $lastName,
                    'role' => 'shopmember',
                ];
                $user_id = wp_insert_user( $user_data );
                if ( $user_id ) {
                  wa_ajax_auto_login($username,$password);
                }
              }
              
            } 
            user_return_json($result);
          // process form data
        }
    }

Như các bạn thấy ở function này mình có làm khác đi so với việc xử lí dữ liệu khi đưa lên api ở bài Custom Api Endpoint Post Request. Đó là mình có sử dụng hàm wp_verify_nonce( $decoded[‘wp_rest’], ‘wp_rest’ ). Hàm này sử dụng nhằm mục đích là để kiểm tra nonce của người dùng có đúng với nonce truyền lên api hay ko. Nếu đúng thì mới thực thi đoạn code bên trong. Việc này mình làm như vậy là để bảo mật khi các bạn gửi request lên api, bên cạnh đó các bạn cũng nên đăng kí SSL để tăng độ bảo mật website nếu chưa có nhé.

Giờ mình sẽ giải thích wp_verify_nonce() cho các bạn hiểu. Ở đây mình sử dụng một hàm là wp_create_nonce() để tạo 1 key nonce, mỗi người dùng sẽ có 1 key riêng và khi refesh lại thì sẽ thay đổi. Các bạn có thể đặt nó trong một element nào đó để các bạn có thể thuận tiện lấy ra khi check. Còn check như thế nào thì mình sẽ nói ở mục kế tiếp. Ví dụ mình tạo một nonce với tên là wp_create_nonce(‘wp_rest’). Thì khi mình check sẽ lấy key đó ra như trên mình sử dụng wp_verify_nonce( $decoded[‘wp_rest’], ‘wp_rest’ )

Kế tiếp mình sử dụng hàm wp_insert_user để add user vào db. Sở dĩ có 2 hàm để add account, một là hàm mình đang sử dung, 2 là hàm wp_create_user . Tuy nhiên mình sử dụng wp_insert_user vì nó có thể truyền vào nhiều tham số. Còn wp_create_user bạn chỉ có thể truyền vào UserName, Password, Email. Sau khi add thành công thì hàm sẽ trả về cho mình là 1 id user. Ta sẽ check xem $user_id đó có tồn tại hay ko? Nếu có thì sẽ tự động login khi mình gọi hàm wa_ajax_auto_login (cách tạo mình sẽ ghi chi tiết sau).

Cuối cùng thì mình trả về ở dạng json để giao tiếp api

function user_return_json( $php_array ) {  
        // encode result as json string
        $json_result = json_encode( $php_array );   
        // return result
        die( $json_result );    
        // stop all other processing 
        exit;
}
 Như vậy là đã tạo xong phần thực thi API. Bây giờ ta bắt đầu tạo function tự động đăng nhập khi thành công.

3/ Tạo Function automatically login

function wa_ajax_auto_login($user_login,$user_pass) {
    $creds = array(
        'user_login'    => $user_login,
        'user_password' => $user_pass,
        'remember'      => true
    );
    $user = wp_signon( $creds, false );
}

4/ Xử lí API

let btnSubmitDataUser = document.querySelector('.btn.btn-submit-create-account');
let messageErrorContain = document.querySelector('.notice-des-create-account');
let messageError = document.querySelector('.info-des-list');
if(btnSubmitDataUser){
    btnSubmitDataUser.onclick = () =>{
        let fistName = document.querySelector('#first-name').value;
        let lastName = document.querySelector('#last-name').value;
        let email = document.querySelector('#email').value;
        let userName = fistName+lastName;
        let password = document.querySelector('#password').value;
        let apiUrlUser =`${apiObject.homeurl}/wp-json/user-api/v1/save-data?_wpnonce=${apiObject.nonce}`;       
        fetch(apiUrlUser,{
            method: 'POST',
            mode:    'cors',
            headers: {
             'Content-Type': 'application/json',  // sent request
             'Accept':       'application/json'   // expected data sent back
            },
            body: JSON.stringify({
                'firstName': fistName,
                'lastName':lastName,
                'email':email,
                'userName':userName,
                'password':password,
                'wp_rest':apiObject.nonce,
            })
        })
        .then(response => response.json())
        .then(data => {
            if(data.error === "error"){
                messageError.innerHTML = "";
                if(messageErrorContain.classList.contains('d--none')){
                    messageErrorContain.classList.remove('d--none');                    
                    if(data.message.length>0){
                        for(let i = 0; i <data.message.length;i++){
                            messageError.innerHTML += `<div class="info-des-item">${data.message[i]}</div>`;
                        }
                    }
                } else {
                    if(data.message.length>0){
                        for(let i = 0; i <data.message.length;i++){
                            messageError.innerHTML += `<div class="info-des-item">${data.message[i]}</div>`;
                        }
                    }
                }
            } else {
                if(!messageErrorContain.classList.contains('d--none')){
                    messageErrorContain.classList.remove('d--none');
                }
                location.replace(apiObject.homeurl);
            }
            return  data;          
        })        
    }
}
Ở đoạn code trên xử lí API trên, các bạn cần chú ý đến những biến sau apiObject.homeurlapiObject.nonce. Mình sẽ nói đến từ biến này trước, apiObject.homeurl là đường dẫn trang chủ của các bạn. Các bạn có thể lấy nó bằng lệnh của javascript như sau: window.location.protocol + window.location.hostname và đưa nó vô chuỗi thay thế cho apiObject.homeurl thành ${protocol}//${hostname}. apiObject.nonce là mình đưa giá trị key nonce ra như nãy mình nói ở trên.
Khi mình fetchAPI dữ liệu sẽ được gửi lên và kiểm tra. Nếu nó thất bại hoặc có lỗi nó sẽ trả về những message thông báo. Nếu nó thành công hì nó sẽ tự động load lại trang thành một trang mới hoàn toàn chứ không phải như windows.location. Vì hàm này giống như là bạn back lại trang cũ vậy.
Còn một điều nữa về truyền nonce trong REST API. Các bạn có 2 cách truyền, Một là các bạn truyền như mình ở trên là truyền thẳng vào apiUrl, Hai là các bạn truyền vô headers khi fetch. Nếu các bạn truyền vào headers thì các bạn truyền như sau:
headers: {             
'Content-Type': 'application/json',  // sent request             
'Accept':       'application/json'   // expected data sent back
'X-WP-Nonce': apiObject.nonce,            
 },
Note: Các bạn chú ý phần này nhé. Nếu trường hợp các bạn truyền như cả hai trường hợp trên mà nó báo lỗi như sau:
Để xem nonce nó có nhận giá trị hay không thì các bạn thay đổi vị trí hàm user_return_json($result) ra bên ngoài if. Và thay đổi lại thành user_return_json($decoded[‘wp_rest’]). Nếu hàm có trả về key nonce thì các bạn đổi lại thành user_return_json(wp_verify_nonce( $decoded[‘wp_rest’], ‘wp_rest’ )) để check xem có trả về giá trị true hay không.
Fix lỗi:

Để fix lỗi trên thì các bạn cần làm như sau mình sẽ chia thành các TH cho các bạn dễ hình dung nhé.

TH1: nếu các bạn đặt nonce trong headers.

Thì các bạn xóa nó đi và thay thành truyền biến vào apiUrl với tên param giống tên key của các bạn tạo nonce cụ thể như thế này:
`${apiObject.homeurl}/wp-json/user-api/v1/save-data?_wpnonce=${apiObject.nonce}`;
Đây là đoạn apiUrl của mình ban đâu. giờ mình sẽ đổi lại cho giống với nonce mình tạo là wp_rest
`${apiObject.homeurl}/wp-json/user-api/v1/save-data?wp_rest=${apiObject.nonce}`;

TH2: nếu các bạn truyền vào giá trị vào url.

Thì các bạn thực hiện như TH1 là được.

5/ Tổng kết

Như vậy mình đã giới thiệu và hướng dẫn cho các bạn về việc sử dụng Rest API để đăng kí user trên WP. Mình nghĩ bài viết này sẽ rất bổ ích cho những ai làm trang web có tính năng đăng nhập và đăng kí account. Cảm ơn các bạn đã theo dõi, mỗi lượt share, tương tác, comment, like fanpage https://www.facebook.com/Wolfactiveweb.design.SEO/ là động lực để tụi mình chia sẽ thêm nhiều kiến thức về WP, FE cho các bạn.
Vui lòng chọn size trước khi đặt hàng (*)