技术对接方案适用于企业覆盖人数众多,且已拥有内部学习平台或内部系统,需要进行系统间账号对接。
此方案可解决学员以免登录的方式直接从企业「内部平台/系统」进入「轻学堂平台」学习内容。
开始对接之前,需要您的技术人员了解相关注意事项,具体流程参考下述说明文档。
普通登录和免登录方式差异
登录方式 | 登录入口 | 优势 | 不足 |
---|---|---|---|
手动登录 | 轻学堂app 轻学堂H5页面地址 轻学堂微信小程序 |
在轻学堂app和小程序上体验更好的效果,不会出现息屏停播的现象,轻学堂APP支持课程缓存到本地播放,内容还可以分享。 | 1、无法集成到用户系统内。 2、需要用户名密码登录学习。 3、客户需要下载轻学堂app客户端。 |
免登录 | 方案一:在客户app页面内创建免登录跳转到轻学堂H5主页面,课程详情页,课程专题,学习项目入口,采用OAuth2.0授权。 | 1、较灵活,支持免登陆跳转到轻学堂H5首页,单课程详情页,学习专题详情页,学习项目详情页)。 2、较安全,基于OAuth2.0协议标准授权登录(开发周期约为10人天)。 3、固定的入口地址,方便后续运营。 |
1、第三方开发量较大 2、不支持iframe内嵌方式。 3、息屏停播(已有处理方案,需客户方修改app处理) |
方案三:在客户app页面内创建免登录跳转到轻学堂H5主页面,课程详情页,课程专题,学习项目入口,采用轻学堂提供的第三方用户登录方式实现免登录跳转。 | 1、较灵活,方便后续运营需要,针对某个内容页面免登。 2、自主研发免等录方式,第三方开发量较小(开发周期约6人天)。 |
1、动态验证地址,除了用户信息外,校验参数一次性全部传输验证。 2、不支持iframe内嵌方式。 3、息屏停播(已有处理方案,需客户方修改app处理)。 4、不支持通过轻学堂页面内容分享链接免登。 |
一、手动登录方式
应用场景,首先访问轻学堂学员端登录地址,采用用户名(手机号或工号)+密码或验证码登录。
二、免登录方式
方案一,采用OAuth 2.0标准授权方式,允许用户授权第三方网站或应用,访问用户存储或授权使用在其它网站上的资源,而不需要将用户名和密码提供给第三方网站或分享他们数据的内容。优点,比较安全,灵活,可以处理某些特殊场景,如出于运营需要针对某个内容免登、分享免登,指定跳转页面(轻学堂主页,课程详情页等);缺点,第三方开发量相比方案三较长,约为10个工作日人天。
方案三,第三方账号快速登录,轻学堂提供的第三方用户登录接口直接实现账号打通。优点,较快捷,第三方开发量较小。动态验证地址,除了用户信息外,校验参数一次性全部传输验证,略有一定的风险。客户发量约为6个工作日人天。
三、用户数据集成
应用场景,客户方统一系统平台显示员工学习数据来自不同学习平台获取的相关信息数据,经过再次加工整合成客户想要的学习数据,方便运营管理,员工阶段性学习数据分析等目前通过轻学堂提供的API接口拉取的用户学习数据为当前时间-1天的数据(今天拉取昨天的用户学习数据)。
1.普通登录轻学堂学员端(H5,APP,小程序)页面及管理端页面流程

2.免登录接入轻学堂H5页面(适用客户APP端,H5系统平台端接入)

2.免登录接入轻学堂H5页面(适用客户APP端,H5系统平台端接入)

4.用户自定义页面显示轻学堂相关API接口数据

