具體請參考官方文檔:https://docs.open.alipay.com/263/105809/
本文由於支付寶官方並沒有提供網站第三方登錄的demo,因此筆者結合自己的實踐經驗做如下總結。
具體步驟:
Step One:創建應用
訪問https://open.alipay.com/platform/home.htm,創建自己的應用,如下圖
因爲我要實現的是網站使用支付寶登錄,因此上圖中選擇"自定義接入"即可。接着 按照官方文檔的步驟創建應用,提交審覈即可。
Step Two:創建RSA密鑰
爲應用生成RSA密鑰,RSA密鑰包含應用私鑰(APP_PRIVATE_KEY)、應用公鑰(APP_PUBLIC_KEY),生成密鑰後在開放平臺開發者中心進行密鑰配置,配置完成後可以獲取支付寶公鑰(ALIPAY_PUBLIC_KEY)。
生成密鑰的方式參考:https://docs.open.alipay.com/291/105971
注意:實際開發使用到的是支付寶公鑰和應用私鑰,具體見下文。
設置完應用的RSA密鑰後,可以查看支付寶公鑰,如上圖。
Step Three:編寫程序實現支付寶第三方登錄
官方提供的接口調用流程圖下圖所示:
首先,在Maven項目中引入依賴
第二步,在你的網站登錄界面中,提供一個超鏈接,用於訪問支付寶登錄/授權頁面,url格式:
https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=商戶的APPID&scope=auth_user&redirect_uri=ENCODED_URL
請求參數主要有三個,分別是app_id、scope和redirect_uri。app_id就是你創建的應用的id;scope可以取的值有多個,這裏使用"auth_user"實現網站授權登錄,其他取值參見官方文檔;最後的redirect_uri是授權成功後重定向的目標地址,一般映射到你後臺的某個控制器,注意這裏的url是需要經過編碼的,這裏提供一個在線編碼的鏈接:http://tool.chinaz.com/Tools/urlencode.aspx。此外這裏的URL需要同應用的“授權回調地址”保持一致!本例子中redirect_uri是:
'https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=xxxxxxxx&scope=auth_user&redirect_uri=http%3a%2f%2f106.14.149.152%3a8080%2falipay%2fgetAuthInfo.json
第三步:完成上述工作後,點擊上面的超鏈接就會跳轉到支付寶的授權登錄頁面:
完成授權後,瀏覽器會重定向到上述的redirect_uri地址,並且請求中會帶有auth_code、app_id和scope等參數,因此需要在後臺控制器中獲取request中的auth_code參數
第四步:根據auth_code獲取access_token,再根據access_token獲取支付寶用戶信息,具體代碼如下:
(服務類)
/** * 支付寶第三方登錄 * * @author minghui.y * @create 2018-05-22 13:10 **/ @Service public class AlipayLoginService implements InitializingBean { private static final Logger LOGGER = LoggerFactory.getLogger(AlipayLoginService.class); /**Alipay客戶端*/ private AlipayClient alipayClient; /**支付寶網關*/ private static final String ALIPAY_BORDER_DEV = "https://openapi.alipaydev.com/gateway.do"; private static final String ALIPAY_BORDER_PROD = "https://openapi.alipay.com/gateway.do"; /**appID**/ private static final String APP_ID_DEV = "xxxxxx"; private static final String APP_ID_PROD = "xxxxxx"; /**私鑰*/ private static final String APP_PRIVATE_KEY = "xxxxxx"; /**公鑰*/ private static final String ALIPAY_PUBLIC_KEY = "xxxxx"; @Override public void afterPropertiesSet() throws Exception { alipayClient = new DefaultAlipayClient(ALIPAY_BORDER_PROD, APP_ID_PROD, APP_PRIVATE_KEY, "json", "UTF-8", ALIPAY_PUBLIC_KEY, "RSA2"); } /** * 根據auth_code獲取用戶的user_id和access_token * @param authCode * @return */ public String getAccessToken(String authCode) { AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest(); request.setCode(authCode); request.setGrantType("authorization_code"); try { AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(request); return oauthTokenResponse.getAccessToken(); } catch (Exception e) { LOGGER.error("使用authCode獲取信息失敗!", e); return null; } } /** * 根據access_token獲取用戶信息 * @param token * @return */ public AlipayUser getUserInfoByToken(String token) { AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest (); try { AlipayUserInfoShareResponse response = alipayClient.execute(request, token); if (response.isSuccess()) { //打印響應信息 // System.out.println(ReflectionToStringBuilder.toString(response)); //封裝支付寶對象信息 AlipayUser alipayUser = new AlipayUser(); alipayUser.setAddress(response.getAddress()); alipayUser.setCertNo(response.getCertNo()); alipayUser.setCity(response.getCity()); alipayUser.setCollegeName(response.getCollegeName()); alipayUser.setDegree(response.getDegree()); alipayUser.setMobile(response.getMobile()); alipayUser.setPhone(response.getPhone()); alipayUser.setProvince(response.getProvince()); alipayUser.setUserName(response.getUserName()); alipayUser.setNickName(response.getNickName()); return alipayUser; } LOGGER.error("根據 access_token獲取用戶信息失敗!"); return null; } catch (Exception e) { LOGGER.error("根據 access_token獲取用戶信息拋出異常!", e); return null; } } }
(控制器)
/** * 支付寶第三方登錄服務 * * @author minghui.y * @create 2018-05-22 14:05 **/ @RestController @RequestMapping("/alipay") public class AlipayController { @Autowired private AlipayLoginService alipayLoginService; @RequestMapping("/getAuthInfo.json") public String getAuthCode(HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println("支付寶返回信息...................................................."); //從request中獲取授權信息 String authCode = request.getParameter("auth_code"); String appID = request.getParameter("app_id"); String scope = request.getParameter("scope"); if (StringUtils.isNotEmpty(authCode)) { //獲取access_token String accessToken = alipayLoginService.getAccessToken(authCode); //獲取用戶信息 if (StringUtils.isNotEmpty(accessToken)) { //獲取用戶信息 AlipayUser alipayUser = alipayLoginService.getUserInfoByToken(accessToken); //存儲到cookie中 Cookie cookieName = new Cookie("account", alipayUser.getNickName()); Cookie cookieRole = new Cookie("roleName", "支付寶賬戶"); cookieName.setMaxAge(3600); cookieRole.setMaxAge(3600); cookieName.setPath("/"); cookieRole.setPath("/"); response.addCookie(cookieName); response.addCookie(cookieRole); //跳轉至主界面 response.sendRedirect("http://106.14.149.152:80/"); } } return "hello alipay!"; } }
最後,在控制器中獲取支付寶用戶信息,重定向到登錄成功後的主界面即可。這裏需要注意的是,似乎只能獲取支付寶用戶的暱稱、城市和省份這三個信息,其他的如地址、手機號登敏感信息是獲取不到的,不過無傷大雅,因此這裏實現的只是利用支付寶實現第三方登錄而已。
Ending ...