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.

366 lines
14 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 System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using POSV.Utils;
namespace POSV.Dianping
{
public class MeituanCouponUtils
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private static object _lock = new object();
private static HttpClient httpClient = null;
private static MeituanCouponUtils _instance = null;
private static string baseUrl = "https://open-api.dianping.com";
private static string version = "2.0";
public static string TEST_APPKEY = "7e75fa08b18f5fcd867e1d1cd58e38ea72fb33c1";
public static string TEST_APPSECRET = "34d4da25d45b4f812ab99a7ab608b50e7d3bbf10";
public static MeituanCouponUtils Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
//remove limits from service point manager
ServicePointManager.MaxServicePoints = 10000;
ServicePointManager.DefaultConnectionLimit = 10000;
ServicePointManager.CheckCertificateRevocationList = true;
ServicePointManager.Expect100Continue = false;
ServicePointManager.MaxServicePointIdleTime = 1000 * 30;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
ServicePointManager.UseNagleAlgorithm = false;
ServicePointManager.DnsRefreshTimeout = 0;
//提升系统外联的最大并发web访问数
ServicePointManager.DefaultConnectionLimit = 1024;
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3
// | SecurityProtocolType.Tls
// | (SecurityProtocolType)0x300 //Tls11
// | (SecurityProtocolType)0xC00; //Tls12
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
// | (SecurityProtocolType)0x300 //Tls11
// | (SecurityProtocolType)0xC00; //Tls12
var handler = new HttpClientHandler();
if (handler.SupportsAutomaticDecompression)
{
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
}
handler.Proxy = null;
handler.UseProxy = false;
handler.UseDefaultCredentials = false;
httpClient = new HttpClient(handler);
Interlocked.CompareExchange(ref httpClient, new HttpClient(handler) { BaseAddress = new Uri(baseUrl) }, null);
httpClient.DefaultRequestHeaders.Connection.Add("Keep-Alive");
httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36");
httpClient.DefaultRequestHeaders.Add("Accept", "*/*");
httpClient.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate"); //声明给服务器客户端支持gzip解压
httpClient.DefaultRequestHeaders.Add("Accept-Language", "zh-cn,en-us;q=0.7,en;q=0.3");
httpClient.DefaultRequestHeaders.Add("Pragma", "no-cache");
httpClient.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
httpClient.DefaultRequestHeaders.Add("ES-API-VERSION", "1.0.0");
httpClient.DefaultRequestHeaders.ExpectContinue = false;
httpClient.Timeout = new TimeSpan(0, 0, 20);
_instance = new MeituanCouponUtils();
}
}
return _instance;
}
}
public string PostAsync(string requestUrl, SortedList<string, object> parameters)
{
Stopwatch watch = Stopwatch.StartNew();
try
{
string appKey = Global.StoreInfo.StoreInfoMessage.MeituanAppKey;
string appSecret = Global.StoreInfo.StoreInfoMessage.MeituanAppSecret;
if (!string.IsNullOrEmpty(appKey))
{
appKey = appKey.Trim();
}
if (!string.IsNullOrEmpty(appSecret))
{
appSecret = appSecret.Trim();
}
var stringParams = JsonUtils.Serialize(parameters);
var content = new StringContent(stringParams, Encoding.UTF8, "application/json");
string timestamp = this.GetTimestamp();
StringBuilder sb = new StringBuilder();
sb.Append(baseUrl).Append(requestUrl);
sb.Append("?");
sb.Append("appKey").Append("=").Append(appKey).Append("&");
sb.Append("ts").Append("=").Append(timestamp).Append("&");
sb.Append("version").Append("=").Append(version).Append("&");
var sign = this.Sign(appKey, appSecret, timestamp, version, parameters);
sb.Append("sign").Append("=").Append(sign);
string url = sb.ToString();
var task = httpClient.PostAsync(url, content);
task.Result.EnsureSuccessStatusCode();
HttpResponseMessage response = task.Result;
var result = response.Content.ReadAsStringAsync();
return result.Result;
}
catch (Exception ex)
{
string message = "调用PostAsync方法发生错误,XP系统不支持";
logger.Error(ex, message);
throw new Exception(message);
}
finally
{
logger.Info("耗时<{0}>毫秒", watch.ElapsedMilliseconds);
}
}
public Tuple<bool, string, TuangouOrderConsumeResponse> OrderConsume(TuangouOrderConsumeRequest request)
{
Tuple<bool, string, TuangouOrderConsumeResponse> result = null;
try
{
var parameters = new SortedList<string, object>();
parameters.Add("vendorOrderId", request.VendorOrderId);
parameters.Add("totalAmount", request.TotalAmount);
parameters.Add("orderSkus", request.OrderSkus);
parameters.Add("couponCode", request.CouponCode);
parameters.Add("vendorShopId", request.VendorShopId);
parameters.Add("eId", request.EId);
parameters.Add("eName", request.EName);
string response = Instance.PostAsync("/tuangou/coupon/orderConsume", parameters);
var data = JsonUtils.Deserialize<BasicResponseModel<TuangouOrderConsumeResponse>>(response);
if (data.Code == 200)
{
result = new Tuple<bool, string, TuangouOrderConsumeResponse>(true, data.Message, data.Content);
}
else
{
result = new Tuple<bool, string, TuangouOrderConsumeResponse>(false, string.Format("{0}<{1}>", data.Message, data.Code), null);
}
}
catch (Exception ex)
{
logger.Error(ex, "券码核销异常");
result = new Tuple<bool, string, TuangouOrderConsumeResponse>(false, "券码核销异常,本次操作无效", null);
}
return result;
}
public Tuple<bool, string, CouponCancelResponse> OrdeCancel(CouponCancelRequest request)
{
Tuple<bool, string, CouponCancelResponse> result = null;
try
{
var parameters = new SortedList<string, object>();
parameters.Add("couponCode", request.CouponCode);
parameters.Add("vendorShopId", request.VendorShopId);
parameters.Add("eId", request.EId);
parameters.Add("eName", request.EName);
string response = Instance.PostAsync("/tuangou/coupon/cancel", parameters);
var data = JsonUtils.Deserialize<BasicResponseModel<CouponCancelResponse>>(response);
if (data.Code == 200)
{
result = new Tuple<bool, string, CouponCancelResponse>(true, data.Message, data.Content);
}
else
{
result = new Tuple<bool, string, CouponCancelResponse>(false, string.Format("{0}<{1}>", data.Message, data.Code), null);
}
}
catch (Exception ex)
{
logger.Error(ex, "撤销验券异常");
result = new Tuple<bool, string, CouponCancelResponse>(false, "撤销验券异常,本次操作无效", null);
}
return result;
}
/// <summary>
/// 券状态查询,通过该接口可获取到团购券的基本信息。
/// </summary>
/// <param name="appKey"></param>
/// <param name="appSecret"></param>
/// <param name="request"></param>
/// <returns></returns>
public Tuple<bool, string, CouponStatusQueryResponse> CouponQuery(CouponStatusQueryRequest request)
{
Tuple<bool, string, CouponStatusQueryResponse> result = null;
try
{
var parameters = new SortedList<string, object>();
parameters.Add("couponCode", request.CouponCode);
parameters.Add("vendorShopId", request.VendorShopId);
string response = Instance.PostAsync("/tuangou/coupon/status/query", parameters);
var data = JsonUtils.Deserialize<BasicResponseModel<CouponStatusQueryResponse>>(response);
if(data.Code == 200)
{
result = new Tuple<bool, string, CouponStatusQueryResponse>(true, data.Message, data.Content);
}
else
{
result = new Tuple<bool, string, CouponStatusQueryResponse>(false, string.Format("{0}<{1}>",data.Message,data.Code), null);
}
}
catch (Exception ex)
{
logger.Error(ex, "查询券状态异常");
result = new Tuple<bool, string, CouponStatusQueryResponse>(false, "查询券状态异常,本次操作无效", null);
}
return result;
}
public Tuple<bool, string, CouponLocalRecordResponse> QueryLocalListByDate(CouponLocalRecordRequest request)
{
Tuple<bool, string, CouponLocalRecordResponse> result = null;
try
{
var parameters = new SortedList<string, object>();
parameters.Add("vendorShopId", request.VendorShopId);
parameters.Add("date", request.Date);
parameters.Add("offset", request.Offset);
parameters.Add("limit", request.Limit);
if(request.VendorOrderId != null && request.VendorOrderId.Count() > 0)
{
parameters.Add("vendorOrderId", request.VendorOrderId);
}
string response = Instance.PostAsync("/tuangou/coupon/queryLocalListByDate", parameters);
var data = JsonUtils.Deserialize<BasicResponseModel<CouponLocalRecordResponse>>(response);
if (data.Code == 200)
{
result = new Tuple<bool, string, CouponLocalRecordResponse>(true, data.Message, data.Content);
}
else
{
result = new Tuple<bool, string, CouponLocalRecordResponse>(false, string.Format("{0}<{1}>", data.Message, data.Code), null);
}
}
catch (Exception ex)
{
logger.Error(ex, "查询门店验券历史异常");
result = new Tuple<bool, string, CouponLocalRecordResponse>(false, "查询门店验券历史异常,本次操作无效", null);
}
return result;
}
/// <summary>
/// 获取当前时间戳兼容Java服务端
/// </summary>
/// <returns></returns>
public string GetTimestamp()
{
TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1, 0, 0, 0).Ticks);
return Convert.ToString((long)ts.TotalMilliseconds);
}
public string Sign(string appKey, string appSecret,string ts,string version, SortedList<string, object> param)
{
StringBuilder sb = new StringBuilder();
sb.Append(appSecret);
sb.Append("appKey").Append(appKey);
sb.Append("ts").Append(ts);
sb.Append("version").Append(version);
if(param == null)
{
param = new SortedList<string, object>();
}
sb.Append(JsonUtils.Serialize(param));
logger.Info("签名字符串:{0}", sb.ToString());
SHA1 sha1 = new SHA1CryptoServiceProvider();//建立一个SHA1
byte[] source = Encoding.UTF8.GetBytes(sb.ToString());//将字符串转为Byte[]
byte[] crypto = sha1.ComputeHash(source);//进行SHA1加密
return ByteArrayToHexString(crypto);//把加密后的字符串从Byte[]转为字符串
}
/// <summary>
/// 字节数组转十六进制字符串
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public string ByteArrayToHexString(byte[] data)
{
StringBuilder sb = new StringBuilder(data.Length * 3);
foreach (byte b in data)
{
sb.Append(Convert.ToString(b, 16).PadLeft(2, '0'));
}
return sb.ToString().ToLower();
}
}
}