mirror of
https://github.com/NecroticBamboo/QRBee.git
synced 2025-12-21 12:11:53 +00:00
Merchant to client to merchant round trip implemented (no security).
This commit is contained in:
parent
de95d78a23
commit
575d0ccf0b
@ -32,7 +32,25 @@
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string AsString() => $"{Request.AsString()}|{ClientId}|{TimeStampUTC:O}";
|
public string AsString() => $"{ClientId}|{TimeStampUTC:O}|{Request.AsString()}";
|
||||||
|
|
||||||
|
public static ClientToMerchantResponse FromString(string input)
|
||||||
|
{
|
||||||
|
var s = input.Split('|');
|
||||||
|
if (s.Length != 3)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("Expected 3 elements");
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = new ClientToMerchantResponse()
|
||||||
|
{
|
||||||
|
Request = MerchantToClientRequest.FromString(string.Join("|", s.Skip(2))),
|
||||||
|
ClientId = s[0],
|
||||||
|
TimeStampUTC = DateTime.ParseExact(s[1], "O", null)
|
||||||
|
};
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
namespace QRBee.Core.Data
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace QRBee.Core.Data
|
||||||
{
|
{
|
||||||
public record MerchantToClientRequest
|
public record MerchantToClientRequest
|
||||||
{
|
{
|
||||||
@ -32,7 +34,27 @@
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string AsString() => $"{TransactionId}|{Name}|{Amount:0.00}|{TimeStampUTC:O}";
|
public string AsString() => $"{TransactionId}|{Name}|{Amount.ToString("0.00", CultureInfo.InvariantCulture)}|{TimeStampUTC:O}";
|
||||||
|
|
||||||
|
public static MerchantToClientRequest FromString(string input)
|
||||||
|
{
|
||||||
|
var s = input.Split('|');
|
||||||
|
if (s.Length != 4)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("Expected 4 elements");
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = new MerchantToClientRequest
|
||||||
|
{
|
||||||
|
TransactionId = s[0],
|
||||||
|
Name = s[1],
|
||||||
|
Amount = Convert.ToDecimal(s[2], CultureInfo.InvariantCulture),
|
||||||
|
TimeStampUTC = DateTime.ParseExact(s[3],"O",null)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,116 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using QRBee.Core.Data;
|
||||||
using System.Text;
|
using QRBee.Services;
|
||||||
|
using QRBee.Views;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace QRBee.ViewModels
|
namespace QRBee.ViewModels
|
||||||
{
|
{
|
||||||
|
internal class ClientPageViewModel: BaseViewModel
|
||||||
|
|
||||||
internal class ClientPageViewModel
|
|
||||||
{
|
{
|
||||||
|
public bool _isVisible;
|
||||||
|
public string _amount;
|
||||||
|
private string _qrCode;
|
||||||
|
private MerchantToClientRequest _merchantToClientRequest;
|
||||||
|
private readonly ClientPage _clientPage;
|
||||||
|
|
||||||
|
public ClientPageViewModel(Views.ClientPage clientPage)
|
||||||
|
{
|
||||||
|
ScanCommand = new Command(OnScanButtonClicked);
|
||||||
|
GenerateQrCommand = new Command(OnGenerateQrClicked);
|
||||||
|
_clientPage = clientPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Command ScanCommand
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Command GenerateQrCommand
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnScanButtonClicked(object sender)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var scanner = DependencyService.Get<IQRScanner>();
|
||||||
|
var result = await scanner.ScanQR();
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
_merchantToClientRequest = MerchantToClientRequest.FromString(result);
|
||||||
|
Amount = $"{_merchantToClientRequest.Amount:N2}";
|
||||||
|
IsVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Amount
|
||||||
|
{
|
||||||
|
get => _amount;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == _amount)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_amount = value;
|
||||||
|
OnPropertyChanged(nameof(Amount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsVisible
|
||||||
|
{
|
||||||
|
get => _isVisible;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == _isVisible)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_isVisible = value;
|
||||||
|
OnPropertyChanged(nameof(IsVisible));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string QrCode
|
||||||
|
{
|
||||||
|
get => _qrCode;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// _qrCode = $"{Amount}/{Name}";
|
||||||
|
if (_qrCode == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_qrCode = value;
|
||||||
|
OnPropertyChanged(nameof(QrCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void OnGenerateQrClicked(object obj)
|
||||||
|
{
|
||||||
|
|
||||||
|
bool answer = await _clientPage.DisplayAlert("Confirmation", "Would you like to accept the offer?", "Yes", "No");
|
||||||
|
if (answer)
|
||||||
|
{
|
||||||
|
var response = new ClientToMerchantResponse
|
||||||
|
{
|
||||||
|
ClientId = Guid.NewGuid().ToString("D"),
|
||||||
|
TimeStampUTC = DateTime.UtcNow,
|
||||||
|
Request = _merchantToClientRequest
|
||||||
|
|
||||||
|
};
|
||||||
|
// TODO Create merchant signature.
|
||||||
|
QrCode = response.AsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1,43 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using QRBee.Core.Data;
|
||||||
|
using QRBee.Services;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace QRBee.ViewModels
|
namespace QRBee.ViewModels
|
||||||
{
|
{
|
||||||
internal class MerchantPageViewModel : BaseViewModel
|
internal class MerchantPageViewModel : BaseViewModel
|
||||||
{
|
{
|
||||||
|
private bool _isVisible;
|
||||||
private string _name;
|
private string _name;
|
||||||
private decimal _amount;
|
private decimal _amount;
|
||||||
private string _qrCode;
|
private string _qrCode;
|
||||||
|
|
||||||
public Command GenerateQrCommand { get; }
|
public Command GenerateQrCommand { get; }
|
||||||
|
public Command ScanCommand{ get; }
|
||||||
|
|
||||||
public MerchantPageViewModel()
|
public MerchantPageViewModel()
|
||||||
{
|
{
|
||||||
|
ScanCommand = new Command(OnScanButtonClicked);
|
||||||
GenerateQrCommand = new Command(OnGenerateQrClicked);
|
GenerateQrCommand = new Command(OnGenerateQrClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void OnScanButtonClicked(object sender)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var scanner = DependencyService.Get<IQRScanner>();
|
||||||
|
var result = await scanner.ScanQR();
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get => _name;
|
get => _name;
|
||||||
@ -42,6 +64,20 @@ namespace QRBee.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsVisible
|
||||||
|
{
|
||||||
|
get => _isVisible;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == _isVisible)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_isVisible = value;
|
||||||
|
OnPropertyChanged(nameof(IsVisible));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string QrCode
|
public string QrCode
|
||||||
{
|
{
|
||||||
get => _qrCode;
|
get => _qrCode;
|
||||||
@ -58,9 +94,16 @@ namespace QRBee.ViewModels
|
|||||||
|
|
||||||
public async void OnGenerateQrClicked(object obj)
|
public async void OnGenerateQrClicked(object obj)
|
||||||
{
|
{
|
||||||
QrCode = $"{Name}.{Amount:0.00}.{DateTime.UtcNow:O}";
|
var trans = new MerchantToClientRequest
|
||||||
// Prefixing with `//` switches to a different navigation stack instead of pushing to the active one
|
{
|
||||||
// await Shell.Current.GoToAsync($"//{nameof(AboutPage)}");
|
TransactionId = Guid.NewGuid().ToString("D"),
|
||||||
|
Name = Name,
|
||||||
|
Amount = Amount,
|
||||||
|
TimeStampUTC = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
// TODO Create merchant signature.
|
||||||
|
QrCode = trans.AsString();
|
||||||
|
IsVisible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:viewmodels="clr-namespace:QRBee.ViewModels"
|
||||||
|
xmlns:forms="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
|
||||||
|
xmlns:common="clr-namespace:ZXing.Common;assembly=zxing.portable"
|
||||||
|
x:DataType="viewmodels:ClientPageViewModel"
|
||||||
x:Class="QRBee.Views.ClientPage">
|
x:Class="QRBee.Views.ClientPage">
|
||||||
<ContentPage.Content>
|
<ContentPage.Content>
|
||||||
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
|
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
|
||||||
@ -9,13 +13,28 @@
|
|||||||
<!-- HorizontalOptions="CenterAndExpand" /> -->
|
<!-- HorizontalOptions="CenterAndExpand" /> -->
|
||||||
<StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand">
|
<StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand">
|
||||||
<StackLayout Orientation="Vertical">
|
<StackLayout Orientation="Vertical">
|
||||||
<Label x:Name="Name" VerticalOptions="FillAndExpand" Text="Merchant name: "/>
|
<Label VerticalOptions="FillAndExpand" Text="Amount:"/>
|
||||||
<Label x:Name="Amount" VerticalOptions="FillAndExpand" Text="Amount: "/>
|
<Label VerticalOptions="FillAndExpand" Text="{Binding Amount}"/>
|
||||||
</StackLayout>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
<StackLayout Orientation="Horizontal" VerticalOptions="End" Margin="0,0,0,10">
|
<forms:ZXingBarcodeImageView
|
||||||
<Button Text="Scan me" HorizontalOptions="CenterAndExpand" BackgroundColor="Aqua" TextColor="Red" Clicked="OnScanButtonClicked"/>
|
BarcodeFormat="QR_CODE"
|
||||||
|
BarcodeValue="{Binding QrCode}"
|
||||||
|
HorizontalOptions="FillAndExpand"
|
||||||
|
VerticalOptions="FillAndExpand">
|
||||||
|
<forms:ZXingBarcodeImageView.BarcodeOptions>
|
||||||
|
<common:EncodingOptions Width="300" Height="300" />
|
||||||
|
</forms:ZXingBarcodeImageView.BarcodeOptions>
|
||||||
|
</forms:ZXingBarcodeImageView>
|
||||||
|
|
||||||
|
</StackLayout>
|
||||||
|
|
||||||
|
<StackLayout Orientation="Vertical" VerticalOptions="End" Margin="0,0,0,10">
|
||||||
|
<StackLayout Orientation="Horizontal">
|
||||||
|
<Button Text="Accept" HorizontalOptions="FillAndExpand" BackgroundColor="DarkGreen" IsVisible="{Binding IsVisible}" Command="{Binding GenerateQrCommand}"/>
|
||||||
|
<Button Text="Deny" HorizontalOptions="FillAndExpand" BackgroundColor="DarkRed" IsVisible="{Binding IsVisible}"/>
|
||||||
|
</StackLayout>
|
||||||
|
<Button Text="Scan me" HorizontalOptions="FillAndExpand" BackgroundColor="Aqua" TextColor="Red" Command="{Binding ScanCommand}"/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using QRBee.Services;
|
using QRBee.Services;
|
||||||
|
using QRBee.ViewModels;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using Xamarin.Forms.Xaml;
|
using Xamarin.Forms.Xaml;
|
||||||
|
|
||||||
@ -11,25 +12,7 @@ namespace QRBee.Views
|
|||||||
public ClientPage()
|
public ClientPage()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
this.BindingContext = new ClientPageViewModel(this);
|
||||||
|
|
||||||
private async void OnScanButtonClicked(object sender, EventArgs args)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var scanner = DependencyService.Get<IQRScanner>();
|
|
||||||
var result = await scanner.ScanQR();
|
|
||||||
if (result != null)
|
|
||||||
{
|
|
||||||
Name.Text = result;
|
|
||||||
Amount.Text = result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -23,9 +23,6 @@
|
|||||||
<!-- -->
|
<!-- -->
|
||||||
<!-- </StackLayout> -->
|
<!-- </StackLayout> -->
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<!-- <StackLayout Orientation="Horizontal"> -->
|
|
||||||
<!-- -->
|
|
||||||
<!-- </StackLayout> -->
|
|
||||||
|
|
||||||
<forms:ZXingBarcodeImageView
|
<forms:ZXingBarcodeImageView
|
||||||
BarcodeFormat="QR_CODE"
|
BarcodeFormat="QR_CODE"
|
||||||
@ -40,9 +37,9 @@
|
|||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<StackLayout Orientation="Vertical" VerticalOptions="End" Margin="0,0,0,10">
|
||||||
<StackLayout Orientation="Horizontal" VerticalOptions="End" Margin="0,0,0,10">
|
<Button Text="Scan response" HorizontalOptions="FillAndExpand" BackgroundColor="Aqua" TextColor="Red" IsVisible="{Binding IsVisible}" Command="{Binding ScanCommand}"/>
|
||||||
<Button Text="Generate QR code" HorizontalOptions="CenterAndExpand" BackgroundColor="Red" TextColor="Aqua" Command="{Binding GenerateQrCommand}"/>
|
<Button Text="Generate QR code" HorizontalOptions="FillAndExpand" BackgroundColor="Red" TextColor="Aqua" Command="{Binding GenerateQrCommand}"/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user