xuwei 3 vuotta sitten
vanhempi
commit
8db8b1b551

+ 1 - 0
.gitignore

@@ -108,3 +108,4 @@ _UpgradeReport_Files/
 Backup*/
 UpgradeLog*.XML
 
+/.vs

+ 41 - 0
HEGII.ss.mes.pushdata.sln

@@ -0,0 +1,41 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.32929.386
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "wwwroot", "wwwroot\", "{DB74DD9E-F84B-4372-A298-41376272D607}"
+	ProjectSection(WebsiteProperties) = preProject
+		TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0"
+		Debug.AspNetCompiler.VirtualPath = "/localhost_62172"
+		Debug.AspNetCompiler.PhysicalPath = "wwwroot\"
+		Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_62172\"
+		Debug.AspNetCompiler.Updateable = "true"
+		Debug.AspNetCompiler.ForceOverwrite = "true"
+		Debug.AspNetCompiler.FixedNames = "false"
+		Debug.AspNetCompiler.Debug = "True"
+		Release.AspNetCompiler.VirtualPath = "/localhost_62172"
+		Release.AspNetCompiler.PhysicalPath = "wwwroot\"
+		Release.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_62172\"
+		Release.AspNetCompiler.Updateable = "true"
+		Release.AspNetCompiler.ForceOverwrite = "true"
+		Release.AspNetCompiler.FixedNames = "false"
+		Release.AspNetCompiler.Debug = "False"
+		VWDPort = "62172"
+		SlnRelativePath = "wwwroot\"
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{DB74DD9E-F84B-4372-A298-41376272D607}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DB74DD9E-F84B-4372-A298-41376272D607}.Debug|Any CPU.Build.0 = Debug|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {9CA3E13F-6ECD-4AFF-BB80-B7C099FAE7B3}
+	EndGlobalSection
+EndGlobal

+ 0 - 3
README.md

@@ -1,3 +0,0 @@
-# HEGIIss.mes.pushdata
-
-恒洁三水厂数据推送

+ 22 - 0
wwwroot/App_Code/ReworkHttp.cs

@@ -0,0 +1,22 @@
+using System.Net;
+using System.Threading;
+
+/// <summary>
+/// 重新唤醒当前应用
+/// </summary>
+public class ReworkHttp
+{
+    /// <summary>
+    /// 唤醒当前应用
+    /// </summary>
+    public static void Rework()
+    {
+        //iis会回收这个定时任务,这边在回收的时候触发一个请求,10秒后来再次唤醒该服务
+        Thread.Sleep(10000);
+
+        WebRequest myWebRequest = WebRequest.Create("http://localhost:9600/");
+        WebResponse myWebResponse = myWebRequest.GetResponse();
+        myWebResponse.GetResponseStream();
+        myWebResponse.Close();
+    }
+}

+ 79 - 0
wwwroot/App_Code/Scale36.cs

@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+
+/// <summary>
+/// 36进制换算
+/// </summary>
+public class Scale36
+{
+    /// <summary>
+    /// 进制符号字符串
+    /// </summary>
+    private static string scString = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ";
+
+    /// <summary>
+    /// 字符集,可以根据编号索引拿到字符
+    /// </summary>
+    private static char[] scArray = scString.ToCharArray();
+
+    /// <summary>
+    /// 字符字典,可以根据字符拿到编号索引
+    /// </summary>
+    private static Dictionary<char, int> scDic = ToCharDic();
+
+    /// <summary>
+    /// 根据字符串反馈进制数
+    /// </summary>
+    public static int Len { get { return scString.Length; } }
+
+    /// <summary>
+    /// 将字符串处理成字符字典
+    /// </summary>
+    private static Dictionary<char, int> ToCharDic()
+    {
+        Dictionary<char, int> dic = new Dictionary<char, int>();
+        for (int i = 0; i < scArray.Length; i++)
+        {
+            dic.Add(scArray[i], i);
+        }
+        return dic;
+    }
+
+    /// <summary>
+    /// 根据传入的字符符号定义进制,字符符号不能重复,模拟十进制字符串为:0123456789
+    /// </summary>
+    public static void SetScale(string scaleString)
+    {
+        scString = scaleString;
+        scArray = scString.ToCharArray();
+        scDic = ToCharDic();
+    }
+
+    /// <summary>
+    /// 将Int64转成当前进制字符串
+    /// </summary>
+    public static string ToCurr36(long num)
+    {
+        string curr = "";
+        while (num >= Len)
+        {
+            curr = scArray[num % Len] + curr;
+            num = num / Len;
+        }
+        curr = scArray[num] + curr;
+        return curr;
+    }
+
+    /// <summary>
+    /// 将当前进制字符串转成Int
+    /// </summary>
+    public static long ToInt(string curr)
+    {
+        double num = 0;
+        for (int i = 0; i < curr.Length; i++)
+        {
+            num += scDic[curr[i]] * Math.Pow(Len, curr.Length - 1 - i);
+        }
+        return Convert.ToInt32(num);
+    }
+}

+ 1073 - 0
wwwroot/App_Code/SyncZhongTai.cs

