环境:.NetCore、NuonuoSDK
1 /// <summary> 2 /// 申请诺诺电子发票 3 /// </summary> 4 /// <param name="applySource">1:支付完自动开票;2:手动选择小订单开票</param> 5 /// <returns></returns> 6 public async Task ApplyEInvoice(string orderNo, Guid invoiceTitleId, int applySource) 7 { 8 try 9 { 10 var orderDetailList = await _orderDetailRepository.GetListAsync(f => f.OrderNo == orderNo); 11 if (applySource == 2) 12 { 13 orderDetailList = await _orderDetailRepository.GetListAsync(f => f.OrderDetailNo == orderNo); 14 } 15 if (orderDetailList != null) 16 { 17 var invoiceTitle = await _invoiceTitleRepository.GetAsync(invoiceTitleId); 18 if (invoiceTitle != null) 19 { 20 foreach (var orderDetail in orderDetailList) 21 { 22 var fpkjModel = _fpkjRequestOptions.Value; 23 fpkjModel.buyerName = invoiceTitle.Name; 24 fpkjModel.buyerTaxNum = invoiceTitle.TaxNumber; 25 fpkjModel.buyerTel = invoiceTitle.Mobile; 26 fpkjModel.buyerAddress = invoiceTitle.Address; 27 fpkjModel.buyerAccount = invoiceTitle.Bank + invoiceTitle.BankNumber; 28 fpkjModel.orderNo = orderDetail.OrderDetailNo; 29 fpkjModel.invoiceDate = orderDetail.CreationTime.ToString("yyyy-MM-dd HH:mm:ss"); 30 fpkjModel.buyerPhone = invoiceTitle.SendPhoneNumber; //购方手机(pushMode为1或2时,此项必填 31 fpkjModel.email = invoiceTitle.SendEmailAddress; //推送邮箱 推送邮箱(pushMode为0或2时,此项为必填,同时受企业资质是否必填控制) 32 fpkjModel.pushMode = "2"; //推送方式:-1;不推送;0;邮箱;1;手机(默认); 2;邮箱、手机 33 fpkjModel.invoiceType = "1"; //蓝票 34 fpkjModel.invoiceLine = "pc"; //电子发票(普通发票)-即数电普票(电子) 35 fpkjModel.invoiceDetail = new List<InvoiceDetail>() 36 { 37 new InvoiceDetail() 38 { 39 taxIncludedAmount = orderDetail.OrderAmount.ToString(), 40 withTaxFlag = "1", 41 num = "1" 42 }, 43 }; 44 45 //string str = await _openInvoiceManager.GetEInvoiceTokenAsync(); 46 //var pxResponseResult = JsonConvert.DeserializeObject<PxResponseResult<JYEInvoiceTokenResponse>>(str); 47 //var tokenInfo = pxResponseResult.Data; 48 49 (string invoiceSerialNum, string message) openInvoiceResponse = _openInvoiceManager.OpenInvoice(fpkjModel, fpkjModel.salerTaxNum); 50 Logger.LogInformation("申请诺诺电子发票:流水号:" + openInvoiceResponse.invoiceSerialNum + ",描述:" + openInvoiceResponse.message); 51 if (!string.IsNullOrEmpty(openInvoiceResponse.invoiceSerialNum) || openInvoiceResponse.message == "订单编号或流水号不能重复") 52 { 53 var openInvoice = await _openInvoiceRepository.FirstOrDefaultAsync(f => f.OrderNo == orderDetail.OrderDetailNo); 54 if (openInvoice == null) 55 { 56 OpenInvoiceRecord openInvoiceRecord = new OpenInvoiceRecord() 57 { 58 InvoiceNature = invoiceTitle.InvoiceNature, 59 InvoiceStatus = (EnumInvoiceStatus)20, 60 OrderNo = orderDetail.OrderDetailNo, 61 PayAmount = orderDetail.OrderAmount, 62 PurchaserInvoiceTitle = invoiceTitle.Name, 63 PurchaserIdTaxpayer = invoiceTitle.TaxNumber, 64 PurchaserAddressMobile = invoiceTitle.Mobile, 65 PurchaserBank = invoiceTitle.Bank, 66 PurchaserBankNumber = invoiceTitle.BankNumber, 67 UserEmail = invoiceTitle.SendEmailAddress, 68 UserMobile = invoiceTitle.SendPhoneNumber, 69 SerialNo = openInvoiceResponse.invoiceSerialNum 70 }; 71 openInvoice = await _openInvoiceRepository.InsertAsync(openInvoiceRecord, true); 72 } 73 74 //查询发票:提交成功后,返回是开票提交成功,会立即返回开票流水号,这里电子票的状态不是最终状态,如果使用流水号查询开票信息,有可能是开票中状态 75 var query = QueryInvoiceAsync(openInvoice, fpkjModel.salerTaxNum); 76 } 77 } 78 } 79 else 80 { 81 Logger.LogInformation("申请诺诺电子发票:未查询到发票抬头信息"); 82 } 83 } 84 else 85 { 86 Logger.LogInformation("申请诺诺电子发票:未查询到订单信息"); 87 } 88 } 89 catch (Exception ex) 90 { 91 Logger.LogInformation("申请诺诺电子发票:" + ex.Message); 92 } 93 } 94 95 /// <summary> 96 /// 查询发票,完善发票信息 97 /// </summary> 98 private async Task QueryInvoiceAsync(OpenInvoiceRecord invoice, string taxNum) 99 { 100 // 等待 5 秒钟 101 await Task.Delay(TimeSpan.FromSeconds(10)); 102 Logger.LogInformation($"查询发票信息:{JsonConvert.SerializeObject(invoice)}"); 103 string fpckMsg = "查询发票信息"; 104 while (!string.IsNullOrEmpty(fpckMsg)) 105 { 106 List<string> serialNos = new List<string>(); 107 if (!string.IsNullOrEmpty(invoice.SerialNo)) 108 { 109 serialNos.Add(invoice.SerialNo); 110 } 111 List<string> orderNos = new List<string>() 112 { 113 invoice.OrderNo 114 }; 115 116 (List<InvoicePdf> pdfList, string msg) fpInfoList = _openInvoiceManager.QueryInvoice( 117 new FpcxRequest() 118 { 119 serialNos = serialNos, 120 orderNos = orderNos 121 }, 122 taxNum); 123 fpckMsg = fpInfoList.msg; 124 125 if (fpInfoList.pdfList != null && string.IsNullOrEmpty(fpckMsg)) 126 { 127 Logger.LogInformation($"查询发票信息:pdfList:{JsonConvert.SerializeObject(fpInfoList.pdfList)}"); 128 InvoicePdf invoicePdf = fpInfoList.pdfList.FirstOrDefault<InvoicePdf>(); 129 if (!string.IsNullOrEmpty(invoicePdf.URL)) 130 { 131 invoice.InvoiceUrl = invoicePdf.URL; 132 invoice.InvoiceCode = invoicePdf.FPDM; 133 invoice.InvoiceNo = invoicePdf.FPHM; 134 invoice.SerialNo = invoicePdf.FPLSH; 135 invoice.CheckCode = invoicePdf.JYM; 136 invoice.InvoiceStatus = (EnumInvoiceStatus)2; 137 invoice.InvoiceTime = DateTimeHelper.StampToDateTime(invoicePdf.KPRQ.ToString()); 138 139 var temp = await _openInvoiceRepository.UpdateAsync(invoice); 140 if (temp != null) 141 { 142 return; 143 } 144 } 145 } 146 else 147 { 148 Logger.LogInformation($"查询发票信息:描述:{fpInfoList.msg},{JsonConvert.SerializeObject(fpInfoList.pdfList)}"); 149 } 150 } 151 }View Code
1 /// <summary> 2 /// 诺诺开放平台开票 3 /// </summary> 4 /// <returns></returns> 5 public (string invoiceSerialNum, string message) OpenInvoice(FpkjRequest fpkj, string taxNum) 6 { 7 foreach (var item in fpkj.invoiceDetail) 8 { 9 var sl = Convert.ToDouble(item.taxRate); 10 var hsje = Convert.ToDouble(item.taxIncludedAmount); 11 var xmdj = 0.00;//项目单价 12 var se = 0.00;//税额 13 var bhsje = 0.00;//不含税金额 14 if (item.withTaxFlag == "1") 15 { 16 xmdj = hsje / Convert.ToInt32(item.num);//项目单价 17 se = Math.Round(hsje * sl / (1 + sl), 2); 18 bhsje = hsje - se; 19 } 20 else 21 { 22 xmdj = hsje / Convert.ToInt32(item.num) / (1 + sl); 23 se = Math.Round(xmdj * Convert.ToInt32(item.num) * sl, 2); 24 bhsje = hsje - se; 25 } 26 item.tax = se.ToString(); 27 item.taxExcludedAmount = bhsje.ToString(); 28 item.price = xmdj.ToString(); 29 } 30 31 string jsonStr = JsonConvert.SerializeObject(fpkj); 32 string content = "{"; 33 content += "\"order\":"; 34 content += jsonStr; 35 content += " }"; 36 Logger.LogInformation($"诺诺开放平台开票接口请求:{content}"); 37 var invoiceConfigDto = _invoiceConfigOptions.Value; 38 var returnStr = NuoNuoSdkHelper.sendRequest("nuonuo.OpeMplatform.requestBillingNew", content, taxNum, invoiceConfigDto); 39 Logger.LogInformation($"诺诺开放平台开票接口返回:{returnStr}"); 40 var FpkjReturnModel = JsonConvert.DeserializeObject<FpkjResponse>(returnStr); 41 var invoiceSerialNum = ""; 42 if (FpkjReturnModel.code == "E0000") 43 { 44 var resultSerialNumModel = JsonConvert.DeserializeObject<resultSerialNum>(JsonConvert.SerializeObject(FpkjReturnModel.result)); 45 invoiceSerialNum = resultSerialNumModel.invoiceSerialNum; 46 } 47 48 return (invoiceSerialNum, FpkjReturnModel.describe); 49 } 50 51 /// <summary> 52 /// 诺诺开放平台发票查询 53 /// </summary> 54 /// <returns></returns> 55 public (List<InvoicePdf> pdfList, string msg) QueryInvoice(FpcxRequest fpcx, string taxNum) 56 { 57 string content = JsonConvert.SerializeObject(fpcx); 58 Logger.LogInformation($"诺诺开放平台发票查询接口请求:{content}"); 59 var invoiceConfigDto = _invoiceConfigOptions.Value; 60 var returnStr = NuoNuoSdkHelper.sendRequest("nuonuo.OpeMplatform.queryInvoiceResult", content, taxNum, invoiceConfigDto); 61 Logger.LogInformation($"诺诺开放平台发票查询接口返回:{returnStr},参数:{content}---{taxNum}---{JsonConvert.SerializeObject(invoiceConfigDto)}"); 62 63 string msg = ""; 64 List<InvoicePdf> dataList = new List<InvoicePdf>(); 65 var FpcxReturnModel = JsonConvert.DeserializeObject<FpcxResponse>(returnStr); 66 if (FpcxReturnModel.code == "E0000") 67 { 68 var fpInfo = FpcxReturnModel.result; 69 if (fpInfo.Count < 1) 70 { 71 msg = "发票查询:未查询到发票数据"; 72 } 73 else 74 { 75 foreach (var item in fpInfo) 76 { 77 var pdfInfo = new InvoicePdf(); 78 pdfInfo.DDLSH = item.orderNo; 79 pdfInfo.FPLSH = item.serialNo; 80 pdfInfo.FPDM = item.invoiceCode; 81 pdfInfo.FPHM = item.invoiceNo; 82 pdfInfo.KPRQ = item.invoiceTime; 83 pdfInfo.URL = item.pdfUrl; 84 pdfInfo.JYM = item.checkCode; 85 pdfInfo.status = item.status; 86 pdfInfo.statusMsg = item.statusMsg; 87 pdfInfo.failCause = item.failCause; 88 dataList.Add(pdfInfo); 89 } 90 } 91 } 92 else 93 { 94 msg = FpcxReturnModel.describe; 95 } 96 97 return (dataList, msg); 98 }View Code
1 public class NuoNuoSdkHelper 2 { 3 /// <summary> 4 /// 调用诺诺开放平台API 5 /// </summary> 6 /// <returns></returns> 7 public static string sendRequest(string method, string content, string taxNum, InvoiceConfigDto _invoiceConfigDto) 8 { 9 string senid = Guid.NewGuid().ToString().Replace("-", "").Substring(0, 32); // 唯一标识,由企业自己生成32位随机码 10 return NNOpenSDK.sendPostSyncRequest(_invoiceConfigDto.Url, senid, _invoiceConfigDto.AppKey, _invoiceConfigDto.AppSecret, _invoiceConfigDto.Token, taxNum, method, content); 11 } 12 }View Code
1 public override void ConfigureServices(ServiceConfigurationContext context) 2 { 3 var configuration = context.Services.GetConfiguration(); 4 5 ConfigureSalerInvoiceConfig(context, configuration); 6 ConfigureInvoiceConfig(context, configuration); 7 } 8 9 /// <summary> 10 /// 设置发票配置信息 11 /// </summary> 12 /// <param name="context"></param> 13 /// <param name="configuration"></param> 14 private void ConfigureInvoiceConfig(ServiceConfigurationContext context, IConfiguration configuration) 15 { 16 context.Services.Configure<InvoiceConfigDto>(options => 17 { 18 options.AppKey = configuration["InvoiceConfigString:AppKey"]; 19 options.AppSecret = configuration["InvoiceConfigString:AppSecret"]; 20 options.Url = configuration["InvoiceConfigString:Url"]; 21 options.Token = configuration["InvoiceConfigString:ZheJiangJianYuanShuDianToken"]; 22 }); 23 } 24 25 /// <summary> 26 /// 设置销售方发票配置信息 27 /// </summary> 28 /// <param name="context"></param> 29 /// <param name="configuration"></param> 30 private void ConfigureSalerInvoiceConfig(ServiceConfigurationContext context, IConfiguration configuration) 31 { 32 context.Services.Configure<FpkjRequest>(options => 33 { 34 options.clerk = configuration["SalerInvoiceConfig:clerk"]; 35 options.checker = configuration["SalerInvoiceConfig:checker"]; 36 options.payee = configuration["SalerInvoiceConfig:payee"]; 37 options.salerTaxNum = configuration["SalerInvoiceConfig:salerTaxNum"]; 38 options.salerTel = configuration["SalerInvoiceConfig:salerTel"]; 39 options.salerAddress = configuration["SalerInvoiceConfig:salerAddress"]; 40 options.salerAccount = configuration["SalerInvoiceConfig:salerAccount"]; 41 }); 42 }View Code
//销售方发票配置 "SalerInvoiceConfig": { "clerk": "", //开票人 "checker": "", //复核人 "payee": "", //收款人 "salerTaxNum": "", //销售方税号(测试) "salerTel": "", //销售方电话 "salerAddress": "", //销售方地址 "salerAccount": "" //销方银行账号和开户行地址 }, //发票配置 "InvoiceConfigString": { "AppKey": "", "AppSecret": "", "Url": "https://sandbox.nuonuocs.cn/open/v1/services", "ZheJiangJianYuanShuDianToken": "", //获取开票token密钥 "InvoiceAmountLimit": 10000 //发票最大金额限制 }标签:string,开票,invoiceTitle,item,诺诺,var,发票,fpkjModel From: https://www.cnblogs.com/zhaoyl9/p/18020747