Files
KJD/TEMUKJD/WXForms/ShopForms/WXShopMultiLoginForm.cs
T
2026-11-09 16:54:40 +08:00

510 lines
20 KiB
C#

using AllBase;
using AllBase.Helper;
using AllBase.Model.Result;
using CefSharp;
using CefSharp.WinForms;
//using TemuKJD.DashBoardForms;
using TemuKJD.Helper;
using TemuKJD.BaseForms;
using Microsoft.Win32;
using NaiBa.CefHelper;
using NaiBa.CefHelper.Handler;
using NaiBa.Util.Extension;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
//using System.Web.Hosting;
using System.Windows.Forms;
using Work;
using Work.BLL.Tools;
using TemuKJD.BLL;
using AllBase.Model.Result.PDDResult;
using NaiBa.Util;
namespace TemuKJD.WXForms.ShopForms
{
public partial class WXShopMultiLoginForm : BaseGeneralForm
{
public static WXShopMultiLoginForm shopMultiLoginFormInstance { get; set; } = null;
public bool isAutoLogin = false;
public int CloseAfterSecond { get; set; }
public EnumOpenType openType = EnumOpenType.manage;
public bool isMultiLogin = false;
public string MultiLoginCookieName = "";
public string InitUrl = "";
public ChromiumWebBrowser cefWebBrowser = null;
public ShopLoginInfo mainShop = null;
public ConcurrentList<ShopLoginInfo> lstSwitchShop = new ConcurrentList<ShopLoginInfo>();
public ConcurrentList<ShopSwitchInfo> lstSwitchInfo = new ConcurrentList<ShopSwitchInfo>();
public ConcurrentList<ShopLoginInfo> lstNeedUpdateShop = new ConcurrentList<ShopLoginInfo>();
const string DefaultUrl = "https://store.weixin.qq.com/shop/home";
const string shopLoginUrl = "https://store.weixin.qq.com/shop?redirect_url=%2Fhome";
private string currentUrl = "";
private string shopCookieHead = "store.weixin.qq.com";
private ConcurrentList<ShopCompany> lstShopCompany = new ConcurrentList<ShopCompany>();
public WXShopMultiLoginForm(ShopLoginInfo shopInfo)
{
InitializeComponent();
shopMultiLoginFormInstance = this;
this.mainShop = shopInfo;
Task.Run(() =>
{
var shopSwitchRst = WXShopSwitch.getShopSwitchList(mainShop);
if (!shopSwitchRst.Contains("\"code\":0"))
{
BaseMsgForm.ShowError("获取切换列表失败!");
return;
}
try
{
string shopSwitchStr = JsonHelper.SerializeObject(JsonHelper.JObjectParse(shopSwitchRst)["list"]);
lstSwitchInfo.Clear();
lstSwitchShop.Clear();
lstSwitchInfo.AddRange(JsonHelper.DeserializeJsonToList<ShopSwitchInfo>(shopSwitchStr));
lstSwitchShop.AddRange(GlobalConfig.ShopLoginList.Where(s => lstSwitchInfo.Any(sw => sw.appid == s.ShopId)));
foreach(var shop in lstSwitchShop)
{
bool canUse = shop.LoginStatus == "登录成功";
Invoke(new Action(() =>
{
this.dgvShop.Rows.Add
(
true,
shop.LoginName,
shop.ShopId,
shop.ShopAccount,
shop.Notes,
canUse ? "在线" : "掉线",
canUse,
"-"
);
}));
displayAuthStatus(shop);
}
}
catch (Exception ex)
{
BaseMsgForm.ShowError("切换列表解析失败!");
}
if (isAutoLogin)
{
Thread.Sleep(Randomx.GetId(2500, 3500));
while(this.cefWebBrowser == null || this.cefWebBrowser.IsLoading)
{
if (!this.Created)
return;
Thread.Sleep(100);
continue;
}
if (!this.Created)
return;
Invoke(() =>
{
btnRefreshNum_Click(null, null);
});
}
});
}
private void ShopLoginForm_Load(object sender, EventArgs e)
{
this.Size = new Size(1680, 900);
this.CenterToScreen();
this.splitContainer3.SplitterDistance = this.splitContainer3.Height - 62;
if (string.IsNullOrWhiteSpace(InitUrl))
InitUrl = DefaultUrl;
if (CloseAfterSecond > 0)
{
Task.Run(() =>
{
Thread.Sleep(1000 * CloseAfterSecond);
if (this.Created)
{
Invoke(new Action(() => { this.Close(); }));
}
});
}
initSwitchShop();
initCefAndMainShop();
}
public void initSwitchShop()
{
}
/// <summary>
/// 初始化CEF并登录主店铺
/// </summary>
private void initCefAndMainShop()
{
if (openType != EnumOpenType.login && mainShop == null)
return;
if (cefWebBrowser == null)
{
cefWebBrowser = CEFBrowser.CreateChromiumWebBrowser(InitUrl, false);
CustomResourceRequestHandlerLocal resourceRequestHandler = new CustomResourceRequestHandlerLocal();
resourceRequestHandler.ResourceLoadCompleteEvent += RequestHandler_ResourceLoadComplete;
resourceRequestHandler.BeforeResourceLoadEvent += RequestHandler_BeforeResourceLoad;
cefWebBrowser.RequestHandler = new CustomRequestHandler(resourceRequestHandler);
var lifeSapnHandler = new LifeSpanHandlerLocal(PopWindowType.SelfWindow);
cefWebBrowser.LifeSpanHandler = lifeSapnHandler;
cefWebBrowser.KeyboardHandler = new KeyboardHandler();
cefWebBrowser.FrameLoadEnd += CefWebBrowser_FrameLoadEnd;
cefWebBrowser.AddressChanged += CefWebBrowser_AddressChanged;
cefWebBrowser.LoadError += CefWebBrowser_LoadError;
cefWebBrowser.Dock = DockStyle.Fill;
//js绑定C#对象
WXShopBrowserObject shopObj = new WXShopBrowserObject();
shopObj.OnInfoReceived += ShopObj_OnInfoReceived;
CefSharpSettings.WcfEnabled = true;
cefWebBrowser.JavascriptObjectRepository.Register(
name: "shopObj",
objectToBind: shopObj,
isAsync: false,
options: new BindingOptions { Binder = BindingOptions.DefaultBinder.Binder /*CamelCaseJavascriptNames = false*/ /*cef79*/ }
);
List<Cookie> cookieLst = new List<Cookie>();
try
{
if (mainShop != null)
{
cookieLst = JsonHelper.DeserializeJsonToList<CefSharp.Cookie>(mainShop.Cookies.ParseToString());
if (cookieLst == null)
cookieLst = new List<Cookie>();
}
}
catch
{
}
Task.Run(() =>
{
Invoke(new Action(() =>
{
splitContainer1.Panel1.Controls.Add(cefWebBrowser);
}));
// cef138必须init后方可设置或删除cookie
while (!cefWebBrowser.IsBrowserInitialized || !cefWebBrowser.GetBrowser().MainFrame.IsValid)
Thread.Sleep(20);
CEFBrowser.DeleteCookie(cefWebBrowser.GetCookieManager(null));
//cef 138 如果没有设置RequestContext 可能为空,直接getCookieManager
//异步设置cookie
//var t = CEFBrowser.SetCookieAsync(JsonHelper.SerializeObject(cookieLst), cefWebBrowser.GetCookieManager(null));
string address = InitUrl;
foreach (var cook in cookieLst)
{
// 同步设置cookie
cefWebBrowser.GetCookieManager(null).SetCookie(address, cook);
//var t = CEFBrowser.SetCookieAsync(cook.Domain, cook.Name + "=" + cook.Value + ";", cefWebBrowser.GetCookieManager(null));
//t.Wait(5000);
}
cefWebBrowser.Load(InitUrl);
});
}
}
private void ShopObj_OnInfoReceived(string information)
{
//BaseMsgForm.ShowInfo(information);
if (!string.IsNullOrEmpty(information))
cefWebBrowser.GetBrowser().MainFrame.EvaluateScriptAsync("alert('" + information + "');");
}
private void CefWebBrowser_LoadError(object sender, CefSharp.LoadErrorEventArgs e)
{
}
private void CefWebBrowser_AddressChanged(object sender, CefSharp.AddressChangedEventArgs e)
{
if (this.Created && !this.Disposing && !this.IsDisposed)
{
Invoke(new Action(() =>
{
currentUrl = e.Address;
txtAddress.Text = e.Address;
}));
}
}
private void CefWebBrowser_FrameLoadEnd(object sender, CefSharp.FrameLoadEndEventArgs e)
{
//js绑定C#对象 html页面内声明绑定的C#对象
StringBuilder sb = new StringBuilder();
sb.Append("(function(){");
sb.Append("CefSharp.BindObjectAsync('shopObj');");
sb.Append("})();");
cefWebBrowser.GetBrowser().MainFrame.EvaluateScriptAsync(sb.ToString());
}
//public Func<object, string, string, request, bool> BeforeResourceLoadEvent; // sender, requestUrl, postData, request, true(表示取消执行)
private bool RequestHandler_BeforeResourceLoad(object sender, string url, string postData, IRequest request)
{
return false;
}
private void RequestHandler_ResourceLoadComplete(object sender, string url, string postData, string responseData, IRequest request)
{
if (url == "https://store.weixin.qq.com/shop/home" && this.openType == EnumOpenType.login)
{
Task.Run(() =>
{
var data = responseData;
var index = data.IndexOf("window.__INITIAL_PINIA_DATA__=") + "window.__INITIAL_PINIA_DATA__=".Length;
var indexEnd = data.IndexOf(";window.__USE_VITE__=");
if (index < 1000)
{
return;
}
var dataStr = data.Substring(index, indexEnd - index);
dataStr = GetHtml.Unicode2String(dataStr);
var shopId = BaseRegex.GetStringJson(ref data, "appid");
var nickName = BaseRegex.GetStringJson(ref data, "nickName");
var openId = BaseRegex.GetStringJson(ref data, "openid"); // oGu7k7HxmUyOmc1X6VM7GQwS-9cI
if (mainShop != null && mainShop.ShopId != shopId)
{
BaseMsgForm.ShowError("cookie与店铺不匹配,请核对店铺!");
return;
}
if (mainShop == null && GlobalConfig.ShopLoginList.Any(s=>s.ShopId == shopId))
{
BaseMsgForm.ShowError("录入的新店铺已存在,请核对店铺!");
return;
}
ShopCompany sc = new ShopCompany()
{
UserName = BaseClass.UserName, // 登录的用户信息
AccountId = shopId,
AccountName = nickName,
LoginName = shopId,
openid = openId,
LoginStatus = "登录成功",
};
this.lstShopCompany.RemoveAll(s => s.AccountId == sc.AccountId);
this.lstShopCompany.Add(sc);
});
}
}
private void ShopLoginForm_FormClosed(object sender, FormClosedEventArgs e)
{
////OnSaveComplete(shop);
//Task.Run(() =>
//{
// Thread.Sleep(500);
// MainForm.instance.Invoke(new Action(() =>
// {
// if (!this.Disposing && !this.IsDisposed)
// {
// this.Dispose();
// }
// }));
//});
}
private void txtAddress_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (cefWebBrowser != null)
{
cefWebBrowser.Load(txtAddress.Text);
}
}
}
private void btnPrev_Click(object sender, EventArgs e)
{
cefWebBrowser.Back();
}
private void btnNext_Click(object sender, EventArgs e)
{
cefWebBrowser.Forward();
}
private void btnRefreshNum_Click(object sender, EventArgs e)
{
pbLoading.Visible = true;
btnRefreshNum.Enabled = false;
lstNeedUpdateShop = new ConcurrentList<ShopLoginInfo>();
Task.Run(() =>
{
foreach (var shop in lstSwitchShop)
{
var switchInfo = lstSwitchInfo.FirstOrDefault(s => s.appid == shop.ShopId);
var row = dgvShop.Rows.Cast<DataGridViewRow>().FirstOrDefault(r => r.Cells["colShopId"].Value.ParseToString() == shop.ShopId);
Invoke(new Action(() =>
{
row.Cells["colMessage"].Value = "-";
}));
WXShopListForm.Instance.CheckShopLogin(new ShopLoginInfo[] { shop }, false);
if (shop.LoginStatus == "登录成功")
{
Thread.Sleep(100);
Invoke(new Action(() =>
{
row.Cells["colMessage"].Value = "登录成功";
}));
continue;
}
lstNeedUpdateShop.Add(shop);
string jsStr1 = @"document.getElementsByClassName('shop-info-popover')[0].style ='';
var divLst = document.getElementsByClassName('shop-info-popover')[0].getElementsByTagName('div');
(function() { for (i=0; i<divLst.length; i++){
if(divLst[i].innerHTML.indexOf('切换店铺') >= 0){
divLst[i].click();
//return 'success';
}
} })();";
var t1 = cefWebBrowser.GetMainFrame().EvaluateScriptAsync(jsStr1);
t1.Wait(5000);
Thread.Sleep(Randomx.GetId(500, 1000));
jsStr1 = @"(function() { for (i=0; i<divLst.length; i++){
//if(divLst[i].innerHTML.indexOf('" + switchInfo.nickname + @"') >= 0){
if(divLst[i].innerHTML == '" + switchInfo.nickname + @"'){
divLst[i].click();
return 'success';
}
} })();";
t1 = cefWebBrowser.GetMainFrame().EvaluateScriptAsync(jsStr1);
t1.Wait(5000);
Thread.Sleep(Randomx.GetId(3000, 3500));
List<Cookie> cookieList = CEFBrowser.GetCookieList(shopCookieHead, cefWebBrowser.GetCookieManager(null));
var cookies = cookieList.Where(c => c.Domain == this.shopCookieHead).ToList();
if (!cookies.Any(c => c.Name == "biz_ticket"))
{
cookies.Add(new CefSharp.Cookie()
{
Name = "biz_ticket",
Value = "",
Domain = "store.weixin.qq.com",
Expires = null,
HttpOnly = true,
Path = "/",
Priority = CefSharp.Enums.CookiePriority.Medium,
SameSite = CefSharp.Enums.CookieSameSite.Unspecified,
Secure = true,
});
}
WXShopUpdateCookieForm.CheckCookieUpdate(shop, cookies);
Invoke(new Action(() =>
{
bool canUse = shop.LoginStatus == "登录成功";
row.Cells["colMessage"].Value = canUse ? "登录成功" : "登录失败,请稍后重试";
row.Cells["colLoginStatus"].Value = canUse ? "在线" : "掉线";
row.Cells["colCanUse"].Value = canUse;
displayAuthStatus(shop);
}));
Thread.Sleep(Randomx.GetId(2500, 5000));
}
if (!this.Created)
return;
Invoke(new Action(() =>
{
btnRefreshNum.Enabled = true;
pbLoading.Visible = false;
if (this.isAutoLogin)
this.Close();
else
BaseMsgForm.ShowInfo("操作完成!");
}));
});
}
void displayAuthStatus(ShopLoginInfo shop)
{
var rows = this.dgvShop.Rows.Cast<DataGridViewRow>().Where(r => r.Cells["colShopId"].Value.ParseToString() == shop?.ShopId);
foreach (var row in rows)
{
bool canUse = row.Cells["colLoginStatus"].Value.ParseToString() == "在线";
(row.Cells["colLoginStatus"] as DataGridViewLinkCell).Style.ForeColor = canUse ? Color.Blue : Color.Red;
(row.Cells["colLoginStatus"] as DataGridViewLinkCell).LinkColor = canUse ? Color.Blue : Color.Red;
(row.Cells["colLoginStatus"] as DataGridViewLinkCell).ActiveLinkColor = canUse ? Color.LightBlue : Color.OrangeRed;
(row.Cells["colLoginStatus"] as DataGridViewLinkCell).VisitedLinkColor = canUse ? Color.DarkBlue : Color.DarkRed;
}
}
}
public class WXShopSwitch
{
public static string getShopSwitchList(ShopLoginInfo shop)
{
string url = "https://store.weixin.qq.com/shop-faas/mmecnodelogin/session/getShopSwitchList?token=&lang=zh_CN";
string refere = "https://store.weixin.qq.com/shop/home";
var result = WXHttpResponseBLL.WeiXinGetResponse(shop, url, refere);
return result;
}
public static async Task<string> getShopSwitchListAsync(ShopLoginInfo shop)
{
string url = "https://store.weixin.qq.com/shop-faas/mmecnodelogin/session/getShopSwitchList?token=&lang=zh_CN";
string refere = "https://store.weixin.qq.com/shop/home";
var result = await WXHttpResponseBLL.WeiXinGetResponseAsync(shop, url, refere);
return result;
}
}
public class ShopSwitchInfo
{
public string appid { get; set; } // "wxa20bb379d0961414",
public string nickname { get; set; } // "夜笙服装店",
public string headimgurl { get; set; } // "http://mmbiz.qpic.cn/mmbiz_jpg/ZZIOBibOYfic6CDwhCA8lSSOAZSuEF8HdlBiaJC8RXsTRucB6Xopic49PKgViapwRZDTuGuVxDEtKvhkXNZG63uqUwA/0?wx_fmt=jpeg",
public object appuin { get; set; } // null,
public List<ShopSwitchJobInfo> jobInfoList { get; set; }
public long? lastLoginTime { get; set; } // 1773216675,
public int? ecAcctType { get; set; } // 101,
public int? ecAcctStatus { get; set; } // 100,
public int? ecSubType { get; set; } // 0,
public int? shopType { get; set; } // 6,
public string kfMsgNum { get; set; } // "0",
public string shopMsgNum { get; set; } // "2002"
}
public class ShopSwitchJobInfo
{
public string jobName { get; set; } // "经理人" "资金充值"
public long? jobId { get; set; } // 3 99998
}
}