zhangbo1_wd

新增网络接口调用(封装token失效处理逻辑)

@@ -4,3 +4,5 @@ export { HttpRequest as WDHttp } from "./src/main/ets/http/HttpRequest" @@ -4,3 +4,5 @@ export { HttpRequest as WDHttp } from "./src/main/ets/http/HttpRequest"
4 4
5 export { HttpUrlUtils } from "./src/main/ets/http/HttpUrlUtils" 5 export { HttpUrlUtils } from "./src/main/ets/http/HttpUrlUtils"
6 6
  7 +export { HttpBizUtil } from "./src/main/ets/http/HttpBizUtil"
  8 +
  1 +/*
  2 + * refresh token接口返回
  3 + */
  4 +export interface RefreshTokenRes {
  5 + jwtToken: string;
  6 + refreshToken: string;
  7 +}
  1 +import { SpConstants } from 'wdConstant/Index';
  2 +import { EmitterEventId, EmitterUtils, Logger, SPHelper, ToastUtils } from 'wdKit/Index';
  3 +import HashMap from '@ohos.util.HashMap';
  4 +import { ResponseDTO } from '../bean/ResponseDTO';
  5 +import { HttpUrlUtils, WDHttp } from '../../../../Index';
  6 +import { RefreshTokenRes } from '../bean/RefreshTokenRes';
  7 +
  8 +const TAG: string = 'HttpBizUtil'
  9 +
  10 +/**
  11 + * 网络请求工具,业务封装http,暂添加TokenInterceptor功能
  12 + * TODO 待优化,将HttpBizUtil接入 AxiosInstance.interceptors.response.use
  13 + */
  14 +export class HttpBizUtil {
  15 + /**
  16 + * get请求,封装了刷新token逻辑,接口选用,不涉及业务接口可以用原来的接口(如page接口)。
  17 + *
  18 + * @param url 请求地址
  19 + * @param headers 请求header参数
  20 + * @returns 返回值
  21 + */
  22 + static get<T = string>(url: string, headers?: HashMap<string, string>): Promise<ResponseDTO<T>> {
  23 + return new Promise<ResponseDTO<T>>((success, debug) => {
  24 + WDHttp.get<ResponseDTO<T>>(url, headers).then((resDTO: ResponseDTO<T>) => {
  25 + Logger.debug(TAG, 'get: ' + resDTO.code)
  26 + Logger.debug(TAG, 'get: ' + resDTO.message)
  27 + // 403:临时token;406:强制下线、封禁、清空登录信息还要跳转登录页面
  28 + if (resDTO.code == 403 || resDTO.code == 406) {
  29 + HttpBizUtil.refreshToken().then((token: string) => {
  30 + if (headers) {
  31 + headers.replace('RMRB-X-TOKEN', token)
  32 + headers.replace('cookie', 'RMRB-X-TOKEN=' + token)
  33 + }
  34 + Logger.debug(TAG, 'get again send: ' + token)
  35 + // refreshToken为空场景不处理,直接请求接口。
  36 + WDHttp.get<ResponseDTO<T>>(url, headers).then((resDTO: ResponseDTO<T>) => {
  37 + Logger.debug(TAG, 'get again: ' + resDTO.message)
  38 + success(resDTO)
  39 + }).catch((res: object) => {
  40 + debug(res)
  41 + })
  42 + });
  43 + } else {
  44 + success(resDTO)
  45 + }
  46 + }).catch((res: object) => {
  47 + debug(res)
  48 + })
  49 + })
  50 + }
  51 +
  52 + /**
  53 + * post请求,封装了刷新token逻辑,接口选用,不涉及业务接口可以用原来的接口(如page接口)。
  54 + *
  55 + * @param url 请求地址
  56 + * @param headers 请求header参数
  57 + * @returns 返回值
  58 + */
  59 + static post<T = string>(url: string, data?: object, headers?: HashMap<string, string>): Promise<ResponseDTO<T>> {
  60 + return new Promise<ResponseDTO<T>>((success, debug) => {
  61 + WDHttp.post<ResponseDTO<T>>(url, data, headers).then((resDTO: ResponseDTO<T>) => {
  62 + Logger.debug(TAG, 'post: ' + resDTO.code)
  63 + Logger.debug(TAG, 'post: ' + resDTO.message)
  64 + // 403:临时token;406:强制下线、封禁、清空登录信息还要跳转登录页面
  65 + if (resDTO.code == 0 || resDTO.code == 406) {
  66 + HttpBizUtil.refreshToken().then((token: string) => {
  67 + if (headers) {
  68 + headers.replace('RMRB-X-TOKEN', token)
  69 + headers.replace('cookie', 'RMRB-X-TOKEN=' + token)
  70 + }
  71 + // refreshToken为空场景不处理,直接请求接口。
  72 + WDHttp.post<ResponseDTO<T>>(url, headers).then((resDTO: ResponseDTO<T>) => {
  73 + success(resDTO)
  74 + }).catch((res: object) => {
  75 + debug(res)
  76 + })
  77 + });
  78 + } else {
  79 + success(resDTO)
  80 + }
  81 + }).catch((res: object) => {
  82 + debug(res)
  83 + })
  84 + })
  85 + }
  86 +
  87 + /*
  88 + * 获取刷新后的token,可能为空
  89 + */
  90 + static refreshToken(): Promise<string> {
  91 + let url = HttpUrlUtils.getRefreshTokenUrl();
  92 + let params: HashMap<string, string> = new HashMap<string, string>()
  93 + params.set('refreshToken', HttpUrlUtils.getRefreshToken())
  94 + params.set('deviceId', HttpUrlUtils.getDeviceId())
  95 + let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
  96 + Logger.debug(TAG, 'refreshToken getRefreshToken: ' + HttpUrlUtils.getRefreshToken())
  97 + // // 请求刷新token接口
  98 + return new Promise<string>((success, debug) => {
  99 + WDHttp.post<ResponseDTO<RefreshTokenRes>>(url, params, headers).then((resDTO: ResponseDTO<RefreshTokenRes>) => {
  100 + let newToken = ''
  101 + if (resDTO) {
  102 + Logger.debug(TAG, 'refreshToken getRefreshToken: ' + resDTO.message)
  103 + Logger.debug(TAG, 'refreshToken getRefreshToken: ' + resDTO.code)
  104 + if (resDTO.code == 377) {
  105 + // 377强制用户下线、重新登录、封禁等场景;refreshToken 失效
  106 + ToastUtils.showToast("已登出,请重新登入", 1000);
  107 + EmitterUtils.sendEmptyEvent(EmitterEventId.FORCE_USER_LOGIN_OUT)
  108 + // WDRouterRule.jumpWithPage(WDRouterPage.loginPage)
  109 + } else if (resDTO.code == 0 && resDTO.data) {
  110 + newToken = resDTO.data.jwtToken
  111 + let refreshToken = resDTO.data.refreshToken
  112 + SPHelper.default.save(SpConstants.USER_JWT_TOKEN, newToken)
  113 + SPHelper.default.save(SpConstants.USER_REFRESH_TOKEN, refreshToken)
  114 + Logger.debug(TAG, 'refreshToken jwtToken: ' + resDTO.data.jwtToken)
  115 + Logger.debug(TAG, 'refreshToken refreshToken: ' + resDTO.data.refreshToken)
  116 + }
  117 + }
  118 + success(newToken)
  119 + });
  120 + })
  121 + }
  122 +}
