547 lines
23 KiB
C#
547 lines
23 KiB
C#
using Api.Framework;
|
||
using Api.Framework.Enums;
|
||
using Api.Framework.Events;
|
||
using Api.Framework.Model;
|
||
using Api.Framework.Tools;
|
||
using CsharpHttpHelper;
|
||
using CsharpHttpHelper.Enum;
|
||
using Microsoft.Win32;
|
||
using Newtonsoft.Json;
|
||
using Newtonsoft.Json.Linq;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Net;
|
||
using System.Net.Sockets;
|
||
using System.Runtime.InteropServices;
|
||
using System.Text;
|
||
using System.Text.RegularExpressions;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using static FLSystem.Forms.point_manage_control;
|
||
|
||
namespace FLSystem
|
||
{
|
||
#region 同步Win系统时间
|
||
public class Daytime
|
||
{
|
||
// Internet Time Server class by Alastair Dallas 01/27/04
|
||
|
||
// Number of seconds
|
||
private const int THRESHOLD_SECONDS = 15;
|
||
// that Windows clock can deviate from NIST and still be okay
|
||
|
||
//Server IP addresses from
|
||
//http://www.boulder.nist.gov/timefreq/service/time-servers.html
|
||
private static string[] Servers = {
|
||
//"129.6.15.28",
|
||
//"129.6.15.29",
|
||
//"132.163.4.101",
|
||
//"132.163.4.102",
|
||
//"132.163.4.103",
|
||
//"128.138.140.44",
|
||
//"192.43.244.18",
|
||
//"131.107.1.10",
|
||
//"66.243.43.21",
|
||
//"216.200.93.8",
|
||
//"208.184.49.9",
|
||
//"207.126.98.204",
|
||
//"205.188.185.33"
|
||
"time.windows.com"//微软时间同步服务器
|
||
};
|
||
public static string LastHost = "";
|
||
|
||
public static DateTime LastSysTime;
|
||
public static DateTime GetTime()
|
||
{
|
||
//Returns UTC/GMT using an NIST server if possible,
|
||
// degrading to simply returning the system clock
|
||
|
||
//If we are successful in getting NIST time, then
|
||
// LastHost indicates which server was used and
|
||
// LastSysTime contains the system time of the call
|
||
// If LastSysTime is not within 15 seconds of NIST time,
|
||
// the system clock may need to be reset
|
||
// If LastHost is "", time is equal to system clock
|
||
|
||
string host = null;
|
||
DateTime result = default(DateTime);
|
||
|
||
LastHost = "";
|
||
foreach (string host_loopVariable in Servers)
|
||
{
|
||
host = host_loopVariable;
|
||
result = GetNISTTime(host);
|
||
if (result > DateTime.MinValue)
|
||
{
|
||
LastHost = host;
|
||
break; // TODO: might not be correct. Was : Exit For
|
||
}
|
||
}
|
||
|
||
if (string.IsNullOrEmpty(LastHost))
|
||
{
|
||
//No server in list was successful so use system time
|
||
result = DateTime.Now;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
public static int SecondsDifference(DateTime dt1, DateTime dt2)
|
||
{
|
||
TimeSpan span = dt1.Subtract(dt2);
|
||
return span.Seconds + (span.Minutes * 60) + (span.Hours * 360);
|
||
}
|
||
|
||
public static bool WindowsClockIncorrect()
|
||
{
|
||
DateTime nist = GetTime();
|
||
if ((Math.Abs(SecondsDifference(nist, LastSysTime)) > THRESHOLD_SECONDS))
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private static DateTime GetNISTTime(string host)
|
||
{
|
||
//Returns DateTime.MinValue if host unreachable or does not produce time
|
||
DateTime result = default(DateTime);
|
||
string timeStr = null;
|
||
|
||
try
|
||
{
|
||
StreamReader reader = new StreamReader(new TcpClient(host, 13).GetStream());
|
||
LastSysTime = DateTime.UtcNow;
|
||
timeStr = reader.ReadToEnd();
|
||
reader.Close();
|
||
}
|
||
catch (SocketException ex)
|
||
{
|
||
//Couldn't connect to server, transmission error
|
||
Debug.WriteLine("Socket Exception [" + host + "]");
|
||
return DateTime.MinValue;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
//Some other error, such as Stream under/overflow
|
||
return DateTime.MinValue;
|
||
}
|
||
|
||
//Parse timeStr
|
||
if ((timeStr.Substring(38, 9) != "UTC(NIST)"))
|
||
{
|
||
//This signature should be there
|
||
return DateTime.MinValue;
|
||
}
|
||
if ((timeStr.Substring(30, 1) != "0"))
|
||
{
|
||
//Server reports non-optimum status, time off by as much as 5 seconds
|
||
return DateTime.MinValue;
|
||
//Try a different server
|
||
}
|
||
|
||
int jd = int.Parse(timeStr.Substring(1, 5));
|
||
int yr = int.Parse(timeStr.Substring(7, 2));
|
||
int mo = int.Parse(timeStr.Substring(10, 2));
|
||
int dy = int.Parse(timeStr.Substring(13, 2));
|
||
int hr = int.Parse(timeStr.Substring(16, 2));
|
||
int mm = int.Parse(timeStr.Substring(19, 2));
|
||
int sc = int.Parse(timeStr.Substring(22, 2));
|
||
|
||
if ((jd < 15020))
|
||
{
|
||
//Date is before 1900
|
||
return DateTime.MinValue;
|
||
}
|
||
if ((jd > 51544))
|
||
yr += 2000;
|
||
else
|
||
yr += 1900;
|
||
|
||
return new DateTime(yr, mo, dy, hr, mm, sc);
|
||
}
|
||
|
||
[StructLayout(LayoutKind.Sequential)]
|
||
public struct SYSTEMTIME
|
||
{
|
||
public Int16 wYear;
|
||
public Int16 wMonth;
|
||
public Int16 wDayOfWeek;
|
||
public Int16 wDay;
|
||
public Int16 wHour;
|
||
public Int16 wMinute;
|
||
public Int16 wSecond;
|
||
public Int16 wMilliseconds;
|
||
}
|
||
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
|
||
private static extern Int32 GetSystemTime(ref SYSTEMTIME stru);
|
||
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
|
||
private static extern Int32 SetSystemTime(ref SYSTEMTIME stru);
|
||
|
||
[DllImport("Kernel32.dll")]
|
||
public static extern void GetLocalTime(ref SYSTEMTIME lpSystemTime);
|
||
|
||
[DllImport("Kernel32.dll")]
|
||
public static extern bool SetLocalTime(ref SYSTEMTIME lpSystemTime);
|
||
|
||
|
||
public static void SetWindowsClock(DateTime dt)
|
||
{
|
||
//Sets system time. Note: Use UTC time; Windows will apply time zone
|
||
|
||
SYSTEMTIME timeStru = default(SYSTEMTIME);
|
||
Int32 result = default(Int32);
|
||
|
||
timeStru.wYear = (Int16)dt.Year;
|
||
timeStru.wMonth = (Int16)dt.Month;
|
||
timeStru.wDay = (Int16)dt.Day;
|
||
timeStru.wDayOfWeek = (Int16)dt.DayOfWeek;
|
||
timeStru.wHour = (Int16)dt.Hour;
|
||
timeStru.wMinute = (Int16)dt.Minute;
|
||
timeStru.wSecond = (Int16)dt.Second;
|
||
timeStru.wMilliseconds = (Int16)dt.Millisecond;
|
||
SetLocalTime(ref timeStru);
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
public class Tools
|
||
{
|
||
//private static Dictionary<string, object> Config { get; set; }
|
||
|
||
static Tools()
|
||
{
|
||
EventClient.MethodEvent += EventClient_MethodEvent;
|
||
}
|
||
|
||
private static void EventClient_MethodEvent(object sender, MethodType e)
|
||
{
|
||
if (e == MethodType.刷新配置文件)
|
||
{
|
||
ApiClient.GetPointManageConfig(true);
|
||
//Config = Util.ReadConfig("插件-积分管理-配置", true);//刷新积分管理中的配置文件
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取积分插件配置文件
|
||
/// </summary>
|
||
/// <param name="flush"></param>
|
||
/// <returns></returns>
|
||
//public static Dictionary<string, object> GetPointConfig(bool flush = false)
|
||
//{
|
||
// if (Config == null || flush)
|
||
// Config = Util.ReadConfig("插件-积分管理-配置", true);//刷新积分管理中的配置文件
|
||
// return Config;
|
||
//}
|
||
|
||
|
||
/// <summary>
|
||
/// 判断.Net Framework的Release是否符合需要
|
||
/// (.Net Framework 版本在4.0及以上)
|
||
/// </summary>
|
||
///<param name="release">需要的版本 version = 4.5 release = 379893
|
||
/// <returns></returns>
|
||
public static bool GetDotNetRelease(int release)
|
||
{
|
||
const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
|
||
using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey))
|
||
{
|
||
if (ndpKey != null && ndpKey.GetValue("Release") != null)
|
||
{
|
||
return (int)ndpKey.GetValue("Release") >= release ? true : false;
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public static void GetFileFromNetUrl(string url, string file)
|
||
{
|
||
try
|
||
{
|
||
System.Net.WebRequest req = System.Net.WebRequest.Create(url);
|
||
req.Method = "GET";
|
||
//获得用户名密码的Base64编码 添加Authorization到HTTP头 不需要的账号密码的可以注释下面两行代码
|
||
string code = Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", "userName", "passWord")));
|
||
req.Headers.Add("Authorization", "Basic " + code);
|
||
byte[] fileBytes;
|
||
using (WebResponse webRes = req.GetResponse())
|
||
{
|
||
int length = (int)webRes.ContentLength;
|
||
HttpWebResponse response = webRes as HttpWebResponse;
|
||
Stream stream = response.GetResponseStream();
|
||
|
||
//读取到内存
|
||
MemoryStream stmMemory = new MemoryStream();
|
||
byte[] buffer = new byte[length];
|
||
int i;
|
||
//将字节逐个放入到Byte中
|
||
while ((i = stream.Read(buffer, 0, buffer.Length)) > 0)
|
||
{
|
||
stmMemory.Write(buffer, 0, i);
|
||
}
|
||
fileBytes = stmMemory.ToArray();//文件流Byte,需要文件流可直接return,不需要下面的保存代码
|
||
stmMemory.Close();
|
||
|
||
MemoryStream m = new MemoryStream(fileBytes);
|
||
//string file = Util.MapFile("NDP46-KB3045560-Web.exe", @"Cache\_NetFramework");//可根据文件类型自定义后缀
|
||
FileStream fs = new FileStream(file, FileMode.OpenOrCreate);
|
||
m.WriteTo(fs);
|
||
m.Close();
|
||
fs.Close();
|
||
}
|
||
}
|
||
catch (System.Exception ex)
|
||
{
|
||
throw ex;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
public class Utils
|
||
{
|
||
//private static Timer timer = new Timer(new TimerCallback(ShpaySync), null, 0, 1000 * 60 * 10);
|
||
|
||
//private static bool IsRunSendShPay = false;
|
||
//private static void ShpaySync(object state)
|
||
//{
|
||
// if (IsRunSendShPay) return;
|
||
// IsRunSendShPay = true;
|
||
// try
|
||
// {
|
||
// //EventClient.OnEvent("", "执行状态:" + ApiClient.Setting.SystemConfig.send_shpay_switch);
|
||
// if (!ApiClient.Setting.SystemConfig.send_shpay_switch) return;
|
||
// var db = ApiClient.GetSession();
|
||
// var time = HttpExtend.GetTimeStamp(DateTime.Now.AddDays(-1));
|
||
// var shpayList = db.Queryable<fl_shpay_hist>().Where(f => f.paytype == PayGetType.未领取 && f.sendtime == 0 && f.ctime <= time).ToList();
|
||
// //EventClient.OnEvent("", "执行的数量:" + shpayList.Count);
|
||
// SendShPayMes(shpayList);
|
||
// }
|
||
// catch (Exception ex)
|
||
// {
|
||
// EventClient.OnEvent("", $"通知24小时商户未领取异常:{ex.Message} - {ex.StackTrace}");
|
||
// }
|
||
// finally
|
||
// {
|
||
// IsRunSendShPay = false;
|
||
// }
|
||
//}
|
||
|
||
#region 兑换发送消息
|
||
public static void SendShPayMes(List<fl_shpay_hist> shpayList)
|
||
{
|
||
try
|
||
{
|
||
if (shpayList == null || shpayList.Count == 0) return;
|
||
var session = ApiClient.GetSession();
|
||
|
||
var yjPayList = new List<fl_shpay_hist>();//已经领取的连接
|
||
var sendShpayDic = new Dictionary<string, List<fl_shpay_hist>>();//需要发送的商户
|
||
|
||
var ShPayTmpDic = new Dictionary<string, List<ShPayTmp>>();//需要发送并且能发送商户小程序
|
||
|
||
#region 重新获取商户地址并发送消息
|
||
var timedate = shpayList.GroupBy(f => f.ctimedate).Select(f => f.Key).ToList();
|
||
//EventClient.OnEvent("", "A " + timedate.Count);
|
||
foreach (var date in timedate)
|
||
{
|
||
var strb = new StringBuilder();
|
||
var html = string.Empty;
|
||
try
|
||
{
|
||
strb.Append("手动处理未领取的商户:");
|
||
var arr = shpayList.Where(f => f.ctimedate == date).Select(f => "\"" + f.orderid + "\"").ToList();
|
||
if (arr.Count() != 0)
|
||
{
|
||
string parm = "orders=[" + string.Join(",", arr) + $"]&time={date}";
|
||
strb.Append($"手动处理未领取的商户:{parm}");
|
||
HttpHelper http = new HttpHelper();
|
||
HttpItem item = new HttpItem()
|
||
{
|
||
URL = "https://pay.api.52cmg.cn/pay/getNewLinks",
|
||
Method = "POST",
|
||
Timeout = 100000,
|
||
ReadWriteTimeout = 30000,
|
||
IsToLower = false,
|
||
Cookie = "",
|
||
UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",
|
||
Accept = "text/html, application/xhtml+xml, */*",
|
||
ContentType = "application/json",
|
||
Referer = "",
|
||
Allowautoredirect = false,
|
||
AutoRedirectCookie = false,
|
||
Postdata = parm,
|
||
ResultType = ResultType.String,
|
||
};
|
||
html = http.GetHtml(item).Html;
|
||
strb.AppendLine($"最新的数据:{html}");
|
||
//{"ok":true,"res":"7d043f8e8e4be0784a596a25cbc078fb|{\"code\":1,\"msg\":\"https://txbgl.kuaizhan.com/?orderid=7d043f8e8e4be0784a596a25cbc078fb\u0026appid=wxb8485eacd6e3b832\",\"appinfo\":null}\r\n144a00f52c271c39513937c252a54ef6|已支付"}
|
||
|
||
//{"ok":true,"res":"1ec1dada9db612ab972bca104c273909|{\"code\":1,\"msg\":\"https://txbgl.kuaizhan.com/?orderid=1ec1dada9db612ab972bca104c273909\u0026appid=wx6e0df44505ec10f5\",\"appinfo\":{\"ShopId\":15000000,\"appId\":\"wxe5d3b3d276b346c3\",\"appSecret\":\"441c959d0491be8a136db63d5cca6497\",\"appName\":\"gh_ec03868ecfeb\",\"target\":\"\\\"pages/index/index.html?orderId=[订单编号]\\\"\"}}"}
|
||
|
||
var shResult = JsonConvert.DeserializeObject<shpayResult>(html);
|
||
if (shResult != null && shResult.ok)
|
||
{
|
||
var regs = Regex.Split(shResult.res, @"[\r\n]").Where(f => !string.IsNullOrWhiteSpace(f)).ToList();
|
||
if (regs.Count == 0) continue;
|
||
|
||
foreach (var tmp in regs)
|
||
{
|
||
var split = tmp.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
|
||
var shpay = shpayList.FirstOrDefault(f => split[0] == f.orderid);
|
||
if (shpay != null)
|
||
{
|
||
shpay.paytype = split[1] == "已支付" ? PayGetType.已领取 : PayGetType.未领取;
|
||
if (shpay.paytype == PayGetType.已领取)
|
||
yjPayList.Add(shpay);
|
||
else
|
||
{
|
||
if (!sendShpayDic.ContainsKey(shpay.robotname))
|
||
sendShpayDic.Add(shpay.robotname, new List<fl_shpay_hist>());
|
||
|
||
var jObj = JObject.Parse(split[1]);
|
||
if (jObj["msg"] != null)
|
||
shpay.payurl = jObj["msg"].ToString();
|
||
|
||
sendShpayDic[shpay.robotname].Add(shpay);
|
||
|
||
if (!ShPayTmpDic.ContainsKey(shpay.robotname))
|
||
ShPayTmpDic.Add(shpay.robotname, new List<ShPayTmp>());
|
||
|
||
if (jObj["appinfo"] != null && jObj["appinfo"].ToString().ToLower() != "null")
|
||
ShPayTmpDic[shpay.robotname].Add(new ShPayTmp()
|
||
{
|
||
id = shpay.id,
|
||
shpayInfo = jObj["appinfo"].ToObject<Dictionary<string, object>>()
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
EventClient.OnEvent("", $"商户状态查询异常:{ex.Message} - {ex.StackTrace} , {html}");
|
||
}
|
||
finally
|
||
{
|
||
//EventClient.OnEvent("",strb.ToString());
|
||
}
|
||
}
|
||
|
||
//EventClient.OnEvent("", "B " + sendShpayDic.Count);
|
||
|
||
#region 获取到商户数据以后发送消息
|
||
var sendShpayList = new List<fl_shpay_hist>();
|
||
if (sendShpayDic.Count != 0)
|
||
{
|
||
try
|
||
{
|
||
foreach (KeyValuePair<string, List<fl_shpay_hist>> item in sendShpayDic)
|
||
{
|
||
//EventClient.OnEvent("", $"C : {item.Key} - {item.Value.Count} - {(Chat.Framework.ChatClient.WXClient.FirstOrDefault(f => f.Key == item.Key).Value == null)}");
|
||
var wx = Chat.Framework.ChatClient.WXClient.FirstOrDefault(f => f.Key == item.Key && f.Value.Status == Chat.Framework.WXSdk.WxStatus.在线).Value;
|
||
if (wx == null) continue;
|
||
foreach (var tmp in item.Value)
|
||
{
|
||
var msg = string.Empty;
|
||
var flag = false;//是否为xml
|
||
if (ApiClient.Setting.SystemConfig.send_shpay_minixml && ShPayTmpDic.ContainsKey(item.Key))
|
||
{
|
||
var shpayTmpList = ShPayTmpDic[item.Key];
|
||
var payInfo = shpayTmpList.FirstOrDefault(f => f.id == tmp.id);
|
||
if (payInfo != null)
|
||
{
|
||
msg = Util.GetMiNiAppXml(payInfo.shpayInfo, tmp.chattype);
|
||
if (!string.IsNullOrWhiteSpace(msg))
|
||
{
|
||
wx.SendMessage(tmp.username, msg.Replace("[订单编号]", tmp.orderid));
|
||
flag = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!flag)
|
||
{
|
||
msg = ApiClient.Setting.SystemConfig.send_shpay_msg.Replace("[账号]", tmp.username).Replace("[昵称]", tmp.usernick).Replace("[领取地址]", tmp.payurl).Replace("[兑换金额]", tmp.point.ToString("0.00")).Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName);
|
||
wx.SendMessage(tmp.username, msg);
|
||
}
|
||
tmp.sendtime = HttpExtend.GetTimeStamp(DateTime.Now);
|
||
EventClient.OnEvent("提示用户商户未领取", $"{wx.User.Nick}[{wx.User.Username}]【{wx.User.Uin}】:发送:{tmp.usernick}({tmp.username}),领取地址:{tmp.payurl} ,未领金额:{tmp.point.ToString("0.00")},{(msg == null ? 0 : msg.Length)},xml ? {(flag ? "是" : "否")}");
|
||
sendShpayList.Add(tmp);
|
||
Thread.Sleep(1000);
|
||
}
|
||
}
|
||
if (shpayList.Count != 0)
|
||
session.Saveable(shpayList).ExecuteCommand();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
EventClient.OnEvent("", $"商户状态修改异常:{ex.Message} - {ex.StackTrace}");
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 修改数据库中的状态
|
||
var shpayList1 = new List<fl_shpay_hist>();
|
||
if (yjPayList.Count != 0)
|
||
{
|
||
try
|
||
{
|
||
foreach (var item in yjPayList)
|
||
{
|
||
item.paytime = HttpExtend.GetTimeStamp(DateTime.Now);
|
||
item.paytype = PayGetType.已领取;
|
||
shpayList1.Add(item);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
EventClient.OnEvent("", $"商户状态修改异常1:{ex.Message} - {ex.StackTrace}");
|
||
}
|
||
}
|
||
if (sendShpayList.Count != 0)
|
||
{
|
||
try
|
||
{
|
||
foreach (var item in sendShpayList)
|
||
{
|
||
shpayList1.Add(item);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
EventClient.OnEvent("", $"商户状态修改异常1:{ex.Message} - {ex.StackTrace}");
|
||
}
|
||
}
|
||
if (shpayList1.Count != 0)
|
||
session.Updateable(shpayList1).ExecuteCommand();
|
||
#endregion
|
||
|
||
#endregion
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
EventClient.OnEvent("", $"{ex.Message} - {ex.StackTrace}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 商户小程序信息临时类
|
||
/// </summary>
|
||
class ShPayTmp
|
||
{
|
||
public long id { get; set; }
|
||
|
||
public object shpayInfo { get; set; }
|
||
}
|
||
#endregion
|
||
}
|
||
}
|