前言
本文将以APICloud开发的app为前端,Java为后台接入支付宝授权登录功能并获取用户基本公开信息(六个字段: 支付宝唯一的用户ID,用户昵称,头像地址,城市,省份,性别)为例,其他语言和pc端类似
一、创建开发者账号和应用并配置
(1)创建应用
登录支付宝开发平台(https://open.alipay.com/develop/manage),点击右上角的控制台,进入如下页面:
选择你的项目类型,并点击创建
填写对应的信息,关于移动应用的BundleID,应用签名以及应用包名怎么获取,由于各个开发平台的不一致,这里不一一赘述,在本社区应该可以找到答案,APICloud平台的应用可以直接在网页端的控制台查看应用包名以及Bundle ID,应用签名需要打包成正式包在真机安装GenSignature工具获取
安装成功后输入应用包名获取应用签名
(2)接入产品并配置
应用创建成功后添加相应的产品并开通,由于个人开发者需上传营业执照才能接入支付宝支付功能,所以个人开发者只能接入支付宝登录功能(免费)
(3)开发设置
添加产品后进行开发设置
下载支付宝开发助手生成应用的密钥进行加签配置(上图红框填应用公钥)(这一步很重要,千万别搞错,仔细来)
然后再给设置下面的接口内容加密方式,其他的设置不用管,如果没有这些方面的需求的话
最后就是在应用详情那里提交审核了,审核时间一般为一天内.
二、接入SDK
(1)下载SDK
按需求来,官方提供的SDK有两种形式,jar包和Maven:
Maven:(直接放在pom.xml的依赖中就好)
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83_noneautotype</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.62</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
如果是下载jar包需要将jar包引入你的项目中
(2)写后台
不用去看官方的SDK文档,人家官方都已经帮你封装好了完整功能的SDK,只需要填入你自己的参数就可以了,以下代码只需填写appid,应用私钥,支付宝公钥就行(appid在支付宝开发平台创建完应用后可以看到,应用私钥,支付宝公钥在本文 一、创建开发者账号和应用并配置> (3)开发设置) 步骤完成后可以看到, 再对应一下Java的包名类名与访问后台路径名啥的就行,响应的值也注意一下(应用私钥和支付宝公钥一定不要错,很重要)
以SSM框架为例:
完整代码:
package com.sail.controller;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayUserInfoShareRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
@Controller
public class GetInfoController {
private static final String URL = "https://openapi.alipay.com/gateway.do";
private static final String APPID = "你的APP ID";
private static final String PRIVATE_KEY = "你自己应用的私钥";
private static final String FORMAT = "JSON";
private static final String CHARSET = "UTF-8";
private static final String SIGN_TYPE = "RSA2";
private static final String ALIPAY_PUBLIC_KEY = "你的支付宝公钥";
//通过授权码换取令牌
@RequestMapping("getToken")
@ResponseBody
public void getToken(@RequestParam("code") String code,HttpServletResponse httpServletResponse) throws IOException, AlipayApiException {
System.out.println(code);
PrintWriter out = httpServletResponse.getWriter();
AlipayConfig alipayConfig = new AlipayConfig();
//设置网关地址
alipayConfig.setServerUrl(URL);
//设置应用ID
alipayConfig.setAppId(APPID);
//设置应用私钥
alipayConfig.setPrivateKey(PRIVATE_KEY);
//设置请求格式,固定值json
alipayConfig.setFormat(FORMAT);
//设置字符集
alipayConfig.setCharset(CHARSET);
//设置签名类型
alipayConfig.setSignType(SIGN_TYPE);
//设置支付宝公钥
alipayConfig.setAlipayPublicKey(ALIPAY_PUBLIC_KEY);
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.open.public.template.message.industry.modify
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
request.setGrantType("authorization_code");
request.setCode(code);
// request.setRefreshToken("201208134b203fe6c11548bcabd8da5bb087a83b");
AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
if(response.isSuccess()){
System.out.println("获取令牌调用成功");
String accessToken = response.getAccessToken();
out.print(accessToken);
} else {
System.out.println("获取令牌调用失败");
}
}
//通过令牌获取用户信息
@RequestMapping("/getUserInfo")
@ResponseBody
public void getUserInfo(@RequestParam("token")String token,HttpServletResponse httpServletResponse) throws IOException, AlipayApiException {
System.out.println(token);
PrintWriter out = httpServletResponse.getWriter();
AlipayConfig alipayConfig = new AlipayConfig();
//设置网关地址
alipayConfig.setServerUrl(URL);
//设置应用ID
alipayConfig.setAppId(APPID);
//设置应用私钥
alipayConfig.setPrivateKey(PRIVATE_KEY);
//设置请求格式,固定值json
alipayConfig.setFormat(FORMAT);
//设置字符集
alipayConfig.setCharset(CHARSET);
//设置签名类型
alipayConfig.setSignType(SIGN_TYPE);
//设置支付宝公钥
alipayConfig.setAlipayPublicKey(ALIPAY_PUBLIC_KEY);
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
AlipayUserInfoShareResponse response = alipayClient.execute(request,token);
Map<String,String> map = new HashMap<>();
if(response.isSuccess()){
System.out.println("获取用户信息调用成功");
map.put("userId",response.getUserId());
map.put("userName",response.getNickName());//实际为支付宝用户的昵称,个人开发者权限不够获取不到用户名
map.put("avatar",response.getAvatar());//头像地址
map.put("city",response.getCity());
map.put("province",response.getProvince());
map.put("gender",response.getGender());
map.put("msg","success");
} else {
System.out.println("获取用户信息调用失败");
map.put("msg","failed");
}
String jsonStr = JSON.toJSONString(map);
out.print(jsonStr);
}
}
代码解释 :
getToken方法的code参数怎么来的?
支付宝登录的整个流程为:点击登录按钮>调起用户授权页>同意授权>得到授权码>通过授权码换取令牌>通过令牌获取用户信息
所以code就是对应官方文档中的auth_code,也就是授权码,这个可以在前端获得,我是使用了APICloud封装的aliPayPlus模块,也可以在后台获得,详见官方的接口参数说明文档,注意scopes字段的值为auth_user,不然获取不到用户信息,文档中有举例,就是和上面代码中的两个方法类似,改一下
接口方法就行,获取授权的接口为alipay.user.info.auth,如下图调用
获取code的APICloud前端代码如下(sign参数在此方法中可以不写),authInfoStr为此接口的各个请求参数以键值对& = 拼接而成的字符串
var aliPayPlus = api.require('aliPayPlus');
aliPayPlus.authDirect({
authInfoStr: "详见官方文档的参数,此为所有参数拼接的字符串"
}, function (ret) {
switch (ret.resultStatus) {
case "4000": api.toast({ msg: '系统异常' }); break;
case "6001": api.toast({ msg: '用户中途取消' }); break;
case "6002": api.toast({ msg: '网络连接出错' }); break;
case "9000":
//处理返回结果中的code
let resultStr = ret.result;
let resultArray = resultStr.split("&");
let code;
for (let i = 0; i < resultArray.length; i++) {
if (resultArray[i].includes("auth_code")) {
code = resultArray[i].split("=")[1];
}
}
关于过程中出现的错误,可以使用支付宝官方的云排查工具,点击红框还可以跳转到错误原因和解决方案
以上.
本人其实也是一个小白,有什么不对的地方欢迎指正