官网教程https://help.aliyun.com/document_detail/150017.html?spm=a2c4g.11186623.0.0.3168637fiVsJeJ
建议先看一遍官网教程。上面得每一步下面都会用到
需要准备得东西有:
1.使用AK&SK初始化账号Client。前提得开通服务
2.购买号码(进行拨号使用)。
3.提交自己需要得语音模板,每个语音模板创建后会有个模板ID。
4.确定自己用的是MNS得Queue模型还是发送网络请求得方式获取回执消息。
准备好以上东西好导入对应得依赖,下面依赖得版本根据自己拿到得jar版本进行改变。
<dependency>
<groupId>com.aliyungroupId>
<artifactId>tea-consoleartifactId>
<version>0.0.1version>
dependency>
<dependency>
<groupId>com.aliyungroupId>
<artifactId>darabonba-envartifactId>
<version>0.1.1version>
dependency>
<dependency>
<groupId>com.aliyungroupId>
<artifactId>tea-openapiartifactId>
<version>0.1.3version>
dependency>
<dependency>
<groupId>com.aliyungroupId>
<artifactId>dyvmsapi20170525artifactId>
<version>2.1.3version>
dependency>
<dependency>
<groupId>com.aliyungroupId>
<artifactId>tea-utilartifactId>
<version>0.2.13version>
dependency>
<dependency>
<groupId>com.aliyungroupId>
<artifactId>darabonba-numberartifactId>
<version>0.0.2version>
dependency>
<dependency>
<groupId>com.aliyungroupId>
<artifactId>teaartifactId>
<version>[1.1.13, 2.0.0)version>
dependency>
<dependency>
<groupId>com.aliyun.alicomgroupId>
<artifactId>alicom-mns-receive-sdkartifactId>
<version>1.0.1version>
<scope>systemscope>
<systemPath>${project.basedir}/src/main/resources/lib/alicom-mns-receive-sdk-1.0.1.jarsystemPath>
dependency>
<dependency>
<groupId>com.aliyun.mnsgroupId>
<artifactId>aliyun-sdk-mnsartifactId>
<version>1.1.8version>
<scope>systemscope>
<systemPath>${project.basedir}/src/main/resources/lib/aliyun-sdk-mns-1.1.8.jar
systemPath>
dependency>
<dependency>
<groupId>com.aliyungroupId>
<artifactId>aliyun-java-sdk-coreartifactId>
<version>3.2.2version>
<scope>systemscope>
<systemPath>${project.basedir}/src/main/resources/lib/aliyun-java-sdk-core-3.2.2.jar
systemPath>
dependency>
<dependency>
<groupId>com.aliyungroupId>
<artifactId>aliyun-java-sdk-dybaseapiartifactId>
<version>1.0.0version>
<scope>systemscope>
<systemPath>${project.basedir}/src/main/resources/lib/aliyun-java-sdk-dybaseapi-1.0.0.jar
systemPath>
dependency>
<dependency>
<groupId>commons-logginggroupId>
<artifactId>commons-loggingartifactId>
<version>1.1.1version>
<scope>systemscope>
<systemPath>${project.basedir}/src/main/resources/lib/commons-logging-1.1.1.jarsystemPath>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-lang3artifactId>
<version>3.1version>
<scope>systemscope>
<systemPath>${project.basedir}/src/main/resources/lib/commons-lang3-3.1.jarsystemPath>
dependency>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpasyncclientartifactId>
<version>4.1version>
<scope>systemscope>
<systemPath>${project.basedir}/src/main/resources/lib/httpasyncclient-4.1.jarsystemPath>
dependency>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpcoreartifactId>
<version>4.4.1version>
<scope>systemscope>
<systemPath>${project.basedir}/src/main/resources/lib/httpcore-4.4.1.jarsystemPath>
dependency>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpcore-nioartifactId>
<version>4.4.1version>
<scope>systemscope>
<systemPath>${project.basedir}/src/main/resources/lib/httpcore-nio-4.4.1.jarsystemPath>
dependency>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpclientartifactId>
<version>4.4.1version>
<scope>systemscope>
<systemPath>${project.basedir}/src/main/resources/lib/httpclient-4.4.1.jarsystemPath>
dependency>
<dependency>
<groupId>commons-codecgroupId>
<artifactId>commons-codecartifactId>
<version>1.9version>
<scope>systemscope>
<systemPath>${project.basedir}/src/main/resources/lib/commons-codec-1.9.jarsystemPath>
dependency>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<includeSystemScope>trueincludeSystemScope>
configuration>
plugin>
plugins>
build>
建议去下载个官方Demo项目,将其中得jar包获取出来放入自己得Spring项目中
建议创建一个实体类专门处理语音功能
@Component
@ConfigurationProperties(prefix = "voice")
@Data
@Slf4j
public class Voice implements MessageListener, CommandLineRunner {
@Value("${voice.accessKeyId}")
private String accessKeyId;
@Value("${voice.accessKeySecret}")
private String accessKeySecret;
@Value("${voice.calledShowNumber}")
private String calledShowNumber; //主叫号码
@Value("${voice.enable:false}")
private boolean enable; //是否开启语音功能
private String templateFirst; //模板
private String templateConfirm; //确认模板
private String templateRefuse; //拒绝模板
private String templateSecond; //模板XX
private static Log logger = LogFactory.getLog(Voice.class);
/**
* 使用AK&SK初始化账号Client
* @param accessKeyId
* @param accessKeySecret
* @return Client
* @throws Exception
*/
public Client createClient(String accessKeyId, String accessKeySecret) throws Exception{
Config config=new Config()
//您得AccessKey ID
.setAccessKeyId(accessKeyId)
//您得AccessKey Secret
.setAccessKeySecret(accessKeySecret);
//访问得域名
config.endpoint="dyvmsapi.aliyuncs.com";
return new Client(config);
}
/**
* @Author: OUO
* @DateTime: 2022/4/11 11:48
* @Description: 因为实现了CommandLineRunner接口。启动spring项目时会执行下面run方法得内容,用于注册回执消息用到得
*/
@Override
public void run(String... args) throws Exception {
if (enable){
DefaultAlicomMessagePuller puller = new DefaultAlicomMessagePuller();
//设置异步线程池大小及任务队列的大小,还有无数据线程休眠时间
puller.setConsumeMinThreadSize(6);
puller.setConsumeMaxThreadSize(16);
puller.setThreadQueueSize(200);
puller.setPullMsgThreadSize(1);
//和服务端联调问题时开启,平时无需开启,消耗性能
puller.openDebugLog(false);
/*
* TODO 将messageType和queueName替换成您需要的消息类型名称和对应的队列名称
*云通信产品下所有的回执消息类型:
*1:短信回执:SmsReport,
*2:短息上行:SmsUp
*3:语音呼叫:VoiceReport
*4:流量直冲:FlowReport
*/
String messageType = "VoiceReport";//此处应该替换成相应产品的消息类型
String queueName = "Alicom-Queue-XXXXXXXXXXX-VoiceReport";//在云通信页面开通相应业务消息后,就能在页面上获得对应的queueName,格式类似Alicom-Queue-xxxxxx-SmsReport
puller.startReceiveMsg(accessKeyId, accessKeySecret, messageType, queueName, this);
}
}
/**
* @Author: OUO
* @DateTime: 2022/3/14 14:36
* @Description: 语音IVR 类型为1的模板
* CalledShowNumber被叫显号--专门买了号码就填,否则不填
* CalledNumber接收语音通知的手机号码
* TtsCode已通过审核的语音验证码模板ID
* TtsParam模板中的变量参数
* PlayTimes一通电话内语音通知内容的播放次数
* Volume语音通知的播放音量
* Speed语速控制
* OutId发起请求时预留给调用方的自定义ID
* no此处是我自己这边业务需求所加,实际根据自己需求变更参数内容即可
*/
private void sendVoice(String phoneNumber, TestDO test,int no) throws Exception{
Map<String, String> map = new HashMap<>();
map.put("proName", "测试一"); //模板中变量参数1
map.put("proNameTwo", "测试二");//模板中变量参数2
map.put("proDate", DateUtil.format(new Date(),"yyyy-MM-dd HH:mm"));//模板中变量参数3
String params = JSON.toJSONString(map);
boolean mobile = Validator.isMobile(phoneNumber);
if (!mobile){
log.error("{}不是有效手机号码");
return;
}
IvrCallResponseBody body;
Date now=new Date();
try {
log.info("发送语音消息,OUO");
Client client=createClient(accessKeyId,accessKeySecret);
IvrCallRequest request=new IvrCallRequest();
//设置等待用户按键超时时间
request.setTimeout(1000*5);
//必填-被叫显号,可在语音控制台找到所购买的显号
// request.setCalledShowNumber(calledShowNumber);
request.setCalledShowNumber(calledShowNumber);
//必填-被叫号码
request.setCalledNumber(phoneNumber);
//设置播放次数
request.setPlayTimes(3L);
voiceSendRecordDO.setPlayTimes(3);
//必填-语音文件ID或者tts模板的模板号,有参数的模板需要设置模板变量的值
request.setStartCode(templateFirst);
//如果有模板里面包含变量参数,下面这个必填变量参数值
request.setStartTtsParams(params);
//设置按键触发得语音模板
List<IvrCallRequest.IvrCallRequestMenuKeyMap> menuKeyMaps=new ArrayList<>();
IvrCallRequest.IvrCallRequestMenuKeyMap menuKeyMap1=new IvrCallRequest.IvrCallRequestMenuKeyMap();
menuKeyMap1.setKey("1");
menuKeyMap1.setCode(templateConfirm);
menuKeyMaps.add(menuKeyMap1);
IvrCallRequest.IvrCallRequestMenuKeyMap menuKeyMap2=new IvrCallRequest.IvrCallRequestMenuKeyMap();
menuKeyMap2.setKey("2");
menuKeyMap2.setCode(templateRefuse);
menuKeyMaps.add(menuKeyMap2);
// IvrCallRequest.IvrCallRequestMenuKeyMap menuKeyMap3=new IvrCallRequest.IvrCallRequestMenuKeyMap();
// menuKeyMap3.setKey("3");
// menuKeyMap3.setTtsParams(params);
// menuKeyMap3.setCode(templateFirst);//再次播放一遍(待确认)
// menuKeyMaps.add(menuKeyMap3);
request.setMenuKeyMap(menuKeyMaps);
//可选-外部扩展字段-一般用于携带自己业务那个实体类得主键ID
request.setOutId(testDo.getId()+":"+no);
voiceSendRecordDO.setParams(JSON.toJSONString(request));
IvrCallResponse response=client.ivrCall(request);
//此处有可能有异常
body =response.getBody();
String code=body.code;
log.info("状态码:{}",code);
//todo 发送成功或者失败都给管理员发送信息
if ("OK".equalsIgnoreCase(code)){
log.info("状态码为OK");
//语音发送成功
log.info("语音发送成功,手机:{}",phoneNumber);
//todo 发送成功或者失败都给管理员发送信息
}else {
//发送失败
}
}catch (Exception e){
//发送失败,给超级管理员发送消息
e.printStackTrace();
// Map stringStringMap = JSON.parseObject(params, new TypeReference
String format = StrFormatter
.format("系统错误,发送语音给{}失败,号码:{},报错信息:{}",
"********","**********",e.getMessage()+"\n"+e.getCause());
//todo 给管理员发送通知,此处代码省略,根据自己得业务需求来
}finally {
//todo 记录日志,此处代码省略,根据自己得业务需求来
}
}
/**
* @Author: OUO
* @DateTime: 2022/4/11 12:09
* @Description: 此处我选择得是 阿里MNS的Queue模型来处理回执消息
*/
@Override
public boolean dealMessage(Message message) {
//消息的几个关键值
log.info("消息接收时间[{}],message handle[{}],body[{}],id[{}],dequeue count[{}]", null, message.getReceiptHandle(),
message.getMessageBodyAsString(), message.getMessageId(), message.getDequeueCount());
log.info("监听到语音回执消息------------------------------{}", message);
try {
Map < String, Object > contentMap = gson.fromJson(message.getMessageBodyAsString(), HashMap.class);
//TODO 根据文档中具体的消息格式进行消息体的解析
String callId = (String) contentMap.get("call_id"); //呼叫ID。
String startTime = (String) contentMap.get("start_time"); //通话接通时间,即被叫接起电话时间,未接通则为空。
String endTime = (String) contentMap.get("end_time"); //通话结束时间。
String caller = (String) contentMap.get("caller"); //主叫号码。
String callee = (String) contentMap.get("callee"); //被叫号码
String duration = (String) contentMap.get("duration"); //通话时长,单位为秒,未接通为0秒。
String statusCode = (String) contentMap.get("status_code"); //呼叫结果状态码
String earlyMediaCode = (String) contentMap.get("early_media_code"); //早媒体结果状态码(功能开启才会有),状态码说明请查看呼叫状态码。
String hangupDirection = (String) contentMap.get("hangup_direction");//挂断方向。取值:用户,机器
String statusMsg = (String) contentMap.get("status_msg"); //结果描述。
String outId = (String) contentMap.get("out_id"); //扩展字段回传
String dtmf = (String) contentMap.get("dtmf"); //DTMF按键。
String voiceType = (String) contentMap.get("voice_type"); //话单类型。取值voice为普通话单
String dialogId = (String) contentMap.get("dialog_id"); //话术ID,智能外呼SAAS助手专有。
String tollType = (String) contentMap.get("toll_type"); //通话类型。取值:LOCAL:市话~~
log.info("消息回执的code++++++++{}", statusCode);
// 这里开始编写业务代码
if (StrUtil.isEmpty(outId)){
return true;
}
//将绘制信息存入数据库
String[] split=outId.split(":");
String Id=split[0];
String no=split[1];
log.info("回执携带得参数是否正常:主键ID:{},no:{},statusCode:{}",Id,no,statusCode);
/** 判断是否呼叫结果返回正常 */
if (USER_CALL_SUCCESS.equals(statusCode)||USER_CALL_HANGUP.equals(statusCode)){
log.info("用户应答,状态码:{},用户按键操作:{}",statusCode,dtmf);
if ("1".equals(dtmf)){
//同意
log.info("用户同意操作,状态:{}",Constant.EXTRACT_NOTICE_ACCEPT_CODE);
//业务代码此处省略
}else if ("2".equals(dtmf)){
//不同意
log.info("用户同意操作,状态:{}",Constant.EXTRACT_NOTICE_REFUSE_CODE);
//业务代码此处省略
}else if ("3".equals(dtmf)){
//重听一遍语音
log.info("用户重听操作,啥都不干");
//业务代码此处省略
}else{
//其他情况
//业务代码此处省略
}
//业务代码此处省略
} else {
log.info("用户无法接通或者拒接{}",callee);
//用户无法接通,业务代码省略
}
} catch (com.google.gson.JsonSyntaxException e) {
logger.error("error_json_format:" + message.getMessageBodyAsString(), e);
//理论上不会出现格式错误的情况,所以遇见格式错误的消息,只能先delete,否则重新推送也会一直报错
return true;
} catch (Throwable e) {
e.printStackTrace();
//您自己的代码部分导致的异常,应该return false,这样消息不会被delete掉,而会根据策略进行重推
log.error("系统内部异常,消息重试.");
return false;
}finally {
//存入到日志表中
//业务代码此处省略
}
log.info("清除本条回执消息");
//消息处理成功,返回true, SDK将调用MNS的delete方法将消息从队列中删除掉
return true;
}
}
以上就是示例代码了,若有疑问可在评论区留言,我看到有空会回复