# C# Integration
Before the integration can begin, artifactory must be added as source so that the NuGet packages can be installed. Instructions on how to do this can be found here.
# Required Packages
The following packages must be installed:
- anybill.POS.Client
- anybill.POS.Client.Abstractions
Optional Packages:
- anybill.POS.Client.Microsoft.Extensions.DependencyInjection
- anybill.POS.Client.Newtonsoft
Download the full documentation here
# Initialization
After all required packages are installed, you can continue with the initialization of the AnybillClientFactory
and the creation of the AnybillClient
.
For this the following parameters are necessary:
- Username
- Password
- ClientId
var clientFactory = new AnybillClientFactory();
var anybillClient = clientFactory.Create(x => x.WithUsername(username).WithPassword(password).WithClientId(clientId), AnybillEnvironment.Staging);
The environment can be optionally added when creating the AnybillClient
. By default, Production
is stored here.
# Authentication
After the AnybillClient
exists, the authentication can be executed in a second step. An AccessToken is requested and stored internally.
await anybillClient.Authentication.EnsureAsync();
# Register new bill
If you want to display a QR code already during the checkout process and before the purchase is completed, you can request a new BillId using the RegisterIdAsync
method.
var registerBillId = new RegisterBillId
{
StoreId = storeId
};
var registerBillIdResponse = await anybillClient.Bill.RegisterIdAsync(registerBillId);
switch (registerBillIdResponse)
{
case IRegisterBillIdUrlResponse registerBillIdUrlResponse:
// do something
break;
case IRegisterBillIdExternalIdResponse registerBillIdExternalResponse:
// do something
break;
}
The result is an interface of type IRegisterBillIdUrlResponse
or IRegisterBillIdExternalIdResponse
.
The difference between the 2 interfaces is that the IRegisterBillIdExternalIdResponse only contains the BillId
, while the IRegisterBillIdUrlResponse additionally contains the Url
to display the QR code.
Since IRegisterBillIdExternalIdResponse has already been assigned to a user, it is no longer necessary to display the QR code here.
# Add Bill
Adding the bill is composed of the bill
itself and the associated billOptions
. As a result one of the following interfaces is returned:
- IExternalIdResponse
- ILoyaltyCardResponse
- IMatchedBillResponse
- IUrlBillResponse
- IUserIdResponse
var billResponse = await anybillClient.Bill.CreateAsync(bill, billOptions);
switch (billResponse)
{
case IExternalIdResponse externalIdResponse:
// do something
break;
case ILoyaltyCardResponse loyaltyCardResponse:
// do something
break;
case IMatchedBillResponse matchedBillResponse:
// do something
break;
case IUrlBillResponse urlBillResponse:
// do something
break;
case IUserIdResponse userIdResponse:
// do something
break;
}
# Get Categories
To get all existing bill-categories GetAllCategoriesAsync
can be used.
var categories = await anybillClient.Category.GetAllCategoriesAsync();
A specific category can be fetched by GetCategoryByIdAsync
.
var category = await anybillClient.Category.GetCategoryByIdAsync(categoryId);
# Check the Activation-Status of a Customer
To find out whether a Customer finished the Onboarding process and is allowed to use other VendorAPI endpoints or not, IsActivatedAsync
can be used.
var customerActivated = await anybillClient.Customer.IsActivatedAsync();
if(customerActivated.Type == "activated")
// Allowed to call other endpoints
# Onboarding
To do the automatic Onboarding of a vendor customer, OnboardingAsync
can be used.
var onboardingCreateVendorCustomer = new OnboardingCreateVendorCustomer()
{
Address = new Address()
{
// ...
},
Email = "<e-mail address>",
BillingAddress = new BillingAddress()
{
// ...
},
CompanyName = "<name of company>",
InvoicingEmail = "<invoicing email>",
DistributorCustomerId = <optional guid of distributor>
};
var onboarding = new Onboarding()
{
PosSoftwareCustomerId = <posSoftwareCustomerId>,
Stores = new List<OnboardingCreateStore>()
{
// ...
},
VendorCustomer = onboardingCreateVendorCustomer
};
var onboardingResponse = await anybillClient.Onboarding.OnboardingAsync(onboarding);
# Stores
Multiple functions exist to manage stores. To get all stores GetStoresAsync
can be used.
var skip = 0;
var take = 100;
var stores = await anybillClient.Store.GetStoresAsync(skip, take);
If you want to get a specific store you can use GetStoreByIdAsync
.
var store = await anybillClient.Store.GetStoreByIdAsync(storeId);
To find out how the information about a store was changed over time, GetStoreHistoryAsync
can be used.
var storeHistory = await anybillClient.Store.GetStoreHistoryAsync(storeId);
To delete an existing store by id, DeleteStoreAsync
can be used. The flag IsSuccess
in the response of the call indicated if the store was deleted or not.
var deleteStoreResponse = await anybillClient.Store.DeleteStoreAsync(storeId);
if(deleteStoreResponse.IsSuccess)
// Store was deleted successfully
To create a new store or to update the information of an existing store the method UpSertStoreAsync
exists.
var newStore = new UpSertStore()
{
// Add store information here
};
var storeResponse = await anybillClient.Store.UpSertStoreAsync(newStore);
# User
To identify a user by its User-Id, Loyalty-Card-Barcode or external Id, you can use IdentifyAsync
.
The UserIdentification
object can hold the three values UserId, LoyaltyCardBarcode and ExternalId.
The user will be identified by one of those. If more values are set, the UserId has the highest priority, then the LoyaltyCardBarcode and finally the ExternalId with lowest priority.
var userIdentificationResponse = await anybillClient.User.IdentifyAsync(userIdentificationObject, cancellationToken);
var userId = userIdentificationResponse.UserId;
# Exception Handling
The following list describe all exceptions which can occur in case of an error.
AuthenticationException
: Occurs when authentication fails, e.g. when no username is specified.BadRequestException
: Occurs when the request fails. For example due to a validation error.ForbiddenException
: Occurs when the user does not have the necessary rights to access this endpoint.NotFoundException
: Occurs when the endpoint could not be found.UnauthorizedException
: Occurs when the user is not authenticated.UnhandledException
: Occurs if an unexpected error occurs.
# Example
The following example shows the simplest implementation of the C# SDK and should serve as a help.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using anybill.POS.Client.Exceptions;
using anybill.POS.Client.Factories;
using anybill.POS.Client.Models.Bill;
using anybill.POS.Client.Models.Bill.CashRegister;
using anybill.POS.Client.Models.Bill.Data;
using anybill.POS.Client.Models.Bill.Data.VatAmount;
using anybill.POS.Client.Models.Bill.Head;
using anybill.POS.Client.Models.Bill.Misc;
using anybill.POS.Client.Models.Bill.Misc.Extension;
using anybill.POS.Client.Models.Bill.Response;
using anybill.POS.Client.Models.Bill.Security;
using anybill.POS.Client.Models.Bill.Security.Extension;
using anybill.POS.Client.Options;
namespace POSLibraryTestProject
{
class Program
{
static async Task Main(string[] args)
{
// necessary login data + storeId
const string username = "";
const string password = "";
const string clientId = "";
const string storeId = "";
// bill object with billOptions
var bill = new AddBill
{
StoreId = storeId,
Bill = new Bill()
{
CashRegister = new CashRegister()
{
SerialNumber = "1234",
},
Head = new Head()
{
Date = DateTimeOffset.Now
},
Data = new Data()
{
Currency = "EUR",
VatAmounts = new List<DataVatAmount>()
{
new()
{
Percentage = 7,
Vat = (decimal)1.00,
ExclVat = (decimal)12.00,
InclVat = (decimal)13.00
}
}
},
Security = new Security()
{
Extension = new AnybillSecurityExtension()
{
TseFailure = true,
TseRequired = false
}
},
Misc = new Misc()
{
Extension = new AnybillMiscExtension()
{
IsExample = true,
IsInvoice = false
}
}
}
};
var billOptions = new AddBillOptions();
// registerBillId object
var registerBillId = new RegisterBillId
{
StoreId = storeId
};
// create clientFactory and anybillClient
var clientFactory = new AnybillClientFactory();
var anybillClient = clientFactory.Create(x => x.WithUsername(username).WithPassword(password).WithClientId(clientId), AnybillEnvironment.Staging);
try
{
// 1. create authentication token
await anybillClient.Authentication.EnsureAsync();
// 2. create preGenerated billID (if necessary)
var registerBillIdResponse = await anybillClient.Bill.RegisterIdAsync(registerBillId);
switch (registerBillIdResponse)
{
case IRegisterBillIdUrlResponse registerBillIdUrlResponse:
Console.WriteLine("BillID: " + registerBillIdUrlResponse.BillId);
Console.WriteLine("GetMy website: " + registerBillIdUrlResponse.Url);
break;
case IRegisterBillIdExternalIdResponse registerBillIdExternalResponse:
Console.WriteLine("BillID: " + registerBillIdExternalResponse.BillId);
break;
}
// 3. add Bill
var billResponse = await anybillClient.Bill.CreateAsync(bill, billOptions);
switch (billResponse)
{
case IExternalIdResponse externalIdResponse:
Console.WriteLine("IsAssigned: " + externalIdResponse.IsAssigned);
break;
case ILoyaltyCardResponse loyaltyCardResponse:
Console.WriteLine("IsAssigned: " + loyaltyCardResponse.IsAssigned);
break;
case IMatchedBillResponse matchedBillResponse:
Console.WriteLine("IsAssigned: " + matchedBillResponse.IsAssigned);
break;
case IUrlBillResponse urlBillResponse:
Console.WriteLine("GetMy website: " + urlBillResponse.Url);
break;
case IUserIdResponse userIdResponse:
Console.WriteLine("IsAssigned: " + userIdResponse.IsAssigned);
break;
}
}
catch (AuthenticationException authenticationException)
{
// Authentication failed because username, password or clientId is wrong.
Console.WriteLine(authenticationException);
}
catch (BadRequestException badRequestException)
{
// Request failed. e.g. validation error.
Console.WriteLine(badRequestException.Body);
}
catch (ForbiddenException forbiddenException)
{
// Request failed because user is not allowed to use the called endpoint.
Console.WriteLine(forbiddenException);
}
catch (NotFoundException notFoundException)
{
// Request failed because called endpoint does not exists.
Console.WriteLine(notFoundException);
}
catch (UnauthorizedException unauthorizedException)
{
// Request failed because user is not authorized.
Console.WriteLine(unauthorizedException);
}
catch (UnhandledException unhandledException)
{
// Request failed for some reason.
Console.WriteLine(unhandledException);
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
}
}
# Changelog
# 2023-11-20 (Version 3.0.0.34)
- added
customQuantityMeasure
tobill.data.lines.item.extension:anybill
- made
quantityMeasure
inbill.data.lines.item
optional (if customQuantityMeasure is set) - added
EmailAddress
andSendReceiptByMail
tobill.head.buyer
to allow custom email solutions - FIX: Changes type of
remainingAmount
inbill.data.paymentTypeInformation.extension:anybill
from decimal to double
# 2023-08-21 (Version 3.0.0.33)
- added
remainingAmount
tobill.data.paymentTypeInformation.extension:anybill
# 2023-06-07 (Version 3.0.0.31)
- added
publicKey
tobill.security.extension:anybill
# 2023-04-26 (Version 3.0.0.30)
- added
isVisible
toVatAmountsDto
and exclude a vat group from the list overview
# 2023-03-27 (Version 3.0.0.29)
- Added group taxing to the vat amounts
- Added countryCode to the
UpSertStoreDto
# 2023-03-06 (Version 3.0.0.28)
- simplify LineItems Object
- added EquivalentValue to BillDiscount Object
- added Number to cashRegister Object
- added PositionCount to Data Object
- added EquivalentValue to DefaultLineDiscount and mark FullAmountInclVat nullable
- mark FullAmountInclVat nullable
- added VatId to Seller Object
- added Language to UpSertStore Object
- added PrintedBill Endpoint
# 2022-12-13 (Version 3.0.0.27)
- Internal changes
# 2022-11-28 (Version 3.0.0.26)
- Added new
BarcodeType
toBarcodeCustomSectionData
# 2022-11-25 (Version 3.0.0.25)
- Added
Version
toCashRegister
- Added
EquivalentValueName
andFullEquivalentValue
toAnybillDataExtension
- Added
EquivalentValue
andIsReturn
toAnybillDefaultLineExtension
- Added
EquivalentValue
toAnybillPaymentTypeInformationExtension
- Added
VendorAdditionalReceipt
toAdditionalReceipt
- Added
CountrySpecificAttributes
toextension:anybill
atmisc
- Added
ReceiptTransactionType
toextension:anybill
atmisc
- Added
BoiTva
toTse
atSecurity
# 2022-10-17 (Version 3.0.0.24)
- removed
phoneNumber
andcreditorId
fromhead.extension:anybill
- Added new
additionalHeaderInformation
tohead.extension:anybill
# 2022-10-04 (Version 3.0.0.23)
- Adding the new endpoint to cancel a bill
- Fixed bug in the
TSE
andRKSV
object whenTseFailure = true
and empty TSE object is transmitted
# 2022-09-28 (Version 3.0.0.22)
- Removed
AdditionalTerminalText
andPaymentReceipt
in the CardPaymentDetails.
# 2022-09-27 (Version 3.0.0.21)
- Added new attribue
DisableVatAmountsValidation
toAnybillDataExtension
. With this attribute its possible to disable VatAmounts validation
# 2022-09-26 (Version 3.0.0.20)
- Added new type
KilowattHour
toQuantityMeasure
- Added documentation to
PaymentType
andQuantityMeasure
# 2022-09-12 (Version 3.0.0.19)
- Added new barcode types
Code128ABarcode
,Code128BBarcode
,Code128CBarcode
to thereturnBarcodeType
# 2022-08-31 (Version 3.0.0.18)
- Internal code refactoring
# 2022-08-30 (Version 3.0.0.17)
- Added Example code snippets for endpoints
# 2022-07-26 (Version 3.0.0.16)
- Added onboarding endpoint to the SDK
# 2022-07-22 (Version 3.0.0.15)
- Added store endpoints to the SDK
# 2022-06-20 (Version 3.0.0.14)
- Added
Ean128
to theAfterSalesCouponType
in theAfterSalesCouponsDto
# 2022-05-29 (Version 3.0.0.13)
- Added
isPrintBuffer
to the SDK
# 2022-05-02 (Version 3.0.0.12)
- Added user endpoints to the SDK
- added customer endpoints to the SDK
# 2022-04-28 (Version 3.0.0.11)
- Added
phoneNumber
to head.extension:anybill - Added new type
Barcode
to the ReturnBarcodeType
# 2022-03-15
- Added new optional attribute
alignment
intextCustomSectionData
to align the text on the PDF receipt. - Adjusted user not found object when user couldn't find using the userIdentification object.