@@ -112,6 +112,10 @@ export class HttpUrlUtils { @@ -112,6 +112,10 @@ export class HttpUrlUtils {
112 */ 112 */
113 static readonly APPOINTMENT_userArea_PATH: string = "/api/rmrb-content-center/c/service/sys-area/treeselect"; 113 static readonly APPOINTMENT_userArea_PATH: string = "/api/rmrb-content-center/c/service/sys-area/treeselect";
114 /** 114 /**
  115 + * 用户token刷新接口(token过期,需要刷新)
  116 + */
  117 + static readonly REFRESH_TOKEN_PATH: string = "/api/rmrb-user-center/auth/zh/c/refreshToken";
  118 + /**
115 /** 119 /**
116 * 个人中心 关注列表详情 120 * 个人中心 关注列表详情
117 */ 121 */
@@ -188,7 +192,6 @@ export class HttpUrlUtils { @@ -188,7 +192,6 @@ export class HttpUrlUtils {
188 * 搜索主页 热词 192 * 搜索主页 热词
189 */ 193 */
190 static readonly SEARCH_HOTS_DATA_PATH: string = "/api/rmrb-search-api/zh/c/hots"; 194 static readonly SEARCH_HOTS_DATA_PATH: string = "/api/rmrb-search-api/zh/c/hots";
191 -  
192 /** 195 /**
193 * 搜索联想词 196 * 搜索联想词
194 */ 197 */
@@ -198,7 +201,6 @@ export class HttpUrlUtils { @@ -198,7 +201,6 @@ export class HttpUrlUtils {
198 * 直播详情 201 * 直播详情
199 */ 202 */
200 static readonly LIVE_DETAILS_PATH: string = "/api/rmrb-bff-display-zh/content/zh/c/content/detail"; 203 static readonly LIVE_DETAILS_PATH: string = "/api/rmrb-bff-display-zh/content/zh/c/content/detail";
201 -  
202 /** 204 /**
203 * 直播详情-直播间列表 205 * 直播详情-直播间列表
204 */ 206 */
@@ -358,7 +360,7 @@ export class HttpUrlUtils { @@ -358,7 +360,7 @@ export class HttpUrlUtils {
358 return ''; 360 return '';
359 } 361 }
360 362
361 - private static getDeviceId() { 363 + public static getDeviceId() {
362 // TODO 364 // TODO
363 return '8a81226a-cabd-3e1b-b630-b51db4a720ed'; 365 return '8a81226a-cabd-3e1b-b630-b51db4a720ed';
364 } 366 }
@@ -452,6 +454,10 @@ export class HttpUrlUtils { @@ -452,6 +454,10 @@ export class HttpUrlUtils {
452 return url; 454 return url;
453 } 455 }
454 456
  457 + static getRefreshTokenUrl() {
  458 + let url = HttpUrlUtils._hostUrl + HttpUrlUtils.REFRESH_TOKEN_PATH;
  459 + return url;
  460 + }
455 461
456 static getResetPassworddUrl() { 462 static getResetPassworddUrl() {
457 let url = HttpUrlUtils._hostUrl + "/api/rmrb-user-center/user/zh/c/resetPassword"; 463 let url = HttpUrlUtils._hostUrl + "/api/rmrb-user-center/user/zh/c/resetPassword";
@@ -66,3 +66,6 @@ export { ListHasNoMoreDataUI } from "./src/main/ets/components/reusable/ListHasN @@ -66,3 +66,6 @@ export { ListHasNoMoreDataUI } from "./src/main/ets/components/reusable/ListHasN
66 export { LottieView } from './src/main/ets/lottie/LottieView' 66 export { LottieView } from './src/main/ets/lottie/LottieView'
67 67
68 export { SpacialTopicPageComponent } from './src/main/ets/components/SpacialTopicPageComponent' 68 export { SpacialTopicPageComponent } from './src/main/ets/components/SpacialTopicPageComponent'
  69 +
  70 +export { LogoutViewModel } from "./src/main/ets/viewmodel/LogoutViewModel"
  71 +
@@ -11,22 +11,26 @@ export class LogoutViewModel{ @@ -11,22 +11,26 @@ export class LogoutViewModel{
11 requestLogout(){ 11 requestLogout(){
12 return new Promise<string>((success, fail) => { 12 return new Promise<string>((success, fail) => {
13 this.logout.requestLogout().then((data) => { 13 this.logout.requestLogout().then((data) => {
14 - SPHelper.default.save(SpConstants.USER_FIRST_MARK, '')  
15 - SPHelper.default.save(SpConstants.USER_ID, '')  
16 - SPHelper.default.save(SpConstants.USER_JWT_TOKEN, '')  
17 - SPHelper.default.save(SpConstants.USER_LONG_TIME_NO_LOGIN_MARK, '')  
18 - SPHelper.default.save(SpConstants.USER_REFRESH_TOKEN, '')  
19 - SPHelper.default.save(SpConstants.USER_STATUS, '')  
20 - SPHelper.default.save(SpConstants.USER_Type, '')  
21 - SPHelper.default.save(SpConstants.USER_NAME, '')  
22 - SPHelper.default.save(SpConstants.USER_PHONE, '')  
23 - HttpUrlUtils.setUserId("")  
24 - HttpUrlUtils.setUserType("")  
25 - HttpUrlUtils.setUserToken('') 14 + LogoutViewModel.clearLoginInfo()
26 success(data) 15 success(data)
27 }).catch((message: string) => { 16 }).catch((message: string) => {
28 fail(message) 17 fail(message)
29 }) 18 })
30 }) 19 })
31 } 20 }
  21 +
  22 + static clearLoginInfo() {
  23 + SPHelper.default.save(SpConstants.USER_FIRST_MARK, '')
  24 + SPHelper.default.save(SpConstants.USER_ID, '')
  25 + SPHelper.default.save(SpConstants.USER_JWT_TOKEN, '')
  26 + SPHelper.default.save(SpConstants.USER_LONG_TIME_NO_LOGIN_MARK, '')
  27 + SPHelper.default.save(SpConstants.USER_REFRESH_TOKEN, '')
  28 + SPHelper.default.save(SpConstants.USER_STATUS, '')
  29 + SPHelper.default.save(SpConstants.USER_Type, '')
  30 + SPHelper.default.save(SpConstants.USER_NAME, '')
  31 + SPHelper.default.save(SpConstants.USER_PHONE, '')
  32 + HttpUrlUtils.setUserId("")
  33 + HttpUrlUtils.setUserType("")
  34 + HttpUrlUtils.setUserToken('')
  35 + }
32 } 36 }
@@ -7,10 +7,8 @@ import cryptoFramework from '@ohos.security.cryptoFramework' @@ -7,10 +7,8 @@ import cryptoFramework from '@ohos.security.cryptoFramework'
7 import buffer from '@ohos.buffer' 7 import buffer from '@ohos.buffer'
8 import { encryptMessage } from '../../utils/cryptoUtil' 8 import { encryptMessage } from '../../utils/cryptoUtil'
9 9
10 -import {  
11 - SpConstants  
12 -} from '../../../../../../../commons/wdNetwork/oh_modules/wdConstant/src/main/ets/constants/SpConstants'  
13 import { HttpUrlUtils } from 'wdNetwork/src/main/ets/http/HttpUrlUtils' 10 import { HttpUrlUtils } from 'wdNetwork/src/main/ets/http/HttpUrlUtils'
  11 +import { SpConstants } from 'wdConstant/Index'
14 12
15 const TAG = "LoginViewModel" 13 const TAG = "LoginViewModel"
16 14
1 -import { BottomNavigationComponent} from 'wdComponent'; 1 +import { BottomNavigationComponent, LogoutViewModel} from 'wdComponent';
2 import { BreakpointConstants } from 'wdConstant'; 2 import { BreakpointConstants } from 'wdConstant';
3 3
4 -import { BreakpointSystem, Logger } from 'wdKit'; 4 +import { BreakpointSystem, EmitterEventId, EmitterUtils, Logger } from 'wdKit';
5 import router from '@ohos.router'; 5 import router from '@ohos.router';
  6 +import { promptAction } from '@kit.ArkUI';
6 7
7 8
8 const TAG = 'MainPage'; 9 const TAG = 'MainPage';
@@ -22,6 +23,9 @@ struct MainPage { @@ -22,6 +23,9 @@ struct MainPage {
22 aboutToAppear() { 23 aboutToAppear() {
23 this.breakpointSystem.register() 24 this.breakpointSystem.register()
24 Logger.info(TAG, `aboutToAppear `); 25 Logger.info(TAG, `aboutToAppear `);
  26 + EmitterUtils.receiveEvent(EmitterEventId.FORCE_USER_LOGIN_OUT, () => {
  27 + LogoutViewModel.clearLoginInfo()
  28 + })
25 } 29 }
26 30
27 aboutToDisappear() { 31 aboutToDisappear() {