Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions HOWTO_01_Payment_csharp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,12 @@ static async Task Main(string[] args)
// - the terminal ID is not defined here (null) so the request will be processed by all available terminals for the cashbox
// IMPORTANT: In a real setup you might want to define a specific terminal ID here to target a specific payment terminal device; especially when multiple payment terminals are registered for the same cashbox!
// - we provide the operation ID to be able to retry in case of failure
ExecutedResult<PayResponse> payResult = await ftPosAPI.Pay.PaymentAsync(new PayItemRequest
var payItemRequest = new PayItemRequest
{
Description = "Card",
Amount = amount,
}, fiskaltrust.Payment.DTO.PaymentProtocol.use_auto, null, operationId);
};
ExecutedResult<PayResponse> payResult = await ftPosAPI.Pay.PaymentAsync(payItemRequest, fiskaltrust.Payment.DTO.PaymentProtocol.use_auto, null, operationId);

/////////////////////////////////////////////////////////////////////////////////////////////////
// Check Result
Expand All @@ -80,7 +81,7 @@ static async Task Main(string[] args)
{
// YES --> SUCCESS: Payment was successful
PayResponse payResp = await payResult.Operation.GetResponseAsAsync();
Utils.DumpToLogger(payResp);
Utils.DumpToLogger(payResp, payItemRequest);
break;
}
else
Expand Down
19 changes: 19 additions & 0 deletions HOWTO_01_Payment_csharp/README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,22 @@ Several critical error scenarios must be managed carefully to prevent double pay
- The response is not received within the expected time frame (HTTP timeout), which can be simulated by a device losing internet connectivity during payment execution.

In all of these cases, the solution is to resend the original request using the identical operation ID and request body. The backend will then return the final result of the operation.

## Special case - payment vendor added TIP

In many payment vendor apps it is possible to add a tip to the payment amount.
Comment thread
MaximilianFT marked this conversation as resolved.
Outdated
Flow example in a restaruant:
Comment thread
turtletramp marked this conversation as resolved.
Outdated
- Guest asks for the bill
Comment thread
MaximilianFT marked this conversation as resolved.
Outdated
- Waiter triggers to create the bill at the POS (e.g. mobile device)
Comment thread
MaximilianFT marked this conversation as resolved.
Outdated
- The POS on the mobile device pushes the amount (for example 10€) to be paid to the configured payment app (via POS System API and the fiskaltrust InStore App)
Comment thread
MaximilianFT marked this conversation as resolved.
Outdated
- The payment app opens and the waiter hands the mobile device over to the guest
Comment thread
MaximilianFT marked this conversation as resolved.
Outdated
- The guest sees a TIP entry screen and adds a tip of 2€
Comment thread
MaximilianFT marked this conversation as resolved.
Outdated
- The guests now pays the full sum of 12€
Comment thread
MaximilianFT marked this conversation as resolved.
Outdated
- The payment app reports a paid amount of 12€ (including 2€ of tip)
Comment thread
MaximilianFT marked this conversation as resolved.
Outdated
- The fiskaltrust InStore App / POS System API does report back the following in the payment response (see also example in the POS System API docs):
Comment thread
MaximilianFT marked this conversation as resolved.
Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should a hyperlink be added to: (see also an example on the POS System API docs)?

- 2 pay items
- Pay item 1: The fully paid amount with the receipt -> 12€
Comment thread
MaximilianFT marked this conversation as resolved.
Outdated
- Pay item 2: The tip with negative amount -> -2€
Comment thread
MaximilianFT marked this conversation as resolved.
Outdated
- sum of the 2 pay items is the orginal requested amount of 10€
Comment thread
turtletramp marked this conversation as resolved.
Outdated

NOTE: The tip can be calculated by simply substracting the requested amount from the paid amount (12-10 = 2€ tip) or alternatively from the 2nd pay item (-2 * -1 = 2€ tip).
Comment thread
turtletramp marked this conversation as resolved.
Outdated
13 changes: 7 additions & 6 deletions HOWTO_08_pay_sign_issue_csharp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,15 @@ static async Task Main(string[] args)
decimal totalAmount = chargeItems.Sum(ci => ci.Amount);
Logger.LogInfo($"Total amount to pay: {totalAmount} EUR");

PayItemRequest payRequest = new()
{
Amount = totalAmount,
Description = "Card"
};
var payRunner = new ftPosAPIOperationRunner();
(PayResponse? pResp, string errorMsg) = await payRunner.Execute<PayResponse>(async () =>
{
PayItemRequest payRequest = new()
{
Amount = totalAmount,
Description = "Card"
};

Comment thread
turtletramp marked this conversation as resolved.
return await ftPosAPI.Pay.PaymentAsync(payRequest, PaymentProtocol.use_auto, null, payRunner.OperationID);
});

