SpringBoot+Vue实现第三方支付宝登录(二)


1 支付宝登录授权流程

本步骤的作用

  登录 开放平台控制台 获取创建应用的 APPID

  接入支付宝登录前,网站需首先进行申请,获得对应的appid,以保证后续流程中可正确对网站与用户进行验证与授权。

    注意:对appid和appkey信息进行保密,不要随意泄漏。

2 放置“支付宝登录”按钮

本步骤的作用

  在网站页面上放置“支付宝登录”按钮,并为按钮添加前台代码,实现点击按钮即弹出支付宝登录对话框 。

2.1 下载“支付宝登录”按钮图片,并将按钮放置在页面合适的位置

  按钮图片下载: 点击这里下载 。

  可以到阿里矢量图库下载更多图标:阿里巴巴矢量图标库 。

  按照UI规范,将按钮放置在页面合适的位置:点击这里查看 。

2.2 为“支付宝登录”按钮添加前台代码

2.2.1 效果演示

2.2.2 前端代码(Vue)

  为了实现上述效果,应该为“支付宝登录”按钮图片添加如下前台代码:


第三方登录:






 

// 支付宝登录
handleZhiFuBaoLogin() {
this.dialogVisible = true;
this.pictureType = 'ZhiFuBaoLogin'
},

2.2.3 后端代码(Java)

  支付宝登录配置文件信息:

# 支付宝登录配置
zhifubao.appID = 66666666 ( 替换成你的 )
zhifubao.redirectURI = https://www.youyoushop.work/zhiFuBaoCallback ( 替换成你的 )
zhifubao.authorizeURL = https://openauth.alipay.com/oauth2/publicAppAuthorize.htm
zhifubao.gateway = https://openapi.alipay.com/gateway.do
zhifubao.appPrivateKey = MIIujfisadjfeifjsaldjfjaejfufsdf0d8fsad ( 替换成你的私钥 )
zhifubao.alipayPublicKey = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlO1HqdX5uME+xdtMXY3JiKq27FbovsgdTUqaUKhF ( 替换成你的公钥 )

  读取配置文件信息常量类:

package com.liyh.modules.security.constants;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Data
@Configuration
@PropertySource("classpath:thirdparty/config.properties") // 指定配置文件的路径,属性文件需放在根目录的resources文件夹下面,才能被读取出来
public class ZhiFuBaoConstants {

@Value("${zhifubao.appID}")
private String appID;

@Value("${zhifubao.redirectURI}")
private String redirectURI;

@Value("${zhifubao.authorizeURL}")
private String authorizeURL;

@Value("${zhifubao.gateway}")
private String gateway;

@Value("${zhifubao.appPrivateKey}")
private String appPrivateKey;

@Value("${zhifubao.alipayPublicKey}")
private String alipayPublicKey;

}

  Conteoller(获取支付宝登录的url)

@ApiOperation("获得跳转到支付宝登录页的url")
@GetMapping("/getZhiFuBaoCode")
public ResponseEntity getZhiFuBaoCode() throws Exception {
// 授权地址 ,进行Encode转码
String authorizeURL = zhiFuBaoConstants.getAuthorizeURL();

// 回调地址 ,回调地址要进行Encode转码
String redirectUri = zhiFuBaoConstants.getRedirectURI();

//用于第三方应用防止CSRF攻击
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
// 保存到Redis
redisUtils.set(ZHIFUBAOSTATE + "-" + uuid, uuid, expiration, TimeUnit.MINUTES);

// https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?
// app_id=appid
// &scope=auth_user
// &redirect_uri=redirectUri
// &state=init

// 拼接url
StringBuilder url = new StringBuilder();
url.append(authorizeURL);
url.append("?app_id=" + zhiFuBaoConstants.getAppID());
// 转码
url.append("&redirect_uri=" + URLEncodeUtil.getURLEncoderString(redirectUri));
url.append("&state=" + uuid);
url.append("&scope=auth_user");

return ResponseEntity.ok(url);
}

3 使用Authorization_Code获取Access_Token

本步骤的作用

  通过用户验证登录和授权,获取Access Token,为下一步获取用户的OpenID做准备。

  同时,Access Token是应用在调用OpenAPI访问和修改用户数据时必须传入的参数。

3.1 简介

  即server-side模式,是OAuth2.0认证的一种模式,又称Web Server Flow。

  适用于需要从web server访问的应用,例如Web网站。

对于应用而言,需要进行两步:

  1. 获取Authorization Code。

  2. 通过Authorization Code获取Access Token。

3.2 获取Authorization Code

示例代码

https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?
app_id=66666
&scope=auth_user
&redirect_uri=redirectUri
&state=init

请求参数

