一键登录的思路是
获取支付宝账号的手机号,如果手机号已存在就自动登录,如果不存在就生成该手机号的账号信息,当然也可以让用户绑定自己的账号信息。
所以我们要先获取手机号:
https://opendocs.alipay.com/mini/api/getphonenumber?pathHash=a67c2790
注意
获取会员手机号仅对企业支付宝账户开放,个人账号不支持,详见获取会员手机号。
开放平台
https://open.alipay.com/develop/manage
创建小程序
https://open.alipay.com/develop/mini/create?bundleId=com.alipay.alipaywallet&from=createMenuPage
小程序API
https://opendocs.alipay.com/mini/api/
获取手机号
https://opendocs.alipay.com/mini/api/getphonenumber
页面中
<!-- #ifdef MP-ALIPAY -->
<button class="login" type="default" open-type="getAuthorize" @getAuthorize="onGetAuthorize"
@error="onAuthError" scope='phoneNumber'>授权手机号一键登录</button>
<!-- #endif -->
JS
onGetAuthorize: function() {
return new Promise((resolve, reject) => {
my.getPhoneNumber({
scopes: "auth_user",
success: res => {
console.info("response", res.response);
this.zfbLogin(res.response); // 调取这个自定义方法
resolve(res);
},
fail: res => {
reject(res);
}
});
});
},
response 是一个JSON对象转的字符串,包含两个属性:
response
和sign
,我们可以前端取传给后端,也可以传整个字符串让后端解析。
添加引用
<dependencies>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.39.74.ALL</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.50</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
代码
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipayEncrypt;
import com.alipay.api.internal.util.AlipaySignature;
import java.util.Map;
public class MyTest {
public static void main(String[] args) throws Exception {
String response = "{\"response\":\"xxxxxxx\",\"sign\":\"xxx\"}";
getResult(response);
}
public static String getResult(String response) throws Exception {
//1. 获取验签和解密所需要的参数
Map<String, String> openapiResult = JSON.parseObject(response, new TypeReference<Map<String, String>>() {
}, Feature.OrderedField);
String sign = openapiResult.get("sign");
String content = openapiResult.get("response");
//判断是否为加密内容
boolean isDataEncrypted = !content.startsWith("{");
boolean signCheckPass = false;
//2. 验签
String signType = "RSA2";
String charset = "UTF-8";
String encryptType = "AES";
String signContent = content;
String signVeriKey = "你的小程序对应的支付宝公钥(为扩展考虑建议用appId+signType做密钥存储隔离)";
String decryptKey = "你的小程序对应的加解密密钥(为扩展考虑建议用appId+encryptType做密钥存储隔离)";//如果是加密的报文则需要在密文的前后添加双引号
if (isDataEncrypted) {
signContent = "\"" + signContent + "\"";
}
try {
signCheckPass = AlipaySignature.rsaCheck(signContent, sign, signVeriKey, charset, signType);
} catch (AlipayApiException e) {
// 验签异常, 日志
}
if (!signCheckPass) {
//验签不通过(异常或者报文被篡改),终止流程(不需要做解密)
throw new Exception("验签失败");
}
//3. 解密
String plainData = null;
if (isDataEncrypted) {
try {
plainData = AlipayEncrypt.decryptContent(content, encryptType, decryptKey, charset);
} catch (AlipayApiException e) {
//解密异常, 记录日志
throw new Exception("解密异常");
}
} else {
plainData = content;
}
System.out.println("plainData:" + plainData);
return plainData;
}
}
获取用户信息不用解密,用户信息仅包含用户的昵称和头像。
页面
<button open-type="getAuthorize" scope="userInfo" @getAuthorize="getOpenUserInfo"> 会员基础信息授权 </button>
JS
getOpenUserInfo: function() {
my.getOpenUserInfo({
success: (res) => {
let userInfo = JSON.parse(res.response).response;
console.info("userInfo", userInfo);
},
fail: (err) => {
console.log(err)
}
});
},