卡券列表
通过该流程获取用户的卡券信息
简要流程
开发者主要操作步骤:
- 开发者小程序通过
isHostLogin判断用户是否登录,未登录时使用appLogin唤起登录页面并完成登录 - 开发者通过
getUserId获取用户信息查询令牌 - 开发者通过后台调用小程序开放平台接口
/api/developer/coupon/pageList拉取用户卡券列表
流程图如下所示:

详细步骤
1. 开发者小程序通过 isHostLogin 判断用户是否登录,未登录时使用 appLogin 唤起登录页面并完成登录
相关接口如下:
isHostLogin(OBJECT)
OBJECT参数说明:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | Function | 是 | 成功处理时的回调函数 |
| fail | Function | 是 | 处理失败时的回调函数 |
success返回参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| isHostLogin | String | 登录状态下成功时返回: 1 |
| msg | String | 登录状态下返回: 未登录 |
fail返回参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| isHostLogin | String | 登录状态下成功时返回: 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/coupon/pageList拉取用户卡券列表
这是一个 HTTPS 接口,开发者通过后台服务器 使用 查询令牌 从小程序开放平台换取卡券列表信息。
为了保证数据安全,开发者需要使用 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/coupon/pageList?access_token=C89B2C0D6A4D4262B17CD7DC1EC05E11&request_id=123451
生产地址
POST https://api.pingan.com.cn/open/mina-store/api/developer/coupon/pageList?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获取 | |
| businessNo | string | 否 | 商家编码,一般只有一个商户,不用传值;多商户时根据不同场景必须传对应的商家编码获取对应商户卡券列表。该值由平安配置提供 | |
| deviceId | string | 是 | 设备ID,获取途径同miniAppId | |
| identityCode | string | 是 | 一次性身份令牌, 有效时间 60 秒,从getUserId获取 | |
| mobileMd5 | string | 否 | 用户的手机号MD5值,和openId必须传一个 | |
| openId | string | 否 | 小程序openId,和mobileMd5必须传一个 | |
| productId | string | 否 | 提前约定,传值会根据商品编码过滤,不传值需要业务方对卡券进行过滤 | |
| couponStatus | List<String> | 否 | 卡券状态:默认查询未使用卡券;0-未使用 2-已使用 3-已过期 4-已回收 6-已冻结 7-未激活 10-已转赠 |
响应参数
| 名称 | 类型 | 备注 |
|---|---|---|
| responseCode | string | 默认0为成功 |
| responseMsg | string | 提示信息 |
| data | String | 业务数据(AES加密字符串) |
解密后结构
| 名称 | 类型 | 备注 |
|---|---|---|
| ├─ list | List | 卡券列表信息 |
| ├─ idProfitItem | string | 卡券实例ID |
| ├─ startTime | string | 卡券生效时间 |
| ├─ endTime | string | 卡券过期时间 |
| ├─ couponStatus | string | 卡券状态:0:未使用、2:已使用、3:已过期、 4:已收回、5:退兑换、6:已冻结 、7:未激活 |
| ├─ couponName | string | 卡券名称 |
| ├─ idCoupon | string | 卡券编码 |
| ├─ couponVersion | string | 卡券版本:0-旧版本,1-新版本 |
| ├─ couponSubType | string | 卡券子类型 |
| ├─ productList | List | 关联商品配置 |
| ├─ label | string | 商家流程编码 |
| ├─ productId | string | 平安商品id |
| ├─ standardProcessNo | string | 标准流程编码 |
| ├─ productName | string | 商品名称 |
| ├─ thirdPartyGoodsId | string | 第三方商品编码 |
| ├─ businessNo | string | 商家编码 |
| ├─ productCouponInfo | object | 优惠券信息 |
| ├─ couponNo | string | 优惠券编码 |
| ├─ couponName | string | 优惠券名称 |
| ├─ productTypeNo | string | 产品类型编码 |
| ├─ couponTypeNo | string | 优惠券类型编码 |
| ├─ deductType | string | 抵扣业务类型 |
| ├─ discountAmount | string | 优惠金额或者时长 |
| ├─ discountRuleAmount | string | 优惠规则大于等于xxx元时可以用 |
| ├─ discountAmountType | string | 优惠类型:1按小时,2按天 |
| ├─ productNo | String | 产品编码 |
| └─ isMutex | String | 是否互斥券 |
| └─ settlementPrice | BigDecimal | 结算价 |
| └─ encryptedProfitInfo | string | 卡券加密数据,使用卡券时将该字段根据接口 要求回传 |
| └─ total | string | 卡券总数量 |
调用示例
axios(
{
method: "post",
url: `https://api.pingan.com.cn/open/mina-store/api/developer/coupon/pageList`,
data: '', // 入参
headers: {} // 请求头
}
).then((res) => {
console.log("msgSend---sucess", res);
this.msgSendResult = JSON.stringify(res);
})
完整代码示例
示例代码(前端 vue):
示例代码(后端 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);
}
AES解密
/**
* 解密方法
* @param data 待解密数据
* @param key 密钥
* @return byte[] 解密数据
*/
public static String decrypt(
byte[] data, byte[] key
) throws IllegalBlockSizeException, BadPaddingException,
NoSuchPaddingException, NoSuchAlgorithmException,
UnsupportedEncodingException, InvalidAlgorithmParameterException, InvalidKeyException {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
// 初始化,设置解密模式
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(key));
// 执行操作
return new String(cipher.doFinal(data), "UTF-8");
}
/**
* 根据String 生成 密钥
* @param code 字符串
* @param keySize 密钥位数, 例如 128/192/256
* @return 二进制密钥
*/
public static byte[] getKey(String code, int keySize) {
int keyByteSize = keySize / 8;
byte[] aesBytes = new byte[keyByteSize];
System.arraycopy(code.getBytes(), 0, aesBytes, 0, keyByteSize);
SecretKeySpec aes = new SecretKeySpec(aesBytes, "AES");
return aes.getEncoded();
}
//解密用户数据( 对应 response.data.data 字段)
// 1. 根据 identityCode 生成 AES 密钥
byte[] aesKeyBytes = getKey(code, 128);
// 2. 解密用户信息(import org.apache.commons.codec.binary.Base64;)
String decryptedUserInfoBytes = decrypt(Base64.decodeBase64(encryptedUserInfo), aesKeyBytes);
返回示例(解密后)
{
"reqId": "17259378452890AC1WDM",
"responseCode": "0",
"data": "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"
}
返回示例(data解密后结构)
{
"totalCount": 1,
"couponList": [
{
"idProfitItem": "9BA7CFE2E47B428B8290A105B0174A13",
"idGiftItem": null,
"idProfitRedeem": null,
"startTime": "2024-08-27 00:00:00",
"endTime": "2024-11-25 23:59:59",
"couponStatus": "0",
"idCoupon": "704814000",
"couponName": "壹启优车全额服务券",
"couponSubType": "2-1",
"couponVersion": "1",
"productList": [
{
"productId": "D2024082200000327",
"label": "P_MINI_YQYC123",
"standardProcessNo": "P_MINI_YQYC",
"settlementPrice": 200,
"productCouponInfo": {
"couponNo": "PRC2024080100000865",
"couponName": "壹启优车全额服务券",
"productTypeNo": "HCZT2024080100000126",
"couponTypeNo": "CYQ000000001",
"deductType": "",
"discountAmount": "100",
"discountRuleAmount": "1",
"discountAmountType": "0",
"productNo": "",
"isMutex": "false"
}
}
],
"encryptedProfitInfo": "B43C6F5CCEDADC09FBA69C0D8E3DCE49DDB7CEE82DFD53856FF8C2CA5BDA28E3784CC18AB2EA632AFB428EE7E43FAC8B"
}
]
}