IPPIngCOde

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;
using System.Xml;
using YGApp.Encryption;
using System.Configuration;
using System.Reflection;
using System.Collections.Specialized;
using DevExpress.XtraEditors.Controls;
using System.Net;
using System.Runtime.InteropServices;
using System.Management;
using log4net;
using YGApp.Base.Log;
using System.Security.Cryptography;
using System.Collections;
using Microsoft.Win32; //对注册表操作一定要引用这个命名空间
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

 


namespace YGApp.WinClient
{


    /// <summary>
    /// 公共函数类
    /// </summary>
   
    public class CommFunc
    {
        //ping IP API调用
        [DllImport("Iphlpapi.dll")]
        private static extern int SendARP(Int32 dest, Int32 host, byte[] mac, ref Int32 length);
        [DllImport("Ws2_32.dll")]
        private static extern Int32 inet_addr(string ip);
        public static string IMG_LOGIN_LOGO = "Login_Logo.jpg";
        public static string IMG_LOGIN_OK = "Login_OK.gif";
        public static string IMG_LOGIN_CANCEL = "Login_Cancel.gif";
        public static string IMG_TREE_FLODER = "Tree_Folder.gif";
        public static string IMG_TREE_LEAF = "Tree_FolderLeaf.gif";
        public static string IMG_TREE_SELECTNODE = "Tree_FolderSelectedLeaf.gif";
        public static string IMG_MAIN_BACKGROUND = "YGAppEPBackGround.jpg";
        public static string IMG_TREE_NOTES = "Tree_Notes.gif";
        public static string LOG_FILENAME = Application.StartupPath + "//YGApp.WinClient.exe.log4net";
        public static string APPLICATION_CONFIG = Application.StartupPath + "//YGApp.WinClient.exe.config";
        public static string ICO_APPLICATION = "Application.ico";
        public static int DEFALUT_SESSION_TIMEOUT = 15;
        public static string REMOTE_CONFIG = Application.StartupPath + "//config//YGApp.Remoting.ClientConfig.xml";
        public static string MINVERSIONNUMBER = "1998-12-29 00:00"; //最小版本号
        public static string TEMP_UPATE_PATHS = Environment.GetEnvironmentVariable("Temp") + "//" + "_" + "Update" + "//";


        public enum VerType { cs = 0, personal = 1, none = 2 };

        public static System.Threading.Mutex mutex;

        public static IYGAppLog m_log;

        public static string AppLicationPath = "";

        public static string ApplicationName = "";

        public static DevExpress.XtraEditors.StyleController SystemStyleControl = new DevExpress.XtraEditors.StyleController();

        public static Image GetImages(string fileName)
        {
            fileName = AppLicationPath + "//images//" + fileName;
            if (!File.Exists(fileName))
            {
                return null;
            }
            try
            {
                Image img = Image.FromFile(fileName);
                return img;
            }
            catch
            {
                return null;
            }

        }

        public static Icon GetICON(string fileName)
        {
            fileName = AppLicationPath + "//images//" + fileName;
            if (!File.Exists(fileName))
            {
                return null;
            }
            try
            {
                Icon icon = new Icon(fileName);
                return icon;
            }
            catch
            {
                return null;
            }

        }


        public static void WriteErrorLogs(object message, Exception ex)
        {
            if (m_log != null)
            {
                m_log.Error(message, ex);
            }
        }

        public static void WriteErrorLogs(object message)
        {
            if (m_log != null)
            {
                m_log.Error(message);
            }
        }

        public static void WriteWarnLogs(object message, Exception ex)
        {
            if (m_log != null)
            {
                m_log.Warn(message, ex);
            }
        }

        public static void WriteWarnLogs(object message)
        {
            if (m_log != null)
            {
                m_log.Warn(message);
            }
        }

 

 


