Skip to content
Bitzsoft.Integrationsbitzsoft.integrations

Concept

Ticketing 工单系统

工单系统域完整手册——ITicketService 7 方法工单生命周期、创建/查询/更新/分配/状态变更/评论、Zendesk Basic Auth 与禅道 Session Token 两种鉴权模型。

Last updated

Ticketing 域统一了客服与运维工单系统的工单管理能力。Zendesk 和禅道(Zentao)两家供应商共享同一个 ITicketService 接口,但鉴权机制差异显著:Zendesk 用 Basic Auth(email/token:apiToken),禅道用 Session Token。

域结构

Bitzsoft.Integrations.Ticketing ← 抽象层
├── Bitzsoft.Integrations.Ticketing.Zendesk ← Zendesk(Basic Auth)
├── Bitzsoft.Integrations.Ticketing.Zentao ← 禅道(Session Token)
└── Bitzsoft.Integrations.Ticketing.All ← 聚合包

标准三层包模式。

统一接口(7 方法)

ITicketService 围绕”工单(Ticket)“这一核心概念组织,共 7 个方法:

public interface ITicketService
{
string ProviderName { get; }
// 工单生命周期
Task<TicketInfo> CreateTicketAsync(CreateTicketRequest request, CancellationToken cancellationToken = default);
Task<TicketInfo> GetTicketAsync(string ticketId, CancellationToken cancellationToken = default);
Task<TicketInfo> UpdateTicketAsync(string ticketId, UpdateTicketRequest request, CancellationToken cancellationToken = default);
Task AssignTicketAsync(string ticketId, string assigneeId, CancellationToken cancellationToken = default);
Task ChangeTicketStatusAsync(string ticketId, TicketStatus status, CancellationToken cancellationToken = default);
Task AddCommentAsync(string ticketId, AddCommentRequest request, CancellationToken cancellationToken = default);
Task<List<TicketInfo>> ListTicketsAsync(ListTicketsRequest request, CancellationToken cancellationToken = default);
}

查询类方法(Create / Get / Update / List)返回 TicketInfo,操作类方法(Assign / ChangeStatus / AddComment)为无返回 Task,失败抛 TicketExceptionTicketInfo.Status 反映工单在供应商侧的当前状态。

鉴权模型

两家供应商使用截然不同的鉴权机制:

供应商鉴权机制凭证注入Token 刷新
ZendeskBasic Auth(email/token + apiToken)Authorization: Basic {base64(email/token:apiToken)}静态 API Token,不刷新
禅道账号密码换 Session TokenSession Token(请求头或 query 参数)POST /api.php/v1/tokens 换取,可缓存

供应商清单

供应商Provider IDAPI 基地址StabilityDI 方法
Zendeskzendesk{subdomain}.zendesk.com/api/v2PreviewAddZendeskTicket()
禅道zentao{your-host}/api.php/v1PreviewAddZentaoTicket()

Zendesk 是国际主流客服工单平台,禅道是国内主流研发项目管理与 Bug 工单系统。

注册

单厂商

// ① Zendesk(Basic Auth:email/token + apiToken)
builder.Services.AddZendeskTicket(builder.Configuration.GetSection("Ticketing:Zendesk"));
// ② 禅道(Session Token)
builder.Services.AddZentaoTicket(builder.Configuration.GetSection("Ticketing:Zentao"));

全量聚合

builder.Services.AddBitzsoftTicketingAll(builder.Configuration, "Ticketing");

按配置节存在性自动注册,appsettings.json 只需写出启用的供应商:

{
"Ticketing": {
"Zendesk": {
"Subdomain": "yourcompany",
"Email": "admin@example.com",
"ApiToken": "..."
},
"Zentao": {
"BaseUrl": "https://zentao.example.com",
"Username": "...",
"Password": "..."
}
}
}

消费

创建工单

public class TicketCreateService(IIntegrationProviderResolver<ITicketService> providers)
{
public async Task<TicketInfo> OpenAsync(string vendor, string subject, string description, string requesterEmail)
{
var ticketing = providers.GetRequired(vendor); // "zendesk" / "zentao"
return await ticketing.CreateTicketAsync(new CreateTicketRequest
{
Subject = subject,
Description = description,
RequesterEmail = requesterEmail,
Priority = TicketPriority.Normal,
});
}
}

分配、状态变更与评论

// 分配处理人
await ticketing.AssignTicketAsync(ticketId, assigneeId: "user-123");
// 变更状态(如标记为已解决)
await ticketing.ChangeTicketStatusAsync(ticketId, TicketStatus.Resolved);
// 追加内部备注或公开回复
await ticketing.AddCommentAsync(ticketId, new AddCommentRequest
{
Body = "已联系客户确认,问题复现已修复。",
IsPublic = true,
});

查询工单

// 查询单份工单详情
var detail = await ticketing.GetTicketAsync(ticketId);
// detail.Status: New / Open / Pending / Resolved / Closed
// 按条件列表查询
var list = await ticketing.ListTicketsAsync(new ListTicketsRequest
{
Status = TicketStatus.Open,
AssigneeId = "user-123",
PageIndex = 1,
PageSize = 20,
});

多厂商路由

public class TicketRouter(IIntegrationProviderResolver<ITicketService> providers)
{
public async Task<TicketInfo> GetAsync(string source, string ticketId)
{
var ticketing = providers.GetRequired(source); // "zendesk" / "zentao"
return await ticketing.GetTicketAsync(ticketId);
}
}

相关

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%