用户授权之支付宝H5授权
本文主要总结支付宝H5方式获取用户授权信息。
请求地址
静默授权的权限作用于较小为:auth_base
url拼接规则:
https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=APPID&auth_skip=false&scope=SCOPE&redirect_uri=ENCODED_URL
url参数说明
参数名 是否必须 长度 描述 app_id 是 16 开发者应用的app_id; 相同支付宝账号下,不同的app_id获取的token切忌混用。 scope 是 不定,取决于请求授权时scope个数 接口权限值,目前只支持auth_user(获取用户信息、网站支付宝登录)、auth_base(用户信息授权)、auth_ecard(商户会员卡)、auth_invoice_info(支付宝闪电开票)、auth_puc_charge(生活缴费)五个值;多个scope时用”,”分隔,如scope为”auth_user,auth_ecard”时,此时获取到的access_token,既可以用来获取用户信息,又可以给用户发送会员卡。 redirect_uri 是 100 授权回调地址,是经过URLENCODE转义 的url链接(url必须以http或者https开头); 在请求之前,开发者需要先到开发者中心对应应用内,配置授权回调地址。 redirect_uri与应用配置的授权回调地址域名部分必须一致。 state 否 100 商户自定义参数,用户授权后,重定向到redirect_uri时会原样回传给商户。 为防止CSRF攻击,建议开发者请求授权时传入state参数,该参数要做到既不可预测,又可以证明客户端和当前第三方网站的登录认证状态存在关联。
请求参数
在SDK调用前需要进行初始化,以Java代码为示例如下:
AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID,
APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, SIGN_TYPE);
关键参数说明:
配置参数 | 示例值解释 | 获取方式/示例值 |
---|---|---|
URL | 支付宝网关(固定) | https://openapi.alipay.com/gateway.do |
APPID | APPID 即创建应用后生成 | 获取见上面应用设置 |
APP_PRIVATE_KEY | 开发者私钥,由开发者自己生成 | 获取详见上面应用设置 |
FORMAT | 参数返回格式,只支持json | json(固定) |
CHARSET | 编码集,支持GBK/UTF-8 | 开发者根据实际工程编码配置 |
ALIPAY_PUBLIC_KEY | 支付宝公钥,由支付宝生成 | 获取详见上面应用设置 |
SIGN_TYPE | 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 | RSA2 |
获取auth_code
当用户授权成功后,会跳转至开发者定义的回调页面,支付宝会在回调页面请求中加入参数,包括auth_code、app_id、scope等,支付宝请求开发者回调页面示例如下:
http或https打头的授权回调地址? app_id=2016032301002387 &scope=auth_user&
auth_code=10e20498fe5d42f18427d893fc06WX59
关键返回参数说明:
参数名 | 是否必须 | 长度 | 描述 |
---|---|---|---|
app_id | 是 | 16 | 开发者应用的app_id;相同支付宝账号下,不同的app_id获取的token切忌混用。 |
scope | 是 | 不定,取决于请求授权时scope个数 | 成功授权的接口权限值,目前只支持auth_user(获取用户信息、网站支付宝登录)、auth_base(用户信息授权)、auth_ecard(商户会员卡)、auth_invoice_info(支付宝闪电开票)、auth_puc_charge(生活缴费)五个值;多个scope时用“,”分隔,如scope为“auth_user,auth_ecard”时,此时获取到的access_token,既可以用来获取用户信息,又可以给用户发送会员卡 |
error_scope | 否 | 不定,少于请求授权时scope个数 | error_scope表示授权是失败的scope列表及对应的错误信息(错误列表之间用“ |
state | 否 | 100 | 商户自定义参数,用户授权后,重定向到redirect_uri时会原样回传给商户。 为防止CSRF攻击,建议开发者请求授权时传入state参数,该参数要做到既不可预测,又可以证明客户端和当前第三方网站的登录认证状态存在关联。 |
auth_code | 是 | 目前为32,后期会根据安全策略适当调整,请勿限制该字段长度。 | 临时授权码,一次性有效,同时若超过有效期未使用,则会失效。有效期目前至少为5分钟,最长为24小时。请获取auth_code后尽快通过调用alipay.system.oauth.token接口获取访问令牌 |
注意:其余返回字段无需关注。
auth_code换取access_token与user_id
通过接口 alipay.system.oauth.token 获取access_token及userId。
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
APP_ID,
APP_PRIVATE_KEY,
"json",
CHARSET,
ALIPAY_PUBLIC_KEY,
"RSA2");
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
request.setCode("2e4248c2f50b4653bf18ecee3466UC18");
request.setGrantType("authorization_code");
try {
AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(request);
System.out.println(oauthTokenResponse.getAccessToken());
} catch (AlipayApiException e) {
//处理异常
e.printStackTrace();
}
至此,用户信息授权流程已结束,如果只想拿到user_id(支付宝用户唯一标识符),则无需看下一步。
授权接入注意事项【必读】
授权scope
说明:
scope为公开的资源,其使用不需要签约。
开发者可以在授权请求中包含一个或者多个用户授权范围,每个授权范围称为一个scope,一个scope包含若干个开放平台接口,请求的多个scope通过英文逗号分隔。
授权的流程是通用的,在不同的业务场景需要授权的范围不同,需要根据具体产品接入文档中指定的scope替换本文中的scope参数。
scope有效期:
这里的scope有效期和前面的auth_code有效期是两个概念。
scope的有效期会影响开发者最终获取到的access_token和refresh_token的有效期,不同scope的有效期请参考具体的产品文档。
建议:
为了产品体验考虑请按需请求需要的scope,过多的授权范围容易导致用户放弃授权。建议在做产品的登录场景中使用auth_base或者auth_user做用户引流,后续根据需要具体业务需要引导用户请求特定scope的用户授权。
授权作用域
成功授权的接口权限值,目前只支持
auth_user(获取用户信息、网站支付宝登录)、
auth_base(用户信息授权)、
auth_ecard(商户会员卡)、
auth_invoice_info(支付宝闪电开票)、
auth_puc_charge(生活缴费)五个值;
多个scope时用“,”分隔,如scope为“auth_user,auth_ecard”时,此时获取到的access_token,既可以用来获取用户信息,又可以给用户发送会员卡
文档地址
https://docs.open.alipay.com/289/105656/
支付宝显式授权
用户需要完成对商户应用的授权,商户获取token后即可调用接口获取用户信息。
授权流程
如上图所示,对于开发者而言,需要完成以下工作:
- 按照规则拼接授权页面的链接,并且引导用户跳转至该链接;
- 用户在授权页面上确认授权后,将跳转到开发者指定的回调页,并且带上auth_code;
- 开发者通过auth_code换取access_token及用户的userId;
- 如果需要除userId以外的其他信息,则使用access_token调用用户信息共享接口获取。
具体步骤
1.URL拼接
这里因为我们要获取用户信息,因此scope要使用auth_user
使用场景举例:开发者通过URL拼接方案,构造授权页面,并且引导用户授权。
url参数说明
参数名 | 是否必须 | 描述 |
---|---|---|
app_id | 是 | 开发者应用的app_id |
scope | 是 | 接口权限值,目前只支持auth_user和auth_base两个值 |
redirect_uri | 是 | 回调页面,是 经过转义 的url链接(url必须以http或者https开头),比如:http%3A%2F%2Fexample.com 在请求之前,开发者需要先到开发者中心对应应用内,配置授权回调地址。 |
state | 否 | 商户自定义参数,用户授权后,重定向到redirect_uri时会原样回传给商户。 为防止CSRF攻击,建议开发者请求授权时传入state参数,该参数要做到既不可预测,又可以证明客户端和当前第三方网站的登录认证状态存在关联。 |
2. 获取auth_code
具体步骤捅静默授权
当用户授权成功后,会跳转至开发者定义的回调页面,支付宝会在回调页面请求中加入参数,包括auth_code、app_id、scope等,需要注意的是支付宝仅保证auth_code、app_id以及scope参数的有效性。支付宝请求开发者回调页面示例如下:
http://example.com/doc/toAuthPage.html?app_id=2014101500013658&
source=alipay_wallet&scope=auth_user&
auth_code=ca34ea491e7146cc87d25fca24c4cD11
3.使用auth_code换取接口access_token及用户userId
接口名称:alipay.system.oauth.token
换取授权访问令牌,开发者可通过获取到的auth_code换取access_token和用户userId。auth_code作为换取access_token的票据,每次用户授权完成,回调地址中的auth_code将不一样,auth_code只能使用一次,一天未被使用自动过期。
请求发送实例
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
request.setCode("2e4248c2f50b4653bf18ecee3466UC18");
request.setGrantType("authorization_code");
try {
AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(request);
System.out.println(oauthTokenResponse.getAccessToken());
} catch (AlipayApiException e) {
//处理异常
e.printStackTrace();
}
请求参数说明
参数 | 参数名称 | 类型(长度范围) | 参数说明 | 是否可为空 | 样例 |
---|---|---|---|---|---|
grant_type | 授权类型 | String | 值为authorization_code时,代表用code换取;值为refresh_token时,代表用refresh_token换取 | 不可空 | authorization_code |
code | 授权码 | String | 用户对应用授权后得到,即第二步中开发者获取到的auth_code值 | 与refresh_token二选一 | 4b203fe6c11548bcabd8da5bb087a83b |
refresh_token | 刷新令牌 | String | 刷新access_token时使用 | 与code二选一 | 201208134b203fe6c11548bcabd8da5bb087a83b |
返回报文
{
"alipay_system_oauth_token_response": {
"access_token": "publicpBa869cad0990e4e17a57ecf7c5469a4b2",
"user_id": "2088411964574197",
"expires_in": 300,
"re_expires_in": 300,
"refresh_token": "publicpB0ff17e364f0743c79b0b0d7f55e20bfc"
},
"sign": "xDffQVBBelDiY/FdJi4/a2iQV1I7TgKDFf/9BUCe6+l1UB55YDOdlCAir8CGlTfa0zLYdX0UaYAa43zY2jLhCTDG+d6EjhCBWsNY74yTdiM95kTNsREgAt4PkOkpsbyZVXdLIShxLFAqI49GIv82J3YtzBcVDDdDeqFcUhfasII="
}
这一步拿到了userid
同步响应参数说明
参数 | 参数名称 | 类型(长度范围) | 参数说明 | 是否可为空 | 样例 |
---|---|---|---|---|---|
access_token | 交换令牌 | String | 用于获取用户信息 | 不可空 | publicpBa869cad0990e4e17a57ecf7c5469a4b2 |
user_id | 用户的userId | String | 支付宝用户的唯一userId | 不可空 | 2088411964574197 |
expires_in | 令牌有效期 | Number | 交换令牌的有效期,单位秒 | 不可空 | 300 |
re_expires_in | 刷新令牌有效期 | Number | 刷新令牌有效期,单位秒 | 不可空 | 300 |
refresh_token | 刷新令牌 | String | 通过该令牌可以刷新access_token | 不可空 | publicpB0ff17e364f0743c79b0b0d7f55e20bfc |
4.调用接口获取用户信息
如果scope=auth_base,在第三步就可以获取到用户的userId,无需走第四步。如果scope=auth_user,才需要走第四步,通过access_token调用用户信息共享接口获取用户信息。
接口调用示例
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");
AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
String auth_token = "composeBcd261a4867d94837a701f92816f18X18";
try {
AlipayUserInfoShareResponse userinfoShareResponse = alipayClient.execute(request, auth_token);
System.out.println(userinfoShareResponse.getBody());
} catch (AlipayApiException e) {
//处理异常
e.printStackTrace();
}
公共请求参数说明
参数 | 参数名称 | 类型(长度范围) | 参数说明 | 是否可为空 | 样例 |
---|---|---|---|---|---|
auth_token | 授权令牌 | String | 通过auth_code获取的access_token | 不可空 | publicpB9ea460ff5b5c468c9ccf5e967dc34963 |
同步响应结果示例
{
"alipay_user_info_share_response": {
"code": "10000",
"msg": "Success",
"user_id": "2088102104794936",
"avatar": "http://tfsimg.alipay.com/images/partner/T1uIxXXbpXXXXXXXX",
"user_type": "1",
"user_status": "T",
"is_certified": "T",
"province": "安徽省",
"city": "安庆",
"nick_name": "支付宝小二",
"is_student_certified": "T",
"gender": "F"
},
"sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
同步响应参数说明
参数 | 参数名称 | 类型(长度范围) | 参数说明 | 是否可为空 | 样例 |
---|---|---|---|---|---|
user_id | 支付宝用户id | String | 支付宝用户的Use_id | 必填 | 2088102104794936 |
avatar | 用户头像 | String | 如果没有数据的时候不会返回该数据,请做好容错 | 必填 | https://tfsimg.alipay.com/images/partner/T1k0xiXXRnXXXXXXXX |
nick_name | 用户昵称 | String | 如果没有数据的时候不会返回该数据,请做好容错 | 必填 | 张三 |
province | 省份 | String | 用户注册时填写的省份 如果没有数据的时候不会返回该数据,请做好容错 | 必填 | 浙江省 |
city | 城市 | String | 用户注册时填写的城市, 如果没有数据的时候不会返回该数据,请做好容错 | 必填 | 杭州 |
gender | 用户性别 | String | M为男性,F为女性, 如果没有数据的时候不会返回该数据,请做好容错 | 可空 | M |
user_type | 用户类型 | String | 1代表公司账户2代表个人账户 | 可空 | 1 |
user_status | 用户状态 | String | Q代表快速注册用户 T代表已认证用户 B代表被冻结账户 W代表已注册,未激活的账户 | 可空 | T |
is_certified | 是否通过实名认证 | String | T是通过 F是没有实名认证 | 可空 | T |
is_student_certified | 是否是学生 | String | T是学生 F不是学生 | 可空 | T |
接口调用结果码说明
同步返回结果码 | 含义 | 说明 |
---|---|---|
10000 | 业务处理成功 | |
40001~40006 | 业务处理失败 | 具体失败原因请参考公共错误码。其它请参考API文档。 |
20000 | 业务出现未知错误或者系统异常 | 业务出现未知错误或者系统异常(请一定在确定本次调用结果后,发起重试),可调用查询接口发起查询确定结果。 |
注意
注:H5授权页只能在支付宝客户端里使用,否则会报错