Skip to content

Commit

Permalink
Merge pull request #1 from helixge/feature/initiator
Browse files Browse the repository at this point in the history
Feature/initiator
  • Loading branch information
Dzoge authored Oct 6, 2022
2 parents c00e4c8 + 2867dd8 commit 6a584d5
Show file tree
Hide file tree
Showing 14 changed files with 162 additions and 25 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Pull request

on:
workflow_dispatch:
pull_request:
workflow_call:

jobs:
build_and_test:
name: Build and test
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout repo
uses: actions/checkout@v3

- uses: actions/setup-dotnet@v3
with:
dotnet-version: '6'

- name: Build
working-directory: ./Solution
run: dotnet build

- name: Test
working-directory: ./Solution
run: dotnet test
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TBC Bank E-Commerce Card Payments Gateway Client (.NET Library)

[![Version](https://helix.ge/helix-tbcbank-ecommerceclient-nuget.svg?3-2-0)](https://www.nuget.org/packages/Helix.TbcBank.EcommerceClient)
[![Version](https://helix.ge/helix-tbcbank-ecommerceclient-nuget.svg?4-0-0-1)](https://www.nuget.org/packages/Helix.TbcBank.EcommerceClient)

[Helix.TbcBank.EcommerceClient](https://www.nuget.org/packages/Helix.TbcBank.EcommerceClient) is a .NET client library for using TBC Bank e-commerce visa and master card payments gateway .

Expand Down Expand Up @@ -76,7 +76,7 @@ var client = new TbcBankEcommerceClient(clientOptions);
Once the transaction is registered and the corresponding ID is retrieved from TBC, call this method to retrieve URL where the user should be redirected to in order to enter card details and complete the transaction

* **ExecuteReoccurringTransactionAsync**
If you have already successfully completed the transaction using ```RegisterTransactionAndGetReoccuringPaymentIdAsync``` method, you can execute additional transactions without the user intervention using this method.
If you have already successfully completed the transaction using ```RegisterTransactionAndGetReoccuringPaymentIdAsync``` or ```RegisterPreAuthorizationAndGetReoccuringPaymentId``` methods, you can execute additional transactions without the user intervention using this method.

* **RegisterPreAuthorizationAsync**
Use this method if you want to temporarily block the amount on the card while processing offline or asynchronous operation. ```ExecutePreAuthorizationAsync()``` method must be called to complete the transaction.
Expand All @@ -95,6 +95,20 @@ var client = new TbcBankEcommerceClient(clientOptions);

* **CloseBusinessDayAsync**
Closes the business day for a merchant

* **RegisterPreAuthorizationAndGetReoccuringPaymentId**
Pre-authorization is the temporary amount blocking operation, which must be followed by a pre-authorization confirmation or reversal operation. In case none of them follow, the system by default will automatically delete the blocked amount after 30 working days. The block period is regulated by the card issuer (Issuer Bank). Pre-authorization can only be completed within 30 working days, follow the next commands to clarify.

Register payment transaction with specified amount and save information for future transactions. This feature should be enabled by TBC. Once transaction id is retrieved, call ```GetClientRedirectUrl()``` method and navigate the user to the corresponding URL.

Once the operation completes you need to confirm the transaction using ```ExecutePreAuthorizationAsync()``` or reverse the transaction using ```ReverseTransactionAsync()```

* **ExecuteReoccurringPreAuthorizationAsync**
Pre-authorization is the temporary amount blocking operation, which must be followed by a pre-authorization confirmation or reversal operation. In case none of them follow, the system by default will automatically delete the blocked amount after 30 working days. The block period is regulated by the card issuer (Issuer Bank). Pre-authorization can only be completed within 30 working days, follow the next commands to clarify.

If you have already successfully completed the transaction using ```RegisterTransactionAndGetReoccuringPaymentIdAsync``` or ```RegisterPreAuthorizationAndGetReoccuringPaymentId``` methods, you can execute additional transactions without the user intervention using this method.

Once the operation completes you need to confirm the transaction using ```ExecutePreAuthorizationAsync()``` or reverse the transaction using ```ReverseTransactionAsync()```

* **ExecuteCreditTransactionAsync**
This feature should be enabled by TBC.
Expand Down Expand Up @@ -183,4 +197,4 @@ public class HomeController : Controller

//...other methods
}
````
````
5 changes: 5 additions & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
v4.0.0
- Adding required initiator parameter introduced by the TBC regulation: When the merchant has to cut a certain amount from the client on any given date without the client's approval, it is necessary for the merchant to add an additional parameter (initiator = merchant)
- Adding 'RegisterPreAuthorizationAndGetReoccuringPaymentId' method (command "d").
- Adding 'ExecuteReoccurringPreAuthorizationAsync()' method (command "f").
- Note: Pre-authorization is the temporary amount blocking operation, which must be followed by a pre-authorization confirmation ('ExecutePreAuthorizationAsync()', command "t") or reversal operation ('ReverseTransactionAsync()', command "r"). In case none of them follow, the system by default will automatically delete the blocked amount after 30 working days. The block period is regulated by the card issuer (Issuer Bank). Pre-authorization can only be completed within 30 working days, follow the next commands to clarify.
v3.2.0
- Optimize HTTP connection creation. Use singleton HttpClient per merchant
v3.1.0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace TbcBank.EcommerceClient
namespace TbcBank.EcommerceClient
{
public enum CurrencyCode
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace TbcBank.EcommerceClient
{
public enum TransactionInitiator
{
Client = 1,
Merchant = 2
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
<PackageIcon>helix.png</PackageIcon>
<PackageIconUrl />
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<AssemblyVersion>3.2.0.0</AssemblyVersion>
<FileVersion>3.2.0.0</FileVersion>
<Version>3.2.0</Version>
<AssemblyVersion>4.0.0.0</AssemblyVersion>
<FileVersion>4.0.0.0</FileVersion>
<Version>4.0.0</Version>
<Product>TBC Bank Ecommerce Card Payments Gateway Client (.NET Library)</Product>
</PropertyGroup>

Expand Down
80 changes: 77 additions & 3 deletions Solution/TbcBank.EcommerceClient/TbcBankEcommerceClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ public async Task<RegisterTransactionResult> RegisterTransactionAndGetReoccuring
/// <param name="language"></param>
/// <param name="merchantTransactionId"></param>
/// <returns></returns>
public async Task<ExecuteReoccurringTransactionResult> ExecuteReoccurringTransactionAsync(int amount, CurrencyCode currency, string clientIpAddress, string description, string billerClientId, string language = PaymentUiLanguage.Georgian, string merchantTransactionId = null)
public async Task<ExecuteReoccurringTransactionResult> ExecuteReoccurringTransactionAsync(int amount, CurrencyCode currency, string clientIpAddress, string description, string billerClientId, TransactionInitiator initiator, string language = PaymentUiLanguage.Georgian, string merchantTransactionId = null)
{
var options = GetActiveOptions(currency);

Expand All @@ -149,12 +149,16 @@ public async Task<ExecuteReoccurringTransactionResult> ExecuteReoccurringTransac
{ "currency", ((int)currency).ToString() },
{ "client_ip_addr", clientIpAddress },
{ "description", description },
{ "desc", description },
{ "language", language },
{ "biller_client_id", billerClientId },
{ "mrch_transaction_id", merchantTransactionId }
};

if (initiator == TransactionInitiator.Merchant)
{
requestParameters.Add("initiator", "merchant");
}

return new ExecuteReoccurringTransactionResult(await MakePostRequestAsync(requestParameters, options));
}

Expand Down Expand Up @@ -208,7 +212,6 @@ public async Task<ExecutePreAuthorizationResult> ExecutePreAuthorizationAsync(st
{ "currency", ((int)currency).ToString() },
{ "client_ip_addr", clientIpAddress },
{ "description", description },
{ "desc", description },
};

return new ExecutePreAuthorizationResult(await MakePostRequestAsync(requestParameters, options));
Expand Down Expand Up @@ -315,6 +318,77 @@ public async Task<CloseBusinessDayResult> CloseBusinessDayAsync()
return new CloseBusinessDayResult(await MakePostRequestAsync(requestParameters, options));
}

/// <summary>
/// Command - D
/// </summary>
/// <param name="currency"></param>
/// <param name="clientIpAddress"></param>
/// <param name="description"></param>
/// <param name="recurringPaymentUniqueId"></param>
/// <param name="expiryDate"></param>
/// <param name="language"></param>
/// <param name="merchantTransactionId"></param>
/// <returns></returns>
public async Task<RegisterTransactionResult> RegisterPreAuthorizationAndGetReoccuringPaymentId(int amount, CurrencyCode currency, string clientIpAddress, string description, string recurringPaymentUniqueId, DateTimeOffset? expiryDate = null, string language = PaymentUiLanguage.Georgian, string merchantTransactionId = null)
{
var options = GetActiveOptions(currency);

expiryDate = expiryDate ?? GetDefaultExpiryDate();

var requestParameters = new Dictionary<string, string>()
{
{ "command", "d" },
{ "amount", amount.ToString() },
{ "currency", ((int)currency).ToString() },
{ "client_ip_addr", clientIpAddress },
{ "description", description },
{ "language", language },
{ "msg_type", "DMS" },
{ "biller_client_id", recurringPaymentUniqueId },
{ "perspayee_expiry", expiryDate.Value.ToString("MMyy") },
{ "template_type", "DMS" }
};

return new RegisterTransactionResult(await MakePostRequestAsync(requestParameters, options));
}

/// <summary>
/// Command - F
/// </summary>
/// <param name="amount"></param>
/// <param name="currency"></param>
/// <param name="clientIpAddress"></param>
/// <param name="description"></param>
/// <param name="billerClientId"></param>
/// <param name="language"></param>
/// <param name="merchantTransactionId"></param>
/// <returns></returns>
public async Task<ExecuteReoccurringTransactionResult> ExecuteReoccurringPreAuthorizationAsync(int amount, CurrencyCode currency, string clientIpAddress, string description, string billerClientId, TransactionInitiator initiator, string language = PaymentUiLanguage.Georgian, string merchantTransactionId = null)
{
var options = GetActiveOptions(currency);

var requestParameters = new Dictionary<string, string>()
{
{ "command", "f" },
{ "amount", amount.ToString() },
{ "currency", ((int)currency).ToString() },
{ "client_ip_addr", clientIpAddress },
{ "description", description },
{ "language", language },
{ "biller_client_id", billerClientId },
{ "mrch_transaction_id", merchantTransactionId },
{ "template_type", "DMS" }
};

if (initiator == TransactionInitiator.Merchant)
{
requestParameters.Add("initiator", "merchant");
}

return new ExecuteReoccurringTransactionResult(await MakePostRequestAsync(requestParameters, options));
}


/// <summary>
/// Gets redirect URL where the client should be navigated to enter card details
/// </summary>
Expand Down
5 changes: 5 additions & 0 deletions Solution/TbcBankEcommerceClientSolution.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{87E0BC95-E
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.WebApp", "Docs\Example.WebApp\Example.WebApp.csproj", "{204987D7-7ED0-4C7E-9876-1A073B2473CA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DevOps", "DevOps", "{2C81DBA6-53DF-4F04-9CE1-9F3090BF44E5}"
ProjectSection(SolutionItems) = preProject
..\.github\workflows\pull_request.yml = ..\.github\workflows\pull_request.yml
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down
30 changes: 19 additions & 11 deletions Solution/Testing/TbcBank.EcommerceClient.TestConsoleApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,25 @@ string redirectUrl
CheckTransactionResult checkTransactionAndGetReoccuringPaymentIdResult
= await client.CheckTransactionResultAsync(registerTransactionAndGetReoccuringPaymentIdResult.TransactionId, ClientIpAddress);

ExecuteReoccurringTransactionResult executeReoccurringTransactionResult
= await client.ExecuteReoccurringTransactionAsync(4, CurrencyCode.GEL, ClientIpAddress, "Test Transaction - ExecuteReoccurringTransactionAsync", billerClientId);

CheckTransactionResult checkExecuteReoccurringTransactionResult
= await client.CheckTransactionResultAsync(executeReoccurringTransactionResult.TransactionId, ClientIpAddress);

ReverseTransactionResult reverseResult
= await client.ReverseTransactionAsync(executeReoccurringTransactionResult.TransactionId, 1);

RefundTransactionResult refundResult
= await client.RefundTransactionAsync(executeReoccurringTransactionResult.TransactionId, 1);
ExecuteReoccurringTransactionResult executeReoccurringTransactionResultForClient
= await client.ExecuteReoccurringTransactionAsync(4, CurrencyCode.GEL, ClientIpAddress, "Test Transaction - ExecuteReoccurringTransactionAsync", billerClientId, TransactionInitiator.Client);
ExecuteReoccurringTransactionResult executeReoccurringTransactionResultForMerchant
= await client.ExecuteReoccurringTransactionAsync(4, CurrencyCode.GEL, ClientIpAddress, "Test Transaction - ExecuteReoccurringTransactionAsync", billerClientId, TransactionInitiator.Merchant);

CheckTransactionResult checkExecuteReoccurringTransactionResultForClient
= await client.CheckTransactionResultAsync(executeReoccurringTransactionResultForClient.TransactionId, ClientIpAddress);
CheckTransactionResult checkExecuteReoccurringTransactionResultForMerchant
= await client.CheckTransactionResultAsync(executeReoccurringTransactionResultForMerchant.TransactionId, ClientIpAddress);

ReverseTransactionResult reverseResultForClient
= await client.ReverseTransactionAsync(executeReoccurringTransactionResultForClient.TransactionId, 1);
ReverseTransactionResult reverseResultForMerchant
= await client.ReverseTransactionAsync(executeReoccurringTransactionResultForMerchant.TransactionId, 1);

RefundTransactionResult refundResultForClient
= await client.RefundTransactionAsync(executeReoccurringTransactionResultForClient.TransactionId, 1);
RefundTransactionResult refundResultForMerchant
= await client.RefundTransactionAsync(executeReoccurringTransactionResultForClient.TransactionId, 1);
}

{
Expand Down

0 comments on commit 6a584d5

Please sign in to comment.