Tax.Invoice 1.0.7

dotnet add package Tax.Invoice --version 1.0.7
                    
NuGet\Install-Package Tax.Invoice -Version 1.0.7
                    
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="Tax.Invoice" Version="1.0.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Tax.Invoice" Version="1.0.7" />
                    
Directory.Packages.props
<PackageReference Include="Tax.Invoice" />
                    
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 Tax.Invoice --version 1.0.7
                    
#r "nuget: Tax.Invoice, 1.0.7"
                    
#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 Tax.Invoice@1.0.7
                    
#: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=Tax.Invoice&version=1.0.7
                    
Install as a Cake Addin
#tool nuget:?package=Tax.Invoice&version=1.0.7
                    
Install as a Cake Tool

电子发票/数电发票 C# SDK | 开票、验真、红冲一站式集成

NuGet License .NET 10

发票 C# SDK 面向电子发票、数电发票(全电发票)场景,支持开票、红冲、版式文件下载等核心功能,快速对接税务平台API。

关键词: 电子发票SDK,数电票C#,开票接口,发票api,发票开具,发票红冲,全电发票集成


📖 核心功能

基础认证

  • 获取授权 - 快速接入税务平台身份认证
  • 人脸二维码登录 - 支持数电发票平台扫码登录
  • 认证状态查询 - 实时获取纳税人身份状态

发票开具

  • 🎫 数电蓝票开具 - 支持增值税普通/专用电子发票
  • 📄 版式文件下载 - 自动获取销项发票PDF/OFD/XML文件

发票红冲

  • 🔍 红冲前蓝票查询 - 精确检索待红冲的电子发票
  • 🛑 红字信息表申请 - 生成红冲凭证
  • 🔄 负数发票开具 - 自动化红冲流程

🚀 快速安装

NuGet

dotnet add package Tax.Invoice --version 1.0.7

📦 查看NuGet最新版本

本SDK基于 C# 12 与 .NET 10 开发


📚 查看完整中文文档 | 💡 更多示例代码


其他版本请用旧版本

C#8-C#11开发票demo

C#8-C#11红冲发票demo

C#8-C#11发票税额demo


🔍 为什么选择此SDK?

  • 精准覆盖中国数电发票标准 - 严格遵循国家最新接口规范
  • 开箱即用 - 无需处理XML/签名等底层细节,专注业务逻辑
  • 企业级验证 - 已在生产环境处理超100万张电子发票

📊 支持的开票类型

发票类型 状态
数电发票(普通发票) ✅ 支持
数电发票(增值税专用发票) ✅ 支持
数电发票(铁路电子客票) ✅ 支持
数电发票(航空运输电子客票行程单) ✅ 支持
数电票(二手车销售统一发票) ✅ 支持
数电纸质发票(增值税专用发票) ✅ 支持
数电纸质发票(普通发票) ✅ 支持
数电纸质发票(机动车发票) ✅ 支持
数电纸质发票(二手车发票) ✅ 支持

🤝 贡献与支持


🎯 快速开始:

using System;
using System.Collections.Generic;
using System.Text;
using Tax.Invoice;
using Tax.Invoice.Model;
using System.Text.Json;
using StackExchange.Redis;
using System.Threading.Tasks;
using System.Runtime.Versioning;
using ZXing;
using ZXing.QrCode;

using System.Drawing;
using System.IO;
using System.Drawing.Imaging;

public class BasicExample
{

    public static String appKey = "";
    public static String appSecret = "";

    public static String nsrsbh = "";// 统一社会信用代码
    public static String title = "";// 名称(营业执照)
    public static String username = "";// 手机号码(电子税务局)
    public static String password = "";// 个人用户密码(电子税务局)
    public static String type = "6";// 6 基础 7标准
    public static String xhdwdzdh = "重庆市渝北区龙溪街道丽园路2号XXXX 1325580XXXX"; // 地址和电话 空格隔开
    public static String xhdwyhzh = "工商银行XXXX 15451211XXXX";// 开户行和银行账号 空格隔开
    public static String token = "";
    public static Boolean debug = true; // 是否打印日志