@@ -0,0 +1,1073 @@
+using System;
+using System.Data;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+using Curtain.DataAccess;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+/// <summary>
+/// 同步到恒洁中台
+/// </summary>
+public class SyncZhongTai
+{
+    #region 固定常量
+    // 固定常量
+    public static string _ft_gcdm = "1";    // 凤塘
+    public static string _ss_gcdm = "2";    // 三水
+    public static string _gt_gcdm = "7";    // 官塘
+    public static string _grant_type = "client_credentials";
+    public static DateTime _startDate = Convert.ToDateTime("2022-01-01");
+
+    // 数据库连接字符串
+    public static string _connStr_ss = @"Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.18.32.116)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=dkmes)));User Id=hgiboss;Password=dongke";
+    public static string _connStr_cz2 = @"Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.19.22.61)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=hgcz2)));User Id=hgcz2;Password=dongke";
+    public static string _connStr_cz3 = @"Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.19.22.61)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=hgcz3)));User Id=hgcz3;Password=dongke";
+
+    // 测试环境
+    public static string _urlToken = "https://hapcloudq.hegii.com/api/auth/oauth/token";
+    public static string _urlPush = "https://hapcloudq.hegii.com/api/product/prodBarcode/synUniqueCode";
+    public static string _client_id_cz = "83263e79b909439bbd03caaada592b46";
+    public static string _client_secret_cz = "867eeba1e3624645ab18333589780677";
+    public static string _client_id_ss = "e86762528ada4cc3919346f107a7f7ec";
+    public static string _client_secret_ss = "de3e8f5e762c4f948807498a513688c4";
+
+    // 正式环境
+    //public static string _urlToken = "https://hapcloud.hegii.com/api/auth/oauth/token";
+    //public static string _urlPush = "https://hapcloud.hegii.com/api/product/prodBarcode/synUniqueCode";
+    //public static string _client_id_cz = "94cbe967808941b895c636541f28557a";
+    //public static string _client_secret_cz = "1cd2011b447042e4b60e5411988b35f7";
+    //public static string _client_id_ss = "90c8310d77ae453685e9b0c16b386fb5";
+    //public static string _client_secret_ss = "5775f44f16b64124b9e854c1ae659444";
+    #endregion
+
+    #region 推送方法
+    /// <summary>
+    /// 同步产成品交接数据到恒洁中台
+    /// </summary>
+    /// <param name="syncDate">同步日期</param>
+    /// <param name="isPushTodayAllData">是否推送当天剩余所有数据</param>
+    /// <returns></returns>
+    public static string SyncFinishedProduct(DateTime syncDate, bool isPushTodayAllData)
+    {
+        string msg = string.Empty;
+        msg += "ss:" + SyncFinishedProduct_ss(syncDate, isPushTodayAllData);
+        msg += ",cz2:" + SyncFinishedProduct_cz2(syncDate, isPushTodayAllData);
+        msg += ",cz3:" + SyncFinishedProduct_cz3(syncDate, isPushTodayAllData);
+        return msg;
+    }
+
+    /// <summary>
+    /// 同步产成品交接数据到恒洁中台_三水
+    /// </summary>
+    /// <param name="syncDate">同步日期</param>
+    /// <param name="isPushTodayAllData">是否推送当天剩余所有数据</param>
+    /// <returns></returns>
+    public static string SyncFinishedProduct_ss(DateTime syncDate, bool isPushTodayAllData)
+    {
+        int returnRows = 0;
+        string sql = string.Empty;
+        string sqlUpdate = string.Empty;
+        // 本次推送的数据
+        DataTable dtSyncFinishProduct = null;
+        // 返回json
+        JObject returnObj;
+        // 推送结果
+        string message = string.Empty;
+
+        using (IDataAccess connSS = DataAccess.CreateByString(DataBaseType.Oracle, _connStr_ss))
+        {
+            try
+            {
+                #region 获取产成品交接数据
+                // 从gdd表上更新流水号和首次交接日期(预防有交接完又回产线的产品)
+                sqlUpdate = @"
+                UPDATE TP_PM_FINISHEDPRODUCT P
+                   SET (P.FIRSTFHDATE, P.FIRSTFHNO) =
+                       (SELECT GDD.FIRSTFHDATE,
+                               GDD.FIRSTFHNO
+                          FROM TP_PM_GROUTINGDAILYDETAIL GDD
+                         WHERE GDD.FIRSTFHNO IS NOT NULL
+                           AND GDD.BARCODE = P.BARCODE)
+                 WHERE P.FIRSTFHNO IS NULL
+                   AND P.FHTIME >= @DATEBEGIN@
+                   AND P.FHTIME < @DATEEND@ ";
+
+                returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+
+                // 获取当日最大流水号
+                sql = @"
+                SELECT NVL(MAX(FIRSTFHNO), 0) AS MAXFIRSTFHNO
+                  FROM TP_PM_FINISHEDPRODUCT FP
+                 WHERE FP.FHTIME >= @DATEBEGIN@
+                   AND FP.FHTIME < @DATEEND@ ";
+                object objMaxFirstFhNo = connSS.ExecuteScalar(sql,
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+                int maxFirstFhNo = 0;
+                int.TryParse(objMaxFirstFhNo + "", out maxFirstFhNo);
+
+                // 更新流水号和首次交接日期
+                sqlUpdate = @"
+                UPDATE TP_PM_FINISHEDPRODUCT P
+                   SET P.FIRSTFHDATE = @DATEBEGIN@,
+                       P.FIRSTFHNO =
+                       (SELECT T2.FIRSTFHNO
+                          FROM (SELECT T.BARCODE,
+                                       ROWNUM + @MAXFIRSTFHNO@ AS FIRSTFHNO
+                                  FROM (SELECT FP.BARCODE
+                                          FROM TP_PM_FINISHEDPRODUCT FP
+                                         WHERE FP.FIRSTFHNO IS NULL
+                                           AND FP.FHTIME >= @DATEBEGIN@
+                                           AND FP.FHTIME < @DATEEND@
+                                         ORDER BY FP.FHTIME,
+                                                  FP.BARCODE) T) T2
+                         WHERE T2.BARCODE = P.BARCODE)
+                 WHERE P.FIRSTFHNO IS NULL
+                   AND P.FHTIME >= @DATEBEGIN@
+                   AND P.FHTIME < @DATEEND@ ";
+
+                returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                    new CDAParameter("MAXFIRSTFHNO", maxFirstFhNo, DataType.Int32),
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+
+                // 将流水号和首次交接日期更新到gdd表上
+                sqlUpdate = @"
+                 UPDATE TP_PM_GROUTINGDAILYDETAIL GDD
+                    SET (GDD.FIRSTFHDATE, GDD.FIRSTFHNO) =
+                        (SELECT P.FIRSTFHDATE,
+                                P.FIRSTFHNO
+                           FROM TP_PM_FINISHEDPRODUCT P
+                          WHERE GDD.BARCODE = P.BARCODE
+                            AND P.FIRSTFHNO IS NOT NULL
+                            AND P.FHTIME >= @DATEBEGIN@
+                            AND P.FHTIME < @DATEEND@)
+                  WHERE GDD.FIRSTFHNO IS NULL
+                    AND EXISTS (SELECT 1
+                           FROM TP_PM_FINISHEDPRODUCT P
+                          WHERE GDD.BARCODE = P.BARCODE
+                            AND P.FIRSTFHNO IS NOT NULL
+                            AND P.FHTIME >= @DATEBEGIN@
+                            AND P.FHTIME < @DATEEND@) ";
+
+                returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+
+                // 是否推送当天剩余的所有数据
+                if (isPushTodayAllData)
+                {
+                    sql = @"
+                    SELECT GDD.OUTLABELCODE,
+                           GDD.MATERIALCODE,
+                           FP.FIRSTFHDATE,
+                           FP.FIRSTFHNO,
+                           FP.BARCODE
+                      FROM TP_PM_FINISHEDPRODUCT FP
+                     INNER JOIN TP_PM_GROUTINGDAILYDETAIL GDD
+                        ON GDD.GROUTINGDAILYDETAILID = FP.GROUTINGDAILYDETAILID
+                     WHERE FP.FIRSTFHNO IS NOT NULL
+                       AND FP.TOZHONGTAIFLAG = '0'
+                       AND FP.FHTIME >= @DATEBEGIN@
+                       AND FP.FHTIME < @DATEEND@
+                     ORDER BY FP.FHTIME,
+                              FP.BARCODE ";
+                }
+                else
+                {
+                    // 获取本次推送的数据(每次推送数据不超过100条)
+                    sql = @"
+                    SELECT T.*,
+                           ROWNUM
+                      FROM (SELECT GDD.OUTLABELCODE,
+                                   GDD.MATERIALCODE,
+                                   FP.FIRSTFHDATE,
+                                   FP.FIRSTFHNO,
+                                   FP.BARCODE
+                              FROM TP_PM_FINISHEDPRODUCT FP
+                             INNER JOIN TP_PM_GROUTINGDAILYDETAIL GDD
+                                ON GDD.GROUTINGDAILYDETAILID = FP.GROUTINGDAILYDETAILID
+                             WHERE FP.FIRSTFHNO IS NOT NULL
+                               AND FP.TOZHONGTAIFLAG = '0'
+                               AND FP.FHTIME >= @DATEBEGIN@
+                               AND FP.FHTIME < @DATEEND@
+                             ORDER BY FP.FIRSTFHNO) T
+                     WHERE ROWNUM <= 100 ";
+                }
+
+                dtSyncFinishProduct = connSS.ExecuteDatatable(sql,
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+
+                if (dtSyncFinishProduct.Rows.Count == 0)
+                {
+                    return "本时段没有要推送的数据";
+                }
+                #endregion
+
+                #region  获取token
+                sql = @"
+                SELECT TOKEN
+                  FROM TP_SYS_ZHONGTAI_TOKEN
+                 WHERE ENDTIME > SYSDATE + 1 / 24 ";
+                string access_token = connSS.ExecuteScalar<string>(sql);
+
+                if (string.IsNullOrEmpty(access_token))
+                {
+                    string[] paras = new string[] { _grant_type, _client_id_ss, _client_secret_ss };
+                    string jsonStr = GetToken(_urlToken, paras);
+                    returnObj = JsonConvert.DeserializeObject<JObject>(jsonStr);
+                    access_token = returnObj["access_token"].ToString();
+                    DateTime nowDate;
+                    DateTime.TryParse(returnObj["nowDate"].ToString(), out nowDate);
+                    int expires_in;
+                    int.TryParse(returnObj["expires_in"].ToString(), out expires_in);
+                    DateTime endTime = nowDate.AddMilliseconds(expires_in);
+
+                    sqlUpdate = @"
+                    UPDATE TP_SYS_ZHONGTAI_TOKEN
+                       SET TOKEN   = @TOKEN@,
+                           ENDTIME = @ENDTIME@ ";
+                    returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                        new CDAParameter("TOKEN", access_token, DataType.NVarChar),
+                        new CDAParameter("ENDTIME", endTime, DataType.DateTime)
+                    );
+                }
+                #endregion
+
+                #region 向接口推送数据
+                DateTime firstfhdate;
+                string differDays36 = string.Empty;
+                int firstFhNo = 0;
+                JObject jObject = null;
+                string firstFhNo36 = string.Empty;
+                JArray jArray = new JArray();
+                foreach (DataRow row in dtSyncFinishProduct.Rows)
+                {
+                    // 当前日期与2022-01-01的时间间隔,转化为36进制数,0~9+A~Z,不满3位左边补0
+                    DateTime.TryParse(row["FIRSTFHDATE"].ToString(), out firstfhdate);
+                    differDays36 = Scale36.ToCurr36(firstfhdate.Subtract(_startDate).Days).PadLeft(3, '0');
+
+                    // 流水(4位,36进制数流水,0~9+A~Z)
+                    int.TryParse(row["FIRSTFHNO"] + "", out firstFhNo);
+                    firstFhNo36 = Scale36.ToCurr36(firstFhNo).PadLeft(4, '0');
+
+                    jObject = new JObject();
+                    jObject.Add(new JProperty("barcode", row["OUTLABELCODE"]));
+                    jObject.Add(new JProperty("productCode", row["MATERIALCODE"]));
+                    jObject.Add(new JProperty("newUniqueCode", "https://hap.hegii.com/jump?state=productInfo-" + row["OUTLABELCODE"]));
+                    jObject.Add(new JProperty("serviceCode", _ss_gcdm + differDays36 + firstFhNo36));
+                    jObject.Add(new JProperty("codeUuid", row["OUTLABELCODE"]));
+                    jArray.Add(jObject);
+                }
+
+                string jsonPara = JsonConvert.SerializeObject(jArray);
+
+                Curtain.Log.Logger.Info("三水_中台同步开始:" + dtSyncFinishProduct.Rows.Count + "\n" + jsonPara);
+                string returnJsonStr = PostToZhongTai(_urlPush, jsonPara, access_token);
+                Curtain.Log.Logger.Info("三水_中台同步结束:\n" + returnJsonStr);
+
+                // 如果token过期了,重新获取一遍,再推一次试试
+                if (returnJsonStr.Contains("未经授权"))
+                {
+                    string[] paras = new string[] { _grant_type, _client_id_ss, _client_secret_ss };
+                    string jsonStr = GetToken(_urlToken, paras);
+                    returnObj = JsonConvert.DeserializeObject<JObject>(jsonStr);
+                    access_token = returnObj["access_token"].ToString();
+                    DateTime nowDate;
+                    DateTime.TryParse(returnObj["nowDate"].ToString(), out nowDate);
+                    int expires_in;
+                    int.TryParse(returnObj["expires_in"].ToString(), out expires_in);
+                    DateTime endTime = nowDate.AddMilliseconds(expires_in);
+
+                    sqlUpdate = @"
+                    UPDATE TP_SYS_ZHONGTAI_TOKEN
+                       SET TOKEN   = @TOKEN@,
+                           ENDTIME = @ENDTIME@ ";
+                    returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                        new CDAParameter("TOKEN", access_token, DataType.NVarChar),
+                        new CDAParameter("ENDTIME", endTime, DataType.DateTime)
+                    );
+
+                    Curtain.Log.Logger.Info("三水_中台同步开始:" + dtSyncFinishProduct.Rows.Count + "\n" + jsonPara);
+                    returnJsonStr = PostToZhongTai(_urlPush, jsonPara, access_token);
+                    Curtain.Log.Logger.Info("三水_中台同步结束:\n" + returnJsonStr);
+                }
+
+                try
+                {
+                    returnObj = JsonConvert.DeserializeObject<JObject>(returnJsonStr);
+                    if (returnObj.ContainsKey("data"))
+                    {
+                        message = returnObj["data"] + "";
+                    }
+                    if (string.IsNullOrEmpty(message) && returnObj.ContainsKey("msg"))
+                    {
+                        message = returnObj["msg"] + "";
+                    }
+                    if (string.IsNullOrEmpty(message) && returnObj.ContainsKey("message"))
+                    {
+                        message = returnObj["message"] + "";
+                    }
+                }
+                catch (Exception ex)
+                {
+                    if (string.IsNullOrEmpty(returnJsonStr))
+                    {
+                        message = ex.Message;
+                    }
+                    else
+                    {
+                        message = returnJsonStr;
+                    }
+                }
+                #endregion
+
+                #region 结果处理
+                char tozhongtaiflag = message.Equals("条码保存成功") ? '1' : '0';
+                // 超时也当作成功
+                if (tozhongtaiflag.Equals('0') && message.Contains("超时"))
+                {
+                    tozhongtaiflag = '1';
+                }
+
+                // 更新推送结果
+                string barcodes = "('" + string.Join("','", dtSyncFinishProduct.AsEnumerable().Select(d => d.Field<string>("BARCODE")).ToArray()) + "')";
+                sqlUpdate = @"
+                UPDATE TP_PM_FINISHEDPRODUCT
+                   SET TOZHONGTAIFLAG = @TOZHONGTAIFLAG@,
+                       ZHONGTAIMSG   = @ZHONGTAIMSG@,
+                       TOZHONGTAITIME   = SYSDATE
+                 WHERE BARCODE IN " + barcodes;
+
+                returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                    new CDAParameter("TOZHONGTAIFLAG", tozhongtaiflag, DataType.Char),
+                    new CDAParameter("ZHONGTAIMSG", message, DataType.NVarChar)
+                );
+                #endregion
+            }
+            catch (Exception ex)
+            {
+                message = ex.Message;
+            }
+        }
+        return message;
+    }
+
+    /// <summary>
+    /// 同步产成品交接数据到恒洁中台_潮州2厂
+    /// </summary>
+    /// <param name="syncDate">同步日期</param>
+    /// <param name="isPushTodayAllData">是否推送当天剩余所有数据</param>
+    /// <returns></returns>
+    public static string SyncFinishedProduct_cz2(DateTime syncDate, bool isPushTodayAllData)
+    {
+        int returnRows = 0;
+        string sql = string.Empty;
+        string sqlUpdate = string.Empty;
+        // 本次推送的数据
+        DataTable dtSyncFinishProduct = null;
+        // 返回json
+        JObject returnObj;
+        // 推送结果
+        string message = string.Empty;
+
+        using (IDataAccess connSS = DataAccess.CreateByString(DataBaseType.Oracle, _connStr_cz2))
+        {
+            try
+            {
+                #region 获取产成品交接数据
+                // 从gdd表上更新流水号和首次交接日期(预防有交接完又回产线的产品)
+                sqlUpdate = @"
+                UPDATE TP_PM_FINISHEDPRODUCT P
+                   SET (P.FIRSTFHDATE, P.FIRSTFHNO) =
+                       (SELECT GDD.FIRSTFHDATE,
+                               GDD.FIRSTFHNO
+                          FROM TP_PM_GROUTINGDAILYDETAIL GDD
+                         WHERE GDD.FIRSTFHNO IS NOT NULL
+                           AND GDD.BARCODE = P.BARCODE)
+                 WHERE P.FIRSTFHNO IS NULL
+                   AND P.FHTIME >= @DATEBEGIN@
+                   AND P.FHTIME < @DATEEND@ ";
+
+                returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+
+                // 获取当日最大流水号
+                sql = @"
+                SELECT NVL(MAX(FIRSTFHNO), 0) AS MAXFIRSTFHNO
+                  FROM TP_PM_FINISHEDPRODUCT FP
+                 WHERE FP.FHTIME >= @DATEBEGIN@
+                   AND FP.FHTIME < @DATEEND@ ";
+                object objMaxFirstFhNo = connSS.ExecuteScalar(sql,
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+                int maxFirstFhNo = 0;
+                int.TryParse(objMaxFirstFhNo + "", out maxFirstFhNo);
+
+                // 更新流水号和首次交接日期
+                sqlUpdate = @"
+                UPDATE TP_PM_FINISHEDPRODUCT P
+                   SET P.FIRSTFHDATE = @DATEBEGIN@,
+                       P.FIRSTFHNO =
+                       (SELECT T2.FIRSTFHNO
+                          FROM (SELECT T.BARCODE,
+                                       ROWNUM + @MAXFIRSTFHNO@ AS FIRSTFHNO
+                                  FROM (SELECT FP.BARCODE
+                                          FROM TP_PM_FINISHEDPRODUCT FP
+                                         WHERE FP.FIRSTFHNO IS NULL
+                                           AND FP.FHTIME >= @DATEBEGIN@
+                                           AND FP.FHTIME < @DATEEND@
+                                         ORDER BY FP.FHTIME,
+                                                  FP.BARCODE) T) T2
+                         WHERE T2.BARCODE = P.BARCODE)
+                 WHERE P.FIRSTFHNO IS NULL
+                   AND P.FHTIME >= @DATEBEGIN@
+                   AND P.FHTIME < @DATEEND@ ";
+
+                returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                    new CDAParameter("MAXFIRSTFHNO", maxFirstFhNo, DataType.Int32),
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+
+                // 将流水号和首次交接日期更新到gdd表上
+                sqlUpdate = @"
+                 UPDATE TP_PM_GROUTINGDAILYDETAIL GDD
+                    SET (GDD.FIRSTFHDATE, GDD.FIRSTFHNO) =
+                        (SELECT P.FIRSTFHDATE,
+                                P.FIRSTFHNO
+                           FROM TP_PM_FINISHEDPRODUCT P
+                          WHERE GDD.BARCODE = P.BARCODE
+                            AND P.FIRSTFHNO IS NOT NULL
+                            AND P.FHTIME >= @DATEBEGIN@
+                            AND P.FHTIME < @DATEEND@)
+                  WHERE GDD.FIRSTFHNO IS NULL
+                    AND EXISTS (SELECT 1
+                           FROM TP_PM_FINISHEDPRODUCT P
+                          WHERE GDD.BARCODE = P.BARCODE
+                            AND P.FIRSTFHNO IS NOT NULL
+                            AND P.FHTIME >= @DATEBEGIN@
+                            AND P.FHTIME < @DATEEND@) ";
+
+                returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+
+                // 是否推送当天剩余的所有数据
+                if (isPushTodayAllData)
+                {
+                    sql = @"
+                    SELECT GDD.OUTLABELCODE,
+                           GDD.MATERIALCODE,
+                           FP.FIRSTFHDATE,
+                           FP.FIRSTFHNO,
+                           FP.BARCODE
+                      FROM TP_PM_FINISHEDPRODUCT FP
+                     INNER JOIN TP_PM_GROUTINGDAILYDETAIL GDD
+                        ON GDD.GROUTINGDAILYDETAILID = FP.GROUTINGDAILYDETAILID
+                     WHERE FP.FIRSTFHNO IS NOT NULL
+                       AND FP.TOZHONGTAIFLAG = '0'
+                       AND FP.FHTIME >= @DATEBEGIN@
+                       AND FP.FHTIME < @DATEEND@
+                     ORDER BY FP.FHTIME,
+                              FP.BARCODE ";
+                }
+                else
+                {
+                    // 获取本次推送的数据(每次推送数据不超过100条)
+                    sql = @"
+                    SELECT T.*,
+                           ROWNUM
+                      FROM (SELECT GDD.OUTLABELCODE,
+                                   GDD.MATERIALCODE,
+                                   FP.FIRSTFHDATE,
+                                   FP.FIRSTFHNO,
+                                   FP.BARCODE
+                              FROM TP_PM_FINISHEDPRODUCT FP
+                             INNER JOIN TP_PM_GROUTINGDAILYDETAIL GDD
+                                ON GDD.GROUTINGDAILYDETAILID = FP.GROUTINGDAILYDETAILID
+                             WHERE FP.FIRSTFHNO IS NOT NULL
+                               AND FP.TOZHONGTAIFLAG = '0'
+                               AND FP.FHTIME >= @DATEBEGIN@
+                               AND FP.FHTIME < @DATEEND@
+                             ORDER BY FP.FIRSTFHNO) T
+                     WHERE ROWNUM <= 100 ";
+                }
+
+                dtSyncFinishProduct = connSS.ExecuteDatatable(sql,
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+
+                if (dtSyncFinishProduct.Rows.Count == 0)
+                {
+                    return "本时段没有要推送的数据";
+                }
+                #endregion
+
+                #region  获取token
+                sql = @"
+                SELECT TOKEN
+                  FROM TP_SYS_ZHONGTAI_TOKEN
+                 WHERE ENDTIME > SYSDATE + 1 / 24 ";
+                string access_token = connSS.ExecuteScalar<string>(sql);
+
+                if (string.IsNullOrEmpty(access_token))
+                {
+                    string[] paras = new string[] { _grant_type, _client_id_cz, _client_secret_cz };
+                    string jsonStr = GetToken(_urlToken, paras);
+                    returnObj = JsonConvert.DeserializeObject<JObject>(jsonStr);
+                    access_token = returnObj["access_token"].ToString();
+                    DateTime nowDate;
+                    DateTime.TryParse(returnObj["nowDate"].ToString(), out nowDate);
+                    int expires_in;
+                    int.TryParse(returnObj["expires_in"].ToString(), out expires_in);
+                    DateTime endTime = nowDate.AddMilliseconds(expires_in);
+
+                    sqlUpdate = @"
+                    UPDATE TP_SYS_ZHONGTAI_TOKEN
+                       SET TOKEN   = @TOKEN@,
+                           ENDTIME = @ENDTIME@ ";
+                    returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                        new CDAParameter("TOKEN", access_token, DataType.NVarChar),
+                        new CDAParameter("ENDTIME", endTime, DataType.DateTime)
+                    );
+                }
+                #endregion
+
+                #region 向接口推送数据
+                DateTime firstfhdate;
+                string differDays36 = string.Empty;
+                int firstFhNo = 0;
+                JObject jObject = null;
+                string firstFhNo36 = string.Empty;
+                JArray jArray = new JArray();
+                foreach (DataRow row in dtSyncFinishProduct.Rows)
+                {
+                    // 当前日期与2022-01-01的时间间隔,转化为36进制数,0~9+A~Z,不满3位左边补0
+                    DateTime.TryParse(row["FIRSTFHDATE"].ToString(), out firstfhdate);
+                    differDays36 = Scale36.ToCurr36(firstfhdate.Subtract(_startDate).Days).PadLeft(3, '0');
+
+                    // 流水(4位,36进制数流水,0~9+A~Z)
+                    int.TryParse(row["FIRSTFHNO"] + "", out firstFhNo);
+                    firstFhNo36 = Scale36.ToCurr36(firstFhNo).PadLeft(4, '0');
+
+                    jObject = new JObject();
+                    jObject.Add(new JProperty("barcode", row["OUTLABELCODE"]));
+                    jObject.Add(new JProperty("productCode", row["MATERIALCODE"]));
+                    jObject.Add(new JProperty("newUniqueCode", "https://hap.hegii.com/jump?state=productInfo-" + row["OUTLABELCODE"]));
+                    jObject.Add(new JProperty("serviceCode", _ft_gcdm + differDays36 + firstFhNo36));
+                    jObject.Add(new JProperty("codeUuid", row["OUTLABELCODE"]));
+                    jArray.Add(jObject);
+                }
+
+                string jsonPara = JsonConvert.SerializeObject(jArray);
+
+                Curtain.Log.Logger.Info("凤塘_中台同步开始:" + dtSyncFinishProduct.Rows.Count + "\n" + jsonPara);
+                string returnJsonStr = PostToZhongTai(_urlPush, jsonPara, access_token);
+                Curtain.Log.Logger.Info("凤塘_中台同步结束:\n" + returnJsonStr);
+
+                // 如果token过期了,重新获取一遍,再推一次试试
+                if (returnJsonStr.Contains("未经授权"))
+                {
+                    string[] paras = new string[] { _grant_type, _client_id_ss, _client_secret_ss };
+                    string jsonStr = GetToken(_urlToken, paras);
+                    returnObj = JsonConvert.DeserializeObject<JObject>(jsonStr);
+                    access_token = returnObj["access_token"].ToString();
+                    DateTime nowDate;
+                    DateTime.TryParse(returnObj["nowDate"].ToString(), out nowDate);
+                    int expires_in;
+                    int.TryParse(returnObj["expires_in"].ToString(), out expires_in);
+                    DateTime endTime = nowDate.AddMilliseconds(expires_in);
+
+                    sqlUpdate = @"
+                    UPDATE TP_SYS_ZHONGTAI_TOKEN
+                       SET TOKEN   = @TOKEN@,
+                           ENDTIME = @ENDTIME@ ";
+                    returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                        new CDAParameter("TOKEN", access_token, DataType.NVarChar),
+                        new CDAParameter("ENDTIME", endTime, DataType.DateTime)
+                    );
+
+                    Curtain.Log.Logger.Info("凤塘_中台同步开始:" + dtSyncFinishProduct.Rows.Count + "\n" + jsonPara);
+                    returnJsonStr = PostToZhongTai(_urlPush, jsonPara, access_token);
+                    Curtain.Log.Logger.Info("凤塘_中台同步结束:\n" + returnJsonStr);
+                }
+
+                try
+                {
+                    returnObj = JsonConvert.DeserializeObject<JObject>(returnJsonStr);
+                    if (returnObj.ContainsKey("data"))
+                    {
+                        message = returnObj["data"] + "";
+                    }
+                    if (string.IsNullOrEmpty(message) && returnObj.ContainsKey("msg"))
+                    {
+                        message = returnObj["msg"] + "";
+                    }
+                    if (string.IsNullOrEmpty(message) && returnObj.ContainsKey("message"))
+                    {
+                        message = returnObj["message"] + "";
+                    }
+                }
+                catch (Exception ex)
+                {
+                    if (string.IsNullOrEmpty(returnJsonStr))
+                    {
+                        message = ex.Message;
+                    }
+                    else
+                    {
+                        message = returnJsonStr;
+                    }
+                }
+                #endregion
+
+                #region 结果处理
+                char tozhongtaiflag = message.Equals("条码保存成功") ? '1' : '0';
+                // 超时也当作成功
+                if (tozhongtaiflag.Equals('0') && message.Contains("超时"))
+                {
+                    tozhongtaiflag = '1';
+                }
+
+                // 更新推送结果
+                string barcodes = "('" + string.Join("','", dtSyncFinishProduct.AsEnumerable().Select(d => d.Field<string>("BARCODE")).ToArray()) + "')";
+                sqlUpdate = @"
+                UPDATE TP_PM_FINISHEDPRODUCT
+                   SET TOZHONGTAIFLAG = @TOZHONGTAIFLAG@,
+                       ZHONGTAIMSG   = @ZHONGTAIMSG@,
+                       TOZHONGTAITIME   = SYSDATE
+                 WHERE BARCODE IN " + barcodes;
+
+                returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                    new CDAParameter("TOZHONGTAIFLAG", tozhongtaiflag, DataType.Char),
+                    new CDAParameter("ZHONGTAIMSG", message, DataType.NVarChar)
+                );
+                #endregion
+            }
+            catch (Exception ex)
+            {
+                message = ex.Message;
+            }
+        }
+        return message;
+    }
+
+    /// <summary>
+    /// 同步产成品交接数据到恒洁中台_官塘厂
+    /// </summary>
+    /// <param name="syncDate">同步日期</param>
+    /// <param name="isPushTodayAllData">是否推送当天剩余所有数据</param>
+    /// <returns></returns>
+    public static string SyncFinishedProduct_cz3(DateTime syncDate, bool isPushTodayAllData)
+    {
+        int returnRows = 0;
+        string sql = string.Empty;
+        string sqlUpdate = string.Empty;
+        // 本次推送的数据
+        DataTable dtSyncFinishProduct = null;
+        // 返回json
+        JObject returnObj;
+        // 推送结果
+        string message = string.Empty;
+
+        using (IDataAccess connSS = DataAccess.CreateByString(DataBaseType.Oracle, _connStr_cz3))
+        {
+            try
+            {
+                #region 获取产成品交接数据
+                // 从gdd表上更新流水号和首次交接日期(预防有交接完又回产线的产品)
+                sqlUpdate = @"
+                UPDATE TP_PM_FINISHEDPRODUCT P
+                   SET (P.FIRSTFHDATE, P.FIRSTFHNO) =
+                       (SELECT GDD.FIRSTFHDATE,
+                               GDD.FIRSTFHNO
+                          FROM TP_PM_GROUTINGDAILYDETAIL GDD
+                         WHERE GDD.FIRSTFHNO IS NOT NULL
+                           AND GDD.BARCODE = P.BARCODE)
+                 WHERE P.FIRSTFHNO IS NULL
+                   AND P.FHTIME >= @DATEBEGIN@
+                   AND P.FHTIME < @DATEEND@ ";
+
+                returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+
+                // 获取当日最大流水号
+                sql = @"
+                SELECT NVL(MAX(FIRSTFHNO), 0) AS MAXFIRSTFHNO
+                  FROM TP_PM_FINISHEDPRODUCT FP
+                 WHERE FP.FHTIME >= @DATEBEGIN@
+                   AND FP.FHTIME < @DATEEND@ ";
+                object objMaxFirstFhNo = connSS.ExecuteScalar(sql,
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+                int maxFirstFhNo = 0;
+                int.TryParse(objMaxFirstFhNo + "", out maxFirstFhNo);
+
+                // 更新流水号和首次交接日期
+                sqlUpdate = @"
+                UPDATE TP_PM_FINISHEDPRODUCT P
+                   SET P.FIRSTFHDATE = @DATEBEGIN@,
+                       P.FIRSTFHNO =
+                       (SELECT T2.FIRSTFHNO
+                          FROM (SELECT T.BARCODE,
+                                       ROWNUM + @MAXFIRSTFHNO@ AS FIRSTFHNO
+                                  FROM (SELECT FP.BARCODE
+                                          FROM TP_PM_FINISHEDPRODUCT FP
+                                         WHERE FP.FIRSTFHNO IS NULL
+                                           AND FP.FHTIME >= @DATEBEGIN@
+                                           AND FP.FHTIME < @DATEEND@
+                                         ORDER BY FP.FHTIME,
+                                                  FP.BARCODE) T) T2
+                         WHERE T2.BARCODE = P.BARCODE)
+                 WHERE P.FIRSTFHNO IS NULL
+                   AND P.FHTIME >= @DATEBEGIN@
+                   AND P.FHTIME < @DATEEND@ ";
+
+                returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                    new CDAParameter("MAXFIRSTFHNO", maxFirstFhNo, DataType.Int32),
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+
+                // 将流水号和首次交接日期更新到gdd表上
+                sqlUpdate = @"
+                 UPDATE TP_PM_GROUTINGDAILYDETAIL GDD
+                    SET (GDD.FIRSTFHDATE, GDD.FIRSTFHNO) =
+                        (SELECT P.FIRSTFHDATE,
+                                P.FIRSTFHNO
+                           FROM TP_PM_FINISHEDPRODUCT P
+                          WHERE GDD.BARCODE = P.BARCODE
+                            AND P.FIRSTFHNO IS NOT NULL
+                            AND P.FHTIME >= @DATEBEGIN@
+                            AND P.FHTIME < @DATEEND@)
+                  WHERE GDD.FIRSTFHNO IS NULL
+                    AND EXISTS (SELECT 1
+                           FROM TP_PM_FINISHEDPRODUCT P
+                          WHERE GDD.BARCODE = P.BARCODE
+                            AND P.FIRSTFHNO IS NOT NULL
+                            AND P.FHTIME >= @DATEBEGIN@
+                            AND P.FHTIME < @DATEEND@) ";
+
+                returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+
+                // 是否推送当天剩余的所有数据
+                if (isPushTodayAllData)
+                {
+                    sql = @"
+                    SELECT GDD.OUTLABELCODE,
+                           GDD.MATERIALCODE,
+                           FP.FIRSTFHDATE,
+                           FP.FIRSTFHNO,
+                           FP.BARCODE
+                      FROM TP_PM_FINISHEDPRODUCT FP
+                     INNER JOIN TP_PM_GROUTINGDAILYDETAIL GDD
+                        ON GDD.GROUTINGDAILYDETAILID = FP.GROUTINGDAILYDETAILID
+                     WHERE FP.FIRSTFHNO IS NOT NULL
+                       AND FP.TOZHONGTAIFLAG = '0'
+                       AND FP.FHTIME >= @DATEBEGIN@
+                       AND FP.FHTIME < @DATEEND@
+                     ORDER BY FP.FHTIME,
+                              FP.BARCODE ";
+                }
+                else
+                {
+                    // 获取本次推送的数据(每次推送数据不超过100条)
+                    sql = @"
+                    SELECT T.*,
+                           ROWNUM
+                      FROM (SELECT GDD.OUTLABELCODE,
+                                   GDD.MATERIALCODE,
+                                   FP.FIRSTFHDATE,
+                                   FP.FIRSTFHNO,
+                                   FP.BARCODE
+                              FROM TP_PM_FINISHEDPRODUCT FP
+                             INNER JOIN TP_PM_GROUTINGDAILYDETAIL GDD
+                                ON GDD.GROUTINGDAILYDETAILID = FP.GROUTINGDAILYDETAILID
+                             WHERE FP.FIRSTFHNO IS NOT NULL
+                               AND FP.TOZHONGTAIFLAG = '0'
+                               AND FP.FHTIME >= @DATEBEGIN@
+                               AND FP.FHTIME < @DATEEND@
+                             ORDER BY FP.FIRSTFHNO) T
+                     WHERE ROWNUM <= 100 ";
+                }
+
+                dtSyncFinishProduct = connSS.ExecuteDatatable(sql,
+                    new CDAParameter("DATEBEGIN", syncDate, DataType.Date),
+                    new CDAParameter("DATEEND", syncDate.AddDays(1), DataType.Date)
+                );
+
+                if (dtSyncFinishProduct.Rows.Count == 0)
+                {
+                    return "本时段没有要推送的数据";
+                }
+                #endregion
+
+                #region  获取token
+                sql = @"
+                SELECT TOKEN
+                  FROM TP_SYS_ZHONGTAI_TOKEN
+                 WHERE ENDTIME > SYSDATE + 1 / 24 ";
+                string access_token = connSS.ExecuteScalar<string>(sql);
+
+                if (string.IsNullOrEmpty(access_token))
+                {
+                    string[] paras = new string[] { _grant_type, _client_id_cz, _client_secret_cz };
+                    string jsonStr = GetToken(_urlToken, paras);
+                    returnObj = JsonConvert.DeserializeObject<JObject>(jsonStr);
+                    access_token = returnObj["access_token"].ToString();
+                    DateTime nowDate;
+                    DateTime.TryParse(returnObj["nowDate"].ToString(), out nowDate);
+                    int expires_in;
+                    int.TryParse(returnObj["expires_in"].ToString(), out expires_in);
+                    DateTime endTime = nowDate.AddMilliseconds(expires_in);
+
+                    sqlUpdate = @"
+                    UPDATE TP_SYS_ZHONGTAI_TOKEN
+                       SET TOKEN   = @TOKEN@,
+                           ENDTIME = @ENDTIME@ ";
+                    returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                        new CDAParameter("TOKEN", access_token, DataType.NVarChar),
+                        new CDAParameter("ENDTIME", endTime, DataType.DateTime)
+                    );
+                }
+                #endregion
+
+                #region 向接口推送数据
+                DateTime firstfhdate;
+                string differDays36 = string.Empty;
+                int firstFhNo = 0;
+                JObject jObject = null;
+                string firstFhNo36 = string.Empty;
+                JArray jArray = new JArray();
+                foreach (DataRow row in dtSyncFinishProduct.Rows)
+                {
+                    // 当前日期与2022-01-01的时间间隔,转化为36进制数,0~9+A~Z,不满3位左边补0
+                    DateTime.TryParse(row["FIRSTFHDATE"].ToString(), out firstfhdate);
+                    differDays36 = Scale36.ToCurr36(firstfhdate.Subtract(_startDate).Days).PadLeft(3, '0');
+
+                    // 流水(4位,36进制数流水,0~9+A~Z)
+                    int.TryParse(row["FIRSTFHNO"] + "", out firstFhNo);
+                    firstFhNo36 = Scale36.ToCurr36(firstFhNo).PadLeft(4, '0');
+
+                    jObject = new JObject();
+                    jObject.Add(new JProperty("barcode", row["OUTLABELCODE"]));
+                    jObject.Add(new JProperty("productCode", row["MATERIALCODE"]));
+                    jObject.Add(new JProperty("newUniqueCode", "https://hap.hegii.com/jump?state=productInfo-" + row["OUTLABELCODE"]));
+                    jObject.Add(new JProperty("serviceCode", _gt_gcdm + differDays36 + firstFhNo36));
+                    jObject.Add(new JProperty("codeUuid", row["OUTLABELCODE"]));
+                    jArray.Add(jObject);
+                }
+
+                string jsonPara = JsonConvert.SerializeObject(jArray);
+
+                Curtain.Log.Logger.Info("官塘_中台同步开始:" + dtSyncFinishProduct.Rows.Count + "\n" + jsonPara);
+                string returnJsonStr = PostToZhongTai(_urlPush, jsonPara, access_token);
+                Curtain.Log.Logger.Info("官塘_中台同步结束:\n" + returnJsonStr);
+
+                // 如果token过期了,重新获取一遍,再推一次试试
+                if (returnJsonStr.Contains("未经授权"))
+                {
+                    string[] paras = new string[] { _grant_type, _client_id_ss, _client_secret_ss };
+                    string jsonStr = GetToken(_urlToken, paras);
+                    returnObj = JsonConvert.DeserializeObject<JObject>(jsonStr);
+                    access_token = returnObj["access_token"].ToString();
+                    DateTime nowDate;
+                    DateTime.TryParse(returnObj["nowDate"].ToString(), out nowDate);
+                    int expires_in;
+                    int.TryParse(returnObj["expires_in"].ToString(), out expires_in);
+                    DateTime endTime = nowDate.AddMilliseconds(expires_in);
+
+                    sqlUpdate = @"
+                    UPDATE TP_SYS_ZHONGTAI_TOKEN
+                       SET TOKEN   = @TOKEN@,
+                           ENDTIME = @ENDTIME@ ";
+                    returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                        new CDAParameter("TOKEN", access_token, DataType.NVarChar),
+                        new CDAParameter("ENDTIME", endTime, DataType.DateTime)
+                    );
+
+                    Curtain.Log.Logger.Info("官塘_中台同步开始:" + dtSyncFinishProduct.Rows.Count + "\n" + jsonPara);
+                    returnJsonStr = PostToZhongTai(_urlPush, jsonPara, access_token);
+                    Curtain.Log.Logger.Info("官塘_中台同步结束:\n" + returnJsonStr);
+                }
+
+                try
+                {
+                    returnObj = JsonConvert.DeserializeObject<JObject>(returnJsonStr);
+                    if (returnObj.ContainsKey("data"))
+                    {
+                        message = returnObj["data"] + "";
+                    }
+                    if (string.IsNullOrEmpty(message) && returnObj.ContainsKey("msg"))
+                    {
+                        message = returnObj["msg"] + "";
+                    }
+                    if (string.IsNullOrEmpty(message) && returnObj.ContainsKey("message"))
+                    {
+                        message = returnObj["message"] + "";
+                    }
+                }
+                catch (Exception ex)
+                {
+                    if (string.IsNullOrEmpty(returnJsonStr))
+                    {
+                        message = ex.Message;
+                    }
+                    else
+                    {
+                        message = returnJsonStr;
+                    }
+                }
+                #endregion
+
+                #region 结果处理
+                char tozhongtaiflag = message.Equals("条码保存成功") ? '1' : '0';
+                // 超时也当作成功
+                if (tozhongtaiflag.Equals('0') && message.Contains("超时"))
+                {
+                    tozhongtaiflag = '1';
+                }
+
+                // 更新推送结果
+                string barcodes = "('" + string.Join("','", dtSyncFinishProduct.AsEnumerable().Select(d => d.Field<string>("BARCODE")).ToArray()) + "')";
+                sqlUpdate = @"
+                UPDATE TP_PM_FINISHEDPRODUCT
+                   SET TOZHONGTAIFLAG = @TOZHONGTAIFLAG@,
+                       ZHONGTAIMSG   = @ZHONGTAIMSG@,
+                       TOZHONGTAITIME   = SYSDATE
+                 WHERE BARCODE IN " + barcodes;
+
+                returnRows += connSS.ExecuteNonQuery(sqlUpdate,
+                    new CDAParameter("TOZHONGTAIFLAG", tozhongtaiflag, DataType.Char),
+                    new CDAParameter("ZHONGTAIMSG", message, DataType.NVarChar)
+                );
+                #endregion
+            }
+            catch (Exception ex)
+            {
+                message = ex.Message;
+            }
+        }
+        return message;
+    }
+
+    /// <summary>
+    /// 获取token
+    /// </summary>
+    /// <param name="url"></param>
+    /// <param name="paras"></param>
+    /// <returns></returns>
+    private static string GetToken(string url, string[] paras)
+    {
+        try
+        {
+            string EndResult = "";
+            string SendMessageAddress = url;
+            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(SendMessageAddress);
+            request.Method = "POST";
+            request.AllowAutoRedirect = true;
+            request.ContentType = "application/x-www-form-urlencoded";
+            //string PostData = "grant_type=client_credentials&client_id=e86762528ada4cc3919346f107a7f7ec&client_secret=de3e8f5e762c4f948807498a513688c4";
+            string PostData = string.Format("grant_type={0}&client_id={1}&client_secret={2}", paras[0], paras[1], paras[2]);
+
+            byte[] byteArray = Encoding.Default.GetBytes(PostData);
+            request.ContentLength = byteArray.Length;
+            using (Stream newStream = request.GetRequestStream())
+            {
+                newStream.Write(byteArray, 0, byteArray.Length);//写入参数
+                newStream.Close();
+            }
+
+            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+            Stream rspStream = response.GetResponseStream();
+            using (StreamReader reader = new StreamReader(rspStream, Encoding.UTF8))
+            {
+                EndResult = reader.ReadToEnd();
+                rspStream.Close();
+            }
+            response.Close();
+            return EndResult;
+        }
+        catch (Exception ex)
+        {
+            return ex.Message;
+        }
+    }
+
+    /// <summary>
+    /// 推送数据
+    /// </summary>
+    /// <param name="url"></param>
+    /// <param name="data"></param>
+    /// <param name="token"></param>
+    /// <returns></returns>
+    private static string PostToZhongTai(string url, string data, string token)
+    {
+        try
+        {
+            //将单引号转义成双引号
+            data = data.Replace("'", "\"");
+            //创建Web访问对象
+            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
+
+            // 接口慢,设置30分钟超时等待
+            myRequest.Timeout = 1800000;
+
+            //把用户传过来的数据转成“UTF-8”的字节流
+            byte[] buf = System.Text.Encoding.GetEncoding("UTF-8").GetBytes(data);
+
+            myRequest.Method = "POST";
+            myRequest.ContentLength = buf.Length;
+            myRequest.ContentType = "application/json;charset=UTF-8";
+            //myRequest.MaximumAutomaticRedirections = 1;
+            myRequest.AllowAutoRedirect = true;
+            //string base64Header = Convert.ToBase64String(Encoding.UTF8.GetBytes(token));
+            myRequest.Headers.Add("Authorization", "Bearer " + token);
+
+            //发送请求
+            Stream stream = myRequest.GetRequestStream();
+            stream.Write(buf, 0, buf.Length);
+            stream.Close();
+
+            //获取接口返回值
+            //通过Web访问对象获取响应内容
+            HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
+            //通过响应内容流创建StreamReader对象,因为StreamReader更高级更快
+            StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
+            //string returnXml = HttpUtility.UrlDecode(reader.ReadToEnd());//如果有编码问题就用这个方法
+            string returnXml = reader.ReadToEnd();//利用StreamReader就可以从响应内容从头读到尾
+            reader.Close();
+            myResponse.Close();
+            return returnXml;
+        }
+        catch (Exception ex)
+        {
+            return ex.Message;
+        }
+    }
+    #endregion
+}

