diff --git a/29WxOrderWpf/Ctrls/PDDInvoice/ViewModels/PDDInvoiceOrderModel.cs b/29WxOrderWpf/Ctrls/PDDInvoice/ViewModels/PDDInvoiceOrderModel.cs index bc13302..520c574 100644 --- a/29WxOrderWpf/Ctrls/PDDInvoice/ViewModels/PDDInvoiceOrderModel.cs +++ b/29WxOrderWpf/Ctrls/PDDInvoice/ViewModels/PDDInvoiceOrderModel.cs @@ -63,13 +63,18 @@ public class PddBrowserOrderInvoiceViewModel : BindableBaseEx set { SetValue(value); - base.RaisePropertyChanged(nameof(InvoiceStatusText)); + InvoiceStatusText = value ? "已提交申请" : "待开票"; } } public int Quantity => order_Goods?.Sum(a => a.goods_number.Value) ?? 0; + private string _invoiceStatusText = "待开票"; /// 发票状态文案:已开票 / 待开票 - public string InvoiceStatusText => IsInvoiced ? "已提交申请" : "待开票"; + public string InvoiceStatusText + { + get => _invoiceStatusText; + set => SetValue(ref _invoiceStatusText, value); + } public DateTime OrderTime diff --git a/29WxOrderWpf/Ctrls/PDDInvoice/ViewModels/PDDInvoiceViewModel.BrowserDetail.cs b/29WxOrderWpf/Ctrls/PDDInvoice/ViewModels/PDDInvoiceViewModel.BrowserDetail.cs index 43b4224..e8e6686 100644 --- a/29WxOrderWpf/Ctrls/PDDInvoice/ViewModels/PDDInvoiceViewModel.BrowserDetail.cs +++ b/29WxOrderWpf/Ctrls/PDDInvoice/ViewModels/PDDInvoiceViewModel.BrowserDetail.cs @@ -2,6 +2,8 @@ using CefSharp; using CefSharp.Handler; using CefSharp.Wpf; +using Newtonsoft.Json.Linq; +using NPOI.XWPF.UserModel; using System; using System.Collections.Generic; using System.Linq; @@ -11,6 +13,7 @@ using System.Threading.Tasks; using System.Windows.Controls; using Work._29Tools.CefTools; using Work.BaseForms; +using WxOrder.Framework.Commons; using WxOrder.Framework.Helpers; namespace _29WxOrderWpf.Ctrls.PDDInvoice.ViewModels; @@ -29,11 +32,10 @@ public partial class PDDInvoiceViewModel BrowserDetailZIndex = -1; BrowserDetail = WPFCEFBrowser.CreateChromiumWebBrowser("about:blank", false); - LocalResourceRequestHandler resourceRequestHandler = new LocalResourceRequestHandler(); LocalResourceRequestHandler detailResourceRequestHandler = new LocalResourceRequestHandler(); detailResourceRequestHandler.ResourceLoadCompleteEvent += DetailRequestHandler_ResourceLoadComplete; - BrowserDetail.RequestHandler = new LocalRequestHandler(resourceRequestHandler); + BrowserDetail.RequestHandler = new LocalRequestHandler(detailResourceRequestHandler); BrowserDetail.LifeSpanHandler = new LocalLifeSpanHandler(PopWindowType.SelfWindow); BrowserDetail.KeyboardHandler = new KeyboardHandler(); BrowserDetail.LoadingStateChanged += BrowserDetail_LoadingStateChanged; @@ -68,12 +70,17 @@ public partial class PDDInvoiceViewModel string html = await b.GetBrowser().GetSourceAsync(); if (html.Contains("window.rawData")) { - await ExecuteInvoiceApplyScriptAsync(b, orderSN); + if (html.Contains("\"hasApplied\":true,")) + { + _currentInvoiceTcs?.TrySetResult(new Result { Data = true }); + return; + } + await ExecuteInvoiceApplyScriptAsync(b); } else { // 页面异常(未渲染出发票表单)时直接判定失败,避免批量开票长时间等待 - _currentInvoiceTcs?.TrySetResult(false); + _currentInvoiceTcs?.TrySetResult(new Result { Data = false }); } } }); @@ -85,54 +92,40 @@ public partial class PDDInvoiceViewModel /// 单张申请模式保持原有行为;批量开票模式下轮询脚本写入的 /// window.__invoiceApplyResult,完成后通过 回传结果。 /// - private async Task ExecuteInvoiceApplyScriptAsync(ChromiumWebBrowser b, string orderSn) + private async Task ExecuteInvoiceApplyScriptAsync(ChromiumWebBrowser b) { string content = ResourceHelper.GetResourceText("/Ctrls/PDDInvoice/Resources/invoice.js", "29WxFindOrder"); content = content.Replace("{公司}", Config.Title); content = content.Replace("{税号}", Config.TaxNo); if (string.IsNullOrEmpty(content)) return; - await b.EvaluateScriptAsync(content); - - if (_currentInvoiceTcs == null) - { - var temp = Orders?.FirstOrDefault(a => a.order_sn == orderSn); - if (temp != null) temp.IsInvoiced = true; - return; // 单张申请模式:保持原有行为 - } - - // 捕获当前 TCS,避免批量循环超时进入下一个订单后,迟到的轮询误触发新订单的结果 - var tcs = _currentInvoiceTcs; + await b.EvaluateScriptAsync(content);//执行js // 检查是否注入成功 if (await IsInstalledDetailAsync(b) == false) { IsBatchInvoicing = false; BaseMsgForm.ShowError("JS错误,开票失败"); - tcs.TrySetResult(false); + _currentInvoiceTcs.TrySetResult(new Result { Data = false }); return; } - - - - - for (int i = 0; i < 120; i++) - { - await Task.Delay(500); - try - { - var res = await b.EvaluateScriptAsync("window.__invoiceApplyResult"); - if (res.Success && res.Result != null) - { - tcs.TrySetResult(Convert.ToBoolean(res.Result)); - return; - } - } - catch - { - } - } - tcs.TrySetResult(false); + //for (int i = 0; i < 120; i++)//循环获取结果 + //{ + // await Task.Delay(500); + // try + // { + // var res = await b.EvaluateScriptAsync("window.__invoiceApplyResult"); + // if (res.Success && res.Result != null) + // { + // _currentInvoiceTcs.TrySetResult(Convert.ToBoolean(res.Result)); + // return; + // } + // } + // catch + // { + // } + //} + //_currentInvoiceTcs.TrySetResult(false); } @@ -151,9 +144,40 @@ public partial class PDDInvoiceViewModel private void DetailRequestHandler_ResourceLoadComplete(object sender, string url, string postData, string responseData, IRequest request) { - if (url.StartsWith("https://mobile.yangkeduo.com/transac_return_compensation.html")) + if (url.StartsWith("https://mobile.yangkeduo.com/proxy/api/api/order/invoice/apply")) { + var obj = JObject.Parse(responseData); + bool isSuccess = obj.Value("result") == true; + if (isSuccess) + { + _currentInvoiceTcs.TrySetResult(new Result { Data = true }); + } + else + { + IsBatchInvoicing = false; + + string errMsg = obj.Value("error_msg"); + _currentInvoiceTcs.TrySetResult(new Result { Data = false, Msg = errMsg }); + } + return; + + + + + + + //{"order_sn":"260921-458426969742556","mall_id":697300659,"trigger_status":1,"business_type":1,"payer_name":"合肥弘贸电子商务有限公司","invoice_kind":0,"invoice_type":0,"letter_head_id":"690562059266556","letterhead_snapshot_id":"SI298036413700604","paper_certificate_url":"","entrust_certify_url":"","source":1,"anti_content":"0asAfoyqYiPs6gd2J0WQ9QOUtOrZ44_LwPI3lrN83FY_wympvl577D6QppXrSLrHJn8eNWv8uXBTdg6_iPUC1aDYt-JuCI1dMpKg2wsf65KUBPzEhRU8pGAbTnWhcJ29ooVcncR90coLgWQiLJ0Xjo0Y4aHEJnnk2lr2PRkY2Kj9ibYc9QW-i2Mr23mjyQMQIahwAhEX-xjSVJEd35qSDQo9VrbY0Fb4kiiL0tHoKEQqmgMcn1BIH9LQB30NJ9s857b25NDDXQyuIT9hR2fCiRoY-96khLJ8QI6wqNL8Q406RBojM6oYsKqEGEFNn7Qyr4N3q-FELBTkkmyToyzs4cM1iUKl3Zaqe0MtFefxmZcLUj3FFxQ6GdAAfKO2WlAkwx7QuMppG7UtkEpRuNjrkojzegy1jaIBWzPrzevvx3egES52PIHEFZASpZ2gNPXaDGSbVGu8shqGDmXuu94aWgXxEE3CzPfVcUZooGs40ThX0ouQF7IFTKM6-NSsk8ZrVjEHdWO1-EE_SCngMCC1vFeAr1g5NvaUCC_87CibfVcWPe5lhgRaq6dKfSAYDoT_bA0nPm6wSDZSxAQbSk-1JZC-O6OpFqXcrkKVUZk0atnozQtKlf1cxcyCl_EkEMnpwZll4g3jEKUxLK_XCIUz0TjDUbF1dpZOsWd39crq7VktSKKZ32b_e0sk6ZkvAf5F7GKwfvfy6RX5YbcrCcpfsjJqaXNGy2G2Y_Oj0iPcpgaXv0zmJjkB217RMtwxBybZnjdOMIlGJWUFls4unwncEvdy4Udgi7EdgB_MXwgn2zGa1_wHKltF7n37wKjKBKlysnfv8mFfqzH3Jv7L4jj9cCQ7P5Fb3E8KQ9J","payer_register_no":"91340103MAKBDKB764","payer_phone":"","payer_account":"","payer_address":"","payer_bank":""} + + //{"server_time":1792493897,"result":true} + + /* + { + "server_time": 1792493128, + "error_code": 17003, + "error_msg": "商家已与您协商开票,如有需要,请联系商家" + }*/ } + } } diff --git a/29WxOrderWpf/Ctrls/PDDInvoice/ViewModels/PDDInvoiceViewModel.cs b/29WxOrderWpf/Ctrls/PDDInvoice/ViewModels/PDDInvoiceViewModel.cs index 3fa9299..c396c1f 100644 --- a/29WxOrderWpf/Ctrls/PDDInvoice/ViewModels/PDDInvoiceViewModel.cs +++ b/29WxOrderWpf/Ctrls/PDDInvoice/ViewModels/PDDInvoiceViewModel.cs @@ -1,7 +1,5 @@ using _29WxOrderWpf.BaseWindows; using _29WxOrderWpf.CefHelper; -using WxOrder.Framework.Commons; -using WxOrder.Framework.Commons; using _29WxOrderWpf.Ctrls.Statistics; using AllBase; using AllBase.Helper; @@ -14,6 +12,7 @@ using CefSharp.Wpf; using NaiBa.Util.Extension; using Newtonsoft.Json; using NPOI.SS.Formula.Functions; +using Org.BouncyCastle.Asn1.X509; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -37,6 +36,8 @@ using WPFCommon.Converters; using WPFCommon.Helpers; using WPFCommon.Models; using WxOrder.Framework.Commons; +using WxOrder.Framework.Commons; +using WxOrder.Framework.Commons; using WxOrder.Framework.Commons.Dialogs; using WxOrder.Framework.Helpers; @@ -284,7 +285,7 @@ public partial class PDDInvoiceViewModel : BindableBaseEx, IDialogAware, IDispos public ICommand ResetCommand => new DelegateCommand(ResetSearch); - public ICommand OpenInvoiceCommand => new DelegateCommand(OpenInvoice); + public ICommand OpenInvoiceCommand => new AsyncDelegateCommand(OpenInvoice); public ICommand ShowInvoiceCommand => new DelegateCommand(ShowInvoice); @@ -434,7 +435,7 @@ public partial class PDDInvoiceViewModel : BindableBaseEx, IDialogAware, IDispos } /// 当前正在批量处理的订单,页面脚本执行完成后通过它回传结果 - private TaskCompletionSource _currentInvoiceTcs; + private TaskCompletionSource> _currentInvoiceTcs; public ICommand BatchInvoiceCommand => new AsyncDelegateCommand(BatchInvoice); @@ -471,8 +472,19 @@ public partial class PDDInvoiceViewModel : BindableBaseEx, IDialogAware, IDispos //Config.TaxNo = TaxNo; //Config.MaxAmount = MaxAmount; //NaiBa.Util.Helper.ConfigHelper.SaveConfig(ConfigPath, Config); + try + { + await BatchInvoiceAsync(targets); + } + catch (Exception ex) + { + BaseMsgWindow.ShowError("批量开票异常:" + ex.Message); - await BatchInvoiceAsync(targets); + } + finally + { + BaseMsgWindow.ShowInfo(BottomMsg); + } } public ICommand StopBatchInvoiceCommand => new AsyncDelegateCommand(StopBatchInvoice); @@ -541,12 +553,12 @@ public partial class PDDInvoiceViewModel : BindableBaseEx, IDialogAware, IDispos } else { - _currentInvoiceTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + _currentInvoiceTcs = new TaskCompletionSource>(TaskCreationOptions.RunContinuationsAsynchronously); BrowserDetail.Load($"https://mobile.yangkeduo.com/transac_return_compensation.html?_t_timestamp=transac_modify_invoice&order_sn={order.order_sn}"); // 等待页面脚本执行完成(最长 60 秒) - var done = await Task.WhenAny(_currentInvoiceTcs.Task, Task.Delay(TimeSpan.FromSeconds(60))); - ok = done == _currentInvoiceTcs.Task && _currentInvoiceTcs.Task.Result; + Task done = await Task.WhenAny(_currentInvoiceTcs.Task, Task.Delay(TimeSpan.FromSeconds(10))); + ok = done == _currentInvoiceTcs.Task && _currentInvoiceTcs.Task.Result.Data; } if (ok) { @@ -562,6 +574,10 @@ public partial class PDDInvoiceViewModel : BindableBaseEx, IDialogAware, IDispos } else { + if (_currentInvoiceTcs.Task.IsCompleted) + { + order.InvoiceStatusText = _currentInvoiceTcs.Task.Result.Msg; + } fail++; } ProgressValue = success + fail; @@ -580,7 +596,7 @@ public partial class PDDInvoiceViewModel : BindableBaseEx, IDialogAware, IDispos catch (Exception ex) { fail = targets.Count - success; - BaseMsgWindow.ShowError("批量开票异常:" + ex.Message); + throw ex; } finally { @@ -588,7 +604,6 @@ public partial class PDDInvoiceViewModel : BindableBaseEx, IDialogAware, IDispos ProgressMaximum = targets.Count; ProgressValue = targets.Count; IsBatchInvoicing = false; - BaseMsgWindow.ShowInfo(BottomMsg); } } /// @@ -642,7 +657,7 @@ public partial class PDDInvoiceViewModel : BindableBaseEx, IDialogAware, IDispos /// 申请开票 /// /// - private void OpenInvoice(PddBrowserOrderInvoiceViewModel order) + private async Task OpenInvoice(PddBrowserOrderInvoiceViewModel order) { SelectedOrder = order; if (string.IsNullOrEmpty(Config.Title) || string.IsNullOrEmpty(Config.TaxNo)) @@ -650,8 +665,19 @@ public partial class PDDInvoiceViewModel : BindableBaseEx, IDialogAware, IDispos BaseMsgWindow.ShowError("未填写公司或税号"); return; } - BrowserDetail.Load($"https://mobile.yangkeduo.com/transac_return_compensation.html?_t_timestamp=transac_modify_invoice&order_sn={order.order_sn}"); ShowOrderBrowserDetail(); + //BrowserDetail.Load($"https://mobile.yangkeduo.com/transac_return_compensation.html?_t_timestamp=transac_modify_invoice&order_sn={order.order_sn}"); + try + { + await BatchInvoiceAsync(new List + { + order + }); + } + catch (Exception ex) + { + BaseMsgWindow.ShowError("开票异常:" + ex.Message); + } } private void ShowInvoice(PddBrowserOrderInvoiceViewModel order)