    // 创建客户端
    public static InvoiceClient client = new InvoiceClient(appKey, appSecret, debug);
    // redis
    public static ConnectionMultiplexer redis = LazyConnection.Connect("127.0.0.1:6379,password=test123456,abortConnect=false");
    public static async Task Main(string[] args)
    {
        try
        {
            Console.OutputEncoding = Encoding.UTF8;
            Console.WriteLine("dotnet " + Environment.Version);
            // dotnet add package StackExchange.Redis
            // 一 获取token 从Redis获取token
            GetToken(false);
            // 二 开具蓝票
            /*
             * 前端模拟数电发票/电子发票开具 (蓝字发票)
             * @see https://fa-piao.com/fapiao.html?source=github
             */
            var invoiceResponse = BlueTicket();
            switch (invoiceResponse.Code)
            {
                case 200:
                    // 三 下载发票
                    DownloadPdfOfdXml(invoiceResponse.Data["fphm"].ToString(), invoiceResponse.Data["kprq"].ToString());
                    break;
                case 420:
                    Console.WriteLine("登录(短信认证)");
                    /*
                     * 前端模拟短信认证弹窗
                     * @see https://fa-piao.com/fapiao.html?action=sms&source=github
                     */
                    // 1. 发短信验证码
                    /*
                     * @see https://fa-piao.com/doc.html#api2?source=github
                     */
                    var loginResponse = client.LoginDppt(nsrsbh, username, password, "");
                    if (loginResponse.Code == 200)
                    {
                        Console.WriteLine("请输入验证码");
                        var smsTimeout = TimeSpan.FromSeconds(300);
                        Console.WriteLine($"请在{smsTimeout.TotalSeconds}秒内输入验证码,过期时间为: {DateTime.UtcNow.Add(smsTimeout).ToString("yyyy-MM-dd HH:mm:ss")}前)输入验证码: ");
                        var inputSmsTask = Task.Run(Console.ReadLine);
                        var completedSmsTask = await Task.WhenAny(inputSmsTask, Task.Delay(smsTimeout));
                        if (completedSmsTask == inputSmsTask)
                        {
                            Console.WriteLine($"输入: {inputSmsTask.Result}");
                            // 2. 输入验证码
                            /*
                             * @see https://fa-piao.com/doc.html#api2?source=github
                             */
                            var loginResponse2 = client.LoginDppt(nsrsbh, username, password, inputSmsTask.Result);
                            if (loginResponse2.Code == 200)
                            {
                                Console.WriteLine("短信验证成功");
                                Console.WriteLine("请再次调用BlueTicket");
                                invoiceResponse = BlueTicket();
                                if (invoiceResponse.Code == 200)
                                {
                                    DownloadPdfOfdXml(invoiceResponse.Data["fphm"].ToString(), invoiceResponse.Data["kprq"].ToString());
                                }
                                else
                                {
                                    Console.WriteLine(invoiceResponse.Code + "开具蓝票失败: " + invoiceResponse.Msg);
                                }
                            }
                            else
                            {
                                Console.WriteLine(loginResponse2.Code + "短信验证失败: " + loginResponse2.Msg);
                            }
                        }
                        else
                        {
                            Console.WriteLine("超时!未输入验证码!");
                        }
                    }
                    else
                    {
                        Console.WriteLine(loginResponse.Code + "发短信验证码失败: " + loginResponse.Msg);
                    }
                    break;
                case 430:
                    Console.WriteLine("人脸认证");
                    /*
                     * 前端模拟人脸认证弹窗
                     * @see https://fa-piao.com/fapiao.html?action=face&source=github
                     */
                    // 1. 获取人脸二维码
                    /*
                     * @see https://fa-piao.com/doc.html#api3?source=github
                     */
                    var qrCodeResponse = client.GetFaceImg(nsrsbh, username, "1");
                    var qrData = qrCodeResponse.Data;
                    if (qrData == null)
                    {
                        Console.WriteLine(qrCodeResponse.Code + "人脸二维码返回为空: " + qrCodeResponse.Msg);
                        break;
                    }
                    var ewmly = qrData.GetValueOrDefault("ewmly")?.ToString() ?? "";
                    Console.WriteLine(ewmly == "swj" ? "请使用电子税务局app扫码" : "个人所得税app扫码");
                    Console.WriteLine("成功做完人脸认证,请输入数字 1");
                    var ewmObj = qrData.GetValueOrDefault("ewm");
                    if (ewmObj != null && ewmObj.ToString()?.Length < 500)
                    {
                        // 生成二维码图片base64字符串
                        // var base64 = StringToQrcodeBase64(ewmObj.ToString());
                        // qrData["ewm"] = base64;
                        // Console.WriteLine("生成二维码图片base64字符串");
                        //前端使用示例: <img src='data:image/png;base64,{base64}' width='200' />
                    }
                    StringToQrcode(ewmObj.ToString());
                    var faceTimeout = TimeSpan.FromSeconds(300);
                    Console.WriteLine($"请在{faceTimeout.TotalSeconds}秒内输入内容,过期时间为: {DateTime.UtcNow.Add(faceTimeout).ToString("yyyy-MM-dd HH:mm:ss")}");
                    var inputFaceTask = Task.Run(Console.ReadLine);
                    var completedFaceTask = await Task.WhenAny(inputFaceTask, Task.Delay(faceTimeout));
                    if (completedFaceTask == inputFaceTask)
                    {
                        Console.WriteLine($"输入: {inputFaceTask.Result}");
                        // 2. 认证完成后获取人脸二维码认证状态
                        /*
                        * @see https://fa-piao.com/doc.html#api4?source=github
                        */
                        var rzid = qrData.GetValueOrDefault("rzid")?.ToString() ?? "";
                        var faceStatusResponse = client.GetFaceState(nsrsbh, rzid, username, "1");
                        if (faceStatusResponse.Data != null && faceStatusResponse.Data.GetValueOrDefault("slzt") != null)
                        {
                            var slzt = faceStatusResponse.Data.GetValueOrDefault("slzt")?.ToString() ?? "";
                            if (slzt == "2")
                            {
                                Console.WriteLine("人脸认证成功");
                                Console.WriteLine("请再次调用BlueTicket");
                                invoiceResponse = BlueTicket();
                                if (invoiceResponse.Code == 200)
                                {
                                    DownloadPdfOfdXml(invoiceResponse.Data["fphm"].ToString(), invoiceResponse.Data["kprq"].ToString());
                                }
                                else
                                {
                                    Console.WriteLine(invoiceResponse.Code + "开具蓝票失败: " + invoiceResponse.Msg);
                                }
                                break;
                            }
                            else
                            {
                                Console.WriteLine(slzt == "1" ? "人脸未认证" : "人脸认证二维码过期");
                                break;
                            }
                        }
                        else
                        {
                            Console.WriteLine("获取人脸二维码认证状态失败: " + faceStatusResponse.Msg);
                            break;
                        }
                    }
                    else
                    {
                        Console.WriteLine("人脸认证 超时!");
                    }
                    break;
                case 401:
                    Console.WriteLine("授权失败:" + invoiceResponse.Msg);
                    Console.WriteLine("401  token过期 重新获取并缓存token");
                    GetToken(true);
                    Console.WriteLine("再调用BlueTicket");
                    invoiceResponse = BlueTicket();
                    if (invoiceResponse.Code == 200)
                    {
                        DownloadPdfOfdXml(invoiceResponse.Data["fphm"].ToString(), invoiceResponse.Data["kprq"].ToString());
                    }
                    else
                    {
                        Console.WriteLine(invoiceResponse.Code + "开具蓝票失败: " + invoiceResponse.Msg);
                    }
                    break;
                default:
                    // Console.WriteLine("参数:" + invoiceParams);
                    Console.WriteLine(invoiceResponse.Code + "异常" + invoiceResponse.Msg);
                    break;
            }


        }
        catch (Exception e)
        {
            Console.WriteLine("系统错误:" + e.Message);
            Console.WriteLine(e);
        }
    }

