钉钉新版服务端修改流程Task状态( 同意或拒绝审批流程 )API调用的大坑

文章目录

  • 1.背景
  • 2.新版服务端的java依赖
  • 3.接入流程
    • 3.1 创建企业内部应用
    • 3.2 获取AppKey和AppSecret
    • 3.3 添加接口权限
    • 3.4 获取应用访问凭证accessToken
    • 3.5 调用服务端OA相关API
  • 4.问题及其解决办法
  • 5.新版API相关代码分享

1.背景

  由于之前做了一个财务收付款关联管理的项目中接入了钉钉流程,用户会通过手机端提交一些钉钉收付款的流程,通过第三方接入的内部的酷应用实现自动化的控制,当用户提交的流程已经走到财务出纳审批的时候,到这一步会在我们后台中进行收付款的关联,然后会进行调用钉钉的流程接口去自动更改出纳这一步的task任务的状态的操作,这一步骤看似简单只要按照官方给的实列代码调用接口即可,其实不然,里面暗藏这很大的坑,官方也没有给出明确的说明,只有自己亲子踩过之后才知道,遇到这种无法解决的报错就算给官方提几个工单,没有付费官方人员也不晓得是啥问题,随便回复下你,这就是没有付费使用官方的态度,找个技术支持都找不到,这一步骤是这个项目的关键,调试了半个月都没啥进展,最后问题还是在官方的文档上找到的,参看下面第3点接入流程的第5点调用服务端OA相关API里面有相关新版流程和旧版流程的分辨,这一点恰恰是解决该问题的关键。

2.新版服务端的java依赖

       <dependency><groupId>com.aliyun</groupId><artifactId>dingtalk</artifactId><version>1.4.89</version></dependency>

3.接入流程

官方说明
https://open.dingtalk.com/document/orgapp-server/approve-or-reject-the-new-version

3.1 创建企业内部应用

在这里插入图片描述

3.2 获取AppKey和AppSecret

在这里插入图片描述

3.3 添加接口权限

在这里插入图片描述

3.4 获取应用访问凭证accessToken

  注意:服务端API差异详情参见新旧版规范服务端API区别。

  • 服务端API接口SDK下载,详情参见服务端SDK下载。
  • 新版服务端API接口SDK下载,详情参见新版服务端SDK下载。

  以下接口均使用服务端API接口,SDK下载详情参见新版服务端SDK。

  根据步骤二中的AppKey和AppSecret,获取应用访问凭证获取企业内部应用的accessToken。

 public void getAccessToken() throws Exception {Config config = new Config();config.protocol = "https";config.regionId = "central";com.aliyun.dingtalkoauth2_1_0.Client client = new com.aliyun.dingtalkoauth2_1_0.Client(config);GetAccessTokenRequest accessTokenRequest = new GetAccessTokenRequest().setAppKey("din*********hgn").setAppSecret("9G_O************mBkhgGIO");GetAccessTokenResponse accessToken = client.getAccessToken(accessTokenRequest);System.out.println(JSON.toJSONString(accessToken.getBody()));}

3.5 调用服务端OA相关API

  调用新版服务端API-创建或更新审批表单模板接口,获取模板的唯一编码processCode

  说明 :若没有保存接口返回的模板编码processCode,钉钉管理后台版本不同,获取processCode的方式不同。登录钉钉管理后台,在首页查看版本。如下图所示,页面展示回到旧版新版反馈,说明当前是新版。 审批获取processCode

   新版钉钉管理后台:在审批模板编辑页-基础设置-页面底部查看。 OA审批-使用案例-审批附件-新增获取processcode新旧版方式

  旧版钉钉管理后台:在审批模板编辑页的URL中查看。

processCode

4.问题及其解决办法

  问题一:“errcode”:88,“sub_code”:“60011”,“sub_msg”:"没有调用该接口的权限