        /// <summary>
        /// 从配置文件中获取用户登陆信息
        /// </summary>
        /// <param name="attributeName"></param>
        /// <returns></returns>
        public static string GetUserInfoConfigValue(string attributeName, bool IsEncode)
        {
            try
            {
                NameValueCollection info = ((NameValueCollection)(ConfigurationManager.GetSection("LoginUserInfo")));
                if (info == null || info.AllKeys.Length == 0)
                {
                    return "";
                }

                string[] values = info.GetValues(attributeName);
                if (values.Length == 0)
                {
                    return "";
                }
                if (IsEncode)
                {
                    Encrypt de = new Encrypt();
                    return de.DecodeStr(values[0]);
                }
                else
                {
                    return values[0];
                }
            }
            catch
            {
                return "";
            }

        }

        /// <summary>
        /// 获取当前系统运行版本
        /// </summary>
        /// <returns></returns>
        public static VerType SystemVerType()
        {
            string ver = GetSystemInfoConfigValue("VerType", false);
            if (ver.ToLower() == "cs")
            {
                return VerType.cs;
            }
            else if (ver.ToLower() == "personal")
            {
                return VerType.personal;
            }
            else
            {
                return VerType.none;
            }
        }

 

        /// <summary>
        /// 从配置文件获取系统信息
        /// </summary>
        /// <param name="attributeName"></param>
        /// <returns></returns>
        public static string GetSystemInfoConfigValue(string attributeName, bool IsEncode)
        {

            try
            {
                NameValueCollection info = ((NameValueCollection)(ConfigurationManager.GetSection("SystemConfigInfo")));
                if (info == null || info.AllKeys.Length == 0)
                {
                    return "";
                }

                string[] values = info.GetValues(attributeName);
                if (values.Length == 0)
                {
                    return "";
                }
                if (IsEncode)
                {
                    Encrypt de = new Encrypt();
                    return de.DecodeStr(values[0]);
                }
                else
                {
                    return values[0];
                }
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        /// 给属性赋值
        /// </summary>
        /// <param name="xPath"></param>
        /// <param name="attributeName"></param>
        /// <param name="value"></param>
        public static void SetLoginAttributeValue(string attributeName, string value, bool isEnCode)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(Application.StartupPath + @"/" + "YGApp.WinClient.exe.config");
            XmlNodeList list = doc.SelectNodes("configuration/LoginUserInfo");
            if (list == null || list.Count == 0)
            {
                return;
            }
            foreach (XmlNode node in list[0].ChildNodes)
            {
                if (node.Attributes[0].Value.ToLower() == attributeName.ToLower())
                {
                    if (isEnCode)
                    {
                        Encrypt en = new Encrypt();
                        node.Attributes[1].Value = en.EncodeStr(value);
                    }
                    else
                    {
                        node.Attributes[1].Value = value;
                    }
                    doc.Save(Application.StartupPath + @"/" + "YGApp.WinClient.exe.config");
                    break;
                }
            }

        }

        public static BorderStyles GetEnumStyle(string style)
        {
            switch (style.ToLower())
            {
                case "default":
                    return BorderStyles.Default;
                case "flat":
                    return BorderStyles.Flat;
                case "hotflat":
                    return BorderStyles.HotFlat;
                case "noborder":
                    return BorderStyles.NoBorder;
                case "office2003":
                    return BorderStyles.Office2003;
                case "simple":
                    return BorderStyles.Simple;
                case "style3d":
                    return BorderStyles.Style3D;
                case "ultraflat":
                    return BorderStyles.UltraFlat;
                default:
                    return BorderStyles.Default;
            }
        }

        /// <summary>
        /// 获取本机MAC地址
        /// </summary>
        /// <returns></returns>
        public static string GetNetCardMacAddress()
        {
            try
            {
                ManagementClass mc;
                ManagementObjectCollection moc;
                mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
                moc = mc.GetInstances();
                foreach (ManagementObject mo in moc)
                {
                    if ((bool)mo["IPEnabled"] == true)
                    {
                        return mo["MacAddress"].ToString().Replace(":", "-"); ;
                        //macAddress = ((string[])(mo["IpAddress"]))[0].ToString();
                    }

                }
            }
            catch
            {
                return "";
            }
            return "";
        }

        /// <summary>
        /// 获取本机IP地址
        /// </summary>
        /// <returns></returns>
        public static string GetIpAddress()
        {
            try
            {
                ManagementClass mc;
                ManagementObjectCollection moc;
                mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
                moc = mc.GetInstances();
                foreach (ManagementObject mo in moc)
                {
                    if ((bool)mo["IPEnabled"] == true)
                    {
                        return ((string[])(mo["IpAddress"]))[0].ToString();
                    }
                }
            }
            catch
            {
                return "";
            }
            return "";
        }

        /// <summary>
        /// 获取本机主板信息(标识位+型号+序列号)
        /// </summary>
        /// <returns></returns>
        public static string GetMainboarInfo(out string error)
        {
            error = string.Empty;
            string mainboardSerialInfo = string.Empty;
            string strMachineIdentifier = string.Empty;
            try
            {
                string path = Path.Combine(AppLicationPath + @"/", "Config//YGApp.AppPrivateConfig.xml");
                XmlDocument XmlDoc = new XmlDocument();
                XmlDoc.Load(path);
                XmlNodeList MachineIdentifierList = XmlDoc.SelectNodes("//MachineIdentifier");//读取机器码标识符
                foreach (XmlNode Nodes in MachineIdentifierList)
                    strMachineIdentifier = Nodes.InnerText;
                ManagementClass mc = new ManagementClass("WIN32_BaseBoard");
                ManagementObjectCollection moc = mc.GetInstances();
                foreach (ManagementObject mo in moc)
                    mainboardSerialInfo = strMachineIdentifier +":"+ mo["Product"].ToString() + mo["SerialNumber"].ToString();
            }
            catch (Exception ex)
            {
                error = "获取本机机器码信息失败:" + ex.Message + ex.StackTrace;
            }
            return mainboardSerialInfo;
        }


        #region 客户端mD5文件验证

        /// <summary>
        /// md5物理文件验证
        /// </summary>
        /// <param name="XmlDoc"></param>
        /// <param name="dicFiles"></param>
        /// <returns></returns>
        public static bool BalanceFileMd5(XmlDocument localFileConfig, out Dictionary<string, string> localFiles)
        {
            localFiles = new Dictionary<string, string>();
            XmlNodeList svrFileList = localFileConfig.SelectNodes("//File");
            foreach (XmlNode FileNode in svrFileList)
            {
                string svrfileName = (FileNode.InnerText.StartsWith("//") ? FileNode.InnerText.Substring(1) : FileNode.InnerText);
                string svrMD5 = FileNode.SelectSingleNode("@md5").Value;
                string localFileName = Path.Combine(CommFunc.AppLicationPath, svrfileName);
                if (File.Exists(localFileName))
                {
                    string localMD5 = MD5File(localFileName).ToUpper();
                    if (svrMD5 == localMD5)
                    {
                        localFiles.Add(svrfileName, svrMD5);
                    }
                }
            }
            return (localFiles.Count == svrFileList.Count);
        }


        /// <summary>
        /// 找出Md5的值
        /// </summary>
        /// <param name="xmldoc"></param>
        /// <returns></returns>
        public static Dictionary<string, string> GetMd5Value(XmlDocument XmlDoc)
        {
            Dictionary<string, string> dicMd5Value = new Dictionary<string, string>();
            XmlNodeList NodeList = XmlDoc.SelectNodes("//File");
            foreach (XmlNode FileNode in NodeList)
            {
                dicMd5Value.Add(FileNode.InnerText, FileNode.SelectSingleNode("@md5").Value);
            }
            return dicMd5Value;
        }


        /// <summary>
        /// 找出需要更新的文件
        /// </summary>
        /// <param name="XmlDoc"></param>
        /// <param name="dicFiles"></param>
        /// <returns></returns>
        public static Dictionary<string, string> FindUpdateFile(string serverFileConfig, Dictionary<string, string> localFileMD5Values)
        {
            XmlDocument XmlDoc = new XmlDocument();
            XmlDoc.LoadXml(serverFileConfig);
            Dictionary<string, string> Updatelist = new Dictionary<string, string>();
            string AppMianName = string.Empty;
            XmlNodeList AppMianList = XmlDoc.SelectNodes("//AppMain");

            foreach (XmlNode Nodes in AppMianList)
                AppMianName = Nodes.InnerText;

            XmlNodeList NodeList = XmlDoc.SelectNodes("//File");
            foreach (XmlNode FileNode in NodeList)
            {
                if (FileNode.InnerText != AppMianName)
                {
                    string srvFileMd5 = FileNode.SelectSingleNode("@md5").Value;
                    if (localFileMD5Values.ContainsKey(FileNode.InnerText))
                    {
                        if (!localFileMD5Values[FileNode.InnerText].Equals(srvFileMd5))
                        {
                            Updatelist.Add(FileNode.InnerText, srvFileMd5);
                        }
                    }
                    else
                    {
                        Updatelist.Add(FileNode.InnerText, srvFileMd5);
                    }
                }
            }
            Updatelist.Add(AppMianName, "");
            Updatelist.Add("YGApp.WinClient.pdb", "");
            return Updatelist;

        }

 

        /// <summary>
        /// 获取客户端版本号
        /// </summary>
        /// <param name="XmlDoc"></param>
        /// <param name="dicFiles"></param>
        /// <returns></returns>
        public static string GetEdition(XmlDocument XmlDoc)
        {
            string FileNames = string.Empty;

            XmlNodeList NodeList = XmlDoc.SelectNodes("//AppVersion");
            foreach (XmlNode FileNode in NodeList)
            {
                FileNames = FileNode.InnerText;
            }

            return FileNames;

        }


        /// <summary>
        /// 通过物理验证得到发送服务端的版本号
        /// </summary>
        /// <param name="XmlDoc"></param>
        /// <param name="?"></param>
        /// <returns></returns>
        public static string GetEditionAccord(XmlDocument localFileConfig, out Dictionary<string, string> localFiles)
        {
            if (!BalanceFileMd5(localFileConfig, out  localFiles))
            {
                //如果物理验证不相符合返回最小版本号
                return MINVERSIONNUMBER;
            }
            else
            {
                return CommFunc.GetEdition(localFileConfig);
            }
        }

 

        /// <summary>
        /// 计算文件的 MD5 值
        /// </summary>
        /// <param name="fileName">要计算 MD5 值的文件名和路径</param>
        /// <returns>MD5 值16进制字符串</returns>
        public static string MD5File(string fileName)
        {
            return HashFile(fileName, "md5");
        }

 

        /// <summary>
        /// 计算文件的哈希值
        /// </summary>
        /// <param name="fileName">要计算哈希值的文件名和路径</param>
        /// <param name="algName">算法:sha1,md5</param>
        /// <returns>哈希值16进制字符串</returns>
        public static string HashFile(string fileName, string algName)
        {
            if (!System.IO.File.Exists(fileName))
                return string.Empty;

            FileStream fs = File.OpenRead(fileName);
            byte[] hashBytes = HashData(fs, algName);
            fs.Close();
            return ByteArrayToHexString(hashBytes);
        }

 

        /// <summary>
        /// 计算哈希值
        /// </summary>
        /// <param name="stream">要计算哈希值的 Stream</param>
        /// <param name="algName">算法:sha1,md5</param>
        /// <returns>哈希值字节数组</returns>
        public static byte[] HashData(Stream stream, string algName)
        {
            HashAlgorithm algorithm;
            if (string.Compare(algName, "sha1", true) == 0)
            {
                algorithm = SHA1.Create();
            }
            else
            {
                algorithm = MD5.Create();
            }
            return algorithm.ComputeHash(stream);
        }

 

        ///<summary>
        /// 字节数组转换为16进制表示的字符串
        /// </summary>
        public static string ByteArrayToHexString(byte[] buf)
        {
            StringBuilder sb = new StringBuilder();
            foreach (byte b in buf)
                sb.AppendFormat("{0:x2}", b);
            return sb.ToString();

        }

        /// <summary>
        /// 获取更新工具名称
        /// </summary>
        /// <returns></returns>
        public static string GetUpdateToolExe(XmlDocument XmlDoc)
        {
            string UpdateToolNames = string.Empty;

            XmlNodeList NodeList = XmlDoc.SelectNodes("//ToolsName");
            foreach (XmlNode FileNode in NodeList)
            {
                UpdateToolNames = FileNode.InnerText;
            }

            return UpdateToolNames;


        }


        #endregion


        #region 单点登陆  wdk
        /// <summary>
        /// 注册表注册
        /// </summary>
        public static bool SetRegistry(out string error)
        {
            error = "";
            string ProtocolName = string.Empty;
            string ApploctionName = string.Empty;

            XmlDocument XmlDoc = new XmlDocument();
            //不能使用Directory.GetCurrentDirectory() 因为在游览器访问的时候Directory.GetCurrentDirectory()的地址是游览器的地址
            string path = Path.Combine(AppLicationPath + @"/", "Config//YGApp.AppPrivateConfig.xml");
            try
            {
                XmlDoc.Load(path);
                XmlNodeList ProtocolNameList = XmlDoc.SelectNodes("//ProtocolName");//读取要注册到注册的名称
                XmlNodeList AppNameList = XmlDoc.SelectNodes("//ApplicationName");//启动程序的名称
                foreach (XmlNode Nodes in ProtocolNameList)
                    ProtocolName = Nodes.InnerText;
                foreach (XmlNode AppNodes in AppNameList)
                    ApploctionName = AppNodes.InnerText;
                RegistryKey pregkey;
                pregkey = Registry.ClassesRoot.OpenSubKey(ProtocolName);//AppMianName
                string GetRegisValue = string.Empty;
                string RegisterPath = Path.Combine(AppLicationPath + @"/", "Config//YGAPP.RegisterTemplate.config");
                if (pregkey != null && pregkey.GetValue("URL Protocol") != null)
                {

                    //判断注册信息的注册路径是否正确
                    GetRegisValue = pregkey.GetValue("URL Protocol").ToString();
                    if (!GetRegisValue.Equals(Path.Combine(AppLicationPath + @"/", ApploctionName)))
                    {
                        //路径不正确删除项重新注册
                        Registry.ClassesRoot.DeleteSubKeyTree(ProtocolName);
                        WriteFileToTempDir(RegisterPath, ProtocolName, ApploctionName, out error);
                    }
                }
                else
                {

                    if (pregkey != null)
                        Registry.ClassesRoot.DeleteSubKeyTree(ProtocolName);

                    WriteFileToTempDir(RegisterPath, ProtocolName, ApploctionName, out error);
                }
            }
            catch (System.Exception ex)
            {
                error = ex.Message;
            }
            return string.IsNullOrEmpty(error);
        }

        /// <summary>
        /// 生成文件到临时目录
        /// </summary>
        private static bool WriteFileToTempDir(string LoaclFilePath, string BindingName, string ApploctionName, out string error)
        {
            error = "";
            FileStream FileCreate = null;
            byte[] buffer = null;
            // @"D:/TestUrl/URl.config";
            try
            {
                //读取文件
                FileCreate = File.OpenRead(LoaclFilePath);
                buffer = new byte[FileCreate.Length];
                FileCreate.Read(buffer, 0, buffer.Length);
                FileCreate.Close();
                //模版内容
                string TemplateText = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
                //程序的路径
                string AppLocalPath = Path.Combine(Directory.GetCurrentDirectory(), ApploctionName).Replace("//", "");
                //临时目录的路径
                string TempRegisterPath = Path.Combine(Environment.GetEnvironmentVariable("Temp") + @"/", "Temp_Register.reg");
                //模版替换
                TemplateText = TemplateText.Replace("#SysName#", BindingName).Replace("#ProgrammePath#", AppLocalPath);

                //FileStream _FileCreate = null;
                StreamWriter FileStreamWrite = null;

                FileCreate = new FileStream(TempRegisterPath, FileMode.Create);
                FileStreamWrite = new StreamWriter(FileCreate, System.Text.Encoding.Unicode);
                //开始写入
                FileStreamWrite.Write(TemplateText);
                //清空缓冲区
                FileStreamWrite.Flush();
                //关闭流
                FileStreamWrite.Close();
                FileCreate.Close();

                Process process = new Process();
                process.StartInfo = new ProcessStartInfo("regedit.exe", "/s " + TempRegisterPath);
                process.Start();// Start(startInfo);
                process.WaitForExit();
                //删除临时注册文件
                File.Delete(TempRegisterPath);
                RegistryKey pregkey;
                pregkey = Registry.ClassesRoot.OpenSubKey(BindingName);
                if (pregkey == null)
                {
                    error = "系统无法将信息写入到注册表!/r/n请检查是否有windows系统注册表写入权限,并请暂时停用杀毒软件与防火墙";
                }
            }
            catch (System.Exception ex)
            {
                error = "系统信息写入注册表发生错误" + ex.Message;
            }
            return string.IsNullOrEmpty(error);
        }

        /// <summary>
        /// 获取更新提示
        /// </summary>
        /// <param name="strUpateMegs"></param>
        /// <returns></returns>
        public static string GetUpdateMessage(string strUpateMegs)
        {
            //MessageBox.Show(strUpateMegs);
        
            if (strUpateMegs.Split('|').Length > 1)
                return System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(strUpateMegs.Split('|')[1]));
            else
                return "";

        }