    // 字符串转二维码 在命令行输出
    public static void StringToQrcode(String str)
    {
        var writer = new QRCodeWriter();
        var hints = new Dictionary<EncodeHintType, object>
        {
            [EncodeHintType.MARGIN] = 2,
            [EncodeHintType.ERROR_CORRECTION] = "M"
        };
        var matrix = writer.encode(str, BarcodeFormat.QR_CODE, 0, 0, hints);
        var width = matrix.Width + 4;
        var height = matrix.Height + 4;
        for (var y = 0; y < height; y += 2)
        {
            var line = new StringBuilder(width);
            for (var x = 0; x < width; x++)
            {
                var top = IsDark(matrix, x - 2, y - 2);
                var bottom = IsDark(matrix, x - 2, y - 1);
                line.Append(top
                    ? (bottom ? "█" : "▀")
                    : (bottom ? "▄" : " "));
            }
            Console.WriteLine(line.ToString());
        }
    }
    public static bool IsDark(ZXing.Common.BitMatrix matrix, int x, int y)
    {
        if (x < 0 || y < 0 || x >= matrix.Width || y >= matrix.Height)
        {
            return false;
        }

        return matrix[x, y];
    }

    public static void DownloadPdfOfdXml(String fphm, String kprq)
    {
        /*
         * 获取销项数电版式文件
         * @see https://fa-piao.com/doc.html#api7?source=github
         *
         */
        var pdfParams = new Dictionary<string, object>
        {
            ["downflag"] = "4",
            ["nsrsbh"] = nsrsbh,
            ["username"] = username,
            ["fphm"] = fphm,
            ["Kprq"] = kprq
        };

        var pdfResponse = client.GetPdfOfdXml(pdfParams);
        if (pdfResponse.IsSuccess)
        {
            Console.WriteLine("发票下载成功");
            Console.WriteLine(JsonSerializer.Serialize(pdfResponse.Data, new JsonSerializerOptions
            {
                WriteIndented = true
            }));
        }
    }
    public static ApiResponse<Dictionary<string, object>> BlueTicket()
    {
        /*
         *
         * 开票税额计算demo
         * @see https://github.com/fapiaoapi/invoice-sdk-java/blob/master/examples/TaxExample.java
        */
        // 开具蓝票参数
        var invoiceParams = new Dictionary<string, object>
        {
            ["fplxdm"] = "82",
            ["fpqqlsh"] = appKey + DateTimeOffset.Now.ToUnixTimeMilliseconds(),
            ["ghdwmc"] = "个人",
            ["hjje"] = 396.04,
            ["hjse"] = 3.96,
            ["jshj"] = 400,
            ["kplx"] = 0,
            ["username"] = username,
            ["xhdwdzdh"] = xhdwdzdh,
            ["xhdwmc"] = title,
            ["xhdwsbh"] = nsrsbh,
            ["xhdwyhzh"] = xhdwyhzh,
            ["zsfs"] = 0,
            ["fyxm[0][fphxz]"] = 0,
            ["fyxm[0][spmc]"] = "*软件维护服务*接口服务费",
            ["fyxm[0][ggxh]"] = "",
            ["fyxm[0][dw]"] = "次",
            ["fyxm[0][spsl]"] = 100,
            ["fyxm[0][dj]"] = 1,
            ["fyxm[0][je]"] = 100,
            ["fyxm[0][sl]"] = 0.01,
            ["fyxm[0][se]"] = 0.99,
            ["fyxm[0][hsbz]"] = 1,
            ["fyxm[0][spbm]"] = "3040201030000000000",
            ["fyxm[1][fphxz]"] = 0,
            ["fyxm[1][spmc]"] = "*软件维护服务*接口服务费",
            ["fyxm[1][ggxh]"] = "",
            ["fyxm[1][spsl]"] = 150,
            ["fyxm[1][dj]"] = 2,
            ["fyxm[1][je]"] = 300,
            ["fyxm[1][sl]"] = 0.01,
            ["fyxm[1][se]"] = 2.97,
            ["fyxm[1][hsbz]"] = 1,
            ["fyxm[1][spbm]"] = "3040201030000000000"
        };

        // 二 开具蓝票
        /*
         * 开具数电发票文档
         * @see https://fa-piao.com/doc.html#api6?source=github
         *
         */
        return client.BlueTicket(invoiceParams);
    }

