AuthMiRequest.java 5.0 KB
Newer Older
1 2 3 4 5 6
package me.zhyd.oauth.request;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject;
7
import lombok.extern.slf4j.Slf4j;
8
import me.zhyd.oauth.config.AuthConfig;
9
import me.zhyd.oauth.config.AuthSource;
智布道's avatar
智布道 已提交
10
import me.zhyd.oauth.enums.AuthUserGender;
11
import me.zhyd.oauth.exception.AuthException;
12
import me.zhyd.oauth.model.*;
不合群的混子's avatar
不合群的混子 已提交
13
import me.zhyd.oauth.utils.UrlBuilder;
14 15 16 17 18 19 20 21 22 23

import java.text.MessageFormat;

/**
 * 小米登录
 *
 * @author yangkai.shen (https://xkcoding.com)
 * @version 1.5
 * @since 1.5
 */
24
@Slf4j
智布道's avatar
智布道 已提交
25
public class AuthMiRequest extends AuthDefaultRequest {
26 27 28
    private static final String PREFIX = "&&&START&&&";

    public AuthMiRequest(AuthConfig config) {
不合群的混子's avatar
不合群的混子 已提交
29
        super(config, AuthSource.MI);
30 31 32
    }

    @Override
33
    protected AuthToken getAccessToken(AuthCallback authCallback) {
不合群的混子's avatar
不合群的混子 已提交
34
        return getToken(accessTokenUrl(authCallback.getCode()));
35 36 37 38 39
    }

    private AuthToken getToken(String accessTokenUrl) {
        HttpResponse response = HttpRequest.get(accessTokenUrl).execute();
        String jsonStr = StrUtil.replace(response.body(), PREFIX, StrUtil.EMPTY);
智布道's avatar
智布道 已提交
40
        JSONObject accessTokenObject = JSONObject.parseObject(jsonStr);
41

智布道's avatar
智布道 已提交
42 43
        if (accessTokenObject.containsKey("error")) {
            throw new AuthException(accessTokenObject.getString("error_description"));
44 45 46
        }

        return AuthToken.builder()
不合群的混子's avatar
不合群的混子 已提交
47 48 49 50 51 52 53 54 55
            .accessToken(accessTokenObject.getString("access_token"))
            .expireIn(accessTokenObject.getIntValue("expires_in"))
            .scope(accessTokenObject.getString("scope"))
            .tokenType(accessTokenObject.getString("token_type"))
            .refreshToken(accessTokenObject.getString("refresh_token"))
            .openId(accessTokenObject.getString("openId"))
            .macAlgorithm(accessTokenObject.getString("mac_algorithm"))
            .macKey(accessTokenObject.getString("mac_key"))
            .build();
56 57 58 59 60
    }

    @Override
    protected AuthUser getUserInfo(AuthToken authToken) {
        // 获取用户信息
不合群的混子's avatar
不合群的混子 已提交
61
        HttpResponse userResponse = doGetUserInfo(authToken);
62 63

        JSONObject userProfile = JSONObject.parseObject(userResponse.body());
64
        if ("error".equalsIgnoreCase(userProfile.getString("result"))) {
65 66 67 68 69 70
            throw new AuthException(userProfile.getString("description"));
        }

        JSONObject user = userProfile.getJSONObject("data");

        AuthUser authUser = AuthUser.builder()
不合群的混子's avatar
不合群的混子 已提交
71 72 73 74 75 76 77 78 79
            .uuid(authToken.getOpenId())
            .username(user.getString("miliaoNick"))
            .nickname(user.getString("miliaoNick"))
            .avatar(user.getString("miliaoIcon"))
            .email(user.getString("mail"))
            .gender(AuthUserGender.UNKNOWN)
            .token(authToken)
            .source(AuthSource.MI)
            .build();
80 81 82

        // 获取用户邮箱手机号等信息
        String emailPhoneUrl = MessageFormat.format("{0}?clientId={1}&token={2}", "https://open.account.xiaomi.com/user/phoneAndEmail", config
不合群的混子's avatar
不合群的混子 已提交
83
            .getClientId(), authToken.getAccessToken());
84 85 86

        HttpResponse emailResponse = HttpRequest.get(emailPhoneUrl).execute();
        JSONObject userEmailPhone = JSONObject.parseObject(emailResponse.body());
87
        if (!"error".equalsIgnoreCase(userEmailPhone.getString("result"))) {
88 89
            JSONObject emailPhone = userEmailPhone.getJSONObject("data");
            authUser.setEmail(emailPhone.getString("email"));
90 91
        } else {
            log.warn("小米开发平台暂时不对外开放用户手机及邮箱信息的获取");
92 93 94 95 96 97 98 99 100 101 102 103 104
        }

        return authUser;
    }

    /**
     * 刷新access token (续期)
     *
     * @param authToken 登录成功后返回的Token信息
     * @return AuthResponse
     */
    @Override
    public AuthResponse refresh(AuthToken authToken) {
不合群的混子's avatar
不合群的混子 已提交
105 106 107 108 109
        return AuthResponse.builder()
            .code(AuthResponseStatus.SUCCESS.getCode())
            .data(getToken(refreshTokenUrl(authToken.getRefreshToken())))
            .build();
    }
110

不合群的混子's avatar
不合群的混子 已提交
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
    /**
     * 返回认证url,可自行跳转页面
     *
     * @return 返回授权地址
     */
    @Override
    public String authorize() {
        return UrlBuilder.fromBaseUrl(source.authorize())
            .queryParam("response_type", "code")
            .queryParam("client_id", config.getClientId())
            .queryParam("redirect_uri", config.getRedirectUri())
            .queryParam("state", getRealState(config.getState()))
            .queryParam("scope", "user/profile%20user/openIdV2%20user/phoneAndEmail")
            .queryParam("skip_confirm", "false")
            .build();
    }

    /**
     * 返回获取userInfo的url
     *
     * @param authToken
     * @return 返回获取userInfo的url
     */
    @Override
    protected String userInfoUrl(AuthToken authToken) {
        return UrlBuilder.fromBaseUrl(source.userInfo())
            .queryParam("clientId", config.getClientId())
            .queryParam("token", authToken.getAccessToken())
            .build();
140 141
    }
}