Skip to content
Closed
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
5 changes: 2 additions & 3 deletions .github/nuke/build/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,10 @@ string GetVersion()

PackagesDirectory.CreateOrCleanDirectory();

// Pack projects that are marked as packable
// Pack only the main client project
var packableProjects = new[]
{
RootDirectory / "AppifySheets.TBC.IntegrationService.Client" / "AppifySheets.TBC.IntegrationService.Client.csproj",
RootDirectory / "AppifySheets.Immutable.BankIntegrationTypes" / "AppifySheets.Immutable.BankIntegrationTypes.csproj"
RootDirectory / "AppifySheets.TBC.IntegrationService.Client" / "AppifySheets.TBC.IntegrationService.Client.csproj"
};

DotNetPack(s => s
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,13 @@
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>

<!-- NuGet Package Metadata -->
<PackageId>AppifySheets.Immutable.BankIntegrationTypes</PackageId>
<!-- Version is inherited from Directory.Build.props which reads from VERSION file -->
<Description>Immutable bank integration types and value objects for TBC IntegrationService Client. Provides strongly-typed, immutable data structures for bank accounts, currencies, and periods.</Description>
<PackageTags>TBC;Bank;Immutable;Types;ValueObjects;Banking</PackageTags>
<!-- Repository info and other metadata inherited from Directory.Build.props -->

<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>

<!-- Mark as packable to create NuGet package -->
<IsPackable>true</IsPackable>
<!-- This is an internal library, not a separate NuGet package -->
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CSharpFunctionalExtensions" Version="*" />
<PackageReference Include="JetBrains.Annotations" Version="*" />
</ItemGroup>

<ItemGroup>
<None Include="..\README.md" Pack="true" PackagePath="\" />
<None Include="..\icon.png" Pack="true" PackagePath="\" Condition="Exists('..\icon.png')" />
</ItemGroup>
</Project>
179 changes: 147 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,77 @@
Service Documentation by the TBC Bank is here - https://developers.tbcbank.ge/docs/dbi-overview

## Following services are implemented:
* [Import Single Payments](https://developers.tbcbank.ge/docs/import-single-payments)
* [Account Movement](https://developers.tbcbank.ge/docs/account-movement)
* [Import Single Payment Orders](https://developers.tbcbank.ge/docs/import-single-payments) - Execute various types of payment transfers
* [Get Account Movements](https://developers.tbcbank.ge/docs/account-movement) - Retrieve account transaction history
* [Get Payment Order Status](https://developers.tbcbank.ge/docs/get-payment-order-status) - Check status of submitted payment orders
* [Change Password](https://developers.tbcbank.ge/docs/change-password) - Change API user password

### Usage
See the [Demo](AppifySheets.TBC.IntegrationService.Client.DemoConsole/Program.cs)
## Usage Examples

### Setup
```csharp
var credentials = new TBCApiCredentials("Username", "Password"); // Obtain API Credentials & Certificate with password from the Bank/Banker
var tbcApiCredentialsWithCertificate = new TBCApiCredentialsWithCertificate(credentials, "TBCIntegrationService.pfx", "certificate_password");

var tbcSoapCaller = new TBCSoapCaller(tbcApiCredentialsWithCertificate);

var accountMovements =
await GetAccountMovementsHelper.GetAccountMovement(new Period(new DateTime(2023, 9, 1), new DateTime(2023, 9, 26)), tbcSoapCaller);
// Example IBAN format: GE00TB0000000000000000
var ownAccountGEL = BankAccountWithCurrencyV.Create(new BankAccountV("GE00TB0000000000000001"), CurrencyV.GEL).Value;
var ownAccountUSD = BankAccountWithCurrencyV.Create(new BankAccountV("GE00TB0000000000000002"), CurrencyV.USD).Value;
```

### Account Operations

<details>
<summary><b>Get Account Movements</b></summary>

```csharp
// Get account movements for a specific period
var accountMovements = await GetAccountMovementsHelper.GetAccountMovement(
new Period(new DateTime(2023, 9, 1), new DateTime(2023, 9, 26)),
tbcSoapCaller);

// The helper method handles pagination automatically
// Returns all movements within the specified period
```
</details>

<details>
<summary><b>Get Payment Order Status</b></summary>

```csharp
// Check status of a specific payment order by its ID
var paymentOrderId = 1632027071; // The ID returned when creating a payment order
var checkStatus = await tbcSoapCaller.GetDeserialized(
new GetPaymentOrderStatusRequestIo(paymentOrderId));

// Returns status information including:
// - Current status (pending, completed, rejected, etc.)
// - Processing details
// - Error messages if any
```
</details>

<details>
<summary><b>Change Password</b></summary>

var checkStatus = await tbcSoapCaller.GetDeserialized(new GetPaymentOrderStatusRequestIo(1632027071));
```csharp
// Change API user password (requires digipass code)
var newPassword = "NewSecurePassword123!";
var digipassCode = "123456"; // One-time code from your digipass device

var passwordChangeResult = await tbcSoapCaller.GetDeserialized(
new ChangePasswordRequestIo(newPassword, digipassCode));

// Note: After successful password change, update your credentials
```
</details>

var ownAccountGEL = BankAccountWithCurrencyV.Create(new BankAccountV("GE31TB7467936080100003"), CurrencyV.GEL).Value;
var ownAccountUSD = BankAccountWithCurrencyV.Create(new BankAccountV("GE47TB7467936170100001"), CurrencyV.USD).Value;
### Payment Transfers

#### Common Transfer Parameters
```csharp
// Common parameters for all transfer types
var transferTypeRecordSpecific = new TransferTypeRecordSpecific
{
DocumentNumber = 123,
Expand All @@ -35,64 +86,128 @@ var transferTypeRecordSpecific = new TransferTypeRecordSpecific
SenderAccountWithCurrency = ownAccountGEL,
Description = "TEST"
};
```

var withinBankGel2 = await tbcSoapCaller.GetDeserialized(new ImportSinglePaymentOrdersRequestIo(
<details>
<summary><b>Internal Transfers (Within TBC Bank)</b></summary>

#### Transfer in GEL
```csharp
var withinBankGel = await tbcSoapCaller.GetDeserialized(new ImportSinglePaymentOrdersRequestIo(
new TransferWithinBankPaymentOrderIo
{
RecipientAccountWithCurrency = BankAccountWithCurrencyV.Create(new BankAccountV("GE86TB1144836120100002"), CurrencyV.GEL).Value,
RecipientAccountWithCurrency = BankAccountWithCurrencyV.Create(
new BankAccountV("GE00TB0000000000000003"), CurrencyV.GEL).Value,
TransferTypeRecordSpecific = transferTypeRecordSpecific
}));
```

#### Transfer in Foreign Currency (USD)
```csharp
var withinBankCurrency = await tbcSoapCaller.GetDeserialized(new ImportSinglePaymentOrdersRequestIo(
new TransferWithinBankPaymentOrderIo
{
TransferTypeRecordSpecific = transferTypeRecordSpecific with
{
SenderAccountWithCurrency = ownAccountUSD
},
RecipientAccountWithCurrency = BankAccountWithCurrencyV.Create(new BankAccountV("GE86TB1144836120100002"), CurrencyV.USD).Value,
RecipientAccountWithCurrency = BankAccountWithCurrencyV.Create(
new BankAccountV("GE00TB0000000000000004"), CurrencyV.USD).Value,
}));
```
</details>

<details>
<summary><b>External Transfers (To Other Banks)</b></summary>

#### Domestic Transfer to Another Georgian Bank (GEL)
```csharp
var toAnotherBankGel = await tbcSoapCaller.GetDeserialized(
new ImportSinglePaymentOrdersRequestIo(
new TransferToOtherBankNationalCurrencyPaymentOrderIo(
BankAccountWithCurrencyV.Create(new BankAccountV("GE33BG0000000263255500"), CurrencyV.GEL).Value, "123123123")
BankAccountWithCurrencyV.Create(new BankAccountV("GE00BG0000000000000001"), CurrencyV.GEL).Value,
"123456789") // Beneficiary tax code
{
TransferTypeRecordSpecific = transferTypeRecordSpecific
}));
```

var toAnotherBankCurrencyGood = await tbcSoapCaller.GetDeserialized(
new ImportSinglePaymentOrdersRequestIo(
new TransferToOtherBankForeignCurrencyPaymentOrderIo("test", "test", "SHA", "TEST",
BankAccountWithCurrencyV.Create(new BankAccountV("GE33BG0000000263255500"), CurrencyV.USD).Value)
{
TransferTypeRecordSpecific = transferTypeRecordSpecific with { SenderAccountWithCurrency = ownAccountUSD }
}));

var toAnotherBankCurrencyBad = await tbcSoapCaller.GetDeserialized(
#### International Transfer (Foreign Currency)
```csharp
var toAnotherBankCurrency = await tbcSoapCaller.GetDeserialized(
new ImportSinglePaymentOrdersRequestIo(
new TransferToOtherBankForeignCurrencyPaymentOrderIo("test", "test", "SHA", "TEST",
BankAccountWithCurrencyV.Create(new BankAccountV("GE33BG0000000263255500"), CurrencyV.USD).Value)
new TransferToOtherBankForeignCurrencyPaymentOrderIo(
"Beneficiary Bank Name",
"BANKSWIFT", // Bank SWIFT/BIC code
"SHA", // Charge type: SHA (shared), OUR (sender pays), BEN (beneficiary pays)
"Payment Reference",
BankAccountWithCurrencyV.Create(new BankAccountV("GE00BG0000000000000002"), CurrencyV.USD).Value)
{
TransferTypeRecordSpecific = transferTypeRecordSpecific with { SenderAccountWithCurrency = ownAccountUSD }
TransferTypeRecordSpecific = transferTypeRecordSpecific with
{
SenderAccountWithCurrency = ownAccountUSD
}
}));
```

#### International Transfer Example (To China)
```csharp
var toChina = await tbcSoapCaller.GetDeserialized(
new ImportSinglePaymentOrdersRequestIo(
new TransferToOtherBankForeignCurrencyPaymentOrderIo( "China",
// "ICBKCNBJSZN", "INDUSTRIAL AND COMMERCIAL BANK OF CHINA SHENZHEN BRANCH", "SHA", "Invoice(LZSK202311028)",
"ICBKCNBJSZN", "INDUSTRIAL AND COMMERCIAL BANK OF CHINA SHENZHEN BRANCH", "SHA",
BankAccountWithCurrencyV.Create(new BankAccountV("4000109819100186641"), CurrencyV.USD).Value)
new TransferToOtherBankForeignCurrencyPaymentOrderIo(
"China",
"ICBKCNBJSZN", // Bank SWIFT code
"INDUSTRIAL AND COMMERCIAL BANK OF CHINA SHENZHEN BRANCH", // Bank name
"SHA", // Charge type
BankAccountWithCurrencyV.Create(new BankAccountV("CN0000000000000000001"), CurrencyV.USD).Value)
{
TransferTypeRecordSpecific = transferTypeRecordSpecific with
{
SenderAccountWithCurrency = ownAccountUSD,
BeneficiaryName = "Shenzhen Shinekoo Supply Chain Co.,Ltd"
BeneficiaryName = "Shenzhen Example Company Ltd"
}
}));
```
</details>

<details>
<summary><b>Treasury Transfers</b></summary>

```csharp
// Transfer to Georgian Treasury
var toTreasury = await tbcSoapCaller.GetDeserialized(
new ImportSinglePaymentOrdersRequestIo(
new TreasuryTransferPaymentOrderIo(101001000)
{ TransferTypeRecordSpecific = transferTypeRecordSpecific }));
new TreasuryTransferPaymentOrderIo(101001000) // Treasury code
{
TransferTypeRecordSpecific = transferTypeRecordSpecific
}));
```
</details>

## Error Handling

All operations return a `Result<T>` type from CSharpFunctionalExtensions:

```csharp
var result = await tbcSoapCaller.GetDeserialized(request);

if (result.IsSuccess)
{
var response = result.Value;
// Process successful response
}
else
{
var error = result.Error;
// Handle error
Console.WriteLine($"Operation failed: {error}");
}
```

## Important Notes

- All monetary amounts are in decimal format
- IBAN accounts must be valid Georgian IBANs (starting with GE)
- Document numbers must be unique per day
- Digipass codes are required for sensitive operations like password changes
- Certificate authentication is mandatory for all API calls
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.1
1.0.3