    // 获取token
    public static void GetToken(Boolean forceUpdate)
    {
        var key = nsrsbh + "@" + username + "@TOKEN";
        var redisService = redis.GetDatabase();
        if (forceUpdate)
        {
            /*
            * 获取授权
            * @see https://fa-piao.com/doc.html#api1?source=github
            *
            */
            var authResponse = client.GetAuthorization(nsrsbh, type);
            if (authResponse.IsSuccess)
            {
                token = authResponse.Data.Token;
                client.SetAuthorization(token);
                redisService.StringSet(key, token, TimeSpan.FromDays(30));
            }
        }
        else
        {
            token = redisService.StringGet(key);
            if (token != null)
            {
                client.SetAuthorization(token);
                Console.WriteLine("从Redis获取token成功");
            }
            else
            {
                var authResponse = client.GetAuthorization(nsrsbh, type);
                if (authResponse.IsSuccess)
                {
                    token = authResponse.Data.Token;
                    client.SetAuthorization(token);
                    redisService.StringSet(key, token, TimeSpan.FromDays(30));
                }
            }
        }
    }

    // 生成二维码图片base64
    [SupportedOSPlatform("windows6.1")]
    public static string StringToQrcodeBase64(string str)
    {
        var writer = new QRCodeWriter();
        var hints = new Dictionary<EncodeHintType, object>
        {
            [EncodeHintType.MARGIN] = 2,
            [EncodeHintType.ERROR_CORRECTION] = "M"
        };
        var matrix = writer.encode(str, BarcodeFormat.QR_CODE, 300, 300, hints);

        using var bitmap = new Bitmap(matrix.Width, matrix.Height);
        for (var y = 0; y < matrix.Height; y++)
        {
            for (var x = 0; x < matrix.Width; x++)
            {
                bitmap.SetPixel(x, y, matrix[x, y] ? Color.Black : Color.White);
            }
        }

        using var ms = new MemoryStream();
        bitmap.Save(ms, ImageFormat.Png);
        return Convert.ToBase64String(ms.ToArray());
    }
}

public static class LazyConnection
{
    private static Lazy<ConnectionMultiplexer> _lazy;
    private static string _connectionString;

    public static ConnectionMultiplexer Connect(string connectionString)
    {
        if (_lazy == null || _connectionString != connectionString)
        {
            _connectionString = connectionString;
            _lazy = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(connectionString));
        }
        return _lazy.Value;
    }
}

基础开票示例 红冲示例 税额计算示例

Product Compatible and additional computed target framework versions.
.NET 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.
  • net10.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.7 82 4/5/2026
1.0.6 80 4/5/2026
1.0.5 83 3/29/2026
1.0.4 72 3/29/2026
1.0.3 85 3/29/2026
1.0.2 86 3/28/2026
1.0.1 95 3/28/2026