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#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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; }
}
}