using NetLibrary.Express; using NetLibrary.Log; using NetLibrary.OnlineTrade; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Web; using System.Web.Script.Serialization; using static TradeManageNew.Temu; using TradeManage; using System.Security.Policy; namespace TradeManageNew { public class TikTok { public string IP = "http://50.196.110.198:8099"; //美国跳转服务器ip地址 //public string IP = "http://localhost:5114"; //美国跳转服务器ip地址 public string ShopName { get; set; } public string AccessToken { get; set; } public string AppKey { get; set; } public string AppSecret { get; set; } public string Shop_Cipher { get; set; } public string RefershToken { get; set; } JavaScriptSerializer JsonConvert = null; public TikTok() { JsonConvert = new JavaScriptSerializer(); } public List GetOrders(out string errorMessage) { var orderModels=new List(); try { if(string.IsNullOrEmpty(AccessToken) || string.IsNullOrEmpty(AppKey) || string.IsNullOrEmpty(AppSecret)) { errorMessage = "店铺未授权"; return null; } var isNextPage = true; var nPageToken = ""; while(isNextPage) { var orders = GetTikTokOrder(nPageToken, out nPageToken, out errorMessage); if(!string.IsNullOrEmpty(errorMessage)) throw new Exception(errorMessage); if (string.IsNullOrEmpty(nPageToken)) isNextPage = false; if (orders != null) { foreach (var order in orders) { //未支付,取消状态的订单 if (order.status == "UNPAID" || order.status== "CANCELLED") continue; var rmodel = ToOrderModel(order); if (rmodel != null) orderModels.Add(rmodel); } } } errorMessage = ""; } catch(Exception ex) { errorMessage = ex.Message; } return orderModels; } public List GetTikTokOrder(string next_page_token,out string nPageToken, out string errorMessage) { var rmodel = new List(); try { var path = "/order/202309/orders/search"; long timestamp = (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; var signStr = "app_key" + AppKey + "page_size100" + "page_token" + next_page_token + "shop_cipher" + Shop_Cipher + "sort_fieldcreate_time" + "sort_orderASC" + "timestamp" + timestamp + "version202309"; signStr = path + signStr; var create_time_ge = GetCreateTimeStamp(DateTime.Now.AddDays(-5).Date); var create_time_lt = GetCreateTimeStamp(DateTime.Now.AddDays(1).Date); var body = new { create_time_ge = create_time_ge, create_time_lt = create_time_lt, }; var bodyStr = JsonConvert.Serialize(body); signStr += bodyStr; signStr = AppSecret + signStr + AppSecret; var sign = GetHamcSha256(AppSecret, signStr); var tkurl = "https://open-api.tiktokglobalshop.com/order/202309/orders/search?access_token=" + AccessToken + "&app_key=" + AppKey + "&page_size=100&sign=" + sign + "&shop_cipher=" + Shop_Cipher + "&sort_field=create_time&sort_order=ASC&version=202309×tamp=" + timestamp + "&page_token=" + next_page_token; //using (HttpClient client = new HttpClient()) //{ // HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url); // request.Content = new StringContent(bodyStr, Encoding.UTF8, "application/json"); // request.Headers.Add("x-tts-access-token", AccessToken); // var response = client.SendAsync(request); // if (response.Result.IsSuccessStatusCode) // { // string responseContent = response.Result.Content.ReadAsStringAsync().GetAwaiter().GetResult(); // var rObj = JsonConvert.Deserialize(responseContent); // errorMessage = ""; // if(rObj!=null && rObj.data != null) // { // nPageToken = rObj.data.next_page_token; // rmodel = rObj.data.orders; // errorMessage = ""; // } // else // { // nPageToken = ""; // rmodel = null; // errorMessage = "同步TikTok订单出错"; // } // } // else // { // nPageToken = ""; // rmodel = null; // errorMessage = "同步TikTok订单出错"; // } //} //using (WebClient client = new WebClient()) //{ // client.Encoding = Encoding.UTF8; // 指定下载内容编码方式为 UTF-8 // client.Headers.Add("x-tts-access-token", AccessToken); // client.Headers[HttpRequestHeader.ContentType] = "application/json"; // byte[] bodyBytes = Encoding.UTF8.GetBytes(bodyStr); // byte[] responseData = client.UploadData(url, "POST", bodyBytes); // string responseContent = Encoding.UTF8.GetString(responseData); // var rObj = JsonConvert.Deserialize(responseContent); // errorMessage = ""; // if (rObj != null && rObj.data != null) // { // nPageToken = rObj.data.next_page_token; // rmodel = rObj.data.orders; // errorMessage = ""; // } // else // { // nPageToken = ""; // rmodel = null; // errorMessage = "同步TikTok订单出错"; // } //} ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; var url = IP + "/api/TikTokHelp/getTikTokShopOrderList?bodyStr=" + bodyStr + "&url=" + HttpUtility.UrlEncode(tkurl) + "&accessToken=" + AccessToken; using (WebClient client = new WebClient()) { client.Encoding = Encoding.UTF8; // 指定下载内容编码方式为 UTF-8 string responseContent = client.DownloadString(url); ErrorFollow.TraceWrite("自动导入Tiktok订单返回结果", "店铺名称:" + ShopName, responseContent); if (string.IsNullOrEmpty(responseContent) || responseContent == "Fail") { nPageToken = ""; rmodel = null; errorMessage = "同步TikTok订单出错"; } else { var rObj = JsonConvert.Deserialize(responseContent); errorMessage = ""; if (rObj != null && rObj.data != null) { nPageToken = rObj.data.next_page_token; rmodel = rObj.data.orders; errorMessage = ""; } else { nPageToken = ""; rmodel = null; errorMessage = "同步TikTok订单出错"; } } } } catch(Exception ex) { nPageToken = ""; errorMessage= ex.Message; rmodel = null; } return rmodel; } public long GetCreateTimeStamp(DateTime dt) { long timestamp = (long)(dt.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; //得到的是当前日期上午八点的时间戳 例如2023-12-06 08:00:00 return timestamp - 28800;//返回当前日期0点的时间戳 例如2023-12-06 00:00:00 } public DateTime GetDateTimeFromTimeStamp(long st) { //return DateTimeOffset.FromUnixTimeSeconds(st).DateTime; DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); long lTime = long.Parse(st + "0000000"); TimeSpan toNow = new TimeSpan(lTime); return dtStart.Add(toNow); } public string GetHamcSha256(string key, string value) { HMACSHA256 hmac = new HMACSHA256(); hmac.Key = Encoding.UTF8.GetBytes(key); byte[] hashValue = hmac.ComputeHash(Encoding.UTF8.GetBytes(value)); return BitConverter.ToString(hashValue).Replace("-", "").ToLower(); } #region 转换成统一的订单对象 public OrderModel ToOrderModel(TikTokOrderModel md) { try { OrderModel model = new OrderModel(); if(md.id== "576662364844036518" || md.id== "576616931652768610") { } model.PlatOrderCode = md.id.ToString(); model.OrderCode = md.id.ToString(); #region 原计算单价方式,佣金=单价的2% //var totalRevenue = md.payment.original_total_product_price - md.payment.seller_discount + (md.payment.product_tax.HasValue ? md.payment.product_tax.Value : 0m); //var totalFees = Math.Round((totalRevenue.Value * 0.02m) + 0.3m + (md.payment.product_tax.HasValue ? md.payment.product_tax.Value : 0m), 2); //model.TotalPrice = totalRevenue - totalFees; #endregion //订单销售价格=订单原价-优惠的折扣价格 var sellerPrice = (md.payment.original_total_product_price.HasValue ? md.payment.original_total_product_price.Value : 0) - (md.payment.seller_discount.HasValue ? md.payment.seller_discount.Value : 0); //佣金=订单销售价格*0.06 ERP最终价格=订单销售价格-佣金 model.TotalPrice = Math.Round(sellerPrice - (sellerPrice * 0.06m), 2); model.MoneyCode = md.payment.currency; model.OrderDate = GetDateTimeFromTimeStamp(md.create_time.Value); model.OrderState = 1; //if (md.cancel_order_sla_time != null) //{ // model.OrderState = 3; // model.OrderRemark = md.cancel_reason; //} if (md.recipient_address != null && md.recipient_address.name != null) model.BuyerName = md.recipient_address.name; if (md.recipient_address != null && md.recipient_address.region_code != null) model.BuyerCountry = md.recipient_address.region_code; //if (md.recipient_address != null && md.recipient_address.full_address != null) // model.BuyerAddr = md.recipient_address.full_address; //else if(md.recipient_address != null && md.recipient_address.district_info != null) //{ // var addr = ""; // foreach(var ad in md.recipient_address.district_info) // { // addr += ad.address_name + " "; // } // var detail = ""; // if (!string.IsNullOrEmpty(md.recipient_address.address_detail)) // detail = md.recipient_address.address_detail; // else if(!string.IsNullOrEmpty(md.recipient_address.address_line1)) // detail= md.recipient_address.address_line1; // else if (!string.IsNullOrEmpty(md.recipient_address.address_line2)) // detail = md.recipient_address.address_line2; // else if (!string.IsNullOrEmpty(md.recipient_address.address_line3)) // detail = md.recipient_address.address_line3; // else if (!string.IsNullOrEmpty(md.recipient_address.address_line4)) // detail = md.recipient_address.address_line4; // model.BuyerAddr = addr + detail; //} if(md.recipient_address != null && md.recipient_address.district_info != null) { var addr = ""; foreach (var ad in md.recipient_address.district_info) //地址太长,面单无法显示完整,去掉国家 { if (ad.address_level_name == "Country" || ad.address_level_name == "State" || ad.address_level_name == "County") continue; addr += ad.address_name + " "; } var detail = ""; if (!string.IsNullOrEmpty(md.recipient_address.address_detail)) detail = md.recipient_address.address_detail; else if (!string.IsNullOrEmpty(md.recipient_address.address_line1)) detail = md.recipient_address.address_line1; else if (!string.IsNullOrEmpty(md.recipient_address.address_line2)) detail = md.recipient_address.address_line2; else if (!string.IsNullOrEmpty(md.recipient_address.address_line3)) detail = md.recipient_address.address_line3; else if (!string.IsNullOrEmpty(md.recipient_address.address_line4)) detail = md.recipient_address.address_line4; model.BuyerAddr = addr + detail; if (!string.IsNullOrEmpty(model.BuyerAddr)) model.BuyerAddr = model.BuyerAddr.Replace("United States", ""); } else if(md.recipient_address != null && md.recipient_address.full_address != null) { model.BuyerAddr = md.recipient_address.full_address.Replace("United States,", ""); } if (md.recipient_address != null && md.recipient_address.phone_number != null) model.BuyerPhone = md.recipient_address.phone_number; model.BuyerMail = md.buyer_email; model.BuyerFax = ""; if (md.recipient_address != null && md.recipient_address.postal_code != null) model.BuyerZip = md.recipient_address.postal_code; if(md.recipient_address!=null && md.recipient_address.district_info != null) { //model.BuyerProvince = md.recipient_address.district_info.Where(r => r.address_level_name == "State").FirstOrDefault()?.address_name; var province = md.recipient_address.district_info.Where(r => r.address_level_name == "State").FirstOrDefault(); if (province != null) { var provinceCode = DataNew.GetProvinceCode(province.address_name); model.BuyerProvince = string.IsNullOrEmpty(provinceCode) ? province.address_name : provinceCode; } else model.BuyerProvince = ""; model.BuyerCity = md.recipient_address.district_info.Where(r => r.address_level_name == "City").FirstOrDefault()?.address_name; } model.BuyerArea = ""; model.OrderRemark = ""; model.LeaveWord = md.buyer_message; if (md.paid_time != null) model.PayDate = GetDateTimeFromTimeStamp(md.paid_time.Value); else model.PayDate = model.OrderDate; model.OutOrderDate = DateTime.Now.AddDays(7); if (model.OrderDate != null && model.OrderDate.Value <= Convert.ToDateTime("1753-01-01")) { model.OrderDate = DateTime.Now; } if (model.PayDate != null && model.PayDate.Value <= Convert.ToDateTime("1753-01-01")) { model.PayDate = DateTime.Now; } if (model.OutOrderDate != null && model.OutOrderDate.Value <= Convert.ToDateTime("1753-01-01")) { model.OutOrderDate = DateTime.Now.AddDays(7); } if (md.line_items != null && md.line_items.Count > 0) model.PostInfo = md.line_items[0].shipping_provider_name; model.ListModel = new List(); if (md.line_items != null) { foreach (var item2 in md.line_items) { OrderDetailModel model2 = new OrderDetailModel(); model2.TypeDesc = item2.is_gift ? "备注:gift_card" : ""; model2.OrderItemId = item2.product_id; model2.GoodsNum = 1; model2.GoodsName = item2.product_name; model2.GoodsSKU = item2.seller_sku; model2.PostInfo = item2.shipping_provider_name; model.ListModel.Add(model2); } } return model; } catch (Exception ex) { ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message); return null; } } #endregion public bool RefershAccessToken(out string accessToken,out string refreshToken ) { try { var url = "https://auth.tiktok-shops.com/api/v2/token/refresh?app_key=" + AppKey + "&app_secret=" + AppSecret + "&refresh_token=" + RefershToken + "&grant_type=refresh_token"; //using (var client = new HttpClient()) //{ // // 发送 GET 请求并返回响应结果 // var response = client.GetAsync(url).Result; // var result = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); // Console.WriteLine(result); // var rmodel = JsonConvert.Deserialize(result); // if(rmodel.code==0 && rmodel.data != null) // { // accessToken = rmodel.data.access_token; // refreshToken = rmodel.data.refresh_token; // return true; // } // else // { // accessToken = null; // refreshToken=null; // return false; // } //} //using (WebClient client = new WebClient()) //{ // var result = client.DownloadString(url); // var rmodel = JsonConvert.Deserialize(result); // if (rmodel.code == 0 && rmodel.data != null) // { // accessToken = rmodel.data.access_token; // refreshToken = rmodel.data.refresh_token; // return true; // } // else // { // accessToken = null; // refreshToken = null; // return false; // } //} ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; var tkurl = IP + "/api/TikTokHelp/getTikTokShopRefresh?url=" + HttpUtility.UrlEncode(url); using (WebClient client = new WebClient()) { client.Encoding = Encoding.UTF8; // 指定下载内容编码方式为 UTF-8 string responseContent = client.DownloadString(url); //var rmodel = JsonConvert.Deserialize(result); //if (rmodel.code == 0 && rmodel.data != null) //{ // accessToken = rmodel.data.access_token; // refreshToken = rmodel.data.refresh_token; // return true; //} //else //{ // accessToken = null; // refreshToken = null; // return false; //} ErrorFollow.TraceWrite("自动刷新Tiktok Token返回结果", "店铺名称:" + ShopName, responseContent); if (string.IsNullOrEmpty(responseContent) || responseContent == "Fail") { accessToken = null; refreshToken = null; return false; } else { var rmodel = JsonConvert.Deserialize(responseContent); if (rmodel.code == 0 && rmodel.data != null) { accessToken = rmodel.data.access_token; refreshToken = rmodel.data.refresh_token; return true; } else { accessToken = null; refreshToken = null; return false; } } } } catch (Exception ex) { accessToken = null; refreshToken = null; return false; } } } public class TikTokReturnModel { public int code { get; set; } public string message { get; set; } public string request_id { get; set; } public ResultModel data { get; set; } } public class ResultModel { public string next_page_token { get; set; } public int total_count { get; set; } public List orders { get; set; } } public class TikTokOrderModel { public string buyer_email { get; set; } public string buyer_message { get; set; } public long? cancel_order_sla_time { get; set; } public string cancel_reason { get; set; } public string cancellation_initiator { get; set; } public string cpf { get; set; } public long? create_time { get; set; } public string delivery_option_id { get; set; } public string delivery_option_name { get; set; } public long? delivery_sla_time { get; set; } public string fulfillment_type { get; set; } public bool has_updated_recipient_address { get; set; } public string id { get; set; } public bool is_cod { get; set; } public string is_sample_order { get; set; } public List line_items { get; set; } public string need_upload_invoice { get; set; } public List packages { get; set; } public long? paid_time { get; set; } public TikTok_Order_Payment payment { get; set; } public string payment_method_name { get; set; } public TikTok_Order_Recipient_Address recipient_address { get; set; } public long? rts_sla_time { get; set; } public long? rts_time { get; set; } public string seller_note { get; set; } public string shipping_provider { get; set; } public string shipping_provider_id { get; set; } public string shipping_type { get; set; } public string split_or_combine_tag { get; set; } public string status { get; set; } public string tracking_number { get; set; } public long? tts_sla_time { get; set; } public long? update_time { get; set; } public string user_id { get; set; } public string warehouse_id { get; set; } } public class TikTok_Order_LineItems { public string cancel_reason { get; set; } public string cancel_user { get; set; } public string currency { get; set; } public string display_status { get; set; } public string id { get; set; } public bool is_gift { get; set; } public List item_tax { get; set; } public decimal? original_price { get; set; } public string package_id { get; set; } public string package_status { get; set; } public string platform_discount { get; set; } public string product_id { get; set; } public string product_name { get; set; } public long rts_time { get; set; } public decimal? sale_price { get; set; } public decimal? seller_discount { get; set; } public string seller_sku { get; set; } public string shipping_provider_id { get; set; } public string shipping_provider_name { get; set; } public string sku_id { get; set; } public string sku_image { get; set; } public string sku_type { get; set; } public decimal small_order_fee { get; set; } public string tracking_number { get; set; } } public class TikTok_Order_LineItems_ItemTax { public decimal? tax_amount { get; set; } public string tax_type { get; set; } } public class Packages { public string id { get; set; } } public class TikTok_Order_Payment { public string currency { get; set; } public decimal? original_shipping_fee { get; set; } public decimal? original_total_product_price { get; set; } public decimal? platform_discount { get; set; } public decimal? product_tax { get; set; } public decimal? seller_discount { get; set; } public decimal? shipping_fee { get; set; } public decimal? shipping_fee_platform_discount { get; set; } public decimal? shipping_fee_seller_discount { get; set; } public decimal? shipping_fee_tax { get; set; } public decimal? small_order_fee { get; set; } public decimal? sub_total { get; set; } public decimal? tax { get; set; } public decimal? total_amount { get; set; } } public class TikTok_Order_Recipient_Address { public string address_detail { get; set; } public string address_line1 { get; set; } public string address_line2 { get; set; } public string address_line3 { get; set; } public string address_line4 { get; set; } public List district_info { get; set; } public string full_address { get; set; } public string name { get; set; } public string phone_number { get; set; } public string postal_code { get; set; } public string region_code { get; set; } } public class TikTok_Order_Recipient_Address_District_Info { public string address_level_name { get; set; } public string address_name { get; set; } } public class TikTokRefershTokenReturnModel { public int code { get; set; } public string message { get; set; } public string request_id { get; set; } public TikTok_RefreshTokenModel data { get; set; } } public class TikTok_RefreshTokenModel { public string access_token { get; set; } public long access_token_expire_in { get; set; } public string refresh_token { get; set; } public long refresh_token_expire_in { get; set; } public string open_id { get; set; } public string seller_name { get; set; } public string seller_base_region { get; set; } public int user_type { get; set; } } }