参数是否必须含义
app_id  必须 开发者应用的app_id,相同支付宝账号下,不同的app_id获取的token切忌混用。
scope  必须 接口权限值,目前只支持auth_user(获取用户信息、网站支付宝登录)、auth_base(用户信息授权)、auth_ecard(商户会员卡)、auth_invoice_info(支付宝闪电开票)、auth_puc_charge(生活缴费)五个值;多个scope时用”,”分隔,如scope为”auth_user,auth_ecard”时,此时获取到的access_token,可以用来获取用户信息
redirect_uri 必须 授权回调地址,是经过URLENCODE转义 的url链接(url必须以http或者https开头); 在请求之前,开发者需要先到开发者中心对应应用内,配置授权回调地址。 redirect_uri与应用配置的授权回调地址域名部分必须一致。
state 自定义参数,用户授权后,重定向到redirect_uri时会原样回传给商户。 为防止CSRF攻击,建议开发者请求授权时传入state参数,该参数要做到既不可预测,又可以证明客户端和当前第三方网站的登录认证状态存在

返回说明

1. 如果用户成功登录并授权,则会跳转到指定的回调地址,并在redirect_uri地址后带上Authorization Code和原始的state值。如:  

  https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=APPID&scope=SCOPE&redirect_uri=ENCODED_URL

  注意:此code会在10分钟内过期。

2. 如果用户在登录授权过程中取消登录流程,对于PC网站,登录页面直接关闭。

错误码说明

  接口调用有错误时,会返回code和msg字段,以url参数对的形式返回,value部分会进行url编码(UTF-8)。

  PC网站接入时,错误码详细信息请参见:PC网站接入时的公共返回码

3.3 通过Authorization Code获取Access Token

请求说明

  支付宝登录和qq等第三方登录方式不一样,需要使用支付宝的依赖

      
        
            com.alipay.sdk
            alipay-sdk-java
            3.1.0
        

请求参数

AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");

接口代码:

/**
* 获得token信息(授权,每个用户的都不一致) --> 获得token信息该步骤返回的token期限为一个月
*
* @return
* @throws Exception
*/
public Map getToken(String code) throws Exception {
Map zhiFuBaoProperties = new HashMap();
try {
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
request.setGrantType("authorization_code");
request.setCode(code);

// AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
AlipayClient alipayClient = new DefaultAlipayClient(zhiFuBaoConstants.getGateway(), zhiFuBaoConstants.getAppID(), zhiFuBaoConstants.getAppPrivateKey(), "json", "GBK", zhiFuBaoConstants.getAlipayPublicKey(), "RSA2");
AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(request);

// "user_id": "208834234652",
// "access_token": "2012234234231473993",
// "expires_in": "3600",
// "refresh_token": "2012234234473993",
// "re_expires_in": "3600"

String result = oauthTokenResponse.getAccessToken();
log.info("result = " + result);

// 把token保存
zhiFuBaoProperties = new HashMap();
zhiFuBaoProperties.put("accessToken", result);
} catch (Exception e) {
throw new BadRequestException("支付宝登录信息异常 !!!");
}
return zhiFuBaoProperties;
}

4 通过Access Token 获取用户信息

本步骤的作用

  通过输入在上一步获取的Access Token,得到对应用户的信息。

请求参数:

AlipayClient alipayClient = new DefaultAlipayClient
(zhiFuBaoConstants.getGateway(), zhiFuBaoConstants.getAppID(), zhiFuBaoConstants.getAppPrivateKey(), "json", "GBK", zhiFuBaoConstants.getAlipayPublicKey(), "RSA2");

接口代码:

/**
* accessToken 获取用户信息
*/
public AlipayUserInfoShareResponse getUserJson(Map zhiFuBaoProperties) throws Exception {
AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest ();
AlipayUserInfoShareResponse userInfo = new AlipayUserInfoShareResponse();
try {

// 取出token
String accessToken = (String) zhiFuBaoProperties.get("accessToken");
if (StringUtils.isEmpty(accessToken)) {
throw new BadRequestException("支付宝登录信息异常 !!!");
}

AlipayClient alipayClient = new DefaultAlipayClient(zhiFuBaoConstants.getGateway(), zhiFuBaoConstants.getAppID(), zhiFuBaoConstants.getAppPrivateKey(), "json", "GBK", zhiFuBaoConstants.getAlipayPublicKey(), "RSA2");

// 获取支付宝用户信息相关数据
userInfo = alipayClient.execute(request, accessToken);

// {
// "alipay_user_info_share_response": {
// "code": "10000",
// "msg": "Success",
// "user_id": "2088102104794936",
// "avatar": "http://tfsimg.alipay.com/images/partner/T1uIxXXbpXXXXXXXX",
// "province": "安徽省",
// "city": "安庆",
// "nick_name": "支付宝小二",
// "gender": "F"
// },
// "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
//}

} catch (Exception e) {
throw new BadRequestException("支付宝登录信息异常 !!!");
}
return userInfo;
}

返回数据:

{
  "alipay_user_info_share_response": {
    "code": "10000",
    "msg": "Success",
    "user_id": "2088102104794936",
    "avatar": "http://tfsimg.alipay.com/images/partner/T1uIxXXbpXXXXXXXX",
    "province": "安徽省",
    "city": "安庆",
    "nick_name": "支付宝小二",
    "gender": "F"
    },
  "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}

5 个人网站(YOUYOUSHOP)(用户名:admin,密码:adminliyh),需要的小伙伴可以测试 

5.1 每个人做的项目需求不同,可能会出现不同的问题,文章可以参考,也可以留言你的问题,我会帮你解决,大家一起加油