Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
In many payment vendor apps it is possible to add a tip to the payment amount.
In many payment vendor apps, it is possible to add a tip to the payment amount.

Flow example in a restaurant:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Flow example in a restaurant:
**Example flow in a restaurant:**

- Guest asks for the bill
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- Guest asks for the bill
1. The guest asks for the bill.

- Waiter triggers to create the bill at the POS (e.g. mobile device)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- Waiter triggers to create the bill at the POS (e.g. mobile device)
2. The waiter triggers to create the bill on the POS (e.g., mobile device).

- 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)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- 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)
3. The POS on the mobile device sends the amount (e.g., 10€) to be paid to the configured payment app via POS System API and the **fiskaltrust** InStore App.

- The payment app opens and the waiter hands the mobile device over to the guest
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- The payment app opens and the waiter hands the mobile device over to the guest
4. The payment app opens, and the waiter hands the mobile device to the guest.

- The guest sees a TIP entry screen and adds a tip of 2€
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- The guest sees a TIP entry screen and adds a tip of 2€
5. The guest sees a TIP entry screen and adds a tip of 2€.

- The guests now pays the full sum of 12€
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- The guests now pays the full sum of 12€
6. The guest now pays the full sum of 12€.

- The payment app reports a paid amount of 12€ (including 2€ of tip)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- The payment app reports a paid amount of 12€ (including 2€ of tip)
7. The payment app reports a paid amount of 12€ (including 2€ tip).

- 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):
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- 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):
8. The **fiskaltrust** InStore App / POS System API reports the following in the payment response (see also an example on the POS System API docs):

Copy link
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€
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- Pay item 1: The fully paid amount with the receipt -> 12€
- Pay item 1: The total paid amount with the receipt -> 12€

- Pay item 2: The tip with negative amount -> -2€
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- Pay item 2: The tip with negative amount -> -2€
- Pay item 2: The tip with a negative amount -> -2€

- sum of the 2 pay items is the original requested amount of 10€
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- sum of the 2 pay items is the original requested amount of 10€
- The sum of the 2 pay items is the original requested amount of 10€


NOTE: The tip can be calculated by simply subtracting the requested amount from the paid amount (12-10 = 2€ tip) or alternatively from the 2nd pay item (-2 * -1 = 2€ tip).
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
NOTE: The tip can be calculated by simply subtracting the requested amount from the paid amount (12-10 = 2€ tip) or alternatively from the 2nd pay item (-2 * -1 = 2€ tip).
**NOTE:** The tip can be calculated by simply subtracting the requested amount from the paid amount (12-10 = 2€ tip) or alternatively by using the 2nd pay item (-2 * -1 = 2€ tip).

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"
};

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) |
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
| 30000,50 | SUCCESS with added guest tip (see [HOWTO_01_Payment](HOWTO_01_Payment_csharp/README.MD) on how to handle such a tip) |
| 30000,50 | SUCCESS with added guest tip (see [HOWTO_01_Payment](HOWTO_01_Payment_csharp/README.MD) for instructions on handling tips) |

| 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
Assert.Single(payResponse.ftPayItems);

PayItem pi = payResponse!.ftPayItems![0];
Expand Down
45 changes: 32 additions & 13 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,19 +210,32 @@ public static void DumpToLogger(PayResponse payResp)
{
protocol = protocolValue.GetString() ?? "ERROR: invalid type";
}
Logger.LogInfo($"- {protocol}:");
if (payItemCaseData?.Receipt == null)
{
Logger.LogInfo("\t WARNING: No receipt info received!");
}
else
Logger.LogInfo($"- PayItem {i+1}");
Logger.LogInfo($"\t\tDescription: {ftPayItem.Description}");
if (protocol != "unknown") Logger.LogInfo($"\t\tprotocol: {protocol}");
Logger.LogInfo($"\t\tAmount: {ftPayItem.Amount}");
// only show calculate included tip and process receipt for the real payment item and not for the additional info entries
if (payItemCaseData != null)
{
string[]? payReceipt = ftPayItem.GetPayItemCaseData()?.Receipt;
if (payReceipt != null)
if (payItemRequest != null)
{
decimal tipAmount = ftPayItem.Amount - payItemRequest.Amount;
Logger.LogInfo($"\t\t\tIncluded Tip Amount: {tipAmount}");
}
Logger.LogInfo("\t\tReceipt:");
if (payItemCaseData?.Receipt == null)
{
Logger.LogInfo("\t\t\t WARNING: No receipt info received!");
}
else
{
foreach (string line in payReceipt)
string[]? payReceipt = ftPayItem.GetPayItemCaseData()?.Receipt;
if (payReceipt != null)
{
Logger.LogInfo($"\t{line}");
foreach (string line in payReceipt)
{
Logger.LogInfo($"\t\t\t{line}");
}
}
}
}
Expand Down