登录
可以通过该流程获取用户的 openId、unionId 等信息
简要流程
开发者主要操作步骤:
- 开发者小程序通过
isHostLogin判断用户是否登录,未登录时使用appLogin唤起登录页面并完成登录 - 开发者通过
getUserId获取用户信息查询令牌 - 开发者通过后台效用小程序开放平台接口
/api/developer/user/identityInfo换取用户 openId、unionId
流程图如下所示:

详细步骤
1. 开发者小程序通过 isHostLogin 判断用户是否登录,未登录时使用 appLogin 唤起登录页面并完成登录
相关接口如下:
isHostLogin(OBJECT)
OBJECT参数说明:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | Function | 是 | 成功处理时的回调函数 |
| fail | Function | 是 | 处理失败时的回调函数 |
success返回参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| isHostLogin | String | 登录状态下成功时返回: 1,未登录状态下返回:0 |
| msg | String | 登录状态下返回: 已经登录,未登录状态下返回:未登录 |
调用示例
PAMINA.call('isHostLogin', (res) => {
console.log(res);
}, (e) => {
console.log(e);
});
appLogin(OBJECT)
OBJECT参数说明:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | Function | 是 | 成功处理时的回调函数 |
| fail | Function | 是 | 处理失败时的回调函数 |
success返回参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| msg | String | 登录成功时返回: 登录成功 |
fail返回参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| msg | String | 登录未完成时返回: 登录失败 |
调用示例
appLoginFn() {
PAMINA.call('appLogin', (res) => {
console.log(res);
}, (e) => {
console.log(e);
});
},
2. 开发者通过 getUserId 获取用户信息查询令牌
相关接口如下:
getUserId(OBJECT)
OBJECT参数说明:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | Function | 是 | 成功处理时的回调函数 |
| fail | Function | 是 | 处理失败时的回调函数 |
success返回参数说明:
回参数据结构为 {"data":{"identityCode":"xxxx"}}, 需要取 data 数据, data 数据结构如下
| 参数 | 类型 | 说明 |
|---|---|---|
| identityCode | String | 查询令牌 |
fail返回参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| errCode | String | 异常编码 |
| msg | String | 异常信息 |
调用示例
PAMINA.call('getUserId', (res) => {
console.log(res);
}, (e) => {
console.log(e);
});
3. 开发者通过后台调用小程序开放平台接口/api/developer/user/identityInfo换取用户 openId、unionId
相关接口如下:
查询令牌兑换用户 openId 等信息
这是一个 HTTPS 接口,开发者通过后台服务器 使用 查询令牌 从小程序开放平台换取 openId 和 unionId 等信息。
为了保证数据安全,开发者需要使用 RSA 密钥进行身份认证,RSA 密钥可以从小程序开放平台如下入口获取: 开发中心 -> 你的小程序 -> 基础信息 -> 小程序密钥
在完成上线全部流程前只能通过测试环境接口方式联调,完成上线流程后需再切换为生产环境接口地址。其中调用测试接口联调时需要提供手机号和设备号给产险开发添加测试数据
令牌接口地址
在完成业务接口调用前需要调用访问令牌接口获取access_token,获取到的acess_token在调用业务接口是放到url后面。
测试地址
POST https://test-api.pingan.com.cn:20443/oauth/oauth2/access_token
生产地址
POST https://api.pingan.com.cn/oauth/oauth2/access_token
请求参数
具体入参值可找产险开发老师获取。
| 传值方式 | 参数值 | |
|---|---|---|
| client_id | POST 请求 | 应用ID 例如:P_PA002_ELIS_UWS(在“我的应用”列表中) |
| grant_type | POST 请求 | 授权类型 固定值:client_credentials |
| client_secret | POST 请求 | 应用密钥 例如:znD5x4d1(创建应用时返回的应用密码) |
响应参数
| access_token | oauth系统对获取access_token有调用限制,请将获取的token值放到本地缓存;注意token是有有效期的,当token失效时需要做相应处理。 |
|---|---|
| expires_in | 有效期 例如 :60 (单位:分钟);0表示永久有效;expires_in只是有效期参考,不以这个为唯一更新token的标准。注意调用接口返回13002和13012的错误码必须处理。 |
| openid | openid |
具体指引链接:https://api.pingan.com.cn/dev/index.do?bAPhdWDKZYpPM00
业务接口地址
request_id只要每个请求传的值不一样就可以,建议传时间戳毫秒数。
测试地址
POST https://test-api.pingan.com.cn:20443/open/mina-store/api/stg/developer/user/identityInfo?access_token=C89B2C0D6A4D4262B17CD7DC1EC05E11&request_id=123451
生产地址
POST https://api.pingan.com.cn/open/mina-store/api/developer/user/identityInfo?access_token=C89B2C0D6A4D4262B17CD7DC1EC05E11&request_id=123451
Headers
| 参数名称 | 参数值 | 是否必须 | 备注 |
|---|---|---|---|
| Content-Type | application/json | 是 | |
| X-MINA-MINI-APP-ID | 是 | 小程序ID | |
| X-MINA-TIMESTAMP | 是 | 请求时间(毫秒级) | |
| X-MINA-SIGN | 是 | 请求签名, 签名有效时间 60 秒, 采用 RSA 算法, 签名结果使用 Base64 进行编码;签名格式: RSA(requestBodyString + X-MINA-MINI-APP-ID + X-MINA-TIMESTAMP) |
请求参数
| 名称 | 类型 | 是否必须 | 默认值 | 备注 |
|---|---|---|---|---|
| miniAppId | string | 是 | 小程序ID,可从端能力getSystemInfo获取 | |
| deviceId | string | 是 | 设备ID,获取途径同miniAppId | |
| identityCode | string | 是 | 一次性身份令牌, 有效时间 60 秒,从getUserId获取 |
响应参数
| 名称 | 类型 | 是否必须 | 默认值 | 备注 |
|---|---|---|---|---|
| responseCode | string | 是 | 默认0为成功 | |
| responseMsg | string | 是 | 提示信息 | |
| data | object | 是 | 业务数据 | |
| ├─ openId | string | 是 | 当前 miniAppId 内 的 唯一用户ID | |
| ├─ unionId | string | 是 | 当前 miniAppId 对应商户内的 唯一用户ID | |
| ├─ userId | string | 是 | 当前宿主的登录用户ID,当且仅当小程序与APP同主体是返回 | |
| └─ clientNo | string | 是 | 一账通用户ID,当且仅当clientNo支持互认时返回 |
调用示例
axios(
{
method: "post",
url: `https://api.pingan.com.cn/open/mina-store/api/developer/user/identityInfo`,
data: '', // 入参
headers: {} // 请求头
}
).then((res) => {
console.log("msgSend---sucess", res);
this.msgSendResult = JSON.stringify(res);
})
完整代码示例
示例代码(前端 vue):
export default {
name: "login",
data() {
return {
getDeviceIDResult: '', // 设备ID
getUserIdResult '', // 设备用户ID
}
},
methods: {
// 判断当前是否登录
isHostLoginFn() {
PAMINA.call('isHostLogin', (res) => {
console.log(res);
}, (e) => {
console.log(e);
});
},
// 打开登录页,如果已经登录,该端能力返回登录成功信息
appLoginFn() {
PAMINA.call('appLogin', (res) => {
console.log(res)
this.getAppLoginResult = JSON.stringify(res)
}, (e) => {
console.log(e)
this.getAppLoginResult = JSON.stringify(e)
this.$toast(e.msg)
})
},
// 获取用户的ID信息
getUserId() {
PAMINA.call('getUserId', (res) => {
console.log(res)
this.getUserIdResult = res
// this.getUserIdentityInfo(res.data.identityCode)
}, (e) => {
console.log(e)
this.getUserIdResult = JSON.stringify(e)
this.$toast(e.msg)
})
},
// 获取是设备ID
getDeviceID() {
PAMINA.call('getSystemInfo', (res) => {
console.log('getSystemInfo-->',res)
this.getDeviceIDResult = res.deviceId
this.$toast(res.deviceId)
}, (e) => {
this.$toast(e.msg)
})
},
getUserIdentityInfo(code) {
if (this.getDeviceIDResult === '') {
this.$toast('请先获取设备ID');
return;
}
if (this.getUserIdResult.data === undefined) {
this.$toast('请先获取身份令牌');
return;
}
// code = 'ce1548c2b56243b2ab6ff21be8057537';
if (code === undefined) {
code = this.getUserIdResult.data.identityCode;
}
var now_timestamp = new Date().getTime();
var reqBody = JSON.stringify({
"miniAppId": "cxec128d79635042d7",
"identityCode": code.replace(/\s+/g, ""),
"deviceId": this.getDeviceIDResult
});
console.log('getUserIdentityInfo---reqBody:', reqBody);
let bodyJson = JSON.parse(reqBody);
let appId = bodyJson.miniAppId;
var signstr = reqBody + appId + now_timestamp;
console.log("signString : " + signstr);
let key ="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSj..."; // 秘钥
// let pubKeyBytes= CryptoJS.enc.Base64.parse(key);
console.log("getUserIdentityInfo---privateKey : " + key)
let sign = this.signRsa(key,signstr);
const header = {
"Content-Type": 'application/json',
"X-MINA-TIMESTAMP": now_timestamp,
"X-MINA-SIGN": sign,
"X-MINA-MINI-APP-ID": appId
};
console.log('getUserIdentityInfo---header:', header);
axios(
{
method: "post",
url: `https://api.pingan.com.cn/open/mina-store/api/developer/user/identityInfo`,
data: bodyJson,
headers: header
}
).then((res) => {
console.log("getUserIdentityInfo---sucess", res);
this.getUserOpenIdResult = res;
})
.catch((e) => {
console.log("getUserIdentityInfo---fail", e);
this.getUserOpenIdResult = e;
});
},
signRsa(encrypt_key, clearText){
console.info('cleartext: ' + clearText);
//注意此处上下的BEGIN PRIVATE KEY不要删除,框架自带的
const private_key = '-----BEGIN PRIVATE KEY-----\n'
+ encrypt_key
+ '\n-----END PRIVATE KEY-----';
// !!!请自行下载Forge加密js包引入
var privateKey = forge.pki.privateKeyFromPem(private_key);
// const md = forge.md.sha1.create();//这里的sha1对应的java的SHA1WithRSA
const md = forge.md.sha256.create();
md.update(clearText,"utf8");
let sig = privateKey.sign(md);
let erg = forge.util.encode64(sig);
console.log("Signature is: "+erg);
return erg;
},
}
}
示例代码(后端 java):生成签名
import org.apache.commons.codec.binary.Base64;
/**
* 生成签名
* @param base64PrivateKey base64格式的 RSA 私钥
* @param content 需要签名的内容
* @return 签名传
*/
public static String signBySHA256withRSA(String base64PrivateKey, String content) {
try {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(base64PrivateKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(content.getBytes());
return Base64.encodeBase64String(signature.sign());
} catch (Exception e) {
logger.error("SHA256withRSA is error:{}",e.getMessage());
}
return null;
}
public static void main(String[] args) {
// 请求的body
String requestBody="{\"miniAppId\":\"cxec681d79635042d7\",\"identityCode\":\"dn67tajk0fsx4aa\",\"deviceId\":\"h09e9fbeae0118d69872ed90c84feaea3\"}";
// 你的私钥, 从开放平台获取
String privateKey="yourRsaPrivateBy";
// 生成 rsa 签名
String base64Sign = signBySHA256withRSA(privateKey, content);
System.out.println(base64Sign);
}