Bitzsoft.Integrations.OutboundCall 1.0.0-alpha.10

This is a prerelease version of Bitzsoft.Integrations.OutboundCall.
dotnet add package Bitzsoft.Integrations.OutboundCall --version 1.0.0-alpha.10
                    
NuGet\Install-Package Bitzsoft.Integrations.OutboundCall -Version 1.0.0-alpha.10
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Bitzsoft.Integrations.OutboundCall" Version="1.0.0-alpha.10" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Bitzsoft.Integrations.OutboundCall" Version="1.0.0-alpha.10" />
                    
Directory.Packages.props
<PackageReference Include="Bitzsoft.Integrations.OutboundCall" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Bitzsoft.Integrations.OutboundCall --version 1.0.0-alpha.10
                    
#r "nuget: Bitzsoft.Integrations.OutboundCall, 1.0.0-alpha.10"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Bitzsoft.Integrations.OutboundCall@1.0.0-alpha.10
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Bitzsoft.Integrations.OutboundCall&version=1.0.0-alpha.10&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Bitzsoft.Integrations.OutboundCall&version=1.0.0-alpha.10&prerelease
                    
Install as a Cake Tool

Bitzsoft.Integrations.OutboundCall

外呼服务抽象层 — 统一 IOutboundCallService 接口、号码工具(清洗 / 分类 / 校验)、境内外分离、白名单 / 黑名单控制、per-call 活动编排引擎。

功能特性

  • 统一外呼接口 IOutboundCallService:创建活动、导入名单、启动 / 暂停 / 恢复 / 停止、活动列表 / 详情、话单查询
  • 号码校验 PhoneNumberValidator:内置 150+ 国家 / 地区 ITU 号码长度表,支持全角字符、中文 / 英文标签前缀、/ , ; 空格换行分隔符等多种容错场景,自动识别 +86 / 0086 / (+86) 等区号前缀组合
  • 号码批量分类 PhoneNumberClassifier:将混合号码列表按区号自动分为境内(86)与境外两组,返回统一清洗格式
  • 白名单 / 黑名单过滤 CallListFilter:创建活动前自动过滤号码,支持后缀匹配;非生产环境可强制要求白名单,防止误呼叫真实客户
  • 境内外分离OutboundCallOptions.GetCallers / GetSdkAppId / GetIvrIdPhoneRegion 自动选择主叫号码、应用 ID、IVR 流程
  • per-call 编排引擎 CampaignDialer + CampaignRuntime:为无原生 campaign 概念的供应商(Twilio 等)提供串行拨号 + CPS 节流 + 暂停 / 恢复断点(代次守卫)+ 停止的内存活动编排
  • 统一异常模型 OutboundCallException:携带供应商标识、错误码、请求 ID,便于问题溯源
  • 供应商标识 ProviderName:每个实现暴露固定标识(如 Tencent / Aliyun),用于日志区分与异常溯源

安装

.NET CLI

dotnet add package Bitzsoft.Integrations.OutboundCall

PackageReference

<PackageReference Include="Bitzsoft.Integrations.OutboundCall" Version="1.0.0" />

配置

抽象层本身不注册服务,但 OutboundCallOptions 是所有供应商实现共享的配置契约,供应商实现通过 services.Configure<OutboundCallOptions>(...) 绑定。以下 JSON 是该选项类的完整字段(节名由各供应商扩展方法决定,通常为 OutboundCall)。

appsettings.json

