近期根据客户要求需要开发钉工牌,于是打开钉钉开放平台,搜索出钉工牌,查看钉工牌相关对接流程和相关概念,主要利用钉工牌与客户消费机交互,通过钉工牌获取用户在钉钉云上的员工信息,识别出员工信息。参考文档:https://open.dingtalk.com/document/orgapp-server/introduction-to-dingtalk-badge
钉工牌设备/接入服务/钉云服务交互流程如下:
要调用钉工牌相关服务API,首先需要创建钉工牌应用,创建钉工牌应用流程按如下图所示;
文档链接:https://alidocs.dingtalk.com/i/p/Y7kmbokZp3pgGLq2/docs/Y7kmb5WP0Oxq4XLq
1.入驻钉钉开放平台成为开发者
要和钉工牌集成,调用钉工牌的相关OpenAPI,首先要有调用接口所需的身份,这就需要企业或ISV登录钉钉开放平台,创建应用,成为开发者。
● 点击链接接入钉钉开放平台,点击"开发者后台",选择要进入的组织。
2.ISV创建第三方企业应用或企业创建内部应用
● 创建应用,如果尚未创建应用,选择"应用开放"->"第三方企业应用"或"企业内部应用"进行创建,企业自己开发创建企业内部应用,ISV开发创建第三方企业应用,但要注意ISV需要入驻为应用服务商,才能给其他企业组织使用。
○ 企业内部应用,填写表单必要信息进行创建
○ 第三方企业应用,ISV如何成为应用服务商,点击链接查看教程。
3.获取应用身份信息,并授权应用调用钉工牌相关接口
● 点击接入应用详情,“基础信息”Tab,可查看到应用对应的AppKey和AppSecret,为调用钉钉接口的身份标识。
● 点击侧边栏“权限管理”Tab,搜索“钉工牌”,获取到钉工牌相关权限,并申请权限。
4.使用应用的AppKey和APSecret获取调用接口所需的AccessToken
● 企业内部应用,可直接调用“/v1.0/oauth2/accessToken”接口获取accessToken,细节查看文档详情,样例Java代码如下:
// This file is auto-generated, don't edit it. Thanks.
package com.aliyun.sample;
import com.aliyun.tea.*;
import com.aliyun.teautil.*;
import com.aliyun.dingtalkoauth2_1_0.*;
import com.aliyun.dingtalkoauth2_1_0.models.*;
import com.aliyun.teaopenapi.*;
import com.aliyun.teaopenapi.models.*;
public class Sample {
/**
* 使用 Token 初始化账号Client
* @return Client
* @throws Exception
*/
public static com.aliyun.dingtalkoauth2_1_0.Client createClient() throws Exception {
Config config = new Config();
config.protocol = "https";
config.regionId = "central";
return new com.aliyun.dingtalkoauth2_1_0.Client(config);
}
public static void main(String[] args_) throws Exception {
java.util.List<String> args = java.util.Arrays.asList(args_);
com.aliyun.dingtalkoauth2_1_0.Client client = Sample.createClient();
GetAccessTokenRequest getAccessTokenRequest = new GetAccessTokenRequest()
.setAppKey("dingeqqpkv3xxxxxx")
.setAppSecret("GT-lsu-taDAxxxsTsxxxx");
try {
client.getAccessToken(getAccessTokenRequest);
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
} catch (Exception _err) {
TeaException err = new TeaException(_err.getMessage(), _err);
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
}
}
● ISV作为应用服务商,需要获取授权企业的accessToken,调用接口“/v1.0/oauth2/corpAccessToken”,入参使用应用服务商的“suiteKey”和“suiteSecrect”,细节查看文档详情,样例Java代码如下:
// This file is auto-generated, don't edit it. Thanks.
package com.aliyun.sample;
import com.aliyun.tea.*;
import com.aliyun.teautil.*;
import com.aliyun.dingtalkoauth2_1_0.*;
import com.aliyun.dingtalkoauth2_1_0.models.*;
import com.aliyun.teaopenapi.*;
import com.aliyun.teaopenapi.models.*;
public class Sample {
/**
* 使用 Token 初始化账号Client
* @return Client
* @throws Exception
*/
public static com.aliyun.dingtalkoauth2_1_0.Client createClient() throws Exception {
Config config = new Config();
config.protocol = "https";
config.regionId = "central";
return new com.aliyun.dingtalkoauth2_1_0.Client(config);
}
public static void main(String[] args_) throws Exception {
java.util.List<String> args = java.util.Arrays.asList(args_);
com.aliyun.dingtalkoauth2_1_0.Client client = Sample.createClient();
GetCorpAccessTokenRequest getCorpAccessTokenRequest = new GetCorpAccessTokenRequest()
.setSuiteKey("suitep1f5lzyglm7fryxxxx")
.setSuiteSecret("_FP5PpZF3irDKjxxx")
.setAuthCorpId("ding123456")
.setSuiteTicket("1f5lzyglm7fryxxxx");
try {
client.getCorpAccessToken(getCorpAccessTokenRequest);
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
} catch (Exception _err) {
TeaException err = new TeaException(_err.getMessage(), _err);
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
}
}
5.调用钉工牌接口为企业开通访客码或会展码
注意:工牌码不需要
● 访客或会展码服务,需要企业或ISV的SaaS应用调用接口为目标企业开通,目标企业为被访问的公司或举办会展的公司,接口为“/v1.0/badge/codes/corpInstances”,点击查看接口详情,Java代码样例:
// This file is auto-generated, don't edit it. Thanks.
package com.aliyun.sample;
import com.aliyun.tea.*;
import com.aliyun.teautil.*;
import com.aliyun.teautil.models.*;
import com.aliyun.dingtalkbadge_1_0.*;
import com.aliyun.dingtalkbadge_1_0.models.*;
import com.aliyun.teaopenapi.*;
import com.aliyun.teaopenapi.models.*;
public class Sample {
/**
* 使用 Token 初始化账号Client
* @return Client
* @throws Exception
*/
public static com.aliyun.dingtalkbadge_1_0.Client createClient() throws Exception {
Config config = new Config();
config.protocol = "https";
config.regionId = "central";
return new com.aliyun.dingtalkbadge_1_0.Client(config);
}
public static void main(String[] args_) throws Exception {
java.util.List<String> args = java.util.Arrays.asList(args_);
com.aliyun.dingtalkbadge_1_0.Client client = Sample.createClient();
SaveBadgeCodeCorpInstanceHeaders saveBadgeCodeCorpInstanceHeaders = new SaveBadgeCodeCorpInstanceHeaders();
saveBadgeCodeCorpInstanceHeaders.xAcsDingtalkAccessToken = "<your access token>";
SaveBadgeCodeCorpInstanceRequest saveBadgeCodeCorpInstanceRequest = new SaveBadgeCodeCorpInstanceRequest()
.setCodeIdentity("DT_IDENTITY")
.setCorpId("dingxxxx")
.setStatus("OPEN");
try {
client.saveBadgeCodeCorpInstanceWithOptions(saveBadgeCodeCorpInstanceRequest, saveBadgeCodeCorpInstanceHeaders, new RuntimeOptions());
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
} catch (Exception _err) {
TeaException err = new TeaException(_err.getMessage(), _err);
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
}
}
// This file is auto-generated, don't edit it. Thanks.
package com.aliyun.sample;
import com.aliyun.tea.*;
import com.aliyun.teautil.*;
import com.aliyun.teautil.models.*;
import com.aliyun.dingtalkbadge_1_0.*;
import com.aliyun.dingtalkbadge_1_0.models.*;
import com.aliyun.teaopenapi.*;
import com.aliyun.teaopenapi.models.*;
public class Sample {
/**
* 使用 Token 初始化账号Client
* @return Client
* @throws Exception
*/
public static com.aliyun.dingtalkbadge_1_0.Client createClient() throws Exception {
Config config = new Config();
config.protocol = "https";
config.regionId = "central";
return new com.aliyun.dingtalkbadge_1_0.Client(config);
}
public static void main(String[] args_) throws Exception {
java.util.List<String> args = java.util.Arrays.asList(args_);
com.aliyun.dingtalkbadge_1_0.Client client = Sample.createClient();
CreateBadgeCodeUserInstanceHeaders createBadgeCodeUserInstanceHeaders = new CreateBadgeCodeUserInstanceHeaders();
createBadgeCodeUserInstanceHeaders.xAcsDingtalkAccessToken = "<your access token>";
CreateBadgeCodeUserInstanceRequest.CreateBadgeCodeUserInstanceRequestAvailableTimes availableTimes0 = new CreateBadgeCodeUserInstanceRequest.CreateBadgeCodeUserInstanceRequestAvailableTimes()
.setGmtStart("yyyy-MM-dd HH:mm:ss")
.setGmtEnd("yyyy-MM-dd HH:mm:ss");
CreateBadgeCodeUserInstanceRequest createBadgeCodeUserInstanceRequest = new CreateBadgeCodeUserInstanceRequest()
.setRequestId("202102021212")
.setCodeIdentity("TEST")
.setCodeValue("dingbadge111")
.setStatus("OPEN")
.setCorpId("corpid1234")
.setUserCorpRelationType("INTERNAL_STAFF")
.setUserIdentity("86-xxxxxx")
.setGmtExpired("yyyy-MM-dd HH:mm:ss")
.setAvailableTimes(java.util.Arrays.asList(
availableTimes0
));
try {
client.createBadgeCodeUserInstanceWithOptions(createBadgeCodeUserInstanceRequest, createBadgeCodeUserInstanceHeaders, new RuntimeOptions());
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
} catch (Exception _err) {
TeaException err = new TeaException(_err.getMessage(), _err);
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
}
}
7.调用钉工牌接口解析二维码获取企业和用户信息
● 硬件设备扫码后,获取到二维码值,企业或ISV的SaaS应用调用“/v1.0/badge/codes/decode”接口,获取到码值对应的企业信息和用户信息,根据该信息进行业务判断,如是否有门禁权限,是否就餐账户的余额充足等,点击查看接口详情,Java代码样例:
// This file is auto-generated, don’t edit it. Thanks.
package com.aliyun.sample;
import com.aliyun.tea.*;
import com.aliyun.teautil.*;
import com.aliyun.teautil.models.*;
import com.aliyun.dingtalkbadge_1_0.*;
import com.aliyun.dingtalkbadge_1_0.models.*;
import com.aliyun.teaopenapi.*;
import com.aliyun.teaopenapi.models.*;
public class Sample {
/**
* 使用 Token 初始化账号Client
* @return Client
* @throws Exception
*/
public static com.aliyun.dingtalkbadge_1_0.Client createClient() throws Exception {
Config config = new Config();
config.protocol = "https";
config.regionId = "central";
return new com.aliyun.dingtalkbadge_1_0.Client(config);
}
public static void main(String[] args_) throws Exception {
java.util.List<String> args = java.util.Arrays.asList(args_);
com.aliyun.dingtalkbadge_1_0.Client client = Sample.createClient();
DecodeBadgeCodeHeaders decodeBadgeCodeHeaders = new DecodeBadgeCodeHeaders();
decodeBadgeCodeHeaders.xAcsDingtalkAccessToken = "<your access token>";
DecodeBadgeCodeRequest decodeBadgeCodeRequest = new DecodeBadgeCodeRequest()
.setPayCode("dingbadgexxxx")
.setRequestId("202103232");
try {
client.decodeBadgeCodeWithOptions(decodeBadgeCodeRequest, decodeBadgeCodeHeaders, new RuntimeOptions());
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
} catch (Exception _err) {
TeaException err = new TeaException(_err.getMessage(), _err);
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
}
}
8.调用钉工牌接口通知业务验证或支付结果
● 支付场景,如食堂就餐,园区消费等,调用上报支付结果接口“/v1.0/badge/codes/payResults”,点击查看接口详情,Java代码样例:
// This file is auto-generated, don’t edit it. Thanks.
package com.aliyun.sample;
import com.aliyun.tea.*;
import com.aliyun.teautil.*;
import com.aliyun.teautil.models.*;
import com.aliyun.dingtalkbadge_1_0.*;
import com.aliyun.dingtalkbadge_1_0.models.*;
import com.aliyun.teaopenapi.*;
import com.aliyun.teaopenapi.models.*;
public class Sample {
/**
* 使用 Token 初始化账号Client
* @return Client
* @throws Exception
*/
public static com.aliyun.dingtalkbadge_1_0.Client createClient() throws Exception {
Config config = new Config();
config.protocol = "https";
config.regionId = "central";
return new com.aliyun.dingtalkbadge_1_0.Client(config);
}
public static void main(String[] args_) throws Exception {
java.util.List<String> args = java.util.Arrays.asList(args_);
com.aliyun.dingtalkbadge_1_0.Client client = Sample.createClient();
NotifyBadgeCodePayResultHeaders notifyBadgeCodePayResultHeaders = new NotifyBadgeCodePayResultHeaders();
notifyBadgeCodePayResultHeaders.xAcsDingtalkAccessToken = "<your access token>";
NotifyBadgeCodePayResultRequest.NotifyBadgeCodePayResultRequestPayChannelDetailListFundToolDetailList payChannelDetailList0FundToolDetailList0 = new NotifyBadgeCodePayResultRequest.NotifyBadgeCodePayResultRequestPayChannelDetailListFundToolDetailList()
.setFundToolName("优惠券")
.setAmount("1.00")
.setGmtCreate("2021-01-01")
.setGmtFinish("2021-01-01 11:11:11")
.setPromotionFundTool(true)
.setExtInfo("{\"key\":\"value\"}");
NotifyBadgeCodePayResultRequest.NotifyBadgeCodePayResultRequestPayChannelDetailList payChannelDetailList0 = new NotifyBadgeCodePayResultRequest.NotifyBadgeCodePayResultRequestPayChannelDetailList()
.setPayChannelName("卡余额")
.setGmtCreate("2021-01-01 11:11:11")
.setGmtFinish("2021-01-01 11:11:11")
.setPayChannelType("ALIPAY|BALANCE")
.setAmount("1.23")
.setPayChannelOrderNo("20211234")
.setPromotionAmount("0.00")
.setFundToolDetailList(java.util.Arrays.asList(
payChannelDetailList0FundToolDetailList0
));
NotifyBadgeCodePayResultRequest notifyBadgeCodePayResultRequest = new NotifyBadgeCodePayResultRequest()
.setPayCode("261234567890")
.setCorpId("ding1234")
.setUserId("userId1234")
.setGmtTradeCreate("2021-01-01 11:11:11")
.setGmtTradeFinish("2021-01-01 11:11:11")
.setTradeNo("202101012345678")
.setTradeStatus("SUCCESS/FAIL")
.setTitle("晚餐100.0元")
.setRemark("备注")
.setAmount("1234.56")
.setPromotionAmount("1.23,没有传0.00")
.setChargeAmount("1.00, 没有传0.00")
.setPayChannelDetailList(java.util.Arrays.asList(
payChannelDetailList0
))
.setTradeErrorCode("BALANCE_NOT_ENOUGH")
.setTradeErrorMsg("余额不足,请充值")
.setExtInfo("{ \"akey\": \"avalue“}")
.setMerchantName("XX公司食堂");
try {
client.notifyBadgeCodePayResultWithOptions(notifyBadgeCodePayResultRequest, notifyBadgeCodePayResultHeaders, new RuntimeOptions());
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
} catch (Exception _err) {
TeaException err = new TeaException(_err.getMessage(), _err);
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
}
}
● 身份验证场景,如门禁,访客,班车等级等,调用通知验证结果接口“/v1.0/badge/codes/verifyResults”,点击查看接口详情,Java代码样例:
// This file is auto-generated, don’t edit it. Thanks.
package com.aliyun.sample;
import com.aliyun.tea.*;
import com.aliyun.teautil.*;
import com.aliyun.teautil.models.*;
import com.aliyun.dingtalkbadge_1_0.*;
import com.aliyun.dingtalkbadge_1_0.models.*;
import com.aliyun.teaopenapi.*;
import com.aliyun.teaopenapi.models.*;
public class Sample {
/**
* 使用 Token 初始化账号Client
* @return Client
* @throws Exception
*/
public static com.aliyun.dingtalkbadge_1_0.Client createClient() throws Exception {
Config config = new Config();
config.protocol = "https";
config.regionId = "central";
return new com.aliyun.dingtalkbadge_1_0.Client(config);
}
public static void main(String[] args_) throws Exception {
java.util.List<String> args = java.util.Arrays.asList(args_);
com.aliyun.dingtalkbadge_1_0.Client client = Sample.createClient();
NotifyBadgeCodeVerifyResultHeaders notifyBadgeCodeVerifyResultHeaders = new NotifyBadgeCodeVerifyResultHeaders();
notifyBadgeCodeVerifyResultHeaders.xAcsDingtalkAccessToken = "<your access token>";
NotifyBadgeCodeVerifyResultRequest notifyBadgeCodeVerifyResultRequest = new NotifyBadgeCodeVerifyResultRequest()
.setPayCode("261234567890")
.setCorpId("corpxxxx")
.setUserCorpRelationType("INTERNAL_STAFF")
.setUserIdentity("180xxxx")
.setVerifyTime("2021-01-01 12:12:12")
.setVerifyResult(false)
.setVerifyLocation("钉工牌大道9号");
try {
client.notifyBadgeCodeVerifyResultWithOptions(notifyBadgeCodeVerifyResultRequest, notifyBadgeCodeVerifyResultHeaders, new RuntimeOptions());
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
} catch (Exception _err) {
TeaException err = new TeaException(_err.getMessage(), _err);
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
}
}