Expand All @@ -72,7 +73,7 @@ static async Task Main(string[] args)
else
{
Logger.LogInfo("Payment succeeded.");
Utils.DumpToLogger(pResp);
Utils.DumpToLogger(pResp, payRequest);

///////////////////////////////////////////////////////////////////////////////////////////////////////
///
Expand Down
2 changes: 1 addition & 1 deletion README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Any payment amount will return a SUCCESS response, except for the following defi
| 30000,10 | DECLINED |
| 30000,20 | TIMEOUT (returned as an error message as no other option is available yet) |
| 30000,40 | CANCELLED BY USER |
| 30000,50 | SUCCESS with added guest tip |
| 30000,50 | SUCCESS with added guest tip (see [HOWTO_01_Payment](HOWTO_01_Payment_csharp/README.MD) on how to handle such a tip) |
Comment thread
MaximilianFT marked this conversation as resolved.
Outdated
| 30000,60 | SUCCESS after 1-minute delay |
| 30000,70 | SUCCESS after 3-minute delay |
| 30000,80 | SUCCESS after 6-minute delay |
Expand Down
2 changes: 1 addition & 1 deletion libPosSystemAPI.Test/IntegrationTestsPayment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public async Task TestPayment()
Assert.NotNull(payResponse);
Assert.True(payResponse.Protocol == Payment.DTO.PaymentProtocol.use_auto);
Assert.NotNull(payResponse.ftPayItems);
// dummy payment provider should return exactly one pay item (as we did not execute a 30000,50 which would result in multiple pay items as there would be a tip)
// dummy payment provider should return exactly one pay item
Comment thread
turtletramp marked this conversation as resolved.
Assert.Single(payResponse.ftPayItems);

PayItem pi = payResponse!.ftPayItems![0];
Expand Down
26 changes: 20 additions & 6 deletions libPosSystemAPI/PosAPIUtils/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ public static (Guid ftCashboxID, string ftCashboxAccessToken)? GetCashboxCredent
return (ftCashboxID, ftCashboxAccessToken);
}

public static void DumpToLogger(PayResponse payResp)
public static void DumpToLogger(PayResponse payResp, PayItemRequest? payItemRequest = null)
{
Logger.LogInfo("Payment successful! Queue ID: " + payResp.ftQueueID);
if (payResp.ftPayItems == null || payResp.ftPayItems.Length == 0)
Expand All @@ -193,9 +193,15 @@ public static void DumpToLogger(PayResponse payResp)

// pretty log the response (JSON)
Logger.LogDebug("PayResponse: " + JsonSerializer.Serialize(payResp, new JsonSerializerOptions { WriteIndented = true }));

foreach (PayItem ftPayItem in payResp.ftPayItems)
if (payItemRequest != null)
{
Logger.LogInfo("Requested Payment:");
Logger.LogInfo($"- Amount: {payItemRequest.Amount}");
}
Logger.LogInfo("Received Pay Response:");
for (int i = 0; i < payResp.ftPayItems.Length; i++)
{
PayItem ftPayItem = payResp.ftPayItems[i];
var payItemCaseData = ftPayItem.GetPayItemCaseData();

Dictionary<string, JsonElement>? providerInfo = payItemCaseData?.Provider;
Expand All @@ -204,10 +210,18 @@ public static void DumpToLogger(PayResponse payResp)
{
protocol = protocolValue.GetString() ?? "ERROR: invalid type";
}
Logger.LogInfo($"- {protocol}:");
Logger.LogInfo($"- PayItem {i+1}");
if (protocol != "unknown") Logger.LogInfo($"\t\tprotocol: {protocol}");
Logger.LogInfo($"\t\tAmount: {ftPayItem.Amount}");
if (payItemRequest != null)
{
decimal tipAmount = ftPayItem.Amount - payItemRequest.Amount;
Logger.LogInfo($"\t\t\tIncluded Tip Amount: {tipAmount}");
}
Comment thread
turtletramp marked this conversation as resolved.
Outdated
Logger.LogInfo("\t\tReceipt:");
if (payItemCaseData?.Receipt == null)
{
Logger.LogInfo("\t WARNING: No receipt info received!");
Logger.LogInfo("\t\t\t WARNING: No receipt info received!");
}
else
{
Expand All @@ -216,7 +230,7 @@ public static void DumpToLogger(PayResponse payResp)
{
foreach (string line in payReceipt)
{
Logger.LogInfo($"\t{line}");
Logger.LogInfo($"\t\t\t{line}");
}
}
}
Expand Down