using Edge.Core.Processor;
using Edge.Core.Processor.Dispatcher.Attributes;
using Edge.Core.UniversalApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using VBaoProxyApp.Cloud;
namespace VBaoProxyApp
{
[UniversalApi(Name = OnFuelTrxDoneEventName, EventDataType = typeof(object), Description = "使用短码授权加油的用户完成加油时,将触发此事件")]
[UniversalApi(Name = "OnRemotePaymentFailed", EventDataType = typeof(object), Description = "当与云端进行支付流程进行中,且失败了,将触发此事件")]
[MetaPartsDescriptor(
"V宝车载定位",
"用于与V宝车载定位站级系统的对接",
new[] { "V宝" })]
public class App : IAppProcessor
{
public const string OnFuelTrxDoneEventName = "OnFuelTrxDone";
private IServiceProvider services;
private Applications.FDC.FdcServerHostApp fdcServerApp;
private AppConfigV1 appConfig;
private TimeSpan InRangeBeaconLifeTime = new TimeSpan(0, 1, 30);
private ILogger logger = NullLogger.Instance;
private object syncObject = new object();
public class AppConfigV1
{
public string UserName { get; set; } = "3038";
public string Password { get; set; } = "111111";
///
/// Sample: http://url:8698
/// DO NOT end with slash
///
public string ApiGatewayEntryUrlWithoutLastSlash { get; set; } = "http://47.97.120.160:8698";
public string DeviceSN { get; set; } = "66662e74-d51e-42ae-bc89-2d39312c9c30";
}
public class InRangeBeacon
{
public string BeaconId { get; set; }
public DateTime Timestamp { get; set; }
public string AuthCode { get; set; }
}
private ConcurrentDictionary inRangeBeacons = new ConcurrentDictionary();
public string MetaConfigName { get; set; }
public void Init(IEnumerable processors)
{
this.fdcServerApp =
processors.WithHandlerOrApp().SelectHandlerOrAppThenCast().FirstOrDefault();
if (this.fdcServerApp == null)
{
this.logger.LogInformation("There's no FdcServerHostApp defined");
throw new ArgumentException("Must provide FdcServerHostApp");
}
//this.fdcServerApp.OnFdcFuelSaleTransactinStateChange += async (s, a) =>
//{
// if (a.State == Edge.Core.Database.Models.FuelSaleTransactionState.Payable)
// {
// var trxes = await this.fdcServerApp.GetFuelSaleTrxDetailsAsync(new ApiData()
// {
// Parameters = new List() {
// new ApiDataParameter()
// {
// Name="releasetoken",
// Value = a.Transaction.ReleaseToken.ToString()
// }
// }
// });
// var universalApiHub = this.services.GetRequiredService();
// await universalApiHub.FireEvent(this, OnFuelTrxDoneEventName, new
// {
// InRangeBeacon = new InRangeBeacon()
// {
// AuthCode = new Random().Next(0, 9999).ToString().PadLeft(4, '0'),
// BeaconId = new Random().Next(99999, 999999999).ToString().PadLeft(10, '0'),
// },
// FuelTrx = trxes.FirstOrDefault()
// });
// }
//};
}
public App(AppConfigV1 appConfig, IServiceProvider services)
{
this.appConfig = appConfig;
var loggerFactory = services.GetRequiredService();
this.logger = loggerFactory.CreateLogger("DynamicPrivate_VBaoProxyApp");
this.services = services;
CloudHelper.Default.Credential = new CloudCredential()
{
ApiGatewayEntryUrl = appConfig.ApiGatewayEntryUrlWithoutLastSlash,// "http://wc.shaojun.xyz:8698",
UserName = appConfig.UserName,// "507",
Password = appConfig.Password,//"111111",
DeviceSN = appConfig.DeviceSN,//"1234567890sss",
};
}
public async Task Start()
{
var extraInfos = this.fdcServerApp.GetNozzleExtraInfos();
var fuelItemBarcodes = extraInfos.GroupBy(i => i.ProductBarcode).Select(g => g.Key);
foreach (var barcode in fuelItemBarcodes)
{
try
{
var cloudFuelItem = await CloudHelper.Default.GetPosItemAsync(barcode.ToString());
if (cloudFuelItem == null)
throw new InvalidOperationException($"Local fuel item with barcode: {barcode} could not find mapping item in cloud side.");
}
catch (Exception exxx)
{
this.logger.LogError($"Failed to retrieve Cloud side fuel item based on local barcode: {barcode}, make sure local fuel items are all" +
$" correctly set and mapped(by their item id) in cloud side. error detail: {exxx}");
throw;
}
}
return true;
}
public Task Stop() { return Task.FromResult(true); }
[UniversalApi(Description = "报告用户信标进入了感应范围,并获取验证码短码")]
public async Task NotifyBeaconInRange(string userBeaconId)
{
this.logger.LogDebug($"NotifyBeaconInRange: {userBeaconId}");
try
{
if (!this.inRangeBeacons.TryGetValue(userBeaconId, out InRangeBeacon exist)
|| (DateTime.Now.Subtract(exist.Timestamp) > this.InRangeBeaconLifeTime))
{
//remove the expired one
if (exist != null)
{
this.logger.LogDebug($" removing an expired one...");
this.inRangeBeacons.TryRemove(userBeaconId, out _);
}
string authCode = null;
while (true)
{
authCode = new Random().Next(0, 9999).ToString().PadLeft(4, '0');
if (this.inRangeBeacons.Values.Any(i => i.AuthCode == authCode))
continue;
break;
}
var info = new InRangeBeacon()
{
BeaconId = userBeaconId,
Timestamp = DateTime.Now,
AuthCode = authCode,
};
this.logger.LogDebug($" adding one with beaconId: {userBeaconId}, authCode: {authCode}");
this.inRangeBeacons.TryAdd(userBeaconId, info);
return info;
//var universalApiHub = this.services.GetRequiredService();
//await universalApiHub.FireEvent(this, OnUserAuthCodeGeneratedEventName, info);
}
else
return exist;
}
finally
{
//if (lockTaken) spinLock_NotifyInRangeBeacon.Exit(false);
}
}
[UniversalApi(Description = "验证短码是否有效")]
public async Task