Swift + Server酱:任务完成/出错,微信立刻知道

效果:在 Swift 程序中调用 Server酱 API,任务完成、异常告警等消息实时推送到你的微信。

前置条件

官方示例实现

以下代码来自官方示例仓库 serverchan-demoswift/main.swift),同样自动识别两种 SendKey,可直接复制使用:

import Foundation

func sc_send(text: String, desp: String = "", key: String = "[SENDKEY]") -> String {
    let urlString: String
    let regex = try! NSRegularExpression(pattern: "^sctp(\\d+)t", options: [])

    if key.hasPrefix("sctp") {
    if let match = regex.firstMatch(in: key, options: [], range: NSRange(location: 0, length: key.utf16.count)) {
        let numRange = match.range(at: 1)
        if let numRange = Range(numRange, in: key) {
            let num = key[numRange]
            urlString = "https://\(num).push.ft07.com/send/\(key).send"
        } else {
            // 处理错误:没有提取到数字
            fatalError("Invalid key format")
        }
    } else {
        // 处理错误:正则匹配失败
        fatalError("Invalid key format")
    }
} else {
    urlString = "https://sctapi.ftqq.com/\(key).send"
}
    
    guard let url = URL(string: urlString) else {
        print("Invalid URL")
        return ""
    }
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    let postdata = "text=\(text)&desp=\(desp)"
    request.httpBody = postdata.data(using: .utf8)
    
    let semaphore = DispatchSemaphore(value: 0)
    var result = ""
    
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        if let error = error {
            print("Error: \(error)")
        } else if let data = data {
            result = String(data: data, encoding: .utf8) ?? ""
        }
        semaphore.signal()
    }
    task.resume()
    semaphore.wait()
    
    return result
}

let data = try! String(contentsOfFile: "\(FileManager.default.currentDirectoryPath)/../.env", encoding: .utf8)
let lines = data.components(separatedBy: .newlines)
var key = ""
for line in lines {
    if line.hasPrefix("SENDKEY=") {
        key = line.replacingOccurrences(of: "SENDKEY=", with: "")
        break
    }
}

let ret = sc_send(text: "主人服务器宕机了 via swift", desp: "第一行\n\n第二行", key: key)
print(ret)

运行方式:

swift main.swift

官方示例从仓库根目录的 .env 文件读取 SENDKEY;集成到你的项目时,可改为读取环境变量 SERVERCHAN_SENDKEY 或你的配置系统。

常见问题

免费额度够用吗?

免费版每天 5 条。程序类通知建议在任务结束时合并推送一条摘要;量大可订阅会员目前特价最低 3 元/月,一天最多可发 1000 条(价格详情)。

消息没收到怎么办?

先检查返回 JSON 的 code 是否为 0,再按 常见问题与排查 逐项检查。

有频率限制吗?

每分钟最多 50 条,注意不要在循环里逐条推送,先聚合再发送。

相关集成

懒人方案:把这段话复制给你的 AI 助手

把下面这段文字原样粘贴给 Claude Code、Cursor 或任何 AI 编程助手,它就会替你完成 Server酱 的接入:

请帮我把 Server酱 微信通知接入到我当前的项目/工具中:
1. API:POST https://sctapi.ftqq.com/{SendKey}.send,参数 title(必填,不能含换行)、desp(正文,支持 Markdown,可选);成功时返回 JSON 的 code 为 0。
2. 如果我的 SendKey 以 sctp 开头,则改用 https://{uid}.push.ft07.com/send/{SendKey}.send,uid 是 SendKey 中 sctp 与 t 之间的数字。
3. SendKey 从环境变量 SERVERCHAN_SENDKEY 读取;如果没有,提醒我到 https://sct.ftqq.com 免费获取(每天 5 条额度)。
4. 安全要求:不要把 SendKey 硬编码进代码、不要打印到日志、不要提交到 git。
5. 频率约定:任务结束发 1 条结果摘要即可,批量任务合并成一条,不要每步都推。
请根据我当前的项目和场景直接写好代码/配置并验证。