Line Notify API 串接实作(一)-取得access token

前情提要

Line Notify API 串接实作-前置作业


好的,根据前一篇所提到的OAuth2.0流程,我们需要
1.取得code(Authorization Grant)
2.取得access token
才能利用后续的服务

取得code

GET https://notify-bot.line.me/oauth/authorize

需要参数
图一

成功则回传至请求所带的redirect_uri
图二

失败则回传至请求所带的redirect_uri
图三

以下程式码

Controller送出请求

@GetMapping("sendToOauth")public void sendToOauth(@RequestParam(name="account")String account,HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {String url = userService.getOAuthCode(account);response.sendRedirect(url);}

getOAuthCode取得UR字串

@Overridepublic String getOAuthCode(String account) {StringBuilder sb = new StringBuilder();//资料库取得使用者资料User findResult = Optional.of(userDao.findFirstByAccount(account)).orElseThrow(()->new UserServiceException(UserServiceErrorEnum.USER_DATA_NOT_FOUND.getError(),UserServiceErrorEnum.USER_DATA_NOT_FOUND.getMessage()));//设定请求资料LineOAuthRequest lineOAuthRequest = new LineOAuthRequest();lineOAuthRequest.setClient_id(client_id);lineOAuthRequest.setRedirect_uri(redirect_uri);lineOAuthRequest.setState(findResult.getState());Map<String,Object> variableParams = lineOAuthRequest.getUriParams();//组装GetOAuth URL字串sb.append(LineNotifyUrl.GET_OAUTH.getUrl()).append("?");for(String key:variableParams.keySet()) {                                                          sb.append(key)              .append("=")              .append(String.valueOf(variableParams.get(key)))              .append("&");}sb.deleteCharAt(sb.length()-1);return sb.toString();}

LineOAuthRequest物件

@Data@NoArgsConstructorpublic class LineOAuthRequest {private String client_id;private String redirect_uri;private String response_type = "code";private String scope = "notify";private String state;private String response_mode="form_post";public Map<String, Object> getUriParams(){try {            //检查值并回传 属性名与值构成的键值对beforeSendCheck();return ApiUtil.getRequestUriVariables(this);}catch (Exception e) {throw new LineOauthRequestException(4,e.getMessage());}}public void beforeSendCheck() {if(!StringUtils.hasText(client_id)) {throw new LineOauthRequestException(1,"client_id is empty");}else if(!StringUtils.hasText(redirect_uri)) {throw new LineOauthRequestException(2,"redirect_uri is empty");}else if(!StringUtils.hasText(state)) {throw new LineOauthRequestException(3,"state is empty");}}}

ApiUtil

public static <T> Map<String, Object> getRequestUriVariables(T source) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{Map<String, Object> returnMap = new HashMap<>();Field[] fields = source.getClass().getDeclaredFields();for(int i=0;i<fields.length;i++) {String fieldName = fields[i].getName();String firstLetter = fieldName.substring(0,1).toUpperCase();String getter = "get"+firstLetter+fieldName.substring(1);Method method = source.getClass().getMethod(getter, new Class[] {});Object value = method.invoke(source, new Object[] {}); returnMap.put(fieldName, value);}return returnMap;}

取得access token

POST https://notify-bot.line.me/oauth/token
ContentType: application/x-www-form-urlencoded

需要参数
图四
code无论最后结果成功或只能使用一次,并设定有失效时限

这边有遇到奇怪的点,在取得access token的请求设定redirect_uri,如果与取得code设定的redirect_uri不一致的话,会回传redirect_uri not match的错误。
就算我在Callback URL设定第二个redirect_uri依然是一样的错误,如果有大大知道原因欢迎下方留言告诉我。

成功回应
Content-Type:application/json
图五

以下程式码

getToken方法

@Overridepublic void getToken(LineOAuthResponse lineOAuthResponse) throws InvalidKeyException, UserServiceException, IllegalBlockSizeException, BadPaddingException {//LineOAuthResponse:getOAuth成功回传物件//设定表头参数String code = lineOAuthResponse.getCode();String state = lineOAuthResponse.getState();HttpHeaders headers = new HttpHeaders();    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);    MultiValueMap<String, String> params= new LinkedMultiValueMap<String, String>();    params.add("grant_type", "authorization_code");    params.add("code", code);    params.add("redirect_uri", token_redirectUri);    params.add("client_id", client_id);    params.add("client_secret", token_secret);HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params,headers);LineTokenResponse result = restTemplate.postForObject(LineNotifyUrl.GET_TOKEN.getUrl(),         entity, LineTokenResponse.class);if(HttpStatus.OK.value()!=result.getStatus()) {throw new UserServiceException(UserServiceErrorEnum.USER_TOKEN_BACK_ERROR.getError(),UserServiceErrorEnum.USER_TOKEN_BACK_ERROR.getMessage());}//成功取得回应后根据state取出对应的用户资料User origin = Optional.of(userDao.findFirstByPassword(state)).orElseThrow(()->new UserServiceException(UserServiceErrorEnum.USER_DATA_NOT_FOUND.getError(),UserServiceErrorEnum.USER_DATA_NOT_FOUND.getMessage()));//新增token值后更新回资料库origin.setToken(result.getAccess_token());userDao.save(origin);}

LineTokenResponse物件

@Datapublic class LineTokenResponse {private Integer status;private String message;private String access_token;}

OK 取得access token,我们在就可以传讯息给使用者啦~

下篇
Line Notify API 串接实作(二)-推播讯息

参考资料
Line Notify Document


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章