1自动拍单功能(暂未开放)

This commit is contained in:
wule committed 2026-09-11 18:53:38 +08:00
1 parent b42c17c013
commit 5906a1623f
8 files changed
+287 -185

No files matched your search

+14 -12
View File
@@ -49,14 +49,14 @@ namespace _29WxOrderWpf.BaseWindows
BaseMsgWindow msgBox = null;
Window owner = window ?? MainWindow.Instance;
owner.Dispatcher.Invoke(new Action(() =>
{
//owner.Dispatcher.Invoke(() =>
Application.Current.Dispatcher.Invoke(() =>
{
msgBox = CreateMsgForm(msg, title, wl);
msgBox.imgTip.Source = Application.Current.Resources["imgBaseMsgInfo"] as ImageSource;
msgBox.Owner = owner;
//msgBox.Owner = owner;
msgBox.ShowDialog();
}));
});
return msgBox;
}
@@ -65,13 +65,14 @@ namespace _29WxOrderWpf.BaseWindows
string title = string.IsNullOrEmpty(caption) ? "系统错误" : caption;
BaseMsgWindow msgBox = null;
Window owner = window ?? MainWindow.Instance;
owner.Dispatcher.Invoke(new Action(() =>
{
//owner.Dispatcher.Invoke(() =>
Application.Current.Dispatcher.Invoke(() =>
{
msgBox = CreateMsgForm(msg, title, wl);
msgBox.imgTip.Source = Application.Current.Resources["imgBaseMsgErr"] as ImageSource;
msgBox.Owner = owner;
//msgBox.Owner = owner;
msgBox.ShowDialog();
}));
});
return msgBox;
}
@@ -81,8 +82,9 @@ namespace _29WxOrderWpf.BaseWindows
BaseMsgWindow msgBox = null;
Window owner = window ?? MainWindow.Instance;
owner.Dispatcher.Invoke(() =>
{
//owner.Dispatcher.Invoke(() =>
Application.Current.Dispatcher.Invoke(() =>
{
msgBox = new BaseMsgWindow
{
lblTitle = { Content = title },
@@ -94,7 +96,7 @@ namespace _29WxOrderWpf.BaseWindows
msgBox.Width = (int)MsgWindowLevel.LARGE;
msgBox.Height = 500;
}
msgBox.Owner = owner;
//msgBox.Owner = owner;
msgBox.ShowDialog();
});
return msgBox;
@@ -628,7 +628,7 @@
Padding="4,0"
c:DebugVisibility.Enable="True"
Click="btnAutoBuyIntroduction_Click"
Content="自动拍单说明"
Content="自动拍单设置说明"
FontSize="12"
Style="{StaticResource BasePageButtonLightStyle}" />
<Polyline
@@ -5,6 +5,8 @@ using _29WxOrderWpf.Ctrls.BuyerCtrls;
using _29WxOrderWpf.Ctrls.Statistics;
using _29WxOrderWpf.Services;
using _29WxOrderWpf.Utils;
using _29WxOrderWpf.ViewModels;
using _29WxOrderWpf.Views;
using _29WxOrderWpf.Windows.OrderWindows;
using AllBase;
using AllBase.Extension;
@@ -42,7 +44,6 @@ using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Xml;
using System.Xml.Linq;
using _29WxOrderWpf.ViewModels;
using Work;
using Work._29Tools.BLL;
using Work.BuyUsers;
@@ -2724,7 +2725,12 @@ namespace _29WxOrderWpf.Ctrls.OrderCtrls
private void btnAutoBuyIntroduction_Click(object sender, RoutedEventArgs e)
{
AutoBuyIntroductionView autoBuyIntroForm = new AutoBuyIntroductionView();
new DialogWindow()
{
Title = "自动拍单设置说明",
Content = autoBuyIntroForm,
}.ShowDialog();
}
}
+4 -1
View File
@@ -5,6 +5,7 @@ using AllBase.Model.Config;
using AllBase.Model.DBModel;
using NaiBa.Util;
using NaiBa.Util.Helper;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -27,7 +28,9 @@ namespace _29WxOrderWpf
GlobalConfig.lstWXShopTokenInfo = new ConcurrentList<WXShopTokenInfo>();
// 自动拍单支付宝密码
GlobalConfig.AlipayPassword = ConfigHelper.LoadConfig<string>("ali_pay_password");
GlobalConfig.AlipayPassword = ConfigHelper.LoadConfig<List<string>>("ali_pay_password")?.FirstOrDefault();
if (GlobalConfig.AlipayPassword == null)
GlobalConfig.AlipayPassword = "";
new WxOrder.Framework.Startup();
}
@@ -2,6 +2,7 @@
x:Class="_29WxOrderWpf.Views.AutoBuyIntroductionView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:UserControls="clr-namespace:_29WxOrderWpf.UserControls"
xmlns:comn="clr-namespace:_29WxOrderWpf.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:_29WxOrderWpf.Views"
@@ -16,47 +17,86 @@
Loaded="AutoBuyInstructionView_Loaded"
mc:Ignorable="d">
<Grid Background="White">
<PasswordBox
Width="120"
Height="24"
Margin="198,79,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top" />
<TextBlock
Margin="70,83,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Text="请输入支付宝支付密码:"
TextWrapping="Wrap" />
<PasswordBox
x:Name="pbxPassWord"
Width="169"
Height="24"
Margin="198,79,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
VerticalContentAlignment="Center"
PasswordChanged="pbxPassWord_PasswordChanged" />
<TextBox
x:Name="txtPassWord"
Width="149"
Height="24"
Margin="198,79,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
VerticalContentAlignment="Center"
d:IsHitTestVisible="True"
d:Opacity="0.3"
d:Text="明文密码"
d:Visibility="Visible"
BorderBrush="Transparent"
IsHitTestVisible="True"
TextChanged="txtPassWord_TextChanged"
Visibility="Collapsed" />
<Button
x:Name="btnSee"
Width="18"
Height="18"
Margin="347,82,0,0"
Padding="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Background="Transparent"
BorderBrush="Transparent"
Click="btnSee_Click"
Content="👁"
Cursor="Hand"
Foreground="{StaticResource PageLinkBrush}" />
<Button
x:Name="btnSaveAliPass"
Width="Auto"
Height="22"
MinWidth="48"
Margin="323,80,0,348"
Margin="372,80,0,0"
Padding="4,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="btnSaveAliPass_Click"
Content="保存密码"
FontSize="12"
Style="{StaticResource BasePageButtonStyle}" />
Style="{StaticResource BasePageButtonStyle}"
Visibility="Visible" />
<Button
x:Name="btnClear"
Width="Auto"
Height="22"
MinWidth="48"
Margin="384,80,0,348"
Margin="433,80,0,0"
Padding="4,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="btnClear_Click"
Content="清空密码"
FontSize="12"
Style="{StaticResource BasePageButtonLightStyle}" />
Style="{StaticResource BasePageButtonLightStyle}"
Visibility="Visible" />
<TextBlock
Margin="70,128,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Text="说明:请输入并保存支付宝支付密码(仅记录在本地),首次自动拍单前请手动拍单一次以缓存支付保Cookie"
Margin="70,128,70,128"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Text="说明:请保存支付宝支付密码(仅记录在本地)供自动拍单支付,首次自动拍单前请手动拍单一次以缓存支付宝Cookie。"
TextWrapping="Wrap" />
</Grid>
</UserControl>
@@ -1,4 +1,9 @@
using System;
using _29WxOrderWpf.BaseWindows;
using AllBase.Helper;
using AllBase.Model.DBModel;
using NaiBa.Util;
using NaiBa.Util.Helper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -12,6 +17,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Work.Pinduoduo;
namespace _29WxOrderWpf.Views
{
@@ -27,17 +33,42 @@ namespace _29WxOrderWpf.Views
private void AutoBuyInstructionView_Loaded(object sender, RoutedEventArgs e)
{
this.pbxPassWord.Password = DataOpenSSL.DecryptString(GlobalConfig.AlipayPassword);
}
private void btnSaveAliPass_Click(object sender, RoutedEventArgs e)
{
GlobalConfig.AlipayPassword = DataOpenSSL.EncryptString(this.pbxPassWord.Password);
ConfigHelper.SaveConfig("ali_pay_password", new List<string>() { GlobalConfig.AlipayPassword });
BaseMsgWindow.ShowInfo("密码保存成功!");
}
private void btnClear_Click(object sender, RoutedEventArgs e)
{
this.pbxPassWord.Password = "";
GlobalConfig.AlipayPassword = "";
ConfigHelper.SaveConfig("ali_pay_password", new List<string>() { GlobalConfig.AlipayPassword });
BaseMsgWindow.ShowInfo("密码已清除!");
}
private void btnSee_Click(object sender, RoutedEventArgs e)
{
if (txtPassWord.Visibility == Visibility.Visible)
txtPassWord.Visibility = Visibility.Collapsed;
else
txtPassWord.Visibility = Visibility.Visible;
}
private void pbxPassWord_PasswordChanged(object sender, RoutedEventArgs e)
{
if (txtPassWord.Text != pbxPassWord.Password)
txtPassWord.Text = pbxPassWord.Password;
}
private void txtPassWord_TextChanged(object sender, TextChangedEventArgs e)
{
if (txtPassWord.Text != pbxPassWord.Password)
pbxPassWord.Password = txtPassWord.Text;
}
}
}
+68 -56
View File
@@ -1,4 +1,5 @@
using AllBase;
using NaiBa.Util.Extension;
using System;
using System.Collections.Generic;
using System.IO;
@@ -78,75 +79,86 @@ namespace Work.Pinduoduo
return plainText;
}
/// <summary>
/// 解密
/// </summary>
/// <param name="cipherText"></param>
/// <returns></returns>
public static string DecryptString(string cipherText)
{
cipherText = cipherText.Replace("-", "+").Replace("_", "/");
var x1 = cipherText.Length % 4;
if (x1 > 0)
{
cipherText = cipherText + "====".Substring(x1);
}
// Instantiate a new Aes object to perform string symmetric encryption
Aes encryptor = Aes.Create();
/// <summary>
/// 解密
/// </summary>
/// <param name="cipherText"></param>
/// <returns></returns>
public static string DecryptString(string cipherText)
{
if (cipherText.IsNullOrEmpty())
return "";
try
{
cipherText = cipherText.Replace("-", "+").Replace("_", "/");
var x1 = cipherText.Length % 4;
if (x1 > 0)
{
cipherText = cipherText + "====".Substring(x1);
}
// Instantiate a new Aes object to perform string symmetric encryption
Aes encryptor = Aes.Create();
encryptor.Mode = CipherMode.CBC;
encryptor.Mode = CipherMode.CBC;
// Set key and IV
byte[] aesKey = new byte[32];
Array.Copy(key, 0, aesKey, 0, 32);
encryptor.Key = aesKey;
encryptor.IV = iv;
// Set key and IV
byte[] aesKey = new byte[32];
Array.Copy(key, 0, aesKey, 0, 32);
encryptor.Key = aesKey;
encryptor.IV = iv;
// Instantiate a new MemoryStream object to contain the encrypted bytes
MemoryStream memoryStream = new MemoryStream();
// Instantiate a new MemoryStream object to contain the encrypted bytes
MemoryStream memoryStream = new MemoryStream();
// Instantiate a new encryptor from our Aes object
ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();
// Instantiate a new encryptor from our Aes object
ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();
// Instantiate a new CryptoStream object to process the data and write it to the
// memory stream
CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);
// Instantiate a new CryptoStream object to process the data and write it to the
// memory stream
CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);
// Will contain decrypted plaintext
string plainText = String.Empty;
// Will contain decrypted plaintext
string plainText = String.Empty;
try
{
// Convert the ciphertext string into a byte array
byte[] cipherBytes = Convert.FromBase64String(cipherText);
try
{
// Convert the ciphertext string into a byte array
byte[] cipherBytes = Convert.FromBase64String(cipherText);
// Decrypt the input ciphertext string
cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);
// Decrypt the input ciphertext string
cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);
// Complete the decryption process
cryptoStream.FlushFinalBlock();
// Complete the decryption process
cryptoStream.FlushFinalBlock();
// Convert the decrypted data from a MemoryStream to a byte array
byte[] plainBytes = memoryStream.ToArray();
// Convert the decrypted data from a MemoryStream to a byte array
byte[] plainBytes = memoryStream.ToArray();
// Convert the decrypted byte array to string
plainText = Encoding.UTF8.GetString(plainBytes, 0, plainBytes.Length);
}
catch (Exception)
{
// Convert the decrypted byte array to string
plainText = Encoding.UTF8.GetString(plainBytes, 0, plainBytes.Length);
}
catch (Exception)
{
//throw;
}
finally
{
// Close both the MemoryStream and the CryptoStream
memoryStream.Close();
cryptoStream.Close();
}
//throw;
}
finally
{
// Close both the MemoryStream and the CryptoStream
memoryStream.Close();
cryptoStream.Close();
}
// Return the decrypted data as a string
return plainText;
}
catch (Exception ex)
{
return cipherText;
}
}
// Return the decrypted data as a string
return plainText;
}
+104 -96
View File
@@ -5,8 +5,10 @@ using AllBase.Model.Config;
using AllBase.Model.DBModel;
using AllBase.Model.Result;
using CefSharp;
using CefSharp.DevTools;
using CefSharp.DevTools.IO;
using CefSharp.DevTools.Profiler;
using CefSharp.DevTools.Runtime;
using CefSharp.Web;
using CefSharp.WinForms;
using DevComponents.WinForms.Drawing;
@@ -38,6 +40,7 @@ using Work._29Tools.BLL;
using Work._29Tools.CefTools;
using Work._29Tools.Forms.ToolForms;
using Work.BaseForms;
using Work.Pinduoduo;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
namespace TemuKJD.ToolForms
@@ -640,120 +643,124 @@ namespace TemuKJD.ToolForms
public async Task SetAliPaySecret()
{
var host = cefWebBrowser.GetBrowser().GetHost();
var client = cefWebBrowser.GetDevToolsClient();
for (int i = 0; i < 20; i++)
// 选择支付宝去支付
var ts1 = await EvaluateJsBuyTagNameAndInnerHtml("span", "支付宝", true);
if (ts1.Result?.Value.ParseToString() != "success")
{
Thread.Sleep(50);
if (host == null || client == null)
{
host = cefWebBrowser.GetBrowser().GetHost();
client = cefWebBrowser.GetDevToolsClient();
continue;
}
throw new Exception("支付方式获取失败1");
}
if (host == null || client == null)
{
throw new Exception("页面加载异常");
}
var sourceCode = txtSourceCode.Text.Trim();
var jsStr1 = @"(function() { var elements = document.getElementsByTagName('span');
for (i = elements.length - 1; i >= 0; i--){
var element = elements[i];
if (element.innerHTML.indexOf('支付宝') >= 0) {
element.click();
return 'success';
}
}
return '';
})();";
Thread.Sleep(Randomx.GetId(500, 1000));
var ts1 = await client.Runtime.EvaluateAsync(jsStr1, null, true, null, null, true, null, true);
var jsStr2 = @"(function() { var elements = document.getElementsByTagName('span');
for (i = elements.length - 1; i >= 0; i--){
var element = elements[i];
if (element.innerHTML.indexOf('立即支付') >= 0) {
element.click();
return 'success';
}
}
return '';
})();";
var ts2 = await client.Runtime.EvaluateAsync(jsStr2, null, true, null, null, true, null, true);
if (ts1.Result?.Value.ParseToString() != "success" || ts2.Result?.Value.ParseToString() != "success")
var ts2 = await EvaluateJsBuyTagNameAndInnerHtml("span", "立即支付", true);
if (ts2.Result?.Value.ParseToString() != "success")
{
throw new Exception("支付方式获取失败");
throw new Exception("支付方式获取失败2");
}
Thread.Sleep(Randomx.GetId(1500, 2000));
var jsStr3 = @"(function() { var elements = document.getElementsByTagName('span');
for (i = elements.length - 1; i >= 0; i--){
var element = elements[i];
if (element.innerHTML.indexOf('确认付款') >= 0) {
element.click();
return 'success';
}
}
return '';
})();";
var ts3 = await client.Runtime.EvaluateAsync(jsStr3, null, true, null, null, true, null, true);
if (!this.Created)
throw new Exception("窗口已关闭");
// 点击确认付款
Thread.Sleep(Randomx.GetId(500, 1000));
ts2 = await EvaluateJsBuyTagNameAndInnerHtml("span", "确认付款", true);
for (int i = 0; i < 50; i++)
{
if (ts3.Result?.Value is string rstStr)
{
if (rstStr == "success")
break;
}
Thread.Sleep(200);
ts3 = await client.Runtime.EvaluateAsync(jsStr3, null, true, null, null, true, null, true);
if (ts2.Result?.Value is string rstStr && rstStr == "success")
break;
Thread.Sleep(100);
ts2 = await EvaluateJsBuyTagNameAndInnerHtml("span", "确认付款", true);
}
Thread.Sleep(Randomx.GetId(10000, 12500));
// 输入支付密码
Thread.Sleep(Randomx.GetId(500, 1000));
ts2 = await EvaluateJsBuyTagNameAndInnerHtml("div", "输入支付密码");
for (int i = 0; i < 50; i++)
{
if (ts2.Result?.Value is string rstStr && rstStr == "success")
break;
Thread.Sleep(100);
ts2 = await EvaluateJsBuyTagNameAndInnerHtml("div", "输入支付密码");
}
Thread.Sleep(Randomx.GetId(500, 1000));
foreach (var c in DataOpenSSL.DecryptString(GlobalConfig.AlipayPassword))
{
CEFBrowser.SimulateInputChar(host, c);
}
// 点下一步付款
Thread.Sleep(Randomx.GetId(500, 1000));
ts2 = await EvaluateJsBuyTagNameAndInnerHtml("button", "下一步", true);
for (int i = 0; i < 50; i++)
{
if (ts2.Result?.Value is string rstStr && rstStr == "success")
break;
Thread.Sleep(200);
//ts2 = await EvaluateJsBuyTagNameAndInnerHtml("span", "下一步", true);
ts2 = await EvaluateJsBuyTagNameAndInnerHtml("button", "下一步", true);
}
// 最后未执行成功也关闭窗口。
Thread.Sleep(Randomx.GetId(1112500, 1115000));
}
public async Task CheckSourceCode()
{
var host = cefWebBrowser.GetBrowser().GetHost();
var client = cefWebBrowser.GetDevToolsClient();
for (int i = 0; i < 20; i++)
{
Thread.Sleep(50);
if (host == null || client == null)
{
host = cefWebBrowser.GetBrowser().GetHost();
client = cefWebBrowser.GetDevToolsClient();
continue;
}
}
if (host == null || client == null)
{
throw new Exception("页面加载异常");
}
var sourceCode = txtSourceCode.Text.Trim();
var jsStr1 = @"(function() { var elements = document.getElementsByTagName('div');
for (i = elements.length - 1; i >= 0; i--){
var element = elements[i];
if (element.innerHTML.indexOf('" + sourceCode + @"') >= 0) {
return 'success';
}
}
return '';
})();";
var ts1 = await client.Runtime.EvaluateAsync(jsStr1, null, true, null, null, true, null, true);
var ts1 = await EvaluateJsBuyTagNameAndInnerHtml("div", sourceCode);
if (ts1.Result?.Value.ParseToString() != "success")
{
throw new Exception("溯源码不匹配");
}
}
/// <summary>
/// 获取溯源码
/// </summary>
/// <returns></returns>
public string GetSourceCode(TransitWarehouseParam transit)
IBrowserHost host = null;
DevToolsClient client = null;
public async Task<EvaluateResponse> EvaluateJsBuyTagNameAndInnerHtml(string tagName, string innerHTML, bool isClick = false)
{
if (!this.Created)
throw new Exception("窗口已关闭");
for (int i = 0; i < 25; i++)
{
Thread.Sleep(200);
if (host == null || client == null)
{
host = cefWebBrowser.GetBrowser().GetHost();
client = cefWebBrowser.GetDevToolsClient();
}
else
break;
}
if (host == null || client == null)
{
throw new Exception("页面加载异常");
}
var jsStr1 = @"(function() { var elements = document.getElementsByTagName('" + tagName + @"');
for (i = elements.length - 1; i >= 0; i--){
var element = elements[i];
if (element.innerHTML.indexOf('" + innerHTML + @"') >= 0) {";
if (isClick)
jsStr1 += @"element.click();";
jsStr1 += @"
return 'success';
}
}
return '';
})();";
var rst = await client.Runtime.EvaluateAsync(jsStr1, null, true, null, null, true, null, true);
if (tagName == "button")
{
}
return rst;
}
/// <summary>
/// 获取溯源码
/// </summary>
/// <returns></returns>
public string GetSourceCode(TransitWarehouseParam transit)
{
JObject body = new JObject();
body["province"] = transit.province_name;
@@ -1439,9 +1446,10 @@ namespace TemuKJD.ToolForms
filterOrderAction(order, true);
}
}
#endregion
#endregion
BaseMsgForm.ShowInfo("拍单信息保存成功");
if (!IsAutoBuy)
BaseMsgForm.ShowInfo("拍单信息保存成功");
}
if (BuyType == "direct")