+ 118 - 0
wwwroot/Global.asax

@@ -0,0 +1,118 @@
+<%@ Application Language="C#" %>
+<%@ Import Namespace="Curtain.DataAccess" %>
+<%@ Import Namespace="Curtain.Log" %>
+<%@ Import Namespace="DK.XuWei.WebMes" %>
+
+<script RunAt="server">
+
+    // 定时器
+    System.Timers.Timer tr = null;
+
+    void Application_Start(object sender, EventArgs e)
+    {
+        // 在应用程序启动时运行的代码
+        string connStr = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
+        DataAccess.DefaultParameterType = SQLParameterType.CDA;
+        DataAccess.DefaultDataBaseType = Curtain.DataAccess.DataBaseType.Oracle;
+        DataAccess.DefaultConnectionString = connStr;
+
+        // 设置定时器
+        tr_Load();
+    }
+
+    /// <summary>
+    /// 设置定时器
+    /// </summary>
+    void tr_Load()
+    {
+        Logger.Debug("$$$定时器已启动$$$");
+
+        //设置timer
+        tr = new System.Timers.Timer(60000);
+        tr.Elapsed += new System.Timers.ElapsedEventHandler(tr_Timer);
+        tr.Enabled = true;
+        tr.AutoReset = true;
+    }
+
+    /// <summary>
+    /// 定时器要执行的任务
+    /// </summary>
+    /// <param name="sender"></param>
+    /// <param name="e"></param>
+    void tr_Timer(object sender, EventArgs e)
+    {
+        // 中台任务
+        zhongtai_task();
+    }
+
+    /// <summary>
+    /// 中台任务
+    /// </summary>
+    void zhongtai_task()
+    {
+        DateTime now = System.DateTime.Now;
+        string currTime = now.ToString("HH:mm");
+        //Logger.Debug("当前时间:" + currTime + ",分钟:" + now.Minute);
+
+        if (now.Minute == 5 || now.Minute == 15 || now.Minute == 25 || now.Minute == 35 || now.Minute == 45 || now.Minute == 55)
+        {
+            Logger.Debug("自动同步中台:定时触发开始");
+            string msg = SyncZhongTai.SyncFinishedProduct(now.Date, false);
+            Logger.Debug("自动同步中台:定时触发结束,结果:\n" + msg);
+        }
+
+        // 如果现在是00点10分,把昨天剩余的全都同步过去
+        if ("00:10".Equals(currTime))
+        {
+            Logger.Debug("自动同步中台_剩余条码:定时触发开始");
+            string msg = SyncZhongTai.SyncFinishedProduct(now.Date.AddDays(-1), true);
+            Logger.Debug("自动同步中台_剩余条码:定时触发结束,结果:\n" + msg);
+        }
+    }
+
+
+    void Application_End(object sender, EventArgs e)
+    {
+        //  在应用程序关闭时运行的代码
+        Logger.Debug("$$$定时器被关闭$$$");
+        if (tr != null)
+        {
+            tr.Dispose();
+        }
+
+        // 重新唤醒当前应用
+        ReworkHttp.Rework();
+    }
+
+    void Application_Error(object sender, EventArgs e)
+    {
+        // 在出现未处理的错误时运行的代码
+        Exception error = Server.GetLastError().GetBaseException();
+        if (error != null)
+        {
+            //记录日志
+            Logger.Error(error);
+            //输出错误信息
+            //2022-11-15 冯林勇 出现错误不弹出日志 
+            //HttpContext.Current.Response.Write(new JsonResult(JsonStatus.otherError).ToJson());
+            //2022-11-15 冯林勇 出现错误不弹出日志 
+        }
+        Server.ClearError();
+    }
+
+    void Session_Start(object sender, EventArgs e)
+    {
+        // 在新会话启动时运行的代码
+
+    }
+
+    void Session_End(object sender, EventArgs e)
+    {
+        // 在会话结束时运行的代码。 
+        // 注意: 只有在 Web.config 文件中的 sessionstate 模式设置为
+        // InProc 时,才会引发 Session_End 事件。如果会话模式设置为 StateServer
+        // 或 SQLServer,则不引发该事件。
+
+    }
+
+</script>