{
  "OutboundCall": {
    "AccessKeyId": "your-secret-id",
    "AccessKeySecret": "your-secret-key",
    "Region": "ap-guangzhou",
    "Endpoint": null,
    "SdkAppId": "1400818883",
    "Callers": [ "008602160662606" ],
    "OverseaCallers": [ "0085230087235" ],
    "CnIvrId": 21232,
    "EnIvrId": 21408,
    "OverseaSdkAppId": "1400818885",
    "OverseaCnIvrId": null,
    "OverseaEnIvrId": null,
    "Whitelist": [ "5678" ],
    "Blacklist": [ "008613800000000" ],
    "RequireWhitelistInNonProduction": true,
    "ExtraProperties": {}
  }
}
配置项 说明 必填 默认值
AccessKeyId API 密钥 ID(腾讯 SecretId / 阿里 AccessKeyId / 容联 AccountSid) 空字符串
AccessKeySecret API 密钥(腾讯 SecretKey / 阿里 AccessKeySecret / 容联 AuthToken) 空字符串
Region 地域(如 ap-guangzhou / cn-hangzhou / cn-north-4 空字符串(各供应商使用各自默认地域)
Endpoint API 端点覆盖 null(各供应商使用内置默认端点)
SdkAppId 应用 ID(腾讯 SdkAppId / 阿里 InstanceId / 容联 AppId) 视供应商 null
Callers 境内主叫号码列表(中国大陆外呼) 空列表
OverseaCallers 境外主叫号码列表(海外外呼) 空列表
CnIvrId 中文 IVR 流程 ID(境内呼叫) 视供应商 null
EnIvrId 英文 IVR 流程 ID(境外呼叫) 视供应商 null
OverseaSdkAppId 境外独立应用 ID(与境内不同时使用) null
OverseaCnIvrId 境外中文 IVR 流程 ID null
OverseaEnIvrId 境外英文 IVR 流程 ID null
Whitelist 外呼白名单(仅允许呼叫这些号码,支持后缀匹配) null
Blacklist 外呼黑名单(禁止呼叫这些号码) null
RequireWhitelistInNonProduction 非生产环境是否强制要求白名单 true
ExtraProperties 供应商特有扩展参数 null

注册服务

抽象层不提供 AddBitzsoft* 扩展方法。实际注册由各供应商实现包完成,例如:

腾讯云(从 IConfiguration 绑定)

using Bitzsoft.Integrations.OutboundCall;

// 由供应商扩展方法读取该配置节
builder.Configuration.GetSection("OutboundCall");

通过 Options 直接构造(测试 / 号码工具场景)

抽象层的号码工具、过滤器、编排引擎均为静态类或可直接实例化的类型,无需 DI 即可使用:

using Bitzsoft.Integrations.OutboundCall;
using Bitzsoft.Integrations.OutboundCall.PhoneNumber;

// 直接调用静态号码工具,无需注册服务
var (mainland, oversea) = PhoneNumberClassifier.Classify(rawPhones);

var options = new OutboundCallOptions
{
    Whitelist = new() { "5678" },
    Blacklist = new() { "008613800000000" }
};
var filtered = CallListFilter.Filter(callees, options);

使用示例

号码清洗 + 分类(批量)

using Bitzsoft.Integrations.OutboundCall.PhoneNumber;

var rawPhones = new[]
{
    "0086-138-1234 5678",
    "+12125550123",
    "(+852)30087235",
    "电话:13900000000"
};

// 1. 批量解析,自动全角转半角、剥离标签、识别区号、长度校验
var records = PhoneNumberValidator.ExtractAll(rawPhones);
foreach (var r in records)
{
    // r.FullNumber    "008613812345678" / "+12125550123"
    // r.RegionCode    "86" / "1"
    // r.Region        PhoneRegion.Mainland / PhoneRegion.Overseas
    // r.IsValid       true
}

// 2. 一键分类为境内 / 境外两组(去重)
var (mainland, oversea) = PhoneNumberClassifier.Classify(rawPhones);
// mainland: ["008613812345678", "008613900000000"]
// oversea:  ["+12125550123", "+85230087235"]

单个号码校验

var isValid = PhoneNumberValidator.IsValid("008613812345678");      // true
var (regionCode, ok) = PhoneNumberValidator.IdentifyRegion("12025550123"); // ("1", true)

白名单 / 黑名单过滤

using Microsoft.Extensions.Logging;

var options = new OutboundCallOptions
{
    Whitelist = new() { "5678" },               // 后缀匹配:仅允许以 5678 结尾
    Blacklist = new() { "008613800000000" }     // 精确 / 后缀匹配:禁止该号
};

var callees = new[] { "008613812345678", "008613800000000", "00861399995678" };
// 过滤顺序:黑名单优先排除 → 白名单仅保留
var filtered = CallListFilter.Filter(callees, options, logger);
// 结果:["008613812345678", "00861399995678"]

统一外呼接口(消费方)

using Bitzsoft.Integrations.OutboundCall;
using Bitzsoft.Integrations.OutboundCall.Dtos;

public class ReminderService
{
    private readonly IOutboundCallService _outbound;

    public ReminderService(IOutboundCallService outbound) => _outbound = outbound;

    public async Task RunAsync(string[] rawPhones)
    {
        var (mainland, oversea) = PhoneNumberClassifier.Classify(rawPhones);

        // 创建境内活动
        var resp = await _outbound.CreateCampaignAsync(new CreateCampaignRequest
        {
            Name = "催办-境内",
            Region = PhoneRegion.Mainland,
            Callees = mainland.ToList(),
            MaxAttempts = 2,
            NotBefore = DateTimeOffset.UtcNow,
            NotAfter = DateTimeOffset.UtcNow.AddHours(2)
        });

        // 暂停 / 恢复 / 停止
        await _outbound.PauseCampaignAsync(resp.CampaignId);
        await _outbound.ResumeCampaignAsync(resp.CampaignId);
        await _outbound.StopCampaignAsync(resp.CampaignId);

        // 查询活动列表
        var campaigns = await _outbound.ListCampaignsAsync(pageIndex: 1, pageSize: 20);

        // 查询话单
        var records = await _outbound.QueryCallRecordsAsync(new QueryCallRecordsRequest
        {
            CampaignId = resp.CampaignId,
            PageSize = 50
        });
    }
}

per-call 活动编排引擎(供应商内部使用)

using Bitzsoft.Integrations.OutboundCall.PerCall;

var runtime = new CampaignRuntime
{
    Name = "通知外呼",
    Region = PhoneRegion.Overseas,
    Contacts = new() { "+12025550123", "+12025550124" }
};

var dialer = new CampaignDialer(logger);

// 注入实际的呼叫创建逻辑(含 429 退避),由各供应商实现提供
CallCreator creator = async (callee, ct) =>
{
    var sid = await MyProviderCreateCallAsync(callee, ct);
    return new CallAttempt(true, sid, null, null);
};

dialer.StartAsync(runtime, creator, cps: 1, new CancellationTokenSource());

// 暂停(保留断点)→ 恢复(从断点继续)→ 停止(终态)
dialer.Pause(runtime);
dialer.Resume(runtime, creator, cps: 1);
dialer.Stop(runtime);

核心类型一览

接口与选项

类型 说明
IOutboundCallService 外呼服务统一抽象(创建 / 导入 / 启停 / 查询 / 话单)
OutboundCallOptions 全供应商共享配置(鉴权 / 境内外主叫分离 / IVR / 白名单)
OutboundCallException 外呼异常(含供应商标识 Provider、错误码 ErrorCode、请求 ID RequestId
PhoneRegion 号码区域枚举:Mainland / Overseas / Unknown

号码工具

类型 说明
PhoneNumberValidator 静态号码校验器(Extract / ExtractAll / IsValid / IdentifyRegion,150+ 国家长度表)
PhoneNumberClassifier 静态批量分类器(Classify → 境内 / 境外两组)
PhoneNumberRecord 解析结果(FullNumber / RegionCode / Region / IsValid / CleanNumber

过滤与编排

类型 说明
CallListFilter 静态白名单 / 黑名单过滤器(黑名单优先,后缀匹配)
CampaignDialer per-call 供应商的活动编排引擎(CPS 节流、代次守卫、暂停 / 恢复断点)
CampaignRuntime per-call 活动内存运行态(联系人队列、状态、断点索引、代次)
CallAttempt 单次呼叫尝试结果(Initiated / CallSid / ErrorCode
CallCreator 委托:单个被叫的呼叫创建(由供应商注入,含退避重试)

请求 / 响应 DTO

类型 说明
CreateCampaignRequest 创建活动请求(Name / Region / Callees / NotBefore / NotAfter / MaxAttempts / StrategyType / QueueId
CreateCampaignResponse 创建活动响应(CampaignId / Success / ErrorMessage
ImportContactsRequest 导入名单请求(CampaignId / Contacts
StartCampaignRequest 启动活动请求(CampaignId
CampaignInfo 活动信息(CampaignId / Name / Status / CalleeCount / CalledCount / AnsweredCount
CampaignStatus 活动状态枚举:Pending / Running / Paused / Completed / Stopped / Failed / Unknown
CallRecord 通话记录(CallId / Caller / Callee / StartTime / DurationSeconds / Status / RecordUrl
QueryCallRecordsRequest 话单查询请求(CampaignId / 时间范围 / 分页)
OutboundCallResult 通用操作结果(Success / ErrorMessage / RequestId

安全说明

以下安全职责由宿主应用与各供应商实现承担,抽象层不内置实现。

  • 凭据注入AccessKeyId / AccessKeySecret 必须通过环境变量或 Secret Manager 注入,禁止硬编码在源代码或配置文件中
  • 白名单(防误呼):开发 / 测试环境务必配置 WhitelistRequireWhitelistInNonProduction 默认 true,非白名单号码将在创建活动时自动过滤跳过
  • 号码脱敏PhoneNumberValidator 处理后的 FullNumber 为明文号码,宿主应用在日志、持久化时应按需脱敏
  • 主叫号码合法性:境内外主叫号码分离(Callers / OverseaCallers)需符合各国家 / 地区电信监管要求

依赖

说明
Microsoft.Extensions.Logging.Abstractions 日志抽象(ILogger
Microsoft.Extensions.Options 选项模式(IOptionsMonitor<OutboundCallOptions>

相关包

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (8)

Showing the top 5 NuGet packages that depend on Bitzsoft.Integrations.OutboundCall:

Package Downloads
Bitzsoft.Integrations.OutboundCall.All

外呼服务聚合包 — 包含全部供应商实现(腾讯云/阿里云/火山引擎/容联云/华为云/国际 Twilio/Vonage)

Bitzsoft.Integrations.OutboundCall.Tencent

腾讯云外呼实现 — 手写 TC3-HMAC-SHA256 签名 + HttpClient,实现 IOutboundCallService 统一接口,支持境内外分离与白名单

Bitzsoft.Integrations.OutboundCall.Huawei

华为云云客服外呼实现 — 基于 CEC REST API(AK/SK 签名),实现 IOutboundCallService 统一接口

Bitzsoft.Integrations.OutboundCall.Volcengine

火山引擎智能外呼实现 — 基于 AI 外呼机器人 REST API,实现 IOutboundCallService 统一接口

Bitzsoft.Integrations.OutboundCall.Yuntongxun

容联云通讯外呼实现 — 基于 REST API(ACCOUNT SID + AUTH TOKEN 签名),实现 IOutboundCallService 统一接口

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-alpha.10 81 7/26/2026
1.0.0-alpha.9 82 7/12/2026
1.0.0-alpha.8 84 7/1/2026
1.0.0-alpha.7 107 6/16/2026
1.0.0-alpha.6 98 6/16/2026