|
4 | 4 |
|
5 | 5 | using Baidu.Aip.Ocr; |
6 | 6 | using Microsoft.Extensions.Options; |
| 7 | +using Newtonsoft.Json.Linq; |
7 | 8 |
|
8 | 9 | namespace BootstrapBlazor.Components; |
9 | 10 |
|
10 | 11 | internal class BaiduOcr : IBaiduOcr |
11 | 12 | { |
12 | 13 | protected IOptionsMonitor<BaiduOcrOption> Options { get; set; } |
13 | 14 |
|
| 15 | + protected IHttpClientFactory HttpClientFactory { get; set; } |
| 16 | + |
14 | 17 | /// <summary> |
15 | 18 | /// 构造函数 |
16 | 19 | /// </summary> |
17 | 20 | /// <param name="options"></param> |
18 | | - public BaiduOcr(IOptionsMonitor<BaiduOcrOption> options) |
| 21 | + /// <param name="httpClientFactory"></param> |
| 22 | + public BaiduOcr(IOptionsMonitor<BaiduOcrOption> options, IHttpClientFactory httpClientFactory) |
19 | 23 | { |
20 | 24 | Options = options; |
| 25 | + HttpClientFactory = httpClientFactory; |
21 | 26 | } |
22 | 27 |
|
23 | 28 | /// <summary> |
@@ -58,4 +63,89 @@ public Task<BaiduOcrResult<InvoiceEntity>> CheckVatInvoiceAsync(byte[] image, Ca |
58 | 63 | } |
59 | 64 | return ret; |
60 | 65 | }, token); |
| 66 | + |
| 67 | + /// <summary> |
| 68 | + /// 获得 Baidu AI AccessToken 方法 |
| 69 | + /// </summary> |
| 70 | + /// <returns></returns> |
| 71 | + protected async Task<string> GetAccessToken() |
| 72 | + { |
| 73 | + var client = HttpClientFactory.CreateClient(); |
| 74 | + var para = new Dictionary<string, string>() |
| 75 | + { |
| 76 | + { "grant_type", "client_credentials" }, |
| 77 | + { "client_id", Options.CurrentValue.ApiKey }, |
| 78 | + { "client_secret", Options.CurrentValue.Secret } |
| 79 | + }; |
| 80 | + |
| 81 | + var resp = await client.PostAsync("https://aip.baidubce.com/oauth/2.0/token", new FormUrlEncodedContent(para)); |
| 82 | + var ret = await resp.Content.ReadAsStringAsync(); |
| 83 | + var doc = JObject.Parse(ret); |
| 84 | + return doc.Value<string>("access_token") ?? string.Empty; |
| 85 | + } |
| 86 | + |
| 87 | + /// <summary> |
| 88 | + /// 增值税发票验真方法 |
| 89 | + /// </summary> |
| 90 | + /// <param name="invoiceCode">发票代码</param> |
| 91 | + /// <param name="invoiceNum">发票号码</param> |
| 92 | + /// <param name="invoiceDate">开票日期格式 YYYYMMDD</param> |
| 93 | + /// <param name="invoiceType">发票种类 增值税专用发票:special_vat_invoice 增值税电子专用发票:elec_special_vat_invoice 增值税普通发票:normal_invoice 增值税普通发票(电子):elec_normal_invoice 增值税普通发票(卷式):roll_normal_invoice 通行费增值税电子普通发票:toll_elec_normal_invoice 区块链电子发票(目前仅支持深圳地区):blockchain_invoice 全电发票(专用发票):elec_invoice_special 全电发票(普通发票):elec_invoice_normal 货运运输业增值税专用发票:special_freight_transport_invoice 机动车销售发票:motor_vehicle_invoice 二手车销售发票:used_vehicle_invoice</param> |
| 94 | + /// <param name="checkCode">校验码 后六位</param> |
| 95 | + /// <param name="totalAmount">发票金额</param> |
| 96 | + /// <param name="token"></param> |
| 97 | + /// <returns></returns> |
| 98 | + public Task<BaiduOcrResult<InvoiceVerifyResult>> VerifyInvoiceAsync(string invoiceCode, string invoiceNum, string invoiceDate, string invoiceType, string? checkCode, string? totalAmount, CancellationToken token = default) => Task.Run(async () => |
| 99 | + { |
| 100 | + var token = await GetAccessToken(); |
| 101 | + var url = $"https://aip.baidubce.com/rest/2.0/ocr/v1/vat_invoice_verification?access_token={token}"; |
| 102 | + var client = HttpClientFactory.CreateClient(); |
| 103 | + |
| 104 | + // 拼装参数 |
| 105 | + var para = new Dictionary<string, string>() |
| 106 | + { |
| 107 | + { "invoice_code", invoiceCode }, |
| 108 | + { "invoice_num", invoiceNum }, |
| 109 | + { "invoice_date", invoiceDate }, |
| 110 | + { "invoice_type", invoiceType }, |
| 111 | + }; |
| 112 | + |
| 113 | + if (!string.IsNullOrEmpty(checkCode)) |
| 114 | + { |
| 115 | + para["check_code"] = checkCode; |
| 116 | + } |
| 117 | + if (!string.IsNullOrEmpty(totalAmount)) |
| 118 | + { |
| 119 | + para["total_amount"] = totalAmount; |
| 120 | + } |
| 121 | + |
| 122 | + // 提交数据 |
| 123 | + var resp = await client.PostAsync(url, new FormUrlEncodedContent(para)); |
| 124 | + var payload = await resp.Content.ReadAsStringAsync(); |
| 125 | + var doc = JObject.Parse(payload); |
| 126 | + |
| 127 | + var ret = new BaiduOcrResult<InvoiceVerifyResult>(); |
| 128 | + if (doc.TryGetValue("words_result", out var v)) |
| 129 | + { |
| 130 | + ret.Entity = new InvoiceVerifyResult() |
| 131 | + { |
| 132 | + MachineCode = doc.Value<string>("MachineCode"), |
| 133 | + InvoiceNum = doc.Value<string>("InvoiceNum"), |
| 134 | + InvoiceDate = doc.Value<string>("InvoiceDate"), |
| 135 | + VerifyResult = doc.Value<string>("VerifyResult"), |
| 136 | + InvalidSign = doc.Value<string>("InvalidSign"), |
| 137 | + InvoiceCode = doc.Value<string>("InvoiceCode"), |
| 138 | + InvoiceType = doc.Value<string>("InvoiceType"), |
| 139 | + CheckCode = doc.Value<string>("CheckCode"), |
| 140 | + VerifyMessage = doc.Value<string>("VerifyMessage"), |
| 141 | + Invoice = v.ToObject(typeof(InvoiceEntity)) as InvoiceEntity |
| 142 | + }; |
| 143 | + } |
| 144 | + else |
| 145 | + { |
| 146 | + ret.ErrorCode = doc.Value<int>("error_code"); |
| 147 | + ret.ErrorMessage = doc.Value<string>("error_msg"); |
| 148 | + } |
| 149 | + return ret; |
| 150 | + }, token); |
61 | 151 | } |
0 commit comments