+ 59 - 0
wwwroot/Web.config

@@ -0,0 +1,59 @@
+<?xml version="1.0"?>
+<!--
+  有关如何配置 ASP.NET 应用程序的详细信息,请访问
+  https://go.microsoft.com/fwlink/?LinkId=169433
+-->
+<configuration>
+	<connectionStrings>
+		<!--三水服务器-->
+		<add name="ConnectionString" connectionString="Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.18.32.116)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=dkmes)));User Id=hgiboss;Password=dongke" providerName="Oracle.ManagedDataAccess.Client"/>
+		<!--<add name="ConnectionString" connectionString="Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.18.32.30)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=hgmestest)));User Id=hgiboss;Password=dk" providerName="Oracle.ManagedDataAccess.Client"/>-->
+	</connectionStrings>
+	<appSettings>
+		<!--MES服务器地址-->
+		<add key="MesServer" value="http://172.18.32.32:5678"/>
+
+	</appSettings>
+	<system.web>
+		<webServices>
+			<protocols>
+				<add name="HttpPost"/>
+				<add name="HttpGet"/>
+				<add name="HttpSoap"/>
+				<add name="Documentation"/>
+			</protocols>
+		</webServices>
+		<customErrors mode="Off"/>
+		<compilation targetFramework="4.0" debug="true"/>
+		<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID" validateRequest="false"/>
+		<httpRuntime/>
+		<!--<sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" cookieless="false" timeout="1440"/>-->
+	</system.web>
+	<system.data>
+		<DbProviderFactories>
+			<remove invariant="Oracle.ManagedDataAccess.Client"/>
+			<add name="ODP.NET, Managed Driver" invariant="Oracle.ManagedDataAccess.Client" description="Oracle Data Provider for .NET, Managed Driver" type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.122.19.1, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
+		</DbProviderFactories>
+	</system.data>
+	<system.webServer>
+		<security>
+			<requestFiltering>
+				<requestLimits maxAllowedContentLength="1048576000"/>
+			</requestFiltering>
+		</security>
+		<staticContent>
+			<mimeMap fileExtension=".log" mimeType="text/plain"/>
+			<!--<mimeMap fileExtension=".woff2" mimeType="image/svg+xml" />-->
+		</staticContent>
+		<defaultDocument>
+			<files>
+				<add value="index.ashx"/>
+			</files>
+		</defaultDocument>
+		<directoryBrowse enabled="true"/>
+	</system.webServer>
+	<system.serviceModel>
+		<bindings/>
+		<client/>
+	</system.serviceModel>
+</configuration>