一、轻学堂H5对接方案
1.开发前必读
1)概述
阅读文档前,请贵企业学习平台或者渠道平台(后续简称第三方)开发者先明确和轻学堂H5进行对接的目的。对接的目的是基于第三方现有账号体系,进行账号打通,从而让第三方平台用户能够免登进入轻学堂H5,无需二次登录即可使用轻学堂系统。
基于这个目的,轻学堂目前提供了两种方案,分别是基于OAuth2.0协议标准的授权登录方案(后续简称方案一)和第三方账号快速登录方案(后续简称方案三,原方案二的升级版)。两种方案都可以实现上述目的,但有所差异,具体参照方案差异。第三方根据自身情况确认好对接方案后,就可以按照对应方案文档进行开发。
2)方案差异
目前提供了两种方案,分别是基于OAuth2.0协议标准的授权登录方案和第三方账号快速登录方案。两种方案差异如下:
方案 | 优点 | 缺点 |
---|---|---|
方案一 | 1.较灵活,可以处理某些特殊场景,如出于运营需要针对某个内容免登、分享免登 2.较安全,基于OAuth2.0协议标准授权登录 |
1.第三方开发量较大 2.需要开发授权页面 |
方案三 | 1.相对灵活,可以出于运营需要针对某个内容免登 2.较快捷,开发量适中 3.相对安全,可以处理方案一中第三方token无法定位用户场景 |
1. 不能实现通过轻学堂内容直接分享免登 2. 免登入口需提供获取用户信息的临时授权码 |
3)注意事项
关于接入方式
为了避免出现各种奇怪的兼容问题,禁止第三方使用iframe方式接入轻学堂H5。如果接入方为自有app或者小程序,可以直接使用webview来加载轻学堂h5;如果接入方也是h5比如微信公众号等,可以直接用location.href 链到轻学堂h5地址。请第三方务必遵守,对于仍然使用iframe方式接入而出现的兼容问题,轻学堂H5不会处理。
熄屏停播问题
纯H5对接会有熄屏停播的问题,并且熄屏状态下也不会续播下一个资源,这个问题在Android和IOS都存在,H5对接暂时没有解决办法,只有原生SDK方式的对接才能解决这个问题。
升级的方案三
原方案二保持不变,后续对接不在提供方案二。方案三为方案二的升级,后续对接仅支持方案一和方案三的对接
重要:TLS版本升级提醒
TLS(Transport Layer Security,安全传输层协议)是基于HTTPS下的一个加密协议。在安全和隐私方面,TLS 1.0和TLS 1.1版本的安全性能较低,并且存在漏洞,目前四大Web 浏览器厂商谷歌(Chrome)、Mozilla(Firefox)、微软(IE 11以上和Edge) 、苹果(Safari) 从2020年3月起,停止支持TLS 1.1及TLS 1.0版本安全协议。所以轻学堂从2022年6月1日起,停止支持TLS 1.1及TLS 1.0版本安全协议,仅支持TLS 1.2。截止到2022年5月31日为TLS版本升级过渡期,烦请各位客户尽快升级。
4)开始开发及调测
第三方对接方案评估确认后,就可以按文档要求进行开发,开发完成后可以联系轻学堂获取对接配置进行调测。由于轻学堂侧均为生产环境,调测时如果第三方需要区分不同环境,获取对接配置时务必主动说明情况,否则均按一套线上环境配置(测试数据会和线上数据在同一个企业内)。
2.基本概念介绍
OAuth2.0协议标准
OAuth2的设计背景,在于允许用户在不告知第三方自己的帐号密码情况下,通过授权方式,让第三方服务可以获取自己的资源信息。本文档使用的是OAuth2中的Authorization Code模式,默认静默授权。
详细的协议介绍,开发者可以参考RFC 6749。
关于appId和appSecret机制
appId是第三方唯一标识,appSecret是第三方密钥。目前均由轻学堂统一下发,第三方确认对接方案后联系轻学堂申请。
关于authCorpId机制
authCorpId是第三方企业唯一标识。轻学堂是多企业SaaS学习平台,需要通过authCorpId将第三方企业和轻学堂企业进行关联。每个第三方企业唯一对应一个轻学堂企业。
关于openId机制
openId是第三方企业用户唯一标识。每个第三方企业用户唯一对应一个轻学堂企业用户。对于同一个用户,第三方需要保证该用户openId在第三方企业下唯一。openId一般不超过50个字符,不支持中文。
关于轻学堂userId机制
轻学堂userId为轻学堂平台账号唯一标识,同一个用户在不同企业有相同的userId。
openId、userId和手机号mobile、工号empNo关系
手机号和工号会作为轻学堂登录账号。对于某个第三方企业(authCorpId)下的某个用户(openId),唯一对应一个轻学堂userId。如果该用户绑定了mobile或者empNo,轻学堂通过mobile或者authCorpId + empNo也能定位到userId,进而也能定位到openId。综上,对于某个第三方企业下的某个用户,openId、userId、mobile、empNo一一对应,如果出现不一致,系统会提示账号冲突。
3.H5对接方案
方案一:基于OAuth2.0协议标准的授权登录
时序图
具体而言,轻学堂OAuth2.0授权流程分为如下几步:
1.第三方用户从第三方平台进入轻学堂H5页面。
2.轻学堂H5引导用户进入第三方授权页面同意授权(静默授权,无需用户同意),获取code。
3.第三方授权页生成code后,重定向回轻学堂REDIRECT_URI。
4.轻学堂通过code换取第三方授权access_token。
5.若第三方为SaaS平台(多企业平台),轻学堂会通过auth_corpid获取第三方企业信息,进行企业自动创建和关联。
6.轻学堂通过第三方授权access_token和openid获取第三方用户基本信息。
7.轻学堂获取第三方用户信息后进行用户注册并登录轻学堂H5,实现免登。
其中步骤2、4、5、6均需第三方开发,其中5为可选,具体接口规范如下,第三方务必严格遵守
https://m.qingxuetang.com/partner/{APPID}?fromUri=xxx
参数 | 说明 |
---|---|
fromUri | 非必传,跳转到轻学堂目标页面地址,首页可不传,跳转书课等需传课程详情页、书籍详情页地址等,必须urlEncode |
检查未登录并重定向到步骤2
2. 轻学堂H5引导用户进入第三方授权页,进行静默授权(第三方合作企业提供)
大写的参数值为轻学堂传入
https://xxx/oauth2/authorize
?appid=APPID
&redirect_uri=REDIRECT_URI
&response_type=code
&state=轻学堂生成的state
参数 | 说明 |
---|---|
appid | 应用ID,由第三方和轻学堂沟通确认 |
redirect_uri | 重定向地址,由轻学堂构造地址时传入,第三方需要检查域名合法性 |
response_type | 当前默认都是code |
state | 用于保持请求和回调的状态,授权请求后原样带回给轻学堂 |
https://之前传入的REDIRECT_URI地址
?state=原state
&code=第三方对应的code
4. 轻学堂通过code换取第三方用户token(第三方合作企业提供)
接口样例
https://xxx/oauth2/access_token?appid=APPID&secret=APP_SECRET&code=CODE&grant_type=authorization_code
参数说明
参数 | 是否必须 | 说明 |
---|---|---|
appid | 是 | 应用唯一标识,由第三方和轻学堂沟通确认 |
secret | 是 | 应用密钥AppSecret,由第三方和轻学堂沟通确认 |
code | 是 | 上一步获取的code参数 |
grant_type | 是 | 填authorization_code |
返回示例规范
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"auth_corpid":"AUTH_CORPID"
}
参数说明
参数 | 说明 |
---|---|
access_token | 接口调用凭证 |
expires_in | access_token接口调用凭证超时时间,单位(秒) |
refresh_token | 用户刷新access_token |
openid | 授权用户唯一标识 |
auth_corpid | 授权用户所在公司标识 |
5. 轻学堂通过auth_corpid拿第三方企业信息(第三方合作企业提供,可选)
接口样例
https://xxx/oauth2/corpinfo?auth_corpid=AUTH_CORPID&appid=APPID&sign=SIGN
参数说明
参数 | 是否必须 | 说明 |
---|---|---|
appid | 是 | APPID |
auth_corpid | 是 | 授权用户所在企业标识 |
sign | 是 | 参数签名,计算方法参照计算参数签名相关 |
返回结果样例
{
"auth_corpid": "AUTH_CORPID",
"auth_corpname": "AUTH_CORPNAME",
"industry": "INDUSTRY",
"scale": "SCALE",
"admin_openid": "openid001",
"admin_mobile": "18766666666",
"admin_nickname": "张三"
}
参数说明
参数 | 说明 | 是否必须 |
---|---|---|
auth_corpid | 授权用户所在企业标识 | 必须 |
auth_corpname | 授权用户所在企业名称 | 必须 |
industry | 企业行业 | 可选 |
scale | 企业规模 | 可选 |
admin_openid | 企业主管理员openId | 可选,若需创建企业时自动添加管理员则必须 |
admin_mobile | 企业主管理员手机号 | 可选,若需创建企业时自动添加管理员则必须 |
admin_nickname | 企业主管理员昵称 | 可选,若需创建企业时自动添加管理员则必须 |
6. 轻学堂通过token拿第三方用户信息(第三方合作企业提供)
接口样例
https://xxx/oauth2/userinfo?openid=OPENID&access_token=ACCESS_TOKEN
参数说明
参数 | 是否必须 | 说明 |
---|---|---|
access_token | 是 | 调用接口凭证 |
openid | 是 | 普通用户标识 |
返回结果样例
xxxxxxxxxx
{
"auth_corpid": "AUTH_CORPID",
"openid":"OPENID",
"nickname":"NICKNAME",
"gender":1,
"avatar": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"username": "abc",
"mobile":"13812345678",
"empno":"emp001"
}
参数说明
参数 | 说明 | 是否必须 |
---|---|---|
auth_corpid | 授权用户所在企业标识 | 必须 |
openid | 授权用户唯一标识 | 必须 |
nickname | 用户昵称 | 必须 |
username | 用户名 | 可选 |
gender | 性别,1-男 2-女 | 可选 |
avatar | 用户头像 | 可选 |
mobile | 手机号 | 手机号和工号至少一个必传 |
empno | 工号 | 手机号和工号至少一个必传,企业可以自定义,但是企业内必须唯一 |
7.轻学堂获取第三方用户信息后进行用户注册并登录轻学堂H5,实现免登
关于API返回规范说明
对于接口正常返回对应数据即可,对于接口出现异常,返回格式如下
xxxxxxxxxx
{
"code": -1, //code非0即可
"msg": "" //msg为错误信息
}
方案三:第三方账号快速登录
xxxxxxxxxx
https://www.qingxuetang.com/passport/tp/v3/thirdLogin?appid=APP_ID&code=xxx×tamp=TIMESTAMP&nonce=NONCE&fromUri=xxx&signType=1&sign=SIGN
请求参数
参数名 | 类型 | 是否必须 | 说明 |
---|---|---|---|
appid | String | 是 | 应用ID,由第三方和轻学堂沟通确认 |
code | String | 是 | 获取用户信息临时授权码 |
timestamp | Long | 是 | 时间戳(ms),例如1579058675335 |
nonce | string | 是 | 随机字符串,对接方生成,每次调用不一样 |
fromUri | String | 否 | 跳转到轻学堂目标页面地址,首页可不传,跳转书课等需传课程详情页、书籍详情页地址等,必须urlEncode |
signType | int | 是 | 签名算法 1:MD5;2:HmacSHA1;3:SM3 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
2. 轻学堂通过code获取第三方用户信息(第三方合作企业提供)
接口样例
xxxxxxxxxx
https://xxx/tp/userinfo?code=xx&sign=SIGN
参数说明
参数 | 是否必须 | 说明 |
---|---|---|
code | 是 | 调用接口凭证 |
sign | 是 | 参数签名,计算方法参照计算参数签名相关 |
返回结果样例
x
{
"auth_corpid": "AUTH_CORPID",
"openid":"OPENID",
"nickname":"NICKNAME",
"gender":1,
"avatar": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"mobile":"13812345678",
"empno":"emp001"
}
参数说明
参数 | 说明 | 是否必须 |
---|---|---|
auth_corpid | 授权用户所在企业标识 | 必须 |
openid | 授权用户唯一标识 | 必须 |
nickname | 用户昵称 | 必须 |
gender | 性别,1-男 2-女 | 可选 |
avatar | 用户头像 | 可选 |
mobile | 手机号 | 手机号和工号至少一个必传 |
empno | 工号 | 手机号和工号至少一个必传,企业可以自定义,但是企业内必须唯一 |
3. 轻学堂通过auth_corpid拿第三方企业信息(第三方合作企业提供,可选)
接口样例
xxxxxxxxxx
https://xxx/tp/corpinfo?auth_corpid=AUTH_CORPID&appid=APPID&sign=SIGN
参数说明
参数 | 是否必须 | 说明 |
---|---|---|
appid | 是 | APPID |
auth_corpid | 是 | 授权用户所在企业标识 |
sign | 是 | 参数签名,计算方法参照计算参数签名相关 |
返回结果样例
xxxxxxxxxx
{
"auth_corpid": "AUTH_CORPID",
"auth_corpname": "AUTH_CORPNAME",
"industry": "INDUSTRY",
"scale": "SCALE",
"admin_openid": "openid001",
"admin_mobile": "18766666666",
"admin_nickname": "张三"
}
参数说明
参数 | 说明 | 是否必须 |
---|---|---|
auth_corpid | 授权用户所在企业标识 | 必须 |
auth_corpname | 授权用户所在企业名称 | 必须 |
industry | 企业行业 | 可选 |
scale | 企业规模 | 可选 |
admin_openid | 企业主管理员openId | 可选,若需创建企业时自动添加管理员则必须 |
admin_mobile | 企业主管理员手机号 | 可选,若需创建企业时自动添加管理员则必须 |
admin_nickname | 企业主管理员昵称 | 可选,若需创建企业时自动添加管理员则必须 |
二、轻学堂微信小程序对接方案
1.开发前必读
1)概述
以下小程序即表示微信小程序
阅读文档前,请贵企业学习平台或者渠道平台(后续简称第三方)开发者先明确和轻学堂小程序进行对接的目的。对接的目的是基于第三方现有账号体系,进行账号打通,从而让第三方平台用户能够免登从第三方小程序进入轻学堂小程序,无需二次登录即可使用轻学堂系统。
2)已按H5方案对接的客户
对于已经对接了轻学堂H5的用户,仍然可以在原有的对接平台上进行小程序的对接,实现第三方小程序跳转轻学堂小程序,沿用原来的账号体系,第三方用户的账户在轻学堂是统一的。
3)开始开发及调测
第三方对接方案评估确认后,就可以按文档要求进行开发,开发完成后可以联系轻学堂获取对接配置进行调测。由于轻学堂侧均为生产环境,调测时如果第三方需要区分不同环境,获取对接配置时务必主动说明情况,否则均按一套线上环境配置(测试数据会和线上数据在同一个企业内)。
2.基本概念介绍
关于appId和appSecret机制
appId是第三方唯一标识,appSecret是第三方密钥。目前均由轻学堂统一下发,第三方确认对接方案后联系轻学堂申请。
关于authCorpId机制
authCorpId是第三方企业唯一标识。轻学堂是多企业SaaS学习平台,需要通过authCorpId将第三方企业和轻学堂企业进行关联。每个第三方企业唯一对应一个轻学堂企业。
关于openId机制
openId是第三方企业用户唯一标识。每个第三方企业用户唯一对应一个轻学堂企业用户。对于同一个用户,第三方需要保证该用户openId在第三方企业下唯一。openId一般不超过50个字符,不支持中文。
关于轻学堂userId机制
轻学堂userId为轻学堂平台账号唯一标识,同一个用户在不同企业有相同的userId。
openId、userId和手机号mobile、工号empNo关系
手机号和工号会作为轻学堂登录账号。对于某个第三方企业(authCorpId)下的某个用户(openId),唯一对应一个轻学堂userId。如果该用户绑定了mobile或者empNo,轻学堂通过mobile或者authCorpId + empNo也能定位到userId,进而也能定位到openId。综上,对于某个第三方企业下的某个用户,openId、userId、mobile、empNo一一对应,如果出现不一致,系统会提示账号冲突。
3.小程序对接方案
第三方小程序跳转轻学堂小程序首页,第三方通过微信提供的小程序跳转开放接口wx.navigateToMiniProgram(Object object)进行第三方账号快速登录,实现账号打通。进行调测前除了需要appId和appSecret之外,还需要配置第三方企业关联,因此需要第三方开发者按下述流程提供对应调试环境的企业代码。
1.如果第三方开发者已注册过轻学堂企业,可直接登录轻学堂企业后台获取企业代码。
2.如果第三方开发者未注册过轻学堂企业,则需要第三方开发者先自行注册一个轻学堂企业,注册成功后登陆轻学堂企业后台获取企业代码。
注:
1.企业代码可以在轻学堂企业后台 - 【设置】 - 【企业信息】 - 【企业代码】处获取
2.轻学堂侧均为生产环境,但可以通过企业代码进行区分。如果第三方需要区分不同环境,可以针对不同环境提供不同的企业代码即可。
wx.navigateToMiniProgram(Object object)接口官方文档地址:
https://developers.weixin.qq.com/miniprogram/dev/api/navigate/wx.navigateToMiniProgram.html
注意微信官方文档中的使用限制
跳转接口Object参数
参数名 | 类型 | 是否必须 | 说明 |
---|---|---|---|
appId | String | 是 | 要打开的小程序 appId,固定参数:wxb3008eeb1a07e34c |
path | String | 是 | 打开的页面路径,固定参数:/pages/login/third/third |
extraData | object | 是 | 第三方用户相关信息,下面会有详细参数介绍 |
extraData参数
参数名 | 类型 | 是否必须 | 说明 |
---|---|---|---|
appId | String | 是 | 第三方平台appId,轻学堂在对接前会提供给第三方 |
authCorpId | String | 是 | 企业标识 |
openId | String | 是 | 用户标识 |
nickname | String | 否 | 用户昵称,若传入该参数,nickname将作为轻学堂用户名称,若未传该参数的话,系统将会生成一串随机字符串作为轻学堂用户名称。请求时该参数需要进行URL编码(编码字符集为UTF-8)。 |
gender | Integer | 否 | 性别,1-男 2-女 |
mobile | String | 否 | 手机号,仅openId首次登录时会补充手机号信息 |
empNo | String | 否 | 工号,仅openId首次登录时会补充工号信息。请求时该参数需要进行URL编码(编码字符集为UTF-8)。 |
timestamp | Long | 是 | 时间戳,例如1579058675335 |
nonce | string | 是 | 随机字符串,对接方生成,每次调用不一样 |
signType | int | 是 | 签名算法 1:MD5;2:HmacSHA1;3:SM3,如果不传默认使用MD5算法 |
sign | String | 是 | 参数签名,只对extraData中参数进行计算,计算方法参照计算参数签名相关 |
请求示例
xxxxxxxxxx
wx.navigateToMiniProgram({
appId: 'wxb3008eeb1a07e34c',
path: '/pages/login/third/third',
extraData: {
"appId":"wxb3008eeb1a08e66",
"authCorpId":"p174",
"openId":"qxt001",
"nickname":"lilei",
"timestamp":1618979389737,
"nonce":"1618979389737",
"signType":1,
"sign":"233085FAEB123BAB955F51B12139EDC9"
}
})
响应结果
- 对于已配置的authCorpId下的openId会进行自动注册并登录,登录成功之后自动重定向到首页。
三、会员相关接口
1. 第三方用户会员开通接口
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/vip/v2/batchDispatchCard
请求方式
POST
请求参数
参数全部放在请求体body中,且Content-Type
请求头设置为application/x-www-form-urlencoded; charset=UTF-8
参数名 | 类型 | 是否必填 | 说明 |
---|---|---|---|
appId | String | 是 | APP_ID |
authCorpId | String | 是 | 企业标识 |
cardType | int | 是 | 会员类型 1-年卡 5-季卡 4-月卡 |
partnerUsers | JSONArray | 是 | 待开通会员的用户信息,每次开通个数限制100条;已存在用户的用户信息不会改变 样式如下: [ { "openId":"khkghkgh", "nickName":"张三", "gender":1 }, { "openId":"khkssshkgh", "nickName":"李四", "gender":1 } ] 参数说明: openId:用户标识,必填; nickName:用户昵称,选填,不传则为轻学堂生成随机昵称 gender:用户性别,选填,0未知,1男,2女 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": {
"khkghkgh": {
"beginTime": 1565344893559,
"expireTime": 1596880893561,
"status": 1,
"orderCode": "zQFCD9kkf3A"
}
}
}
响应说明
返回数据以openId为key,value格式如下:
字段 | 类型 | 说明 |
---|---|---|
beginTime | long | 生效时间 |
expireTime | long | 过期时间 |
status | int | 状态: 1-正常 status>1均为异常情况,7为订单处理中 |
orderCode | String | 会员分配订单编号 |
2. 获取用户会员信息
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/vip/getVipInfo
请求方式
POST
请求参数
参数全部放在请求体body中,且Content-Type
请求头设置为application/x-www-form-urlencoded; charset=UTF-8
参数名 | 类型 | 是否必填 | 说明 |
---|---|---|---|
appId | String | 是 | APP_ID |
authCorpId | String | 是 | 企业标识 |
openId | String | 是 | 用户标识 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
1.未开通
{
"ret": 0,
"msg": "操作成功",
"data": {
"status": 0
}
}
2.开通
{
"ret": 0,
"msg": "操作成功",
"data": {
"beginTime": 1565344893559,
"expireTime": 1596880893561,
"status": 1
}
}
响应说明
字段 | 类型 | 说明 |
---|---|---|
beginTime | long | 生效时间 |
expireTime | long | 过期时间 |
status | Int | 状态:0-未开通 1-正常 status>1均为异常情况 |
3. 获取企业会员账号信息
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/vip/getCorpVipAccount
请求方式
POST
请求参数
参数全部放在请求体body中,且Content-Type
请求头设置为application/x-www-form-urlencoded; charset=UTF-8
参数名 | 类型 | 是否必填 | 说明 |
---|---|---|---|
appId | String | 是 | APP_ID |
authCorpId | String | 是 | 企业标识 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": {
"1": { //年卡
"totalCount": 0,
"leftCount": 0
},
"4": { //月卡
"totalCount": 233,
"leftCount": 218
},
"5": { //季卡
"totalCount": 10,
"leftCount": 10
}
}
}
响应说明
返回数据key为会员卡类型,1-年卡 5-季卡 4-月卡,value格式说明如下
字段 | 类型 | 说明 |
---|---|---|
totalCount | int | 总数 |
leftCount | int | 剩余数量 |
四、兑换码相关接口
第三方调用完兑换码兑换接口之后,接口会同步返回兑换的用户会员权益相关信息。由于轻学堂后台是异步处理,且目前没有主动推送兑换码兑换成功消息,可能因网络等异常收不到响应导致双方系统数据不一致。
为了尽量保证整个兑换流程双方系统数据一致性,增加了通过兑换码查询兑换码状态接口,第三方可以通过轮询该接口查询兑换码状态,当兑换成功之后,同步变更该兑换码状态。一般来说兑换流程不会太长,第三方可以合理设置重试间隔和次数,超过指定阈值兑换码仍未兑换成功按兑换失败处理。
1. 兑换码兑换接口
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/coupon/exchange
请求方式
POST
请求参数
参数全部放在请求体body中,且Content-Type
请求头设置为application/x-www-form-urlencoded; charset=UTF-8
参数名 | 类型 | 是否必填 | 说明 |
---|---|---|---|
appId | String | 是 | APP_ID |
authCorpId | String | 是 | 企业标识 |
openId | String | 是 | 第三方用户标识 |
couponNo | String | 是 | 兑换码 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": {
"beginTime": 1565344181443,
"expireTime": 1596880181471,
"status": 1
}
}
响应说明
字段 | 类型 | 说明 |
---|---|---|
beginTime | long | 生效时间 |
expireTime | long | 过期时间 |
status | 状态 | 1-正常 status>1均为异常情况 |
2. 通过兑换码查询兑换码状态
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/coupon/couponStatus
请求方式
POST
请求参数
参数全部放在请求体body中,且Content-Type
请求头设置为application/x-www-form-urlencoded; charset=UTF-8
参数名 | 类型 | 是否必填 | 说明 |
---|---|---|---|
appId | String | 是 | APP_ID |
authCorpId | String | 是 | 企业标识 |
couponNo | String | 是 | 兑换码 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": {
"couponStatus": 1,
"openId": "o001"
}
}
响应说明
字段 | 类型 | 说明 |
---|---|---|
couponStatus | Integer | 兑换码状态 1-兑换成功 2-兑换中 3-兑换失败 4-未知 |
openId | String | 所属第三方用户标识,可能为空 |
五、学习数据相关接口
-
接口有相关频次限制,每次获取数量限制100条。
-
目前提供以下五个接口,前两个接口是分页获取全体员工或指定一批员工的学习概况,提供以下几个员工维度学习数据:
字段 说明 studyTime 学习时长,单位秒,能根据时间范围查询。 learntCourseCount 已学课程数,能根据时间范围查询。 totalLearntCourseCount 总的已学课程数,对于不同时间范围值相同。 totalFinishedCourseCount 总的已学完课程数,对于不同时间范围值相同。 learntBookCount 已学书籍数,能根据时间范围查询。 totalLearntBookCount 总的已学书籍数,对于不同时间范围值相同。 totalFinishedBookCount 总的已完成书籍数,对于不同时间范围值相同。 totalPoint 总学分,保留一位有效数字,比如5.0 第三个接口是获取某个员工已学课程列表,支持按日期维度筛选,提供以下几个课程维度数据:
字段 类型 说明 courseCode String 课程编号 courseTitle String 课程标题 courseSubTitle String 课程子标题 courseCover String 课程封面图 courseStudyTime int 课程指定时间段学习时长(单位秒) courseTotalStudyTime int 课程总学习时长(单位秒) courseStartLearningTime long 课程开始学习时间,时间戳(ms) progress int 课程学习进度% linkUrl String 轻学堂H5页面链接地址 duration int 课程总时长(单位:秒) finishTime long 课程已学完时间,时间戳(ms)。
备注:只有在2021年6月29日之后学完的课程会有该数据第四个接口是获取某个员工已学书籍列表,支持按日期维度筛选,提供以下几个书籍维度数据:
字段 类型 说明 bookCode String 书籍编号(注:不同bookType可能有相同的bookCode) bookType int 书籍类型 2-单课书籍 3-多课书籍 bookTitle String 书籍标题 bookSubTitle String 书籍子标题 bookCover String 书籍封面图 bookStudyTime int 书籍指定时间段学习时长(单位秒) bookTotalStudyTime int 书籍总学习时长(单位秒) bookStartLearningTime long 书籍开始学习时间,时间戳(ms) progress int 书籍学习进度% linkUrl String 轻学堂H5页面链接地址 duration int 书籍总时长(单位:秒) finishTime long 书籍已学完时间,时间戳(ms)。
备注:只有在2021年6月29日之后学完的书籍会有该数据第五个接口是获取用户学习记录列表,包含课程和书籍
type=1为课程,type=2为书籍
课程Course
字段 类型 说明 courseCode string 课程唯一标识 mediaType int 课程类型 1-音频 2-视频 courseTitle string 课程标题 courseSubTitle string 课程副标题 courseCover string 课程封面图 category string 课程分类 lecturerName string 讲师姓名 lecturerAvatar string 讲师头像 lecturerIntro string 讲师简介/头衔 totalCount int 总课时数 linkUrl string 轻学堂H5页面链接地址 latestUpdateTime long 上一次更新时间戳 updateCount int 当前更新课时数 hasFinished int 是否已完结 1/0 lastPlay JSONObject 上一次播放课时 lastPlay.title String 上一次播放课时标题 progress int 学习进度% recordTime long 记录时间 duration int 课程总时长(单位:秒) finishTime long 课程已学完时间,时间戳(ms)。
备注:只有在2021年6月29日之后学完的课程会有该数据书籍Book
字段 类型 说明 bookCode string 书籍唯一标识(注:不同bookType可能有相同的bookCode) bookType int 书籍类型 2-单课书籍 3-多课书籍 bookTitle string 书籍标题 bookSubTitle string 书籍副标题 bookCover string 书籍封面图 category string 书籍分类 bookAuthor string 书籍作者 lecturerName string 讲师姓名 lecturerAvatar string 讲师头像 lecturerIntro string 讲师简介/头衔 duration int 书籍总时长(单位:秒) linkUrl string 轻学堂H5页面链接地址 latestUpdateTime long 上一次更新时间戳 progress int 书籍学习进度% finishTime long 书籍已学完时间,时间戳(ms)。
备注:只有在2021年6月29日之后学完的书籍会有该数据
1. 分批获取员工学习数据
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/corpData/getStatData
请求方式
POST
请求参数
参数全部放在请求体body中,且Content-Type
请求头设置为application/x-www-form-urlencoded; charset=UTF-8
参数 | 类型 | 是否必须 | 默认值 | 说明 |
---|---|---|---|---|
appId | String | 是 | APP_ID | |
authCorpId | String | 是 | 企业标识 | |
startDate | String | 否 | 开始日期,若不限开始日期该参数不传,格式2019-03-10 | |
endDate | String | 否 | 结束日期,若不限结束日期该参数不传,格式2019-03-13 | |
offset | int | 否 | 0 | 分页参数,偏移量,指从第几条开始获取。 比如count=10时, 第1页offset=0&count=10, 第2页offset=10&count=10, 第3页offset=20&count=10,以此类推。 |
count | int | 否 | 20 | 分页参数,获取数量 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": {
"totalCount": 70,
"dataList": [
{
"uidCode": "aaa1",
"openId": "gN4IhtljzZ",
"studyTime": 0,
"learntCourseCount": 0,
"totalLearntCourseCount": 0,
"totalFinishedCourseCount": 0,
"learntBookCount": 0,
"totalLearntBookCount": 1,
"totalFinishedBookCount": 1
}
]
}
}
2. 分批获取指定员工列表学习数据
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/corpData/getStatDataByOpenIds
请求方式
POST
请求参数
参数全部放在请求体body中,且Content-Type
请求头设置为application/x-www-form-urlencoded; charset=UTF-8
参数 | 类型 | 是否必须 | 默认值 | 说明 |
---|---|---|---|---|
appId | String | 是 | APP_ID | |
authCorpId | String | 是 | 企业标识 | |
startDate | String | 否 | 开始日期,若不限开始日期该参数不传,格式2019-03-10 | |
endDate | String | 否 | 结束日期,若不限结束日期该参数不传,格式2019-03-13 | |
openIds | JSONArray String | 是 | 待获取学习数据的用户标识列表,如["openId001", "openId002"] | |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": [
{
"uidCode": "aaa1",
"openId": "open001",
"studyTime": 1000,
"learntCourseCount": 10,
"totalLearntCourseCount": 20,
"totalFinishedCourseCount": 5,
"learntBookCount": 0,
"totalLearntBookCount": 1,
"totalFinishedBookCount": 1
},
{
"uidCode": "aaa2",
"openId": "open002",
"studyTime": 2000,
"learntCourseCount": 10,
"totalLearntCourseCount": 20,
"totalFinishedCourseCount": 5,
"learntBookCount": 0,
"totalLearntBookCount": 1,
"totalFinishedBookCount": 1
}
]
}
3. 获取员工已学课程列表
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/corpData/getUserLearntCourses
请求方式
POST
请求参数
参数全部放在请求体body中,且Content-Type
请求头设置为application/x-www-form-urlencoded; charset=UTF-8
参数 | 类型 | 是否必须 | 默认值 | 说明 |
---|---|---|---|---|
appId | String | 是 | APP_ID | |
authCorpId | String | 是 | 企业标识 | |
openId | String | 是 | 用户标识 | |
startDate | String | 否 | 开始日期,若不限开始日期该参数不传,格式2019-03-10 | |
endDate | String | 否 | 结束日期,若不限结束日期该参数不传,格式2019-03-13 | |
offset | int | 否 | 0 | 分页参数,偏移量,指从第几条开始获取。 比如count=10时, 第1页offset=0&count=10, 第2页offset=10&count=10, 第3页offset=20&count=10,以此类推。 |
count | int | 否 | 20 | 分页参数,获取数量 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": {
"totalCount": 16,
"dataList": [
{
"courseCode": "RJ1ZABxd_S0",
"courseTitle": "星星之火",
"courseSubTitle": "可以燎原",
"courseCover": "http://imagev2.test.ximalaya.com:8080/group1/M00/58/27/wKgDplya8IyAMPR5AABSkSwfzXc26.jpeg!op_type=0",
"courseStudyTime": 90,
"courseTotalStudyTime": 120,
"progress": 100,
"duration": 90,
"courseStartLearningTime": 1553678663000,
"linkUrl": "https://m.test.qingxuetang.com/x/course/RJ1ZABxd_S0?appId=qxtcorp666",
"finishTime": 1596094596081
}
]
}
}
4. 获取员工已学书籍列表
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/corpData/getUserLearntBooks
请求方式
POST
请求参数
参数全部放在请求体body中,且Content-Type
请求头设置为application/x-www-form-urlencoded; charset=UTF-8
参数 | 类型 | 是否必须 | 默认值 | 说明 |
---|---|---|---|---|
appId | String | 是 | APP_ID | |
authCorpId | String | 是 | 企业标识 | |
openId | String | 是 | 用户标识 | |
startDate | String | 否 | 开始日期,若不限开始日期该参数不传,格式2019-03-10 | |
endDate | String | 否 | 结束日期,若不限结束日期该参数不传,格式2019-03-13 | |
offset | int | 否 | 0 | 分页参数,偏移量,指从第几条开始获取。 比如count=10时, 第1页offset=0&count=10, 第2页offset=10&count=10, 第3页offset=20&count=10,以此类推。 |
count | int | 否 | 20 | 分页参数,获取数量 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": {
"totalCount": 16,
"dataList": [
{
"bookCode": "RJ1ZABxd_S0",
"bookType": 2,
"bookTitle": "星星之火",
"bookSubTitle": "可以燎原",
"bookCover": "http://imagev2.test.ximalaya.com:8080/group1/M00/58/27/wKgDplya8IyAMPR5AABSkSwfzXc26.jpeg!op_type=0",
"bookStudyTime": 20,
"bookTotalStudyTime": 120,
"progress": 50,
"duration": 180,
"bookStartLearningTime": 1553678663000,
"linkUrl": "https://m.test.qingxuetang.com/x/book/TDoIozg3hFk?appId=qxtcorp666"
}
]
}
}
5. 获取用户学习记录
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/corpData/getUserPlayRecord
请求方式
POST
请求参数
参数全部放在请求体body中,且Content-Type
请求头设置为application/x-www-form-urlencoded; charset=UTF-8
参数 | 类型 | 是否必须 | 默认值 | 说明 |
---|---|---|---|---|
appId | String | 是 | APP_ID | |
authCorpId | String | 是 | 企业标识 | |
openId | String | 是 | 用户标识 | |
offset | int | 否 | 0 | 分页参数,偏移量,指从第几条开始获取。 比如count=10时, 第1页offset=0&count=10, 第2页offset=10&count=10, 第3页offset=20&count=10,以此类推。 |
count | int | 否 | 20 | 分页参数,获取数量 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": {
"totalCount": 2,
"dataList": [
{
"type": 2,
"item": {
"bookCode": "bOrMXay7DVE",
"bookType": 3,
"bookTitle": "7-29有声书1",
"bookSubTitle": "彩虹啊好帅的口感哈款节省空间蛋",
"bookCover": "http://imagev2.test.ximalaya.com:8080/group1/M01/98/05/wKgDpl8g5DuATOS6AAF_gmiIJDs819.jpg!op_type=0",
"category": "回归分类",
"lecturerName": "一飞",
"lecturerAvatar": "",
"lecturerIntro": "企业版设计师",
"linkUrl": "https://m.test.qingxuetang.com/x/course/bOrMXay7DVE?appId=xmlycorp929666",
"latestUpdateTime": 1596522369000,
"progress": 73,
"duration": 180,
"recordTime": 1596094596081
}
},
{
"type": 1,
"item": {
"courseCode": "EoGMZmfJV4o",
"mediaType": 1,
"courseTitle": "单卖+会员课程音频回归",
"courseSubTitle": "副标题",
"courseCover": "http://imagev2.test.ximalaya.com:8080/group1/M01/26/EC/wKgD3l3U-H2Afl6PAAIh3UllRhw73.jpeg!op_type=0",
"category": "经济",
"lecturerName": "帮主qu",
"lecturerAvatar": "http://imagev2.test.ximalaya.com:8080/group1/M00/20/60/wKgD3l14aiCAO9zRAABeg7qM1Jo27.jpeg",
"lecturerIntro": "轻学堂讲师",
"totalCount": 1,
"linkUrl": "https://m.test.qingxuetang.com/x/course/EoGMZmfJV4o?appId=xmlycorp929666",
"latestUpdateTime": 1576570262000,
"updateCount": 1,
"hasFinished": 1,
"lastPlay": {
"lessonCode": "qknGYvRfu6I",
"title": "课时1"
},
"progress": 100,
"duration": 180,
"recordTime": 1596094596081,
"finishTime": 1596094596081
}
}
]
}
}
6. 获取指定日期的学习人员openId列表
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/corpData/getLearners
请求方式
POST
请求参数
参数全部放在请求体body中,且Content-Type
请求头设置为application/x-www-form-urlencoded; charset=UTF-8
参数 | 类型 | 是否必须 | 默认值 | 说明 |
---|---|---|---|---|
appId | String | 是 | APP_ID | |
authCorpId | String | 是 | 企业标识 | |
date | String | 是 | 指定日期,格式2019-03-09,仅可获取今日之前的数据,如今日为2021-08-09,则所传参数date必须为2021-08-09之前的日期 | |
offset | int | 否 | 0 | 分页参数,偏移量,指从第几条开始获取。 比如count=10时, 第1页offset=0&count=10, 第2页offset=10&count=10, 第3页offset=20&count=10,以此类推。 |
count | int | 否 | 20 | 分页参数,获取数量 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": {
"totalCount": 3,
"dataList": [
"open001", //已学用户openId
"open002",
"open003"
]
}
}
六、内容相关接口
-
每次获取数量限制200条
-
内容目前分课程(Course)和书籍(Book),其中课程分会员精品课和免费课
-
书、课的分类最多为两级,若书课在一级分类中,则不会返回父级分类相关字段
课程Course
字段 类型 说明 courseCode string 课程唯一标识 mediaType int 课程类型 1-音频 2-视频 courseTitle string 课程标题 courseSubTitle string 课程副标题 courseCover string 课程封面图 categoryId Integer 课程分类Id category string 课程分类 parentCategoryId Integer 课程分类的父级分类Id(没有父级分类则不返回) parentCategory string 课程分类的父级分类(没有父级分类则不返回) lecturerName string 讲师姓名 lecturerAvatar string 讲师头像 lecturerIntro string 讲师简介/头衔 totalCount int 总课时数 linkUrl string 轻学堂H5页面链接地址 latestUpdateTime long 上一次更新时间戳 updateCount int 当前更新课时数 hasFinished int 是否已完结 1/0 duration int 课程总时长(单位:秒) 书籍Book
字段 类型 说明 bookCode string 书籍id编码(注:不同bookType可能有相同的bookCode,所以需要bookType+bookCode确认唯一性) bookType int 书籍类型 2-单课书籍 3-多课书籍 bookTitle string 书籍标题 bookSubTitle string 书籍副标题 bookCover string 书籍封面图 categoryId Integer 书籍分类Id category string 书籍分类 parentCategoryId Integer 书籍分类的父级分类Id(没有父级分类则不返回) parentCategory string 书籍分类的父级分类(没有父级分类则不返回) bookAuthor string 书籍作者 lecturerName string 讲师姓名 lecturerAvatar string 讲师头像 lecturerIntro string 讲师简介/头衔 duration int 书籍总时长(单位:秒) linkUrl string 轻学堂H5页面链接地址 latestUpdateTime long 上一次更新时间戳 totalCount int 总课时数,多课书籍会返回 updateCount int 当前更新课时数,多课书籍会返回 hasFinished int 是否已完结 1/0,多课书籍会返回
1. 分批获取精品课列表
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/content/getVipCourses
请求方式
GET
请求参数
参数 | 类型 | 是否必须 | 默认值 | 说明 |
---|---|---|---|---|
appId | String | 是 | APP_ID | |
offset | int | 否 | 0 | 分页参数,偏移量,指从第几条开始获取。 比如count=10时, 第1页offset=0&count=10, 第2页offset=10&count=10, 第3页offset=20&count=10,以此类推。 |
count | int | 否 | 20 | 分页参数,获取数量 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": {
"totalCount": 1,
"dataList": [
{
"courseCode": "DSJVExq33IQ",
"mediaType": 2,
"courseTitle": "结构化写作",
"courseSubTitle": "写作更轻松,观点更有力",
"courseCover": "http://imagev2.xmcdn.com/group60/M01/14/7E/wKgLb1zGbsriC-GFAAiGLdsksS8063.png!op_type=0",
"categoryId": 341,
"category": "领导力",
"parentCategoryId": 2,
"parentCategory": "管理类",
"lecturer": "李忠秋",
"lecturerAvatar": "http://imagev2.xmcdn.com/group58/M0A/7A/A1/wKgLc1y-qiPAnVuIAA5gSQn63tk387.png",
"lecturerIntro": "《结构思考力》作者",
"totalCount": 18,
"duration": 180,
"linkUrl": "https://m.qingxuetang.com/x/course/DSJVExq33IQ?appId=qxtcorp666",
"latestUpdateTime": 1565078222000,
"updateCount": 3,
"hasFinished": 0
}
]
}
}
2. 分批获取书籍列表
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/content/getBooks
请求方式
GET
请求参数
参数 | 类型 | 是否必须 | 默认值 | 说明 |
---|---|---|---|---|
appId | String | 是 | APP_ID | |
offset | int | 否 | 0 | 分页参数,偏移量,指从第几条开始获取。 比如count=10时, 第1页offset=0&count=10, 第2页offset=10&count=10, 第3页offset=20&count=10,以此类推。 |
count | int | 否 | 20 | 分页参数,获取数量 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": {
"totalCount": 1,
"dataList": [
{
"bookCode": "A3h0IrK21OA",
"bookType": 2,
"bookTitle": "睡眠革命",
"bookSubTitle": "小贝、C罗的睡眠教练教你提高睡眠质量",
"bookCover": "http://imagev2.xmcdn.com/group59/M02/A2/1A/wKgLely0KinApb1xAAKxn9yrSkg929.png!op_type=0",
"categoryId": 326,
"category": "影响力",
"parentCategoryId": 3,
"parentCategory": "个人提升",
"bookAuthor": "尼特·利特尔黑尔斯",
"lecturer": "郑佳雯",
"lecturerAvatar": "http://imagev2.xmcdn.com/group58/M0A/7A/A1/wKgLc1y-qiPAnVuIAA5gSQn63tk387.png",
"lecturerIntro": "美国威斯康星大学麦迪逊分校博士",
"duration": 18,
"linkUrl": "https://m.qingxuetang.com/x/book/A3h0IrK21OA?appId=qxtcorp666",
"latestUpdateTime": 1565078222000
},
{
"bookCode": "A3h0IKKUU",
"bookType": 3,
"bookTitle": "平凡的世界",
"bookSubTitle": "倾听自己的故事",
"bookCover": "http://imagev2.xmcdn.com/group59/M02/A2/1A/wKgLely0KinApb1xAAKxn9yrSkg929.png!op_type=0",
"categoryId": 26,
"category": "新经典",
"bookAuthor": "尼科斯",
"lecturer": "郑佳",
"lecturerAvatar": "http://imagev2.xmcdn.com/group58/M0A/7A/A1/wKgLc1y-qiPAnVuIAA5gSQn63tk387.png",
"lecturerIntro": "美校博士",
"duration": 1800,
"linkUrl": "https://m.qingxuetang.com/x/course/A3h0IKKUU?appId=qxtcorp666",
"latestUpdateTime": 1565078222000,
"totalCount": 18,
"updateCount": 3,
"hasFinished": 0
}
]
}
}
3. 分批获取免费课列表
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/content/getFreeCourses
请求方式
GET
请求参数
参数 | 类型 | 是否必须 | 默认值 | 说明 |
---|---|---|---|---|
appId | String | 是 | APP_ID | |
offset | int | 否 | 0 | 分页参数,偏移量,指从第几条开始获取。 比如count=10时, 第1页offset=0&count=10, 第2页offset=10&count=10, 第3页offset=20&count=10,以此类推。 |
count | int | 否 | 20 | 分页参数,获取数量 |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
响应结果
xxxxxxxxxx
{
"ret": 0,
"msg": "操作成功",
"data": {
"totalCount": 1,
"dataList": [
{
"courseCode": "DSJVExq33IQ",
"mediaType": 2,
"courseTitle": "结构化写作",
"courseSubTitle": "写作更轻松,观点更有力",
"courseCover": "http://imagev2.xmcdn.com/group60/M01/14/7E/wKgLb1zGbsriC-GFAAiGLdsksS8063.png!op_type=0",
"categoryId": 341,
"category": "领导力",
"parentCategoryId": 2,
"parentCategory": "管理类",
"lecturer": "李忠秋",
"lecturerAvatar": "http://imagev2.xmcdn.com/group58/M0A/7A/A1/wKgLc1y-qiPAnVuIAA5gSQn63tk387.png",
"lecturerIntro": "《结构思考力》作者",
"totalCount": 18,
"duration": 180,
"linkUrl": "https://m.qingxuetang.com/x/course/DSJVExq33IQ?appId=qxtcorp666",
"latestUpdateTime": 1565078222000,
"updateCount": 3,
"hasFinished": 0
}
]
}
}
七、消息推送
由第三方推送给轻学堂,进行系统数据同步,目前支持员工离职消息推送。
请求地址
xxxxxxxxxx
https://www.qingxuetang.com/open/api/tp/callback
请求方式
POST
请求参数
参数全部放在请求体body中,且Content-Type
请求头设置为application/x-www-form-urlencoded; charset=UTF-8
参数 | 类型 | 是否必须 | 默认值 | 说明 |
---|---|---|---|---|
appId | String | 是 | APP_ID | |
timestamp | long | 是 | 时间戳(ms) | |
nonce | String | 是 | 随机串 | |
msgBody | String | 是 | 消息体JSON字符串。 | |
sign | String | 是 | 参数签名,计算方法参照计算参数签名相关 |
1. 员工离职消息推送
消息体格式:
xxxxxxxxxx
{
"authCorpId": "p666",
"eventType": "resign_user",
"openId": "openId666",
"resignDate": 1555571167
}
参数 | 类型 | 是否必须 | 默认值 | 说明 |
---|---|---|---|---|
authCorpId | String | 是 | 企业标识 | |
eventType | String | 是 | 消息推送类型,离职eventType="resign_user" | |
openId | String | 是 | 用户标识 | |
resignDate | long | 否 | 离职时间戳(s) |
注:如需调用该接口,需找轻学堂技术支持进行相关配置
八、轻学堂数据推送接入
1.接入指引
轻学堂数据推送方案旨在丰富轻学堂开放平台能力,满足第三方对于数据方面的需求。通过HTTP回调方式,轻学堂每日定时向第三方推送回调数据包。因此,第三方需要搭建一个HTTP回调服务,用来接收回调数据包。
为了防止回调数据包被恶意攻击者篡改,第三方需要校验数字签名。具体为双方约定一个token作为密钥,仅第三方和轻学堂知道,在传输中不可见,用于参与签名计算。轻学堂在推送回调数据包时,将回调数据包与token计算出签名sign。第三方接收到回调数据包时,也按相同算法计算出签名。如果为同一签名,则可信任来源为轻学堂,并且内容是完整的。
由于消息是在公网上传输,消息内容是可被截获的,如果内容未加密,则截获者可以直接阅读消息内容。若消息内容包含一些敏感信息,就非常危险了。encodingAESKey就是在这个背景基础上提出,轻学堂会将回调数据包进行AES加密,并组装成一定格式后再发送。第三方需要对接受到的回调数据包进行AES解密才能得到明文。
整体流程如下,第三方开发者可以重点关注第三方HTTP回调侧流程:
2.开始接入
1).搭建HTTP回调服务
假设第三方HTTP回调服务URL为:
xxxxxxxxxx
http://api.th3.com
a.接收回调数据
当轻学堂定时执行推送时,轻学堂会发送类似下述回调数据包到上述URL:
xxxxxxxxxx
curl http://api.th3.com -X POST -d 'sign=B12E73EE33AFED534AFB260FE214E810C5AC77B7×tamp=1592526990117&nonce=08c6b6fd-85ad-4a15-98bf-8b4bc54f15ea&msg_encrypt=5/sSVQt/kEKAJr+0wAnVWu1bmIwUK36M7Kx/ciYD8pTqzbtptfKR0QR4x+dNR/ou8zowP5kb8jbhpodhAQFD+o279Ek7QN572YLCbdn/QA9F5qM5gjoMc6UIHn3/CcuE4jjnZZuxuOjVnXDjUESSArqiAyPaUuwgqZ3Zb1AjQqCYVPhoB9c9CezOFJxlxUpT3D61t93K77rjUJN0fabnURLoxCYMtY9NOzetTa2KbiEQJjtxy5uAkhtift9b/nkPtQB8HIpogHmghJ+NutNdvhnrM3AG056bl0xq49st79HtO3acEi+FHMDT6TrlYqzjE2ls0OvaBxTXNEay6VL3/WVPBBrcdAp9U4CMhvHqDTz7FO6g86xBd9BkS3jfHip9'
回调数据参数说明
参数 | 类型 | 说明 |
---|---|---|
sign | String | 签名信息。参照加解密方案说明-签名相关。 |
timestamp | long | 时间戳。与nonce结合使用,用于防止请求重放攻击。 |
nonce | String | 随机数。与timestamp结合使用,用于防止请求重放攻击。 |
msg_encrypt | String | 加密的字符串。需要解密得到消息内容明文,参照加解密方案说明-AES相关。解密后有random、msg_len、msg、receiveid四个字段,其中msg即为消息内容明文。 |
b.处理回调数据
第三方收到推送后,处理流程如下:
1)对sign进行签名校验;
2)对msg_encrypt做AES解密得到明文的消息结构体;
3)解析明文消息结构体,进行后续业务处理。(消息结构体参照消息格式)
示例:
xxxxxxxxxx
假如收到的推送数据如下:
sign=B12E73EE33AFED534AFB260FE214E810C5AC77B7
timestamp=1592526990117
nonce=08c6b6fd-85ad-4a15-98bf-8b4bc54f15ea
msg_encrypt=5/sSVQt/kEKAJr+0wAnVWu1bmIwUK36M7Kx/ciYD8pTqzbtptfKR0QR4x+dNR/ou8zowP5kb8jbhpodhAQFD+o279Ek7QN572YLCbdn/QA9F5qM5gjoMc6UIHn3/CcuE4jjnZZuxuOjVnXDjUESSArqiAyPaUuwgqZ3Zb1AjQqCYVPhoB9c9CezOFJxlxUpT3D61t93K77rjUJN0fabnURLoxCYMtY9NOzetTa2KbiEQJjtxy5uAkhtift9b/nkPtQB8HIpogHmghJ+NutNdvhnrM3AG056bl0xq49st79HtO3acEi+FHMDT6TrlYqzjE2ls0OvaBxTXNEay6VL3/WVPBBrcdAp9U4CMhvHqDTz7FO6g86xBd9BkS3jfHip9
1.校验签名:
String localSign = HmacSha1(msg_encrypt=xx&nonce=xxx×tamp=xxx, token).toUpperCase();
Assert.equals(localSign, sign);
2.签名校验通过,对msg_encrypt解密,得到明文消息结构体decryptMsg
PushBizMsgCrypt crypt = new PushBizMsgCrypt(encodingAesKey, appId);
String decryptMsg = crypt.decrypt(msg_encrypt);
3.解析明文消息结构体
JSONObject msg = JSON.parseObject(decryptMsg);
...... //后续业务操作
c.响应回调请求
第三方接收成功后,http头部需要返回200响应码,且返回JSON格式响应数据,格式如下:
xxxxxxxxxx
{
"ret":0, //错误码,0-成功 非0表示异常
"msg":"" //信息
}
注:
- 轻学堂10s内收不到响应会断掉连接并重试
- 对响应OK的请求,轻学堂会解析返回的错误码;如果错误码非0,轻学堂也会进行重试
- 轻学堂最多重试三次
2).开始调测
第三方按上述流程搭建好回调服务后,可以联系轻学堂进行调测。
a.联系轻学堂获取token和encodingAESKey
xxxxxxxxxx
目前均由轻学堂统一生成下发。
b.提供回调服务URL
3).启用推送
调测通过后,第三方可以联系轻学堂沟通上线事宜。
a.确认推送时间点
xxxxxxxxxx
第三方可根据自身服务情况,选择推送时间点,默认每日凌晨2:00开始,若需修改可联系轻学堂配置。
b.确认推送数据
xxxxxxxxxx
第三方可根据业务需要订阅数据,目前数据分学习数据和学分,确认后联系轻学堂配置。
c.轻学堂启用推送配置
xxxxxxxxxx
上述推送配置确认完后,轻学堂会启用线上推送配置,每日定时进行数据推送。启用后,第二天开始推送昨日启用时间点至昨日23:59:59期间的数据。
3.附录
1).加解密方案说明
阅读本章节前,需要了解以下术语:
-
token:推送签名密钥
-
sign: 消息签名,用于验证请求是否来自轻学堂(防止攻击者伪造)。
-
encodingAESKey:用于消息体的加密,长度固定为43个字符,从a-z, A-Z, 0-9共62个字符中选取,是AESKey的Base64编码。解码后即为32字节长的AESKey
xxxxxxxxxx
AESKey=Base64_Decode(encodingAESKey + “=”)
-
AESKey:AES算法的密钥,长度为32字节。
-
msg:为消息体明文,格式为JSON
-
msg_encrypt:明文消息msg加密处理后的Base64编码。
a.轻学堂加密流程
轻学堂在推送数据给第三方时,会对JSON格式数据包体msg做AES加密得到密文msg_encrypt,再将得到的msg_encrypt和参数timestamp、nonce一起进行签名计算得到签名sign,然后将msg_encrypt、timestamp、nonce和sign通过HTTPS/HTTP协议POST到第三方指定的URL上。
xxxxxxxxxx
拼装JSON格式数据包msg明文 --> msg_encrypt=AES Encrypt(msg) --> sign=HmacSha1(sort(msg_encrypt, nonce, timestamp), token) --> POST(msg_encrypt, timestamp, nonce, sign)
b.第三方解密流程
因此,第三方收到数据推送请求之后,需要先对收到的参数msg_encrypt、timestamp和nonce进行签名计算得到signTmp,比较localSign和参数sign是否一致。一致认为是正确的请求,然后将msg_encrypt做AES解密得到明文msg;反之,签名不一致,认为是伪造异常请求。
xxxxxxxxxx
signTmp=HmacSha1(sort(msg_encrypt, nonce, timestamp), token) --> 签名正确,msg=AES Decrypt(msg_encrypt)
c.计算签名相关
xxxxxxxxxx
按照参数名ASCII码从小到大排序,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA,对stringA做HmacSha1(stringSignTemp, token)计算,将结果转换为大写即得到sign。
d.AES加解密相关
xxxxxxxxxx
AES采用CBC模式,数据采用PKCS#7填充至32字节的倍数;IV初始向量大小为16字节,取AESKey前16字节,详见:http://tools.ietf.org/html/rfc2315。
AES加密过程
xxxxxxxxxx
1.拼接明文字符串rand_msg。
明文字符串由16个字节的随机字符串、4个字节的msg长度、明文msg和receiveid拼接组成。其中msg_len为msg的字节数,网络字节序。receiveid固定为第三方appId。
rand_msg = random(16B) + msg_len(4B) + msg + receiveid
2.对明文字符串rand_msg加密并Base64编码。
msg_encrypt = Base64_Encode(AES_Encrypt(rand_msg))
AES解密过程
xxxxxxxxxx
1.对密文msg_encrypt进行BASE64解码。
aes_msg=Base64_Decode(msg_encrypt)
2.使用AESKey做AES-256-CBC解密。
rand_msg=AES_Decrypt(aes_msg)
3.去掉rand_msg头部的16个随机字节和4个字节的msg_len,截取msg_len长度的部分即为明文msg,剩下的为尾部的receiveid。
4.验证解密后的receiveid、msg_len。
2).消息格式
目前明文数据分为学习数据和学分两种,数据格式统一为JSON。
注:
- 学习数据推送的为每日增量数据
- 学分数据推送的为总数及每日增量数据
- 学习数据和学分数据会分开发送,若两者都订阅了,会发两类不同的消息。
参数说明:
参数 | 类型 | 说明 |
---|---|---|
msgType | String | 数据推送固定为data_push |
segmentId | String | 每批次唯一ID,第三方需要通过该字段保证数据处理幂等性,避免重复处理导致数据统计有误 |
appId | String | 第三方ID,第三方可以校验正确性 |
pushDate | int | 推送日期,如20200606 |
eventType | String |
事件类型: a.学习增量数据,固定为study_data_increment b.学分数据,固定为point_data |
authCorpId | String | 第三方企业ID |
data | JSON Array | 数据,数组最多100条。 |
data.openId | String | 第三方ID |
data.courses | JSON Array | 课程数据列表 |
data.courses.courseCode | String | 课程编码 |
data.courses.studyTime | int | 课程学习时长,单位秒 |
data.books | JSON Array | 书籍数据列表 |
data.books.bookCode | String | 书籍编码 |
data.books.studyTime | int | 书籍学习时长,单位秒 |
data.point | double | 总学分数据,保留一位有效数字,如5.0 |
data.incrPoint | double | 每日学分变化数据,保留一位有效数字,如5.0;为正值则为学分增加,为负值则为学分减少 |
data.xxx.progress | int | 书籍或课程学习进度% |
a.学习数据
xxxxxxxxxx
{
"msgType": "data_push",
"segmentId": "20200618_650281532",
"appId": "qxtcorp320939",
"pushDate": 20200618,
"eventType": "study_data_increment",
"authCorpId": "p2248",
"data": [
{
"openId": "442002013080218",
"courses": [
{
"courseCode": "tk9OF0em3-8",
"studyTime": 56,
"progress": 66
}
],
"books": [
{
"bookCode": "12k9OF2em3-1",
"bookType": 2,
"studyTime": 100,
"progress": 66
}
]
},
{
"openId": "442002013080219",
"books": [
{
"bookCode": "12k9OF2em3-1",
"bookType": 3,
"studyTime": 100,
"progress": 66
}
]
}
]
}
b.学分
xxxxxxxxxx
{
"msgType": "data_push",
"segmentId": "20200618_6503181532",
"appId": "qxtcorp320939",
"pushDate": 20200618,
"eventType": "point_data",
"authCorpId": "p2248",
"data": [
{
"openId": "442981995070011",
"point": 21.2,
"incrPoint": -79.4
},
{
"openId": "open001",
"point": 10.0,
"incrPoint": 80.6
}
]
}
3).加解密DEMO
AES加解密demo可以联系轻学堂获取
九、附录
1.全局错误码
ret | msg |
---|---|
0 | success,表示操作成功 |
-1 | 服务错误,请稍后重试 |
-3 | 参数错误 |
-999 | 超过频次限制 |
-1000 | appId不正确 |
-1001 | authCorpId不正确,请先联系轻学堂配置 |
-1002 | sign不正确 |
-1003 | openIds为空 |
-1004 | 超过每次开通openIds限制 |
-1005 | cardType不正确 |
-1006 | 企业该类型会员卡剩余数量不足,请先购买 |
-1007 | 员工已是会员 |
-1101 | 超过每批次获取限制 |
-1102 | offset不正确 |
-1103 | count不正确 |
-1104 | 无效的openId |
-1200 | 不支持的eventType |
-1300 | 兑换码不存在! |
-1301 | 该兑换码已失效 |
-1302 | 兑换失败,请稍后重试! |
-1303 | 兑换码批次状态不正确! |
-1304 | 您输错的次数过多,请稍后重试! |
2.签名计算
所有涉及到计算签名的接口如果没有显式指定某个具体的签名算法,比如signType区分不同的签名算法,那么默认使用MD5来计算签名。
参数签名, 生成步骤如下:
-
1.将请求的所有非空参数(sign除外)的原始值(所谓原始值即不能做URL编码等类似处理)按照参数名ASCII码从小到大排序,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
-
2.如果签名算法是MD5或者SM3需要在stringA最后拼上"&appSecret=xxx"得到stringSignTemp。
-
3.如果签名算法是MD5或者SM3,直接对stringSignTemp进行MD5或SM3运算,再将得到的字符串所有字符转换为大写即得到sign。
如果签名算法是HmacSHA1,密钥为appSecret,HmacSha1(stringSignTemp, appSecret),将结果转换为大写即得到sign。
xxxxxxxxxx
计算sign示例(以下仅为示例,具体接口根据具体参数计算):
MD5:
1.stringA = "appId=qxtcorp777777&authCorpId=p7777&nickname=nickname王二小&nonce=7777777&openId=openId77777&signType=1×tamp=1579003771897";
2.stringSignTemp = stringA + "&appSecret=a19de0eb80013fb468fd2ee0cc672211";
3.sign = MD5(stringSignTemp).toUpperCase();//sign=C773D629B11084061F98E3CB2C70CD4F
4.最终完整的请求地址为
https://www.qingxuetang.com/passport/tp/v2/thirdLogin?appId=qxtcorp777777&authCorpId=p7777&nickname=nickname%e7%8e%8b%e4%ba%8c%e5%b0%8f&openId=openId77777&signType=1&nonce=7777777×tamp=1579003771897&sign=C773D629B11084061F98E3CB2C70CD4F
HmacSHA1:
1.stringA = "appId=qxtcorp777777&authCorpId=p7777&nickname=nickname王二小&nonce=7777777&openId=openId77777&signType=2×tamp=1579003771897";
2.stringSignTemp = stringA;
3.sign = HmacSha1(stringSignTemp, "a19de0eb80013fb468fd2ee0cc672211").toUpperCase();//sign=47EDDD5E4F94ED8BF5D31B70CD8169753F9AFAF4
4.最终完整的请求地址为
https://www.qingxuetang.com/passport/tp/v2/thirdLogin?appId=qxtcorp777777&authCorpId=p7777&nickname=nickname%e7%8e%8b%e4%ba%8c%e5%b0%8f&openId=openId77777&signType=2×tamp=1579003771897&nonce=7777777&sign=47EDDD5E4F94ED8BF5D31B70CD8169753F9AFAF4
SM3:
1.stringA = "appId=qxtcorp777777&authCorpId=p7777&nickname=nickname王二小&nonce=7777777&openId=openId77777&signType=3×tamp=1579003771897";
2.stringSignTemp = stringA + "&appSecret=a19de0eb80013fb468fd2ee0cc672211";
3.sign = SM3(stringSignTemp).toUpperCase();//sign=F1BCF194A554ECDB4801371A9C3DFBD5939DEF94A74B04CD2161F7DC6F83E672
4.最终完整的请求地址为
https://www.qingxuetang.com/passport/tp/v2/thirdLogin?appId=qxtcorp777777&authCorpId=p7777&nickname=nickname%e7%8e%8b%e4%ba%8c%e5%b0%8f&openId=openId77777&signType=3×tamp=1579003771897&nonce=7777777&sign=F1BCF194A554ECDB4801371A9C3DFBD5939DEF94A74B04CD2161F7DC6F83E672
3.常见问题 - FAQ
1).H5对接 - FAQ
使用方案一对接,页面提示“无效的状态”
code或者state无效,重试即可。
使用方案一对接,页面提示“无效的auth_corpid”
请确保步骤四返回了auth_corpid信息。
使用方案一对接,页面提示“授权失败,请退出重新授权”
请确保第三方各步骤返回的数据格式无误,确认无误后可以联系轻学堂协助查看。
使用方案二对接,出现白屏
一般这种情况都是出现了错误,由于对接的是轻学堂移动H5,需要匹配移动端样式才会看到相关报错消息。
使用方案二对接,页面提示“无效的请求”
1.确认请求时间戳timestamp是否过期(目前超过10分钟算过期)
2.确认请求随机码nonce是否重复
使用方案二对接,页面提示“authCorpId不正确,请先联系轻学堂配置”
authCorpId未配置或者不正确,请按照方案二调测流程确认。
使用方案二对接,页面提示“sign不正确”
使用方案二对接,页面提示“手机号、工号不匹配”或者“手机号或工号已存在”
一般是由于该用户openId、mobile和empNo出现冲突,请检查相关参数信息。
接入成功后,页面样式错乱等各类兼容问题
目前是禁止第三方使用iframe方式接入轻学堂H5,请第三方先确保没有使用iframe方式接入。如果确实没有使用iframe,可以联系轻学堂协助查看。
接入成功后,导航问题
1.顶部导航可以前往【轻学堂企业后台】 - 【员工端配置】 - 【其他设置】 - 开启【内置导航】尝试解决。
2.导航相关说明参照下图:
接入成功后,android系统机型不能播放,但IOS系统机型没有问题
由于Android的webView升级,加强了安全策略,不允许打开https页面中嵌套的http媒体文件,此种情况会被认为是安全环境中的不安全因素,访问时webView会进行限制。第三方可以联系轻学堂进行处理。
2).会员相关 - FAQ
轻学堂会员和用户账号关系
轻学堂会员体系是基于轻学堂用户账号体系,双方账号打通之后,员工免登进入轻学堂无需开通会员即可学习轻学堂免费内容,如果需要畅听轻学堂会员内容,则需要开通会员。每个企业都可以在轻学堂企业后台-增值服务处进行会员管理,包括员工会员开通等。本文档也提供了通过API方式(第三方用户会员开通接口)来协助第三方企业开通员工会员,但是功能比较单一,推荐在轻学堂企业后台-增值服务处进行会员管理。
3).学习数据查询 - FAQ
学习数据查询API用途
轻学堂是通过H5接入到第三方自有学习平台,用户在轻学堂产生的学习数据会统计在轻学堂侧。如果第三方自有平台需要统计用户在轻学堂侧的学习数据,则可以通过学习数据查询API获取。
学习数据包含哪些维度的数据
目前提供的学习数据主要包括用户学习数据概况和用户学习数据明细(已学课程列表和已学书籍列表),具体可以查看学习数据相关接口说明。用户学习记录接口功能同轻学堂H5-学习历史。
分批获取员工学习数据返回的员工列表中存在部分员工openId为空
这种情况一般由于该员工在轻学堂企业后台存在,但第三方账号关联不存在(openId
不存在)。出现这种情况一般是企业启用第三方配置前通过轻学堂企业后台进行过相关人员管理,导致这部分人员第三方账号关联丢失。
解决办法:如果是调测数据确认不需要后可以在轻学堂企业后台-员工管理处离职掉;如果是需要的员工账号数据,可以通过【轻学堂企业后台】 - 【员工管理】 - 【导入/导出】 -
【第三方批量导入员工功能】补充第三方账号关联。具体方法是在第三方批量导入员工模板里面填上用户已有账号信息(如工号、手机号等,如果工号和手机号都存在则都需要填),并在"open
ID"列补充好该用户openId
。
接口返回“appId不正确”
请先确保接口请求方式是否正确,如Content-Type
需要设置为application/x-www-form-urlencoded; charset=UTF-8
。
接口返回“sign不正确”
4).消息推送 - FAQ
按文档规范推送了离职消息,但实际上没有离职成功
消息推送功能默认关闭,如果需要启用请联系轻学堂。
5).数据推送 - FAQ
数据推送和学习数据查询API差别
两种方式都能满足第三方对于数据方面的需求,但有所区别:
- 数据推送是通过HTTP回调方式,由轻学堂每日定时向第三方推送学习数据;学习数据查询API是需要第三方根据需要通过接口来获取数据
- 数据推送的数据目前包含员工学习时长和学分等
推送数据的学习时长和学分都有吗
目前推送数据包括学习时长和学分这两项,各项分开推送,第三方可以根据需要进行灵活配置。
已按文档开发好回调接口,如何调测
鉴于轻学堂系统需要第二天才会推送数据,第三方可以自行按文档和demo造出测试数据,使用postman模拟进行推送(注意:Content-Type
需要设置为application/x-www-form-urlencoded; charset=UTF-8
)。测试通过的话,可以联系轻学堂进行后续配置和线上启用调测。
定时推送时间点
第三方可根据自身服务情况,选择推送时间点,默认T+1日凌晨2:00开始推送T日数据,若需修改可联系轻学堂配置。
数据推送已启用,但T+1日未查到T日推送日志
如果线上已经正确启用了数据推送,推送定时任务往往是执行了的,只不过T日没有相关增量数据,所以看不到推送日志。轻学堂推送的是每日增量员工数据,请确保T日有员工产生了学习数据或学分。
加解密时出现java.security.InvalidKeyException:illegal Key Size报错
解决方案:在官方网站下载JCE无限制权限策略文件(请到官网下载对应的版本, 例如JDK7的下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html ):下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt。 如果安装了JRE,将两个jar文件放到%JRE_HOME% \lib\security目录下覆盖原来的文件,如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件。
6).签名相关 - FAQ
接口或页面提示“sign不正确”
签名不正确,尝试通过以下方式排查:
- 确保参与签名的参数未做处理(比如URL编码等)
- 确保拼接成的加密串是按照参数名ASCII码从小到大排序
- 确保算出的签名均转成了大写字符
- 利用相关工具网站自行验证签名正确性,比如
https://tool.oschina.net/encrypt?type=2
- 如果签名自行验证不通过请重复以上流程进行排查