这是我拿一个插件对着官方文档修复的,之前无法使用;
里面原本包含了QQ、微信、抖音、微博四个登录的,我只修了QQ的,但是好像没有修好。
主要问题:
1、移动端无法使用
2、无法获取QQ用户头像
3、无法获取QQ用户昵称
链接:http://www.seoyh.net/wp-login.php
按钮在验证码右边那个小小的,没有写样式
文件结构:
user
-----qq
-----qq.php
-----qq/settings.php
-----qq/class-qq.php
qq.php代码
【
<?php
if (!defined('ABSPATH')) die('Invalid request.');
// 定义常量
define('MARK_SOCIAL_SSO_VERION', "1.0.0");
define('MARK_SOCIAL_SSO_THEME_URL', get_template_directory_uri());
define('MARK_SOCIAL_SSO_THEME_DIR', get_template_directory());
// 引入相关文件
require_once MARK_SOCIAL_SSO_THEME_DIR . "/inc/user/qq/settings.php";
// require_once MARK_SOCIAL_SSO_THEME_DIR . "/inc/user/qq/class-basic.php";
// require_once MARK_SOCIAL_SSO_THEME_DIR . "/inc/user/qq/class-dy.php";
// require_once MARK_SOCIAL_SSO_THEME_DIR . "/inc/user/qq/class-wx.php";
require_once MARK_SOCIAL_SSO_THEME_DIR . "/inc/user/qq/class-qq.php";
// require_once MARK_SOCIAL_SSO_THEME_DIR . "/inc/user/qq/class-wb.php";
// 将样式和脚本加入队列
function mksso_login_enqueue_scripts() {
wp_enqueue_style('mksso-css', MARK_SOCIAL_SSO_THEME_URL . '/mksso.css', ['login'], MARK_SOCIAL_SSO_VERION);
}
add_action('login_enqueue_scripts', 'mksso_login_enqueue_scripts');
// 处理自定义请求
add_action("parse_request", 'handle_custom_login');
function handle_custom_login(){
$mksso = isset($_GET['mksso']) ? sanitize_text_field($_GET['mksso']) : false;
if(in_array( $mksso, ['wx', 'qq', 'wb', 'dy'] )){
$code = isset($_GET['code']) ? sanitize_text_field($_GET['code']) : false;
$state = isset($_GET['state']) ? sanitize_text_field($_GET['state']) : false;
if($code){
if( $mksso == 'wb'){
$check = true;
}else if( $state ){
$check = wp_verify_nonce($state, $mksso . "nonce" );
}else{
wp_die("access Denied", "error");
}
if($check){
$model = "OAuth_".strtoupper( $mksso );
$app = get_option('mksso_'.$mksso);
$model = new $model( $app['appid'], $app['secret'] );
$res = $model->code_to_openid($code);
if(is_wp_error($res)) wp_die('登陆失败,请重试');
if($res && isset($res['user']) ){
$user_id = $res['user'];
if(is_numeric($user_id) && $user_id){
$user = get_user_by('ID', $user_id );
wp_set_current_user( $user_id , $user->user_login);
wp_set_auth_cookie( $user_id );
do_action( 'wp_login', $user->user_login );
wp_safe_redirect( admin_url() );
exit;
}else{
wp_die('登陆失败了', '错误提示');
}
}else{
wp_die('登陆失败', '错误提示');
}
}
exit;
}
}
}
function mark_social_sso_request($url, $args = []){
if( isset($args['body']) && !empty($args['body']) ){
$res = wp_remote_post($url, $args);
}else{
$res = wp_remote_request($url, $args);
}
if(is_wp_error( $res ))
return $res;
$body = wp_remote_retrieve_body($res);
$data = json_decode($body, true);
return $data;
}
// 在登录表单上输出自定义登录链接
add_action('login_form', 'custom_login_form_output');
function custom_login_form_output(){
$cb_url = urlencode(admin_url());
$app_dy = get_option('mksso_dy');
$dy_state = wp_create_nonce('dynonce');
$dy_url = 'https://open.douyin.com/platform/oauth/connect?client_key='.$app_dy['appid'].'&response_type=code&scope=user_info&state='.$dy_state.'&redirect_uri='. $cb_url;
$app_qq = get_option('mksso_qq');
$qq_state = wp_create_nonce('qqnonce');
$qq_url = 'https://graph.qq.com/oauth2.0/authorize?response_type=code&state='.$qq_state. '&client_id='.$app_qq['appid'].'&redirect_uri='.home_url('/?mksso=qq');
///.'&state='.$qq_state.'&scope=get_user_info'
$app_wx = get_option('mksso_wx');
$wx_state = wp_create_nonce('wxnonce');
$wx_url = 'https://open.weixin.qq.com/connect/qrconnect?appid='.$app_wx['appid'].'&redirect_uri='.$cb_url.'&response_type=code&scope=SCOPE&state='.$wx_state.'#wechat_redirect';
$app_wb = get_option('mksso_wb');
$wb_state = wp_create_nonce('wbnonce');
$cb_url = home_url().'/?mksso=wb';
$wb_url = 'https://api.weibo.com/oauth2/authorize?client_id='.$app_wb['appid'].'&response_type=code&redirect_uri='.$cb_url;
$str = '<div class="sso-items">';
if(isset($app_wx['status']) && $app_wx['status'] )
$str .= '<div class="sso-item sso-weixin"><a href="'.$wx_url.'">微信登陆</a></div>';
if(isset($app_qq['status']) && $app_qq['status'] )
$str .= '<div class="sso-item sso-qq"><a href="'.$qq_url.'">QQ登陆</a></div>';
if(isset($app_wb['status']) && $app_wb['status'] )
$str .= '<div class="sso-item sso-weibo"><a href="'.$wb_url.'">微博登陆</a></div>';
if(isset($app_dy['status']) && $app_dy['status'] )
$str .= '<div class="sso-item sso-douyin"><a href="'.$dy_url.'">抖音登陆</a></div>';
$str .= '</div>';
echo $str;
}
function qqlogin() {
$app_qq = get_option('mksso_qq');
$qq_state = wp_create_nonce('qqnonce');
$qq_url = 'https://graph.qq.com/oauth2.0/authorize?response_type=code&state='.$qq_state. '&client_id='.$app_qq['appid'].'&redirect_uri='.home_url('/?mksso=qq');
echo $qq_url;
}
】
settings.php代码
【
<?php
add_action("admin_menu", function() {
add_submenu_page(
"options-general.php",
"新媒体登陆设置",
"新媒体登陆设置",
"manage_options",
"mark-social-sso",
"mark_social_sso_options_page"
);
});
// 回调函数用于显示设置页面的HTML
function mark_social_sso_options_page() {
?>
<div class="wrap mark-social-sso-page">
<h1 class="wp-heading-inline">社交媒体登陆设置</h1>
<hr class="wp-header-end">
<form method="post" action="options.php">
<?php
settings_fields("mark_social_setting_group");
do_settings_sections("mksso");
?>
<p class="submit">
<input name="submit" type="submit" id="submit" class="button-primary" value="<?php _e("Save Changes"); ?>" />
</p>
</form>
</div>
<?php
}
// 用于输出特定设置部分的回调
function section_callback($args) {
$allowed_tags = [
'a' => ['href' => [], 'title' => [], 'target' => []],
'span' => [],
'pre' => []
];
$cb = home_url("/?mksso=");
$url = $cb . str_replace("section_id_", "", $args['id']);
$settings_links = [
'section_id_qq' => 'https://connect.qq.com/',
'section_id_wx' => 'https://open.weixin.qq.com/',
'section_id_dy' => 'https://open.douyin.com/platform/doc/m-2-1-1',
'section_id_wb' => 'https://open.weibo.com/authentication'
];
if (array_key_exists($args['id'], $settings_links)) {
echo wp_kses('设置教程<a target="_blank" href="'.$settings_links[$args['id']].'">点击这里</a>, 回调链接为:<span><pre>'.$url.'</pre></span>', $allowed_tags);
}
}
add_action( 'admin_init', 'plugin_admin_init' );
function plugin_admin_init() {
$list = [
'wx' => '微信',
'qq' => 'QQ',
'wb' => '微博',
'dy' => '抖音'
];
foreach ($list as $app_key => $app_val) {
$status = 'mksso_' .$app_key .'[status]';
$appid = 'mksso_' .$app_key .'[appid]';
$secret = 'mksso_' .$app_key .'[secret]';
$section_id = 'section_id_'.$app_key;
register_setting('mark_social_setting_group', 'mksso_'. $app_key);
add_settings_section($section_id , $app_val.'登陆', 'section_callback', 'mksso');
add_settings_field($status, '是否启用', 'mark_sso_field_cb', 'mksso', $section_id , array( 'id' => 'status', 'type' => 'checkbox', 'key' => $app_key));
add_settings_field($appid, $app_val.'应用ID (APP ID)', 'mark_sso_field_cb', 'mksso', $section_id , array( 'id' => 'appid', 'type' => 'text', 'key' => $app_key));
add_settings_field($secret, $app_val.'密匙App Secret', 'mark_sso_field_cb', 'mksso', $section_id , array( 'id' => 'secret', 'type' => 'password', 'key' => $app_key));
}
}
// 输出设置字段的回调
function mark_sso_field_cb($args) {
$options = get_option('mksso_' . $args['key']);
$field_value = isset($options[$args['id']]) ? $options[$args['id']] : '';
$name = 'mksso_' . $args['key'] . '[' . $args['id'] . ']';
$checked = $args['type'] === 'checkbox' ? checked(1, $field_value, false) : '';
printf(
'<input type="%1$s" class="regular-text" name="%2$s" value="%3$s" %4$s>',
$args['type'],
$name,
esc_attr($field_value),
$checked
);
}
】
class-qq.php代码
【
<?php
if ( ! defined( 'ABSPATH' ) ) die( 'Invalid request.' );
/**
* Oauth(OAuth认证)
*/
class OAuth_QQ
{
private string $appid; // QQ开放平台应用的AppID
public const ACCESS_TOKEN = 'https://graph.qq.com/oauth2.0/token'; // 获取访问令牌的URL
public const USER_OPENID = 'https://graph.qq.com/oauth2.0/me'; // 获取用户OpenID的URL
public const USER_INFO = 'https://graph.qq.com/user/get_user_info'; // 获取用户信息的URL
public function __construct(string $appid, string $secret)
{
$this->appid = $appid;
$this->secret = $secret;
}
// 将授权码转换为用户的OpenID
public function code_to_openid($code){
$args = [
'client_id' => $this->appid,
'client_secret' => $this->secret,
'code' => $code,
'fmt' => 'json',
'redirect_uri' => urlencode(home_url('/?mksso=qq')) ,
'grant_type' => 'authorization_code',
'need_openid' => 1,
];
$url = add_query_arg($args, self::ACCESS_TOKEN); // 向获取访问令牌的URL发送请求
$data = mark_social_sso_request($url); // 更改请求函数名称以匹配主题函数名称
if(is_wp_error( $data )) return $data; // 如果获取数据时发生错误,则返回错误对象
if( isset( $data['access_token'], $data['expires_in'] ) ){
$args = [
'access_token' => $data['access_token'],
'oauth_consumer_key' => $this->appid,
'openid' => $data['openid'],
'fmt' => 'json'
];
$user_info_url = add_query_arg(
$args , self::USER_OPENID); // 构建获取用户OpenID的URL
$user = wp_remote_get( $user_info_url ); // 向QQ服务器发送获取用户OpenID的请求
$user = wp_remote_retrieve_body( $user ); // 获取请求的响应体中的内容
$user = json_decode( $user, true ); // 解析响应体中的JSON数据为关联数组
if(is_wp_error($user)) return $user; // 如果获取用户OpenID时发生错误,则返回错误对象
if( !isset($user['openid']) || empty($user['openid']) )
return new WP_Error('get_openid_fail', '无法返回用户信息'); // 如果用户OpenID不存在或为空,则返回错误对象
// 将用户访问令牌和刷新令牌以及用户OpenID存储到缓存中,有效期为令牌的过期时间
wp_cache_set( $data['access_token'] , $user['openid'], 'qq_access_token_list', $data['expires_in'] );
wp_cache_set( $data['access_token'] , $data['refresh_token'], 'qq_access_token_list', $data['expires_in'] );
wp_cache_set( $user['openid'] , $data['access_token'], 'qq_access_token_list', $data['expires_in'] );
wp_cache_set( $user['openid'] , $data['refresh_token'], 'qq_access_token_list', $data['expires_in'] );
get_transient( $user['openid'], 'qq_access_token_list', $data['expires_in'] );
// 查询是否已存在使用QQ登录的用户,若不存在则创建新用户
$wp_user_query = new WP_User_Query( [
'meta_key' => 'qq_openid',
'meta_value' => $user['openid']
] );
$users = $wp_user_query->get_results();
if( count( $users ) == 0 ) {
$userArr = [
'username' => 'QQ_' . $user['openid'],
'password' => wp_generate_password(),
];
$user_id = wp_create_user( $userArr['username'], $userArr['password'] );
if( is_numeric( $user_id )) {
update_user_meta( $user_id, 'qq_openid', $user['openid'] );
}
}else {
$u = $users[0];
$user_id = $u->ID;
}
// 构建返回的数据数组
$data = [
'expires_in' => $data['expires_in'],
'access_token' => $data['access_token'],
'openid' => $user['openid'],
'user' => $user_id,
'refresh_token' => $data['refresh_token'],
];
return $data; // 返回数据数组
}else{
return new WP_Error( $data['code'], $data['msg'] ); // 如果请求数据中不包含访问令牌和过期时间,则返回错误对象
}
}
// 获取用户信息
public function get_user_info($openid) {
// 获取缓存中的访问令牌列表
$access_token_list = get_transient("qq_access_token_list");
if ($access_token_list === false || !isset($access_token_list[$openid])) {
return new WP_Error('no_access_token', 'No access token found for the given openid');
}
$access_token = $access_token_list[$openid]; // 获取特定openid的访问令牌
// 构建获取用户信息的URL
$args = [
'access_token' => $access_token,
'oauth_consumer_key' => $this->appid,
'openid' => $openid
];
$url = add_query_arg($args, self::USER_INFO);
$data = mark_social_sso_request($url); // 发送请求
if (is_wp_error($data)) {
return $data;
}
if (is_array($data) && isset($data['ret']) && $data['ret'] == 0) {
return [
'openid' => $openid,
'nickname' => $data['nickname'],
'avatar' => $data['figureurl_qq_1']
];
} else {
return new WP_Error('api_error', 'Failed to retrieve user information from QQ', $data);
}
}
}
】这样