+ 41 - 0
wwwroot/api/ZhongTai/testSyncZhongTai.ashx

@@ -0,0 +1,41 @@
+<%@ WebHandler Language="C#" Class="testSyncZhongTai" %>
+
+using System;
+using System.Web;
+using System.IO;
+using System.Text;
+using System.Data;
+using Curtain.DataAccess;
+using DK.XuWei.WebMes;
+using Newtonsoft.Json.Linq;
+using System.Web.SessionState;
+using Curtain.Extension.ExObjectConvert;
+
+/// <summary>
+/// apiid=31014
+/// SAP:物料bom同步接口
+/// </summary>
+public class testSyncZhongTai : IHttpHandler, IReadOnlySessionState
+{
+
+    public void ProcessRequest(HttpContext context)
+    {
+        context.Response.ContentType = "text/plain";
+        DateTime syncDate = new DateTime(2023, 3, 2);
+
+        context.Response.Write(DateTime.Now + ":调用开始\n");
+        string msg = SyncZhongTai.SyncFinishedProduct(syncDate, false);
+        context.Response.Write(DateTime.Now + ":调用结束\n");
+        context.Response.Write(new JsonResult() { success = true, status = JsonStatus.success, message = msg }.ToJson());
+    }
+
+
+    public bool IsReusable
+    {
+        get
+        {
+            return false;
+        }
+    }
+
+}