4 changed files with 266 additions and 2 deletions
@ -0,0 +1,168 @@ |
|||
using BBWY.Client.Extensions; |
|||
using BBWY.Client.Models; |
|||
using BBWY.Common.Http; |
|||
using BBWY.Common.Models; |
|||
using Newtonsoft.Json.Linq; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Net.Http; |
|||
using System.Text; |
|||
using System.Text.RegularExpressions; |
|||
|
|||
namespace BBWY.Client.APIServices |
|||
{ |
|||
public class PurchaseProductAPIService : IDenpendency |
|||
{ |
|||
private RestApiService restApiService; |
|||
private string oneBoundKey = "t5060712539"; |
|||
private string oneBoundSecret = "20211103"; |
|||
|
|||
private IDictionary<string, string> _1688ProductDetailRequestHeader; |
|||
|
|||
public PurchaseProductAPIService(RestApiService restApiService) |
|||
{ |
|||
this.restApiService = restApiService; |
|||
_1688ProductDetailRequestHeader = new Dictionary<string, string>() |
|||
{ |
|||
{ "Host","detail.1688.com"}, |
|||
{ "User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36 Edg/104.0.1293.70"}, |
|||
{ "Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"}, |
|||
{ "Accept-Encoding","gzip, deflate, br"}, |
|||
{ "Accept-Language","zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"} |
|||
}; |
|||
} |
|||
|
|||
public (Purchaser purchaser, IList<PurchaseSchemeProductSku> purchaseSchemeProductSkus)? GetProductInfo(Platform platform, string productId, string skuId, string purchaseProductId, PurchaseOrderMode priceMode, PurchaseProductAPIMode apiMode) |
|||
{ |
|||
(Purchaser purchaser, IList<PurchaseSchemeProductSku> purchaseSchemeProductSkus)? data = null; |
|||
if (apiMode == PurchaseProductAPIMode.Spider) |
|||
{ |
|||
data = LoadFromSpider(platform, productId, skuId, purchaseProductId, priceMode); |
|||
} |
|||
else if (apiMode == PurchaseProductAPIMode.OneBound) |
|||
{ |
|||
data = LoadFromOneBound(platform, productId, skuId, purchaseProductId, priceMode); |
|||
} |
|||
|
|||
return data; |
|||
} |
|||
|
|||
private (Purchaser purchaser, IList<PurchaseSchemeProductSku> purchaseSchemeProductSkus)? LoadFromOneBound(Platform platform, string productId, string skuId, string purchaseProductId, PurchaseOrderMode priceMode) |
|||
{ |
|||
try |
|||
{ |
|||
string platformStr = string.Empty; |
|||
if (platform == Platform.阿里巴巴) |
|||
platformStr = "1688"; |
|||
|
|||
if (string.IsNullOrEmpty(platformStr)) |
|||
return null; |
|||
|
|||
var result = restApiService.SendRequest("https://api-gw.onebound.cn/", $"{platformStr}/item_get", $"key={oneBoundKey}&secret={oneBoundSecret}&num_iid={purchaseProductId}&lang=zh-CN&cache=no&agent={(priceMode == PurchaseOrderMode.批发 ? 0 : 1)}", null, HttpMethod.Get, paramPosition: ParamPosition.Query, enableRandomTimeStamp: true); |
|||
if (result.StatusCode != System.Net.HttpStatusCode.OK) |
|||
throw new Exception($"{result.StatusCode} {result.Content}"); |
|||
|
|||
var j = JObject.Parse(result.Content); |
|||
var isOK = j.Value<string>("error_code") == "0000"; |
|||
if (isOK) |
|||
{ |
|||
var skuJArray = (JArray)j["item"]["skus"]["sku"]; |
|||
if (skuJArray.Count == 0) |
|||
{ |
|||
//errorMsg = $"商品{purchaseSchemeProduct.PurchaseProductId}缺少sku信息";
|
|||
return null; |
|||
} |
|||
|
|||
var list = skuJArray.Select(j => new PurchaseSchemeProductSku() |
|||
{ |
|||
ProductId = productId, |
|||
SkuId = skuId, |
|||
PurchaseProductId = purchaseProductId, |
|||
Price = j.Value<decimal>("price"), |
|||
PurchaseSkuId = j.Value<string>("sku_id"), |
|||
PurchaseSkuSpecId = j.Value<string>("spec_id"), |
|||
Title = j.Value<string>("properties_name"), |
|||
Logo = GetSkuLogo(j, (JArray)j["item"]["prop_imgs"]["prop_img"]) |
|||
}).ToList(); |
|||
|
|||
var purchaserId = j["item"]["seller_info"].Value<string>("user_num_id"); |
|||
var purchaserName = j["item"]["seller_info"].Value<string>("title"); |
|||
if (string.IsNullOrEmpty(purchaserName)) |
|||
purchaserName = j["item"]["seller_info"].Value<string>("shop_name"); |
|||
var purchaserLocation = j["item"].Value<string>("location"); |
|||
|
|||
return ( |
|||
new Purchaser() |
|||
{ |
|||
Id = purchaserId, |
|||
Name = purchaserName, |
|||
Location = purchaserLocation |
|||
}, |
|||
list); |
|||
} |
|||
} |
|||
catch { } |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
private string GetSkuLogo(JToken skuJToken, JArray prop_img) |
|||
{ |
|||
if (!prop_img.HasValues) |
|||
return "pack://application:,,,/Resources/Images/defaultItem.png"; |
|||
var properties = skuJToken.Value<string>("properties").Split(';', StringSplitOptions.RemoveEmptyEntries); |
|||
foreach (var p in properties) |
|||
{ |
|||
var imgJToken = prop_img.FirstOrDefault(g => g.Value<string>("properties") == p); |
|||
if (imgJToken != null) |
|||
return imgJToken.Value<string>("url"); |
|||
} |
|||
return "pack://application:,,,/Resources/Images/defaultItem.png"; |
|||
} |
|||
|
|||
private (Purchaser purchaser, IList<PurchaseSchemeProductSku> purchaseSchemeProductSkus)? LoadFromSpider(Platform platform, string productId, string skuId, string purchaseProductId, PurchaseOrderMode priceMode) |
|||
{ |
|||
switch (platform) |
|||
{ |
|||
case Platform.阿里巴巴: |
|||
LoadFrom1688Spider(platform, productId, skuId, purchaseProductId, priceMode); |
|||
break; |
|||
case Platform.拼多多: |
|||
|
|||
break; |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
private (Purchaser purchaser, IList<PurchaseSchemeProductSku> purchaseSchemeProductSkus)? LoadFrom1688Spider(Platform platform, string productId, string skuId, string purchaseProductId, PurchaseOrderMode priceMode) |
|||
{ |
|||
//https://detail.1688.com/offer/672221374773.html?clickid=65f3772cd5d16f190ce4991414607&sessionid=3de47a0c26dcbfde4692064bd55861&sk=order
|
|||
|
|||
//globalData/tempModel/sellerUserId
|
|||
//globalData/tempModel/companyName
|
|||
//data/1081181309101/data/location
|
|||
|
|||
|
|||
//data/1081181309582/data/pirceModel/[currentPrices]/[0]price
|
|||
var _1688pageResult = restApiService.SendRequest("https://detail.1688.com", |
|||
$"offer/{purchaseProductId}.html", |
|||
$"clickid={Guid.NewGuid().ToString().Md5Encrypt()}&sessionid={Guid.NewGuid().ToString().Md5Encrypt()}&sk={(priceMode == PurchaseOrderMode.批发 ? "order" : "consign")}", |
|||
_1688ProductDetailRequestHeader, |
|||
HttpMethod.Get); |
|||
|
|||
if (_1688pageResult.StatusCode != System.Net.HttpStatusCode.OK) |
|||
return null; |
|||
|
|||
var match = Regex.Match(_1688pageResult.Content, @"(window\.__INIT_DATA=)(.*)(\s?</script>)"); |
|||
if (!match.Success) |
|||
return null; |
|||
|
|||
var jsonStr = match.Groups[2].Value; |
|||
var j = JObject.Parse(jsonStr); |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,85 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Security.Cryptography; |
|||
using System.Text; |
|||
|
|||
namespace BBWY.Client.Extensions |
|||
{ |
|||
public static class EncryptionExtension |
|||
{ |
|||
|
|||
public static string Md5Encrypt(this string originStr) |
|||
{ |
|||
using (var md5 = MD5.Create()) |
|||
{ |
|||
return string.Join(string.Empty, md5.ComputeHash(Encoding.UTF8.GetBytes(originStr)).Select(x => x.ToString("x2"))); |
|||
} |
|||
} |
|||
|
|||
//AES加密 传入,要加密的串和, 解密key
|
|||
public static string AESEncrypt(this string input) |
|||
{ |
|||
var key = "dataplatform2019"; |
|||
var ivStr = "1012132405963708"; |
|||
|
|||
var encryptKey = Encoding.UTF8.GetBytes(key); |
|||
var iv = Encoding.UTF8.GetBytes(ivStr); //偏移量,最小为16
|
|||
using (var aesAlg = Aes.Create()) |
|||
{ |
|||
using (var encryptor = aesAlg.CreateEncryptor(encryptKey, iv)) |
|||
{ |
|||
using (var msEncrypt = new MemoryStream()) |
|||
{ |
|||
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, |
|||
CryptoStreamMode.Write)) |
|||
|
|||
using (var swEncrypt = new StreamWriter(csEncrypt)) |
|||
{ |
|||
swEncrypt.Write(input); |
|||
} |
|||
var decryptedContent = msEncrypt.ToArray(); |
|||
|
|||
return Convert.ToBase64String(decryptedContent); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
public static string AESDecrypt(this string cipherText) |
|||
{ |
|||
var fullCipher = Convert.FromBase64String(cipherText); |
|||
|
|||
var ivStr = "1012132405963708"; |
|||
var key = "dataplatform2019"; |
|||
|
|||
var iv = Encoding.UTF8.GetBytes(ivStr); |
|||
var decryptKey = Encoding.UTF8.GetBytes(key); |
|||
|
|||
using (var aesAlg = Aes.Create()) |
|||
{ |
|||
using (var decryptor = aesAlg.CreateDecryptor(decryptKey, iv)) |
|||
{ |
|||
string result; |
|||
using (var msDecrypt = new MemoryStream(fullCipher)) |
|||
{ |
|||
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) |
|||
{ |
|||
using (var srDecrypt = new StreamReader(csDecrypt)) |
|||
{ |
|||
result = srDecrypt.ReadToEnd(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public static string Base64Encrypt(this string originStr) |
|||
{ |
|||
return Convert.ToBase64String(Encoding.UTF8.GetBytes(originStr)); |
|||
} |
|||
} |
|||
} |
Loading…
Reference in new issue