        /// <summary>
        /// 令牌字符串解析
        /// </summary>
        public static string strTokenParse(string strToken,out string userName)
        {
            // YgSale://?Token=1jh34jh213j4kj&para1=value1
            userName="";
            string ParseToken = "";
            //单点登录的解析
            if (strToken.Contains(@":") && strToken.Contains("Token=") )
            {
                string[] strTokenArray = strToken.Split(':');
                if (strTokenArray != null && strTokenArray.Length > 1)
                {
                    string[] strTokenParam = strTokenArray[1].Split(new string[] { "&&" }, StringSplitOptions.None);
                    if (strTokenParam != null && strTokenParam.Length > 1)
                    {
                        userName = strTokenParam[0].Replace("Token=", string.Empty);
                        ParseToken = strTokenParam[1];
                    }
                }
              
              
            }
            //程序更新时的解析
            else if (strToken.Contains("&&"))
            {
                string[] strTokenParam = strToken.Split(new string[] { "&&" }, StringSplitOptions.None);
                if (strTokenParam != null && strTokenParam.Length > 1)
                {
                    userName = strTokenParam[0];
                    ParseToken = strTokenParam[1];
                }
            }
            else
            {
                ParseToken = strToken;
            }
            return ParseToken;
        }


        /// <summary>
        /// 解析提取更新内容提示
        /// </summary>
        /// <param name="Edition"></param>
        /// <returns></returns>
        public static string ParseXmlGetMessages(string strloadXml, out string error)
        {
            error = "";
            XmlDocument xmlDoc = new XmlDocument();
            string Messages = string.Empty;
            try
            {
                xmlDoc.LoadXml(strloadXml.Split('|')[1]);

                XmlNodeList NodeList = xmlDoc.SelectNodes("//ToolipMesg");
                foreach (XmlNode FileNode in NodeList)
                {
                    Messages = FileNode.InnerText;
                }

            }
            catch (System.Exception ex)
            {
                error = "获取提示信息文件读取失败" + ex.Message + "/r/n" + ex;
            }
            return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Messages));

        }


        /// <summary>
        /// 根据ip得到网卡mac地址
        /// </summary>
        /// <param name="ip">给出的ip地址</param>
        /// <returns>对应ip的网卡mac地址</returns>
        public static string GetMACByIP(string ip,out string error)
        {
            error = string.Empty;
            string macinfo = string.Empty;//mac信息
            try
            {
                Int32 len = 6;
                byte[] _byte = new byte[len];
                Int32 destinationIp = inet_addr(ip); //目的地的ip
               // Int64 macinfo = new Int64();
                int res = SendARP(destinationIp, 0, _byte, ref len);
                macinfo = BitConverter.ToString(_byte, 0, len);
                if (macinfo.Equals("00-00-00-00-00-00"))
                {
                    error = "检测到提供的环境服务器IP访问无效,检查该网段是否已被限制访问或管理员没有设置限制环境服务器的IP";
                    macinfo = string.Empty;
                }
             
            }
            catch (Exception err)
            {
                error = "Ping IP获取MAC地址出错, 原因:" + err.Message + err.StackTrace;
            }
            return macinfo;
        }

 

        #endregion


    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值