登录

可以通过该流程获取用户的 openId、unionId 等信息

简要流程

开发者主要操作步骤:

  1. 开发者小程序通过 isHostLogin 判断用户是否登录,未登录时使用 appLogin 唤起登录页面并完成登录
  2. 开发者通过 getUserId 获取用户信息查询令牌
  3. 开发者通过后台效用小程序开放平台接口/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);
}
小程序团队 © 2020-2021 all right reserved,powered by Gitbook文件修订时间: 2026-01-05 11:12:01

results matching ""

    No results matching ""