引入SDK依赖

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-outboundbot</artifactId>
    <version>1.0.4</version>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.5.17</version>
</dependency>

获取实例ID和话术ID

参照用户指南创建外呼实例和外呼话术后,在话术详情页面可以获取到实例ID和话术ID。参见下图:

创建任务组

/**
 *  任务组(JobGroup)是任务的逻辑分组,可以根据业务实际情况,按照时间或者人群等维度划分.
 */
public class CreateJobGroup {

    public static void main(String[] args) throws ClientException {
        DefaultProfile profile = DefaultProfile.getProfile("cn-shanghai", "<accessKeyId>", "<accessSecret>");
        IAcsClient client = new DefaultAcsClient(profile);

        CreateJobGroupRequest request = new CreateJobGroupRequest();
        request.setJobGroupName("第一个作业组");
        request.setInstanceId("<InstanceId>");
        request.setScriptId("<ScriptId>");
        request.setStrategyJson(JSON.toJSONString(createStrategy()));

        try {
            CreateJobGroupResponse response = client.getAcsResponse(request);
            System.out.println(JSON.toJSONString(response));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
        }
    }

    /**
     * AssignJobs接口也可以传入Strategy参数.
     * Strategy优先级为: AssignJobs > CreateJobGroup.
     * @return
     */
    private static JSONObject createStrategy() {
        JSONObject strategy = new JSONObject();
        strategy.put("maxAttemptsPerDay", 3);
        strategy.put("minAttemptInterval", 10);
        strategy.put("name", UUID.randomUUID().toString());
        strategy.put("startTime", System.currentTimeMillis());
        strategy.put("endTime", System.currentTimeMillis() + 60 * 60 * 1000L);
        return strategy;
    }
}

批量下发任务

/**
 * 可使用AssignJobs循环多次向同一任务组下发任务,每次下发任务数建议25个job.
 */
public class AssignJobs {

    public static void main(String[] args) {
        DefaultProfile profile = DefaultProfile.getProfile("cn-shanghai", "<accessKeyId>", "<accessSecret>");
        IAcsClient client = new DefaultAcsClient(profile);

        AssignJobsRequest request = new AssignJobsRequest();
        request.setInstanceId("<InstanceId>");
        request.setJobGroupId("<JobGroupId>");
        request.setJobsJsons(createJobsJson());

        try {
            AssignJobsResponse response = client.getAcsResponse(request);
            System.out.println(JSON.toJSONString(response));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
        }
    }

    /**
     *  JobsJson.N是个List,每个JobJson对应一个联系人(contact)。
     * @return
     */
    private static List<String> createJobsJson() {
        JSONObject contact = new JSONObject();
        contact.put("phoneNumber", "135*********");
        contact.put("honorific", "张先生");
        contact.put("name", "张三");
        contact.put("referenceId", UUID.randomUUID().toString());

        List<JSONObject> extras = new ArrayList<>();
        extras.add(new JSONObject().fluentPut("key", "自定义参数1").fluentPut("value", "1"));
        extras.add(new JSONObject().fluentPut("key", "自定义参数2").fluentPut("value", "2"));

        JSONObject job = new JSONObject();
        job.put("contacts", Collections.singletonList(contact));
        job.put("extras", extras);

        List<String> jobs = new ArrayList<>();
        jobs.add(JSON.toJSONString(job));
        return jobs;
    }
}

任务完成消息

对于每个外呼任务的呼叫完成状态,智能外呼服务会通过消息队列(RocketMQ)的方式通知给调用方。消息中会返回任务Id,外呼任务的状态(接通/无人接听/呼叫失败)等。

消息队列提供两种方式:

  1. 消息推送到外呼服务公共的消息队列中,接入方订阅消息。
  2. 消息推送到接入方在阿里云购买的RocketMQ,授权给智能外呼推送消息的权限。接入方订阅消息。

数据安全考虑,建议采用第二种。

消息体如下:

status枚举值见JobStatus

failureReason枚举值见FailureReason

task.status枚举值见TaskStatus
{
    "contacts":[
        {
            "honorific":"test",
            "id":"762c2e16-1043-4584-9a7c-00a0f13372b1",
            "jobUuid":"08a4c460-525a-4833-a20f-737e069a154f",
            "name":"test",
            "phoneNumber":"11111111",
            "referenceId":"4178"
        }
    ],
    "failureReason":"NoAnswer",
    "groupId":"8869f35d-a310-4b4e-8786-9b46437bc0fa",
    "id":"08a4c460-525a-4833-a20f-737e069a154f",
    "instanceId":"9b9a3318-ff97",
    "status":"Failed",
    "tasks":[
        {
            "callId":"8946e90530914cd2b902a75b50898767",
            "id":"60b48efe-3284-4797-8851-5d6b70479641",
            "status":"NoAnswer"
        }
    ]
}
# JobStatus #
- Scheduling(0) 调度中
- Executing(1) 执行中
- Succeeded(2) 成功
- Paused(3) 挂起
- Failed(4) 失败
- Cancelled(5) 已取消

# FailureReason #
- Unknown(0) 未知错误
- NoAnswer(1) 无人接听
- InvalidStrategy(2) 无效的策略,策略配置不正确
- TimeUp(3) 调度时发现超时
- NoStrategy(4) 策略为空或没有找到
- CallFailed(5) 呼叫失败

# TaskStatus  #
- Executing(0) 正在拨打
- Succeeded(1) 成功
- NoAnswer(2) 无人接听
- NotExist(3)  联系人号码不存在
- Busy(4) 占线
- Cancelled(5) 已经取消
- Failed(6) 呼叫失败