You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

700 lines
29 KiB
C#

2 months ago
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<OrderModel> GetOrders(out string errorMessage)
{
var orderModels=new List<OrderModel>();
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<TikTokOrderModel> GetTikTokOrder(string next_page_token,out string nPageToken, out string errorMessage)
{
var rmodel = new List<TikTokOrderModel>();
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&timestamp=" + 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<TikTokReturnModel>(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<TikTokReturnModel>(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<TikTokReturnModel>(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 080000
return timestamp - 28800;//返回当前日期0点的时间戳 例如2023-12-06 000000
}
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<OrderDetailModel>();
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<TikTokRefershTokenReturnModel>(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<TikTokRefershTokenReturnModel>(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<TikTokRefershTokenReturnModel>(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<TikTokRefershTokenReturnModel>(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<TikTokOrderModel> 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<TikTok_Order_LineItems> line_items { get; set; }
public string need_upload_invoice { get; set; }
public List<Packages> 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<TikTok_Order_LineItems_ItemTax> 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<TikTok_Order_Recipient_Address_District_Info> 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; }
}
}