12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085 |
- using Edge.Core.Processor;using Edge.Core.IndustryStandardInterface.Pump;
- using Dfs.WayneChina.CardTrxManager.Support;
- using Dfs.WayneChina.HengshanFPos.FPosDbManager;
- using Dfs.WayneChina.PosModelMini;
- using Dfs.WayneChina.SpsDbModels.Models;
- 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.CardTrxManager.TrxSubmitter
- {
- public class TrxCreationResponse
- {
- public Guid Id { get; set; }
- }
- public class ClientTrxInfo
- {
- public int Barcode { get; set; }
- public int PumpId { get; set; }
- public int NozzleId { get; set; }
- public int SiteNozzleNo { get; set; }
- public ushort FPosSqNo { get; set; }
- public int FdcSqNo { get; set; }
- public DateTime TimeStamp { get; set; }
- public decimal Volume { get; set; }
- public decimal Amount { get; set; }
- public decimal PayAmount { get; set; }
- public decimal UnitPrice { get; set; }
- public int SeqNo { get; set; }
- public string CardNo { get; set; }
- public decimal CurrentCardBalance { get; set; }
- public DateTime FuelingStartTime { get; set; }
- public DateTime FuelingFinishedTime { get; set; }
- public decimal VolumeTotalizer { get; set; }
- public string CardHolder { get; set; }
- public string AccountName { get; set; }
- }
- public class ReceiptReceivedEventArgs : EventArgs
- {
- public int NozzleNo { get; set; }
- public string ReceiptData { get; set; }
- }
- public class TrxSubmitter
- {
- #region Properties
- public string User { get; }
- public string Password { get; }
- public string AuthServiceBaseUrl { get; }
- public string TransactionServiceBaseUrl { get; }
- public string DeviceSN { get; }
- public string BusinessUnitId { get; set; }
- #endregion
- #region Fields
- public int Id { get; }
- private string grantType = "password";
- private string tokenAuthPath = "token";
- private string authScheme = "bearer";
- private HttpClient _client = new HttpClient();
- private AuthToken _authToken;
- public Dictionary<(int, int), int> SiteNozzles { get; set; }
- private FPosDbManager fPosDbManager;
- private ushort currentFPosSqNo;
- private int currentFdcSqNo;
- AuthToken currentAuthToken = null;
- private int retryCount = 0;
- private TransactionManager transactionManager;
- private StoreFowardTransaction storeForwardTransaction;
- private bool persistCurrentTransaction;
- #endregion
- #region Event handlers
- public event EventHandler<ReceiptReceivedEventArgs> OnReceiptReceived;
- #endregion
- #region Logger
- NLog.Logger logger = NLog.LogManager.LoadConfiguration("NLog.config").GetLogger("PosTrxSubmitter");
- #endregion
- #region Constructor
- public TrxSubmitter(int id, FPosDbManager fPosDbManager, CloudCredential cloudCredential)
- {
- Id = id;
- this.fPosDbManager = fPosDbManager;
- User = cloudCredential.UserName;
- Password = cloudCredential.Password;
- AuthServiceBaseUrl = cloudCredential.AuthServiceBaseUrl;
- TransactionServiceBaseUrl = cloudCredential.TransactionServiceBaseUrl;
- DeviceSN = cloudCredential.DeviceSN;
- BusinessUnitId = cloudCredential.CurrentBuId;
- transactionManager = new TransactionManager();
- transactionManager.Init();
- }
- public TrxSubmitter(int id, CloudCredential cloudCredential)
- {
- Id = id;
- User = cloudCredential.UserName;
- Password = cloudCredential.Password;
- AuthServiceBaseUrl = cloudCredential.AuthServiceBaseUrl;
- TransactionServiceBaseUrl = cloudCredential.TransactionServiceBaseUrl;
- DeviceSN = cloudCredential.DeviceSN;
- BusinessUnitId = cloudCredential.CurrentBuId;
- transactionManager = new TransactionManager();
- transactionManager.Init();
- }
- #endregion
- #region Async version of the methods
- public async Task<bool> SubmitTrxAsync(StoreFowardTransaction sfTrans)
- {
- storeForwardTransaction = sfTrans;
- var fuelingDoneItem =
- (FuelingDoneItem)storeForwardTransaction.TransactionItems.FirstOrDefault(t => t is FuelingDoneItem);
-
- if (fuelingDoneItem != null)
- {
- var clientTrx = CreateFuelingTransactionFromFuelingDoneItem(fuelingDoneItem);
- return await SubmitTrxAsync(clientTrx, false);
- }
- else
- {
- return false;
- }
- }
- public async Task<bool> SubmitTrxAsync(ClientTrxInfo clientTrx, bool persist = true)
- {
- InfoLog("");
- InfoLog($"Start to sumbit trx, retry count: {retryCount}, persist: {persist}");
- persistCurrentTransaction = persist;
- if(storeForwardTransaction == null)
- {
- if (persist)
- {
- InfoLog("No sf transaction, create one!");
- storeForwardTransaction = new StoreFowardTransaction();
- storeForwardTransaction.TransactionItems.Add(CreateFuelingDoneItemFromFuelingTransaction(clientTrx));
- }
- }
- else
- {
- if (storeForwardTransaction.FuelingId != clientTrx.SeqNo)
- {
- InfoLog("Last try unsuccessful");
- storeForwardTransaction = new StoreFowardTransaction();
- storeForwardTransaction.TransactionItems.Add(CreateFuelingDoneItemFromFuelingTransaction(clientTrx));
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- currentAuthToken = await GetTokenAsync(User, Password, AuthServiceBaseUrl);
- if (currentAuthToken != null)
- {
- InfoLog($"Got valid token");
- string productItemUrl = string.Concat(TransactionServiceBaseUrl, "api/products/itemId/");
-
- var posItem = await GetPosItemAsync(productItemUrl, Convert.ToString(clientTrx.Barcode), currentAuthToken);
- if (posItem != null)
- {
- InfoLog($"Got PosItem, id: {posItem.Id}");
- var trxId = await CreateTransactionAsync(posItem, clientTrx);
- if (trxId != Guid.Empty)
- {
- InfoLog($"Got TrxId: {trxId}");
- var success = await CommitTransactionAsync(trxId, clientTrx);
- if (success)
- retryCount = 0;
- return success;
- }
- }
- else
- {
- InfoLog("Could not retrieve POS Item info!");
- }
- }
- if (persistCurrentTransaction)
- {
- storeForwardTransaction = new StoreFowardTransaction();
- storeForwardTransaction.TransactionItems.Add(CreateFuelingDoneItemFromFuelingTransaction(clientTrx));
- transactionManager.SaveTransaction(storeForwardTransaction);
- storeForwardTransaction = null;
- InfoLog($"Persisting current transaction info, for pump: {clientTrx.PumpId}, amount: {clientTrx.Amount}");
- }
- return false;
-
-
-
-
-
-
- }
- private FuelingDoneItem CreateFuelingDoneItemFromFuelingTransaction(ClientTrxInfo clientTrx)
- {
- FuelingDoneItem item = new FuelingDoneItem();
- item.Barcode = clientTrx.Barcode;
- item.PumpId = clientTrx.PumpId;
- item.NozzleId = clientTrx.NozzleId;
- item.SiteNozzleNo = clientTrx.SiteNozzleNo;
- item.FPosSqNo = clientTrx.FPosSqNo;
- item.FdcSqNo = clientTrx.FdcSqNo;
- item.TimeStamp = clientTrx.TimeStamp;
- item.Volume = clientTrx.Volume;
- item.Amount = clientTrx.Amount;
- item.PayAmount = clientTrx.PayAmount;
- item.UnitPrice = clientTrx.UnitPrice;
- item.SeqNo = clientTrx.SeqNo;
- item.CardNo = clientTrx.CardNo;
- item.CurrentCardBalance = clientTrx.CurrentCardBalance;
- item.FuelingStartTime = clientTrx.FuelingStartTime;
- item.FuelingFinishedTime = clientTrx.FuelingFinishedTime;
- item.VolumeTotalizer = clientTrx.VolumeTotalizer;
- item.CardHolder = clientTrx.CardHolder;
- item.AccountName = clientTrx.AccountName;
- return item;
- }
- private ClientTrxInfo CreateFuelingTransactionFromFuelingDoneItem(FuelingDoneItem item)
- {
- ClientTrxInfo clientTrxInfo = new ClientTrxInfo();
- clientTrxInfo.Barcode = item.Barcode;
- clientTrxInfo.PumpId = item.PumpId;
- clientTrxInfo.NozzleId = item.NozzleId;
- clientTrxInfo.SiteNozzleNo = item.SiteNozzleNo;
- clientTrxInfo.FPosSqNo = item.FPosSqNo;
- clientTrxInfo.FdcSqNo = item.FdcSqNo;
- clientTrxInfo.TimeStamp = item.TimeStamp;
- clientTrxInfo.Volume = item.Volume;
- clientTrxInfo.Amount = item.Amount;
- clientTrxInfo.PayAmount = item.PayAmount;
- clientTrxInfo.UnitPrice = item.UnitPrice;
- clientTrxInfo.SeqNo = item.SeqNo;
- clientTrxInfo.CardNo = item.CardNo;
- clientTrxInfo.CurrentCardBalance = item.CurrentCardBalance;
- clientTrxInfo.FuelingStartTime = item.FuelingStartTime;
- clientTrxInfo.FuelingFinishedTime = item.FuelingFinishedTime;
- clientTrxInfo.VolumeTotalizer = item.VolumeTotalizer;
- clientTrxInfo.CardHolder = item.CardHolder;
- clientTrxInfo.AccountName = item.AccountName;
- return clientTrxInfo;
- }
- private async Task<AuthToken> GetTokenAsync(string userName, string password, string baseUrl)
- {
- InfoLog("GetTokenAsync...");
- _client.DefaultRequestHeaders.Clear();
- string tokenUrl = string.Concat(baseUrl, tokenAuthPath);
- var formParam = new AuthenticationParameter(grantType, userName, password);
- CancellationTokenSource cts = new CancellationTokenSource();
- cts.CancelAfter(5000);
- HttpResponseMessage response;
- try
- {
- response = await _client
- .PostAsync(tokenUrl, new FormUrlEncodedContent(formParam.Params), cts.Token)
- .ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- ErrorLog("Exception in retrieving auth token: " + ex.ToString());
- response = null;
- currentAuthToken = null;
- return null;
- }
- InfoLog($"Response for getting token, Response==null? {response == null}");
- if (response != null && response.IsSuccessStatusCode)
- {
- await response.Content.ReadAsStringAsync().ContinueWith(x =>
- {
- currentAuthToken = JsonConvert.DeserializeObject<AuthToken>(x?.Result);
- if (!string.IsNullOrEmpty(currentAuthToken.BusinessUnitsJsonString))
- {
- currentAuthToken.BusinessUnitList = JsonConvert.DeserializeObject<IList<BusinessUnit>>(currentAuthToken.BusinessUnitsJsonString);
- }
- });
- }
- else
- {
- var content = await response.Content.ReadAsStringAsync();
- if (response != null)
- response.Content?.Dispose();
- currentAuthToken = null;
- }
- return currentAuthToken;
- }
- private async Task<PosItem> GetPosItemAsync(string url, string itemId, AuthToken token)
- {
- InfoLog("GetPosItemAsync...");
- if (storeForwardTransaction != null)
- {
- var productCodeIdentifiedItem =
- (ProductCodeIdentitiedItem)storeForwardTransaction.TransactionItems.FirstOrDefault(t => t is ProductCodeIdentitiedItem);
- if (productCodeIdentifiedItem != null)
- {
- InfoLog($"ProductCode already identified, id: {productCodeIdentifiedItem.ItemId}");
- return new PosItem { Id = productCodeIdentifiedItem.ItemId };
- }
- }
- if (storeForwardTransaction == null && !persistCurrentTransaction)
- {
- InfoLog("In the middle of retrying, but somehow the sf trans is gone, abort");
- return null;
- }
- PosItem posItem = null;
- _client.DefaultRequestHeaders.Clear();
- _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authScheme, token.AccessToken);
- InfoLog($"{_client.DefaultRequestHeaders.Authorization.Scheme}, {_client.DefaultRequestHeaders.Authorization.Parameter}");
- BusinessUnitId = currentAuthToken.BusinessUnitList.Count > 0 ? currentAuthToken.BusinessUnitList.First().Id.ToString() : string.Empty;
-
-
- _client.DefaultRequestHeaders.Add("DeviceSN", DeviceSN);
- _client.DefaultRequestHeaders.Add("CurrentBuId", BusinessUnitId);
-
- InfoLog($"DeviceSN: {DeviceSN}");
- InfoLog($"BuId: {BusinessUnitId}");
- var productUrl = string.Concat(url, itemId);
- InfoLog($"Itme url: {productUrl}");
- HttpResponseMessage response;
- try
- {
- response = await _client.GetAsync(productUrl).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- ErrorLog("Exception in retrieving pos item info: " + ex.ToString());
- if (persistCurrentTransaction)
- {
- ErrorLog("Exception occurred during get item, save transaction!");
- transactionManager.SaveTransaction(storeForwardTransaction);
- }
- response = null;
- return null;
- }
- InfoLog($"GetItem, StatusCode: {response.StatusCode}");
- if (response.IsSuccessStatusCode)
- {
- await response.Content.ReadAsStringAsync().ContinueWith(x =>
- {
- posItem = JsonConvert.DeserializeObject<PosItem>(x?.Result);
- if (storeForwardTransaction == null)
- ErrorLog("SF trans is null");
- if (!storeForwardTransaction.TransactionItems.Any(t => t is ProductCodeIdentitiedItem))
- {
- InfoLog("No existing ProductCodeIdentifiedItem");
- storeForwardTransaction.TransactionItems.Add(new ProductCodeIdentitiedItem { ItemId = posItem.Id });
- }
- else
- {
- InfoLog("ProductCodeIdentifiedItem already exists!");
- }
- });
- }
- else
- {
- var content = await response.Content.ReadAsStringAsync();
- response.Content?.Dispose();
- if (persistCurrentTransaction)
- {
- ErrorLog("Failure occurred during get item, save it!");
- transactionManager.SaveTransaction(storeForwardTransaction);
- }
- }
- return posItem;
- }
- private async Task<Guid> CreateTransactionAsync(PosItem posItem, ClientTrxInfo clientTrxInfo)
- {
- InfoLog($"CreateTransactionAsync, pump: {clientTrxInfo.PumpId}, amount: {clientTrxInfo.Amount}");
- InfoLog($"Volume totalizer: {clientTrxInfo.VolumeTotalizer}");
- if (storeForwardTransaction != null)
- {
- var transCreatedItem =
- (TransactionCreatedItem)storeForwardTransaction.TransactionItems.FirstOrDefault(t => t is TransactionCreatedItem);
- if (transCreatedItem != null)
- {
- InfoLog($"Transaction already rung up, id: {transCreatedItem.TransactionId}");
- return transCreatedItem.TransactionId;
- }
- }
- Guid trxId = Guid.Empty;
- var trxUrl = string.Concat(TransactionServiceBaseUrl, "api/transactions");
- var clientPosTrx = new ClientPosTrx
- {
- RequestingCreationTimeInPosClient = DateTime.Now,
- Type = PosTrxType.Sale,
- Source = PosTrxSource.Outdoor,
- Items = new List<ClientRingUpPosItem>
- {
- new ClientRingUpPosItem
- {
- PosItemUniqueId = posItem.Id,
- Qty = clientTrxInfo.Volume,
- ClientRingUpTime = DateTime.Now,
- FuelItemSoldOnPumpId = clientTrxInfo.PumpId,
- FuelItemSoldOnPumpNozzleId = clientTrxInfo.SiteNozzleNo,
- FuelItemOriginalGrossAmount = clientTrxInfo.Amount,
- FuelItemFdcTransactionSeqNo = Convert.ToString(clientTrxInfo.SeqNo),
- fuelItemTransactionEndTime = clientTrxInfo.FuelingFinishedTime,
- TransactionComment = "IC Trx",
- FuelItemPumpTotalizerVolume = clientTrxInfo.VolumeTotalizer
- }
- }
- };
- _client.DefaultRequestHeaders.Clear();
- _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authScheme, currentAuthToken.AccessToken);
- _client.DefaultRequestHeaders.Add("DeviceSN", DeviceSN);
- _client.DefaultRequestHeaders.Add("CurrentBuId", BusinessUnitId);
- HttpResponseMessage response;
- try
- {
- response = await _client.PostAsJsonAsync(trxUrl, clientPosTrx).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- ErrorLog("Exception in creating transaction: " + ex.ToString());
- ErrorLog("Exception occurred during creat transaction, save it!");
- transactionManager.SaveTransaction(storeForwardTransaction);
- response = null;
- return Guid.Empty;
- }
- InfoLog($"CreateTransaction, StatusCode: {response.StatusCode}");
- if (response.IsSuccessStatusCode)
- {
- await response.Content.ReadAsStringAsync().ContinueWith(x =>
- {
- var trxCreationResponse = JsonConvert.DeserializeObject<TrxCreationResponse>(x.Result);
- trxId = trxCreationResponse.Id;
- if (!storeForwardTransaction.TransactionItems.Any(t => t is TransactionCreatedItem))
- {
- InfoLog("No existing TransactionCreatedItem");
- storeForwardTransaction.TransactionItems.Add(new TransactionCreatedItem { TransactionId = trxId });
- }
- else
- {
- InfoLog("TransactionCreatedItem already exists!");
- }
- });
- }
- else
- {
- var content = await response.Content.ReadAsStringAsync();
- response.Content?.Dispose();
- if (persistCurrentTransaction)
- {
- ErrorLog("Failure during Create Transaction, save it!");
- transactionManager.SaveTransaction(storeForwardTransaction);
- }
- }
- return trxId;
- }
- private async Task<bool> CommitTransactionAsync(Guid trxId, ClientTrxInfo clientTrxInfo)
- {
- bool submitted = false;
- var payUrlTemplate = string.Concat(TransactionServiceBaseUrl, "api/transactions/{0}/payment");
- string realPayUrl = string.Format(payUrlTemplate, trxId);
-
- string version = "1.0";
- var icPayDetail = new
- {
- CardNo = clientTrxInfo.CardNo,
- PayAmount = clientTrxInfo.PayAmount,
- CardHolder = clientTrxInfo.CardHolder,
- AccountName = clientTrxInfo.AccountName,
- CardBalance = clientTrxInfo.CurrentCardBalance,
- Version = version
- };
- PosTrxMop posTrxMop = new PosTrxMop();
- posTrxMop.Paid = clientTrxInfo.PayAmount;
- posTrxMop.ICCardNumber = clientTrxInfo.CardNo;
- posTrxMop.RawResult = JsonConvert.SerializeObject(icPayDetail);
- posTrxMop.PosMopId = Guid.Parse("ff64ab36-658d-40a4-94bf-bee7231ac788");
- posTrxMop.Mop = new PosMop
- {
- Id = Guid.Parse("ff64ab36-658d-40a4-94bf-bee7231ac788"),
- Name = "IC",
- PaymentId = 4,
- CreatedDateTime = DateTime.Now,
- ChangesetId = Guid.Parse("84f02b52-6950-4c50-a0b1-9827d6459edc"),
- TargetBusinessUnitId = Guid.Parse("6c40e7f6-2b2d-40de-8c5c-f5693a05ab0d"),
- DisplayName = "IC卡"
- };
- _client.DefaultRequestHeaders.Clear();
- _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authScheme, currentAuthToken.AccessToken);
- _client.DefaultRequestHeaders.Add("DeviceSN", DeviceSN);
- _client.DefaultRequestHeaders.Add("CurrentBuId", BusinessUnitId);
- HttpResponseMessage response;
- try
- {
- response = await _client.PostAsJsonAsync(realPayUrl, posTrxMop).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- ErrorLog("Exception in committing transaction: " + ex.ToString());
- ErrorLog("Exception occurred during commit, save transaction!");
- transactionManager.SaveTransaction(storeForwardTransaction);
- response = null;
- return false;
- }
- InfoLog($"Commit, StatusCode: {response.StatusCode}");
- if (response.StatusCode == System.Net.HttpStatusCode.Conflict)
- InfoLog("Status code: Conflict, treat it as success");
- if (response.IsSuccessStatusCode || response.StatusCode == System.Net.HttpStatusCode.Conflict)
- {
- submitted = true;
-
- if (storeForwardTransaction != null)
- storeForwardTransaction.TransactionItems.Add(new CommittedItem { Success = true });
-
- InfoLog("Since submit is successful, discard the sf trans");
- storeForwardTransaction = null;
- }
- else
- {
- if (persistCurrentTransaction)
- {
- ErrorLog("Failure during commit, save transaction!");
- transactionManager.SaveTransaction(storeForwardTransaction);
- }
- }
- return submitted;
- }
- #endregion
- #region Public methods
- public bool SubmitTrx(TTrdinfo trdInfo, int fdcTrxSqNo, FdcTransaction fdcTrx)
- {
- InfoLog("\n");
- currentFPosSqNo = (ushort)trdInfo.SeqNo;
- currentFdcSqNo = fdcTrx.SequenceNumberGeneratedOnPhysicalPump;
-
-
-
- var reserved = fPosDbManager.ReserveTransaction(currentFPosSqNo, currentFdcSqNo);
- if (!reserved)
- {
- InfoLog($"Unable to reserve the transaction, FPos SqNo: {currentFPosSqNo}, FC SqNo: {currentFdcSqNo}");
- return false;
- }
- InfoLog($"Transaction must be reserved now.");
- AuthToken currentAuthToken = null;
- if (_authToken != null)
- {
- InfoLog($"Valid? {_authToken.IsTokenValid()}");
- }
-
-
- if (_authToken != null && _authToken.IsTokenValid())
- {
- InfoLog("Token is still valid, no need to get a new one.");
- currentAuthToken = _authToken;
- }
- else
- {
- InfoLog("Token not valid anymore, get a new one.");
-
-
-
- currentAuthToken = GetAccessToken(User, Password, AuthServiceBaseUrl);
- }
- if (currentAuthToken != null)
- {
- InfoLog($"AccessToken: {currentAuthToken.AccessToken}");
- string productItemUrl = string.Concat(TransactionServiceBaseUrl, "api/products/itemId/");
-
-
-
- PosItem posItem = GetPosItemByItemId(productItemUrl, Convert.ToString(fdcTrx.Barcode), currentAuthToken);
- InfoLog($"Barcode: {fdcTrx.Barcode}, PosItem, id = {posItem.Id}");
- if (posItem == null)
- {
- InfoLog("Unable to retrieve the PosItem for current transaction");
- return false;
- }
-
-
-
- InfoLog("Creating transaction...");
- var posTrxId = CreateTransaction(trdInfo, posItem, currentAuthToken, fdcTrx);
- InfoLog($"CreateTransaction returns id: {posTrxId}");
- if (posTrxId == Guid.Empty)
- {
- InfoLog("Unable to create transaction on cloud.");
- return false;
- }
-
-
-
- return CommitTransaction(posTrxId, trdInfo, currentAuthToken);
- }
- else
- {
- InfoLog($"Error, could not get an access token, abort submitting current transaction...");
- return false;
- }
- }
- #endregion
- #region Get access token
- private AuthToken GetAccessToken(string userName, string password, string baseUrl)
- {
- InfoLog("Try to get Access Token.");
- _client.DefaultRequestHeaders.Clear();
- string tokenUrl = string.Concat(baseUrl, tokenAuthPath);
- HttpResponseMessage tokenResponse = null;
- var formParam = new AuthenticationParameter(grantType, userName, password);
- try
- {
- tokenResponse = _client.PostAsync(tokenUrl, new FormUrlEncodedContent(formParam.Params)).Result;
- }
- catch (AggregateException aex)
- {
- InfoLog("Exception in GetAccessToken.");
- var e = aex.Flatten();
- for (int i = 0; i < e.InnerExceptions.Count; i++)
- {
- logger.Info(e.InnerExceptions[i].InnerException.Message);
- }
- }
- catch (Exception ex)
- {
- InfoLog("Exception: " + ex.Message + " Inner exception: " + ex.InnerException.Message);
- }
- if (tokenResponse != null)
- {
- InfoLog($"Token response status code: {tokenResponse.StatusCode}");
- }
- else
- {
- bool unreserveResult = fPosDbManager.UnreserveTransaction(currentFPosSqNo, currentFdcSqNo);
- InfoLog($"Token response null, unreserve at GetToken, success {unreserveResult}");
- return null;
- }
- if (!tokenResponse.IsSuccessStatusCode)
- {
- InfoLog("Failed to get Access Token for user: " + userName);
- bool unreserveResult = fPosDbManager.UnreserveTransaction(currentFPosSqNo, currentFdcSqNo);
- InfoLog($"Unreserve at GetToken, success {unreserveResult}");
- return null;
- }
- _authToken = tokenResponse.Content.ReadAsAsync<AuthToken>().Result;
- _authToken.TokenRetrievedTime = DateTime.Now;
- return _authToken;
- }
- #endregion
- #region Get PosItem by ItemId
-
-
-
-
-
-
-
- private PosItem GetPosItemByItemId(string url, string itemId, AuthToken token)
- {
- var trx = fPosDbManager.GetCurrentTrx(currentFPosSqNo, currentFdcSqNo);
- if (trx.PosItemId != null)
- {
- if (!trx.PosItemId.Equals(Guid.Empty))
- return new PosItem { Id = trx.PosItemId };
- }
- try
- {
- _client.DefaultRequestHeaders.Clear();
- _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authScheme, token.AccessToken);
- _client.DefaultRequestHeaders.Add("DeviceSN", DeviceSN);
- var productUrl = string.Concat(url, itemId);
- var productResponse = _client.GetAsync(productUrl).Result;
- if (productResponse == null)
- {
- ErrorLog($"Error in getting the product by ItemId");
- return null;
- }
- InfoLog($"GetPosItemByItemId, StatusCode: {productResponse.StatusCode}");
-
- if (productResponse.IsSuccessStatusCode)
- {
- var setting = new JsonSerializerSettings();
- setting.Converters.Add(new PosJsonDateConverter());
- PosItem item = JsonConvert.DeserializeObject<PosItem>(productResponse.Content.ReadAsStringAsync().Result, setting);
- fPosDbManager.SetPosItemId(currentFPosSqNo, currentFdcSqNo, item.Id);
- return item;
- }
- }
- catch (AggregateException aex)
- {
- InfoLog("oooo Exception in GetPosItemByItemId: " + aex.ToString());
- }
- bool unreserveResult = fPosDbManager.UnreserveTransaction(currentFPosSqNo, currentFdcSqNo);
- InfoLog($"Unreserving transaction FPos SqNo: {currentFdcSqNo}, Fdc SqNo: {currentFdcSqNo}, success? {unreserveResult}");
- return null;
- }
- #endregion
- #region Create transaction
- private Guid CreateTransaction(TTrdinfo trdInfo, PosItem posItem, AuthToken token, FdcTransaction fdcTrx)
- {
-
- var currentFPosTrx = fPosDbManager.GetCurrentTrx(currentFPosSqNo, currentFdcSqNo);
- if (currentFPosTrx != null)
- {
- if (!currentFPosTrx.CloudTrxId.Equals(Guid.Empty))
- return currentFPosTrx.CloudTrxId;
- }
- var trxUrl = string.Concat(TransactionServiceBaseUrl, "api/transactions");
- var clientPosTrx = new ClientPosTrx
- {
- RequestingCreationTimeInPosClient = DateTime.Now,
- Type = PosTrxType.Sale,
- Source = PosTrxSource.Outdoor,
- Items = new List<ClientRingUpPosItem>
- {
- new ClientRingUpPosItem
- {
- PosItemUniqueId = posItem.Id,
- Qty = (decimal)trdInfo.Vol.Value /100,
- ClientRingUpTime = DateTime.Now,
- FuelItemSoldOnPumpId = fdcTrx.Nozzle.PumpId,
- FuelItemSoldOnPumpNozzleId = SiteNozzles[(fdcTrx.Nozzle.PumpId, fdcTrx.Nozzle.LogicalId)],
- FuelItemOriginalGrossAmount = currentFPosTrx.FillingAmount,
- FuelItemFdcTransactionSeqNo = Convert.ToString(fdcTrx.SequenceNumberGeneratedOnPhysicalPump),
-
- TransactionComment = "IC Trx"
- }
- }
- };
- InfoLog($"GrossAmount: {clientPosTrx.Items.First().FuelItemOriginalGrossAmount}");
- InfoLog($"FdcTrxSqNo: {clientPosTrx.Items.First().FuelItemFdcTransactionSeqNo}");
- _client.DefaultRequestHeaders.Clear();
- _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authScheme, token.AccessToken);
- _client.DefaultRequestHeaders.Add("DeviceSN", DeviceSN);
- try
- {
- var trxCreationResponse = _client.PostAsJsonAsync(trxUrl, clientPosTrx);
- InfoLog($"CreateTransaction, StatusCode: {trxCreationResponse.Result.StatusCode}");
- if (trxCreationResponse.IsCompletedSuccessfully)
- {
- var trxResp = trxCreationResponse.Result.Content.ReadAsAsync<TrxCreationResponse>();
- fPosDbManager.SetTransactionId(currentFPosSqNo, currentFdcSqNo, trxResp.Result.Id);
- return trxResp.Result.Id;
- }
- else
- {
- return Guid.Empty;
- }
- }
- catch (AggregateException aex)
- {
- InfoLog("Exception in CreateTransaction: " + aex.ToString());
- }
- fPosDbManager.UnreserveTransaction(currentFPosSqNo, currentFdcSqNo);
- return Guid.Empty;
- }
- #endregion
- #region Transaction commit
- private bool CommitTransaction(Guid id, TTrdinfo trdInfo, AuthToken token)
- {
- InfoLog("Start to commit transaction.");
- var trx = fPosDbManager.GetCurrentTrx(currentFPosSqNo, currentFdcSqNo);
- if (trx != null && trx.Submitted)
- {
- InfoLog($"This is interesting, Trx {trx.CloudTrxId} with FPos SqNo {currentFPosSqNo}, FC SqNo {currentFdcSqNo} already submitted!");
- return true;
- }
-
- var payUrlTemplate = string.Concat(TransactionServiceBaseUrl, "api/transactions/{0}/payment");
- string realPayUrl = string.Format(payUrlTemplate, id);
-
- decimal payAmount = (decimal)trdInfo.RealMon.Value / 100;
-
- string version = "1.0";
- var icPayDetail = new
- {
- CardNo = trdInfo.CardNo,
- PayAmount = payAmount,
- CardBalance = (decimal)trdInfo.CardBal.Value / 100,
- Version = version
- };
- PosTrxMop posTrxMop = new PosTrxMop();
- posTrxMop.Paid = payAmount;
- posTrxMop.ICCardNumber = trdInfo.CardNo;
- posTrxMop.RawResult = JsonConvert.SerializeObject(icPayDetail);
- posTrxMop.PosMopId = Guid.Parse("ff64ab36-658d-40a4-94bf-bee7231ac788");
- posTrxMop.Mop = new PosMop
- {
- Id = Guid.Parse("ff64ab36-658d-40a4-94bf-bee7231ac788"),
- Name = "IC",
- PaymentId = 4,
- CreatedDateTime = DateTime.Now,
- ChangesetId = Guid.Parse("84f02b52-6950-4c50-a0b1-9827d6459edc"),
- TargetBusinessUnitId = Guid.Parse("6c40e7f6-2b2d-40de-8c5c-f5693a05ab0d"),
- DisplayName = "IC卡"
- };
- _client.DefaultRequestHeaders.Clear();
- _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authScheme, token.AccessToken);
- _client.DefaultRequestHeaders.Add("DeviceSN", DeviceSN);
- try
- {
- var payResponse = _client.PostAsJsonAsync(realPayUrl, posTrxMop);
- InfoLog($"Commit Transaction, PayAmount: {payAmount}, StatusCode: {payResponse.Result.StatusCode}");
- if (payResponse.Result.IsSuccessStatusCode)
- {
- fPosDbManager.SetTransactionSubmitted(currentFPosSqNo, currentFdcSqNo, true);
- var receipt = GetHtmlReceipt(token, id, 30);
- if (!string.IsNullOrEmpty(receipt))
- {
- OnReceiptReceived?.Invoke(this, new ReceiptReceivedEventArgs
- {
- NozzleNo = SiteNozzles[(trx.PumpId, trx.NozzleId)],
- ReceiptData = receipt
- });
- }
- return true;
- }
- bool unreserveResult = fPosDbManager.UnreserveTransaction(currentFPosSqNo, currentFdcSqNo);
- InfoLog($"Unreserve at Commit, success? {unreserveResult}");
- return false;
- }
- catch (AggregateException aex)
- {
- InfoLog("oooo Exception in CommitPayment: " + aex.ToString());
- }
- return false;
- }
- #endregion
- #region Get receipt
- private string GetHtmlReceipt(AuthToken token, Guid trxId, int lineWidth = 30)
- {
- string relativeUrl = "api/receipt/{0}/maxChar/{1}";
- InfoLog("Start to get the receipt...");
- _client.DefaultRequestHeaders.Clear();
- _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authScheme, token.AccessToken);
- _client.DefaultRequestHeaders.Add("DeviceSN", DeviceSN);
- try
- {
- string receiptUrl = TransactionServiceBaseUrl + string.Format(relativeUrl, trxId, lineWidth);
- DebugLog($"ReceiptUrl: {receiptUrl}");
- var result = _client.GetAsync(receiptUrl);
- if (result.Result.IsSuccessStatusCode)
- {
- InfoLog($"Getting receipt, StatusCode: {result.Result.StatusCode}");
- return result.Result.Content.ReadAsStringAsync().Result;
- }
- else
- {
- InfoLog($"Getting receipt, result? {result.Result.StatusCode}");
- return string.Empty;
- }
- }
- catch (Exception ex)
- {
- InfoLog($"Retrieving receipt exception: {ex}");
- }
- return string.Empty;
- }
- #endregion
- #region Log methods
- private void InfoLog(string log)
- {
- if (logger.IsInfoEnabled)
- logger.Info($"{Id} " + log);
- }
- private void DebugLog(string log)
- {
- if (logger.IsDebugEnabled)
- logger.Debug($"{Id}" + log);
- }
- private void ErrorLog(string log)
- {
- if (logger.IsErrorEnabled)
- logger.Error($"{Id} " + log);
- }
- #endregion
- }
- }
|