{"errcode":88,"sub_code":"60011","sub_msg":"没有调用该接口的权限,接口权限申请参考:https://open.dingtalk.com/document/orgapp-server/add-api-permission","errmsg":"ding talk error[subcode=60011,submsg=没有调用该接口的权限,接口权限申请参考:https://open.dingtalk.com/document/orgapp-server/add-api-permission]","request_id":"15rf1m82ty8nz"}
DingTalkClient client = new DefaultDingTalkClient(dingDingOldApiUrlConfig.getTaskUpdateUrl());OapiProcessWorkrecordTaskUpdateRequest req = new OapiProcessWorkrecordTaskUpdateRequest();OapiProcessWorkrecordTaskUpdateRequest.UpdateTaskRequest obj1 = new OapiProcessWorkrecordTaskUpdateRequest.UpdateTaskRequest();obj1.setAgentid(agentId);obj1.setProcessInstanceId(processInstanceId);List<OapiProcessWorkrecordTaskUpdateRequest.TaskTopVo> list3 = new ArrayList<OapiProcessWorkrecordTaskUpdateRequest.TaskTopVo>();OapiProcessWorkrecordTaskUpdateRequest.TaskTopVo obj4 = new OapiProcessWorkrecordTaskUpdateRequest.TaskTopVo();obj4.setTaskId(taskId);obj4.setStatus(status);obj4.setResult(result);list3.add(obj4);obj1.setTasks(list3);req.setRequest(obj1);OapiProcessWorkrecordTaskUpdateResponse rsp = null;try {rsp = client.execute(req, this.getOldAccessToken());log.info("TaskUpdate.req:{}",JSON.toJSONString(req));if (Objects.nonNull(rsp) && StringUtils.isNotEmpty(rsp.getCode()) && rsp.isSuccess()) {log.info("TaskUpdate.result:true");return Boolean.TRUE;}} catch (ApiException e) {log.error(e.getMessage());}

  该问题是流程表单是旧版本的流程,修改流程任务状态的接口用的自有OA审批的接口,所以需要将接口换成官方OA审批的接口。

  问题二:com.aliyun.tea.TeaException: code: 400, 审批状态异常,无法执行

com.aliyun.tea.TeaException: code: 400, 审批状态异常,无法执行 request id: 9BE05FB8-1253-7C11-994E-43A49C08B294	at com.aliyun.teaopenapi.Client.doROARequest(Client.java:403)	at com.aliyun.dingtalkworkflow_1_0.Client.executeProcessInstanceWithOptions(Client.java:345)

  该问题是流程表单是旧版本的流程,使用的是新版的API导致的,正确的做法是新建一个新版本的流程然后提交一个钉钉流程实例然后在使用这个新版的流程的实例id,去修改这个流程实列的Task中的某一个任务的状态即可,这个官方文档也没有明文说明,老版本的流程没有这个API,所以使用的老版本的流程在调用新版的API来修改流程实列的任务状态就会报这个错,给官方提了工单也是好几天才回复,他们也就随便应付下,他们都不晓得是啥问题,只能靠自己来解决问题了,没有出钱想要找到技术支持那是白日做梦,就想着白嫖,人家官方的态度就是随便应付一下我们,真TMD坑,当时是心中有万马奔腾但是问题还是得解决。

5.新版API相关代码分享

DingDingConfig配置类

@Data
@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "dingding")
public class DingDingConfig {private List<DingDingProperties> ddp;}

DingDingProperties类

@Data
public class DingDingProperties {private String appKey;private String appSecret;}

新版api代码接口

