我使用了Amit Kayshap 提供的代码并对其进行了改进,以包括额外的检查和功能,例如在用户激活帐户后自动登录,从而带来更流畅的用户体验。
更新:与原始代码不同,此代码也不需要任何现有用户确认他们的电子邮件地址。
就像我基于它的代码一样,它被设计为在运行 WooCommerce 的 WordPress 安装上运行。如果您禁用了标准的 WordPress 注册页面,它也可以工作。
您需要一个带有 URL yoursite.com/verify/ 的空页面,该页面构建在其内容容器中包含 <?php wc_print_notices(); ?> 的模板之上。它将替换原始代码中的/sign-in/ 目标,并将处理此代码创建的几乎所有消息。
接下来,将此代码添加到主题的functions.php:
function wc_registration_redirect( $redirect_to ) { // prevents the user from logging in automatically after registering their account
wp_logout();
wp_redirect( '/verify/?n='); // redirects to a confirmation message
exit;
}
function wp_authenticate_user( $userdata ) { // when the user logs in, checks whether their email is verified
$has_activation_status = get_user_meta($userdata->ID, 'is_activated', false);
if ($has_activation_status) { // checks if this is an older account without activation status; skips the rest of the function if it is
$isActivated = get_user_meta($userdata->ID, 'is_activated', true);
if ( !$isActivated ) {
my_user_register( $userdata->ID ); // resends the activation mail if the account is not activated
$userdata = new WP_Error(
'my_theme_confirmation_error',
__( '<strong>Error:</strong> Your account has to be activated before you can login. Please click the link in the activation email that has been sent to you.<br /> If you do not receive the activation email within a few minutes, check your spam folder or <a href="/verify/?u='.$userdata->ID.'">click here to resend it</a>.' )
);
}
}
return $userdata;
}
function my_user_register($user_id) { // when a user registers, sends them an email to verify their account
$user_info = get_userdata($user_id); // gets user data
$code = md5(time()); // creates md5 code to verify later
$string = array('id'=>$user_id, 'code'=>$code); // makes it into a code to send it to user via email
update_user_meta($user_id, 'is_activated', 0); // creates activation code and activation status in the database
update_user_meta($user_id, 'activationcode', $code);
$url = get_site_url(). '/verify/?p=' .base64_encode( serialize($string)); // creates the activation url
$html = ( 'Please click <a href="'.$url.'">here</a> to verify your email address and complete the registration process.' ); // This is the html template for your email message body
wc_mail($user_info->user_email, __( 'Activate your Account' ), $html); // sends the email to the user
}
function my_init(){ // handles all this verification stuff
if(isset($_GET['p'])){ // If accessed via an authentification link
$data = unserialize(base64_decode($_GET['p']));
$code = get_user_meta($data['id'], 'activationcode', true);
$isActivated = get_user_meta($data['id'], 'is_activated', true); // checks if the account has already been activated. We're doing this to prevent someone from logging in with an outdated confirmation link
if( $isActivated ) { // generates an error message if the account was already active
wc_add_notice( __( 'This account has already been activated. Please log in with your username and password.' ), 'error' );
}
else {
if($code == $data['code']){ // checks whether the decoded code given is the same as the one in the data base
update_user_meta($data['id'], 'is_activated', 1); // updates the database upon successful activation
$user_id = $data['id']; // logs the user in
$user = get_user_by( 'id', $user_id );
if( $user ) {
wp_set_current_user( $user_id, $user->user_login );
wp_set_auth_cookie( $user_id );
do_action( 'wp_login', $user->user_login, $user );
}
wc_add_notice( __( '<strong>Success:</strong> Your account has been activated! You have been logged in and can now use the site to its full extent.' ), 'notice' );
} else {
wc_add_notice( __( '<strong>Error:</strong> Account activation failed. Please try again in a few minutes or <a href="/verify/?u='.$userdata->ID.'">resend the activation email</a>.<br />Please note that any activation links previously sent lose their validity as soon as a new activation email gets sent.<br />If the verification fails repeatedly, please contact our administrator.' ), 'error' );
}
}
}
if(isset($_GET['u'])){ // If resending confirmation mail
my_user_register($_GET['u']);
wc_add_notice( __( 'Your activation email has been resent. Please check your email and your spam folder.' ), 'notice' );
}
if(isset($_GET['n'])){ // If account has been freshly created
wc_add_notice( __( 'Thank you for creating your account. You will need to confirm your email address in order to activate your account. An email containing the activation link has been sent to your email address. If the email does not arrive within a few minutes, check your spam folder.' ), 'notice' );
}
}
// the hooks to make it all work
add_action( 'init', 'my_init' );
add_filter('woocommerce_registration_redirect', 'wc_registration_redirect');
add_filter('wp_authenticate_user', 'wp_authenticate_user',10,2);
add_action('user_register', 'my_user_register',10,2);
如果您正在运行一个多语言网站,您可以非常轻松地准备好代码翻译。只需像这样更改文本字符串:__( 'Text you want to translate', 'your-theme' ) 这允许 WPML 等翻译插件将字符串添加到 your-theme 文本域中的翻译表中。
请注意,任何包含.$url. 等变量的字符串都会在每次不同用户激活其函数时生成一个新字符串。为了避免这种情况(并防止向您的数据库发送垃圾邮件),我们可以直接在代码中翻译它们:
if(ICL_LANGUAGE_CODE=='de'){
wc_add_notice( __( 'German error message' ), 'error' );
} else {
wc_add_notice( __( 'English error message' ), 'error' );
}
在本例中,如果检测到用户的语言代码为de,则会输出德语消息(如果它是类似de_DE_formal 的变体也可以),否则它将输出英语消息。
编辑:我更新了代码,不再要求现有用户追溯确认他们的电子邮件地址。