123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- using Dfs.WayneChina.CardTrxManager;
- using Dfs.WayneChina.CardTrxManager.TrxSubmitter;
- using Newtonsoft.Json;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net.Http;
- using System.Net.Http.Headers;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace Dfs.WayneChina.IPosPlus.ServiceClient
- {
- public class DiscountServiceClient
- {
- #region Fields
- private string grantType = "password";
- private string authScheme = "bearer";
- private string authServicePath = "token";
- private HttpClient httpClient = new HttpClient();
- private AuthToken currentAuthToken;
- private CloudCredential cloudCredential;
- private string promotionCategories = string.Empty;
- // Make periodic check to make sure the token is valid.
- private System.Timers.Timer timer;
- private IPosPlusApp posApp;
- private int count = 0;
- private int discountTimeout = 3;
- #endregion
- #region Logger
- private NLog.Logger logger = NLog.LogManager.LoadConfiguration("NLog.config").GetLogger("IPosPlusApp");
- #endregion
- #region Constructor
- public DiscountServiceClient(IPosPlusApp posApp, CloudCredential cloudCredential, string promoCats, int discountTimeout)
- {
- this.posApp = posApp;
- this.cloudCredential = cloudCredential;
- promotionCategories = promoCats;
- this.discountTimeout = discountTimeout;
- timer = new System.Timers.Timer();
- timer.Interval = 30000;
- timer.Elapsed += Timer_Elapsed;
- timer.Enabled = true;
- }
- private async void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
- {
- InfoLog("Checking token validity");
- if (currentAuthToken == null)
- {
- await GetToken();
- }
- else if (currentAuthToken != null && currentAuthToken.IsTokenValid())
- {
- InfoLog("We already have a valid token");
- }
- else
- {
- await GetToken();
- }
- }
- #endregion
- #region Public Methods
- public async Task<DiscountResponse> CalculatDiscount(DiscountRequest discountRequest)
- {
- var cancellationTokenSource = new CancellationTokenSource();
- cancellationTokenSource.CancelAfter(discountTimeout*1000);
- if (currentAuthToken != null && currentAuthToken.IsTokenValid())
- {
- //httpClient.DefaultRequestHeaders.Clear();
- httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authScheme, currentAuthToken.AccessToken);
- if (!httpClient.DefaultRequestHeaders.Contains("CurrentBuId"))
- httpClient.DefaultRequestHeaders.Add("CurrentBuId", currentAuthToken.BusinessUnitList.First().Id.ToString());
- if (!httpClient.DefaultRequestHeaders.Contains("ProxyType"))
- httpClient.DefaultRequestHeaders.Add("ProxyType", "Discount");
- string discountUrl = string.Concat(cloudCredential.DiscountServiceBaseUrl, "api/marketing/", "pos/discount/conformRules");
- var posTrxRequest = new PromotionRequest()
- {
- AccountId = "",
- OwnerId = currentAuthToken.BusinessUnitList.First().Id, //Guid.Parse(cloudCredential.CurrentBuId),
- Id = new Guid(),
- Amount = 0,
- Created = discountRequest.TimeStamp,
- AccountIcCardNo = discountRequest.CardNo,
- Items = new List<PromotionRequestItem>()
- {
- new PromotionRequestItem()
- {
- Id = new Guid(),
- // so this item should be applied
- Barcode = discountRequest.Barcode,
- Category= promotionCategories,
- LineItemId = Guid.NewGuid(),
- Name = posApp?.GetFuelName(Convert.ToInt32(discountRequest.Barcode)),//"油品",
- Price = discountRequest.UnitPrice,
- Quantity = Math.Round(discountRequest.Volume * 1.00m, 2),
- Amount = Math.Round(discountRequest.FillingAmount * 1.00m, 2)
- },
- },
- Payments = new List<Payment>()
- {
- new Payment()
- {
- Name = "IC",
- Value = Math.Round(discountRequest.FillingAmount * 1.00m, 2)//discountRequest.FillingAmount
- }
- },
- CouponUidList = new List<string>(),
- DiscountUidList = new List<string>()
- };
- var requestLog = JsonConvert.SerializeObject(posTrxRequest);
- InfoLog("Posting request: " + requestLog);
- CancellationTokenSource cts = new CancellationTokenSource();
- try
- {
- var discountResponse = await httpClient
- .PostAsJsonAsync(discountUrl, posTrxRequest, cancellationTokenSource.Token)
- .ConfigureAwait(false);
- if (discountResponse.IsSuccessStatusCode)
- {
- var response = await discountResponse.Content.ReadAsStringAsync();
- InfoLog("Received success response: " + response);
- var result = JsonConvert.DeserializeObject<DiscountForTrx>(response);
- if (result == null || result != null && result.data == null)
- {
- InfoLog("Oops, the reiceved response body is empty!");
- return new DiscountResponse { PayAmount = discountRequest.FillingAmount };
- }
- if (result != null && result.data != null && result.data.discounts != null)
- {
- InfoLog($"Data: {result.data}, Amount after discount: {result.data.discounts.amountAfterDiscount}");
- }
- decimal payAmount = 0M;
- if (result != null && result.data != null && result.data.discounts != null && result.data.discounts.amountAfterDiscount != 0)
- {
- InfoLog("Could get a discount");
- payAmount = Convert.ToDecimal(result.data.discounts.amountAfterDiscount);
- }
- return new DiscountResponse
- {
- PayAmount = payAmount == 0 ? discountRequest.FillingAmount : payAmount
- };
- }
- else
- {
- var response = await discountResponse.Content.ReadAsStringAsync();
- InfoLog("Received failed response: " + response);
- }
- }
- catch (TaskCanceledException tcEx)
- {
- InfoLog($"Exception: {tcEx}");
- }
- catch (Exception ex)
- {
- InfoLog(ex.ToString());
- }
- return null;
- }
- else
- {
- if (count > 3)
- {
- count = 0;
- return null;
- }
- else
- {
- await GetToken();
- InfoLog("Should have a valid token now, re-calculate discount...");
- return await CalculatDiscount(discountRequest);
- }
- }
- }
- #endregion
- #region Private Methods
- private async Task<AuthToken> GetTokenAsync(string userName, string password, string baseUrl)
- {
- var cancellationTokenSource = new CancellationTokenSource();
- cancellationTokenSource.CancelAfter(7000);
- InfoLog("start to get token");
- currentAuthToken = null;
- httpClient.DefaultRequestHeaders.Clear();
- string tokenUrl = string.Concat(baseUrl, authServicePath);
- var formParam = new AuthenticationParameter(grantType, userName, password);
- try
- {
- var response = await httpClient
- .PostAsync(tokenUrl, new FormUrlEncodedContent(formParam.Params), cancellationTokenSource.Token)
- .ConfigureAwait(false);
- InfoLog($"GetToken, StatusCode: {response.StatusCode}");
- if (response.IsSuccessStatusCode)
- {
- await response.Content.ReadAsStringAsync().ContinueWith(x =>
- {
- currentAuthToken = JsonConvert.DeserializeObject<AuthToken>(x?.Result);
- currentAuthToken.TokenRetrievedTime = DateTime.Now;
- if (!string.IsNullOrEmpty(currentAuthToken.BusinessUnitsJsonString))
- {
- currentAuthToken.BusinessUnitList =
- JsonConvert.DeserializeObject<IList<BusinessUnit>>(currentAuthToken.BusinessUnitsJsonString);
- }
- });
- }
- else
- {
- var content = await response.Content.ReadAsStringAsync();
- response.Content?.Dispose();
- }
- return currentAuthToken;
- }
- catch (AggregateException aggregateException)
- {
- foreach (var exception in aggregateException.InnerExceptions)
- {
- InfoLog(exception.ToString());
- }
- }
- catch (Exception ex)
- {
- InfoLog("Exception in getting token: " + ex.ToString());
- }
- return null;
- }
- private async Task GetToken()
- {
- count++;
- InfoLog($"count: {count}, username: {cloudCredential.UserName}, password: {cloudCredential}, url: {cloudCredential.AuthServiceBaseUrl}");
- currentAuthToken = await GetTokenAsync(cloudCredential.UserName, cloudCredential.Password, cloudCredential.AuthServiceBaseUrl);
- }
- private void InfoLog(string log)
- {
- logger.Info("\t" + "Discount service client, " + log);
- }
- #endregion
- }
- }
|