@Service
@Slf4j
public class DingDingServiceImpl{@Autowiredprivate DingDingConfig dingDingConfig;//获取token接口@Overridepublic String getAccessToken() {List<DingDingProperties> ddp = dingDingConfig.getDdp();if (CollectionUtils.isEmpty(ddp)) {throw new RuntimeException("请检查钉钉配置");}DingDingProperties dingDingProperties = ddp.get(0);Config config = new Config();config.protocol = "https";config.regionId = "central";try {com.aliyun.dingtalkoauth2_1_0.Client client = new com.aliyun.dingtalkoauth2_1_0.Client(config);GetAccessTokenRequest getAccessTokenRequest = new GetAccessTokenRequest().setAppKey(dingDingProperties.getAppKey()).setAppSecret(dingDingProperties.getAppSecret());GetAccessTokenResponse accessToken = client.getAccessToken(getAccessTokenRequest);if (Objects.nonNull(accessToken) && Objects.nonNull(accessToken.getBody())) {GetAccessTokenResponseBody body = accessToken.getBody();log.info("DingDing accessToken :{}", body);if (StringUtils.isNotEmpty(body.getAccessToken())) {return body.getAccessToken();}}} catch (TeaException err) {if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {// err 中含有 code 和 message 属性,可帮助开发定位问题}log.error(err.getMessage());} 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 属性,可帮助开发定位问题}log.error(_err.getMessage());}return null;}//根据流程实例id获取流程实例@Overridepublic GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult getProcessInstance(String processInstanceId) {log.info("getProcessInstance.param:{}", processInstanceId);com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();config.protocol = "https";config.regionId = "central";try {com.aliyun.dingtalkworkflow_1_0.Client client = new com.aliyun.dingtalkworkflow_1_0.Client(config);com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceHeaders getProcessInstanceHeaders = new com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceHeaders();getProcessInstanceHeaders.xAcsDingtalkAccessToken = this.getAccessToken();com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceRequest getProcessInstanceRequest = new com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceRequest().setProcessInstanceId(processInstanceId);GetProcessInstanceResponse processInstanceWithOptions = client.getProcessInstanceWithOptions(getProcessInstanceRequest, getProcessInstanceHeaders, new RuntimeOptions());if (Objects.nonNull(processInstanceWithOptions)) {GetProcessInstanceResponseBody body = processInstanceWithOptions.getBody();if (Objects.nonNull(body) && Objects.nonNull(body.getSuccess()) && body.getSuccess().equals("true")) {GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult result = body.getResult();log.info("getProcessInstance.result :{}", result);return result;}}} catch (TeaException err) {if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {// err 中含有 code 和 message 属性,可帮助开发定位问题}log.error(err.getMessage());} 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 属性,可帮助开发定位问题}log.error(err.getMessage());}return null;}//更新流程task的状态@Overridepublic Boolean TaskUpdate(String processInstanceId, Long taskId, String actionerUserId, String result) {log.info("TaskUpdate.processInstanceId:{},taskId:{},actionerUserId:{},result:{}", processInstanceId, taskId, actionerUserId, result);try {com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();config.protocol = "https";config.regionId = "central";com.aliyun.dingtalkworkflow_1_0.Client client = new com.aliyun.dingtalkworkflow_1_0.Client(config);com.aliyun.dingtalkworkflow_1_0.models.ExecuteProcessInstanceHeaders executeProcessInstanceHeaders = new com.aliyun.dingtalkworkflow_1_0.models.ExecuteProcessInstanceHeaders();executeProcessInstanceHeaders.xAcsDingtalkAccessToken = this.getAccessToken();/*com.aliyun.dingtalkworkflow_1_0.models.ExecuteProcessInstanceRequest.ExecuteProcessInstanceRequestFileAttachments fileAttachments0 = new com.aliyun.dingtalkworkflow_1_0.models.ExecuteProcessInstanceRequest.ExecuteProcessInstanceRequestFileAttachments().setSpaceId("123").setFileSize("1024").setFileId("B1oQixxxx").setFileName("文件名称。").setFileType("file");com.aliyun.dingtalkworkflow_1_0.models.ExecuteProcessInstanceRequest.ExecuteProcessInstanceRequestFile file = new com.aliyun.dingtalkworkflow_1_0.models.ExecuteProcessInstanceRequest.ExecuteProcessInstanceRequestFile().setPhotos(java.util.Arrays.asList("https://url1")).setAttachments(java.util.Arrays.asList(fileAttachments0));*/com.aliyun.dingtalkworkflow_1_0.models.ExecuteProcessInstanceRequest executeProcessInstanceRequest = new com.aliyun.dingtalkworkflow_1_0.models.ExecuteProcessInstanceRequest().setProcessInstanceId(processInstanceId).setRemark("同意。").setResult(result).setActionerUserId(actionerUserId).setTaskId(taskId);//.setFile(file);ExecuteProcessInstanceResponse rsp = client.executeProcessInstanceWithOptions(executeProcessInstanceRequest, executeProcessInstanceHeaders, new RuntimeOptions());if (Objects.nonNull(rsp)) {ExecuteProcessInstanceResponseBody body = rsp.getBody();if (Objects.nonNull(body) && body.getSuccess() && body.getResult()) {log.info("TaskUpdate.result:true");return Boolean.TRUE;}}} catch (TeaException err) {if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {// err 中含有 code 和 message 属性,可帮助开发定位问题}err.printStackTrace();log.error(err.getMessage());} 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 属性,可帮助开发定位问题}err.printStackTrace();log.error(err.getMessage());}return Boolean.FALSE;}//获取流程审批的附件下载地址@Overridepublic String getDingDingProcessFileDownLoadUrl(String processInstanceId, String fileId) {log.info("getDingDingProcessFileDownLoadUrl.processInstanceId:{},fileId:{}", processInstanceId, fileId);com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();config.protocol = "https";config.regionId = "central";try {String token = this.getAccessToken();com.aliyun.dingtalkworkflow_1_0.Client client = new com.aliyun.dingtalkworkflow_1_0.Client(config);com.aliyun.dingtalkworkflow_1_0.models.GrantProcessInstanceForDownloadFileHeaders grantProcessInstanceForDownloadFileHeaders = new com.aliyun.dingtalkworkflow_1_0.models.GrantProcessInstanceForDownloadFileHeaders();grantProcessInstanceForDownloadFileHeaders.xAcsDingtalkAccessToken = token;com.aliyun.dingtalkworkflow_1_0.models.GrantProcessInstanceForDownloadFileRequest grantProcessInstanceForDownloadFileRequest = new com.aliyun.dingtalkworkflow_1_0.models.GrantProcessInstanceForDownloadFileRequest().setProcessInstanceId("FTTrgrqLRGa0MN2cvNnKFw07551665450943").setFileId("70572744764");GrantProcessInstanceForDownloadFileResponse grantProcessInstanceForDownloadFileResponse = client.grantProcessInstanceForDownloadFileWithOptions(grantProcessInstanceForDownloadFileRequest, grantProcessInstanceForDownloadFileHeaders, new RuntimeOptions());if (Objects.nonNull(grantProcessInstanceForDownloadFileResponse) && Objects.nonNull(grantProcessInstanceForDownloadFileResponse.getBody())) {GrantProcessInstanceForDownloadFileResponseBody body = grantProcessInstanceForDownloadFileResponse.getBody();if (body.getSuccess()) {log.info("spaceId:{}", body.getResult().getSpaceId());log.info("fileId:{}", body.getResult().getFileId());log.info("downloadUri:{}", body.getResult().getDownloadUri());return body.getResult().getDownloadUri();}}} catch (TeaException err) {if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {// err 中含有 code 和 message 属性,可帮助开发定位问题}log.error(err.getMessage());} 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 属性,可帮助开发定位问题}log.error(_err.getMessage());}return "";}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/37329.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python/Django对接dingtalk-sdk企业内部开发对接钉钉过程手记

前提 需要拥有管理员账号或获得开发者权限 准备 钉钉方面 1. 创建钉钉应用 钉钉开放平台——应用开发——钉钉应用——创建应用 2. 记录应用凭证 记录应用的AgentId、AppKey、AppSecret 3. 打开应用权限 打开需要获取数据的接口权限 开发环境方面 1.安装依赖库 dingta…

钉钉发送消息 java

1、完成钉钉认证才能使用此功能 2、需要登录控制台进行创建应用操作 https://open-dev.dingtalk.com/fe/app 3、需要设置 权限范围及通讯录权限设置 参考 https://www.ngui.cc/el/778161.html?actiononClick pom <dependency><groupId>com.aliyun</groupId&g…

PHP 通过钉钉API向员工推送消息(以工作通知的形式)

通过钉钉 API 向员工推送消息分为多种形式, 今天只以工作通知的形式讲述。 第一步: 进入 钉钉开放平台 注册账号按照流程操作即可 进入开发者后台后需要进行创建应用(之所以创建应用, 是因为以应用为一个 demo) 第二步:创建应用(今天以创建小程序为例) 第三步: 获取企业内部…

LzDingTalk-免费的钉钉机器人框架

LzDingTalk-是一款免费的钉钉机器人框架 1.异常处理规则 2.稳定不易掉线 3.哈希多线程处理 再多消息也能轻松应对 4.框架完全免费&#xff0c;用爱发电&#xff01; 5.多样式API支持二次开发插件&#xff01; 蓝奏下载地址&#xff1a;DingTalk 密码&#xff1a;6jbd界面展示&a…

禅道接入钉钉工作通知与钉钉群机器人二次开发代码详解

目录 禅道接入钉钉工作通知与钉钉群机器人 一、钉钉工作通知使用步骤 1.进入钉钉管理后台工作台添加自建应用进入开发者平台 2.禅道中得操作 3.接收到消息 二、钉钉群机器人使用步骤 1.钉钉群进行设置群机器人 2.禅道设置 三、禅道二次开发添加新功能进行工作通知和群机…

推送Markdown格式信息到钉钉机器人

1.自定义机器人设置 根据钉钉官方开放文档进行自定义机器人的配置&#xff0c;文档地址为&#xff1a;自定义机器人接入 - 钉钉开放平台 (dingtalk.com) 2.Markdown推送形式 Markdown类型 参数说明 3.Markdown图片格式 Markdown中可以使用url连接的图片进行推送&#xff0c…

Java项目如何接入钉钉群机器人

创建群机器人&#xff1a;对于任意我们所在的群&#xff0c;我们都可以创建自己的机器人&#xff0c;不需要群主权限&#xff0c;每个机器人信息只能自己看到。 我们项目通过对应的链接调用机器人发送消息。 创建对应的鉴权方式&#xff0c; 关键字只要消息内容携带即可&…

雷军入局ChatGPT大战/ AutoGPT星标超PyTorch/ 马斯克星舰今晚发射…今日更多新鲜事在此...

h日报君 发自 凹非寺量子位 | 公众号 QbitAI 大家好&#xff0c;今天是4月17日星期一&#xff0c;新的一周要元气满满哦~ 今天科技圈有哪些新鲜事儿&#xff0c;和日报君一起来看看~ 马斯克星舰今晚发射&#xff1a;将进行直播&#xff0c;此前曾延期 SpaceX官网发布通告称&…

[论文阅读] Collaborative and Adversarial Learning of Focused and Dispersive Representation

[论文地址] [代码] [ICCV 21] Abstract 从结肠镜图像中自动分割息肉是计算机辅助诊断结直肠癌的一个重要步骤。近年来报道的大多数息肉分割方法都是基于完全监督的深度学习。然而&#xff0c;医生在诊断过程中对息肉图像的注释是非常耗时和昂贵的。在本文中&#xff0c;我们提…

2000元训练比肩ChatGPT的开源大模型!GPT-4亲自盖章认证,模型权重均可下载

鱼羊 编辑整理量子位 | 公众号 QbitAI 2000块&#xff0c;调教出一个达到ChatGPT九成功力的开源大模型。 还是被GPT-4亲自盖章认证实力的那种。 这事儿&#xff0c;一群主要来自加州大学伯克利分校的研究人员做到了。 如图中所见&#xff0c;这个模型名叫Vicuna &#xff08;小…

chatgpt赋能python:Python处理雷达基数据:从入门到实践

Python处理雷达基数据&#xff1a;从入门到实践 随着气象技术的不断发展&#xff0c;雷达探测技术已成为当今天气预报和气象研究的主要手段之一。雷达基数据是气象雷达接收到的未经加工的原始数据&#xff0c;因其包含大量天气信息&#xff0c;不仅在天气预报、天气预警等方面…

推演语言模型的大小与计算开销

2020年&#xff0c;OpenAI提出了在增加模型尺寸与提高模型性能之间的扩展定律&#xff0c;指出人们应该将大部分预算用于扩大模型规模。这篇论文直接推动了增大模型规模的浪潮。然而&#xff0c;在预算和内存有限的情况下&#xff0c;盲目扩大模型规模并不是提升模型性能的最佳…

codesblocks头文件的正确使用

之前对头文件如何引用一直百思不得其解&#xff0c;现在弄懂了&#xff0c;来复盘一下。关键点在于要建立工程文件。 下面以一个长度转换的程序来简单说明。 第一步&#xff0c;建立C语言项目。 在新建项目点击Console applicaton&#xff0c;接着打上名称&#xff0c;默认设置…

jdbc工具类的定义和使用

DBUtils的定义 导入3个jar包 代码实现 public class DBUtils {//1.配置数据库连接信息&#xff08;MySQL&#xff09;//数据库驱动private static final String DRIVER "com.mysql.jdbc.Driver";//数据库名private static final String DATABASE "test_db&q…

Servlet的介绍与使用

Servlet简介 servlet是运行在服务器上的应用程序&#xff0c; 它的作用是实现前端与后台的数据交互。 Servlet生命周期 三个方法 init()&#xff1a;初始化 service()&#xff1a;处理客户端请求 destroy()&#xff1a;终止 工作原理 客户端向服务器发送一个http请求服务器…

python破解md5_python怎么使用md5加密解密

python采用hashlib这个标准库实现MD5加密解密。方法是:1、updata传数据;2、利用hexdigest进行16进制转换; update(arg)传入arg对象来更新hash的对象。必须注意的是,该方法只接受byte类型,否则会报错。这就是要在参数前添加b来转换类型的原因。 同时要注意,重复调用update…

分布式任务调度平台XXL-JOB的简单使用

推荐使用xxl2.2.0版本 参考地址: 分布式任务调度平台XXL-JOB xxl-job安装到本地打开项目工程对yml配置文件进行修改 主要修改数据库地址和告警邮件地址 将服务注册到xxl-job -如果在xxl里配置了accessToken 服务里就需要使用同样的Token 注册到xxl-job-admin之后打开xxl可视…

selenium获取页面数据入数据库

Selenium是一个用于Web应用程序测试的工具&#xff0c;但是也可以爬取页面中的数据。 开发环境是内网&#xff08;局域网&#xff09;&#xff0c;项目工程是web项目&#xff0c;jdk使用的1.8&#xff0c;tomcat使用的 8。 web项目&#xff1a; 启动时使用tomcat&#xff0c;…

ChatGPT 教我用 200 行代码写一个简版 Vue 框架 - OpenTiny

AI 是未来最好的老师 最近&#xff0c;我正在准备一份关于 Vue 基础的学习材料。期间我突发奇想&#xff1a;能否利用现在热门的 ChatGPT 帮我创建学习内容&#xff1f;其实 Vue 本身不难学&#xff0c;特别是基础用法&#xff0c;但是&#xff0c;如果你想深入掌握 Vue&#…

阿里云AliGenie开发天猫语音功能-入门篇

文章目录结构如下 登录应用开发平台 创建语音技能 云开发部署后端技能服务 语音技能测试 下线不必要的应用 一、登录应用开发平台 1.登录云开发平台。打开网址 https://workbench.aliyun.com/&#xff0c;使用阿里云账号登录&#xff0c;按照提示创建团队&#xff0c;点…