Skip to content
Merged
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
61 changes: 61 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Changelog

All notable changes to SaferPay.NetCore are documented here.

## v1.52.02
+ Multi-targeted the library to `.NET 8.0` and `.NET 10.0`
+ Added the `SaferPay.Tests` xUnit project (unit + sandbox integration coverage)
+ Documented the `Transaction/QueryPaymentMeans` and `Transaction/AdjustAmount` methods

## v1.52.01
+ Updated library target framework to `.NET 8.0`
+ Removed unsupported `.NET 6.0` and legacy test runtime targets
+ Improved overall package compatibility with current and future .NET runtimes
+ Fixed recursive `Dispose()` implementation causing `StackOverflowException`
+ Fixed missing `_jsonSerializerSettings` initialization in the 4-argument constructor
+ Improved `RestClient` lifecycle management to prevent socket/resource leaks under load
+ Fixed exception rethrow handling to preserve original stack traces
+ Normalized `CreditCardExpiration` year handling across constructor, setters and parsing
+ Fixed `CreditCardExpiration.Parse()` producing invalid `MMYYYY` values instead of `MMYY`
+ Improved `CreditCardExpiration.ToString()` formatting consistency
+ Updated package metadata and NuGet packaging configuration
+ Improved GitHub Actions build, validation and NuGet publishing workflow
+ Updated package validation and build pipeline for `.NET 8`
+ General reliability, maintainability and runtime compatibility improvements

## v1.52
+ Updated to use the latest version of the JSON API, `v1.52`
+ Added `Saferpay Management API`.
+ Added `PaymentPage GetConfigurations` method to Saferpay Management API
+ Added `WITH_SUCCESSFUL_THREE_DS_CHALLENGE` as a valid value for the field Condition
+ Added `MastercardTLID` to the `IssuerReference` container in the response
+ removed `PayerId` from the `PayPal` container

## v1.51
+ Updated to use the latest version of the JSON API, `v1.51`
+ added `PAYPAL` as valid value for field Type in `Alias/Insert`
+ added `ONLINE_CHALLENGED` as valid value for field Type of container `Check` in `Alias/Insert`
+ removed `OK_AUTHENTICATED` as valid value from field `Result` of container `CheckResult`.
+ removed `INVOICE` as valid value from `PaymentMethods` in `PaymentPage/Initialize`
+ added fields `Authenticated` and `AuthenticationType` to container `AuthenticationResult`. Removed field `Result` from container in return.
+ added field `FundingSource` to container `Card`
+ field `CountryCode` in container `ForeignRetailer` is now mandatory.

## v1.50
+ Updated to use the latest version of the JSON API, `v1.50`
+ Added value `ONLINE_STRONG` to Type in the `Check` container and added new container `ExternalThreeDS` in `Alias/InsertDirect`
+ Added `GIFTCARD` as valid value for the field `PaymentMethods`
+ Introduced a new function to provide Dynamic Currency Conversion (`DCC`) inquiry details for your customer: `Transaction\DccInquiry`
+ The payment methods `GIROPAY`, `PAYDIREKT`, `SOFORT` and `WLCRYPTOPAYMENTS` are no longer supported.
+ `Transaction/AuthorizeDirect` is extended with the new subcontainer `DCC`, which references the response from `Transaction/DccInquiry` and payer's decision whether he accepts or declines `DCC` offer
+ Added `WERO` as valid value for the field `PaymentMethods`
+ Added `HolderName` and `IBAN` to the BankAccount container in `PaymentPage/Assert`
+ `Transaction/RefundDirect` is extended with the new subcontainer `BankAccount`. This is a required container for PostFinance Instant Payout

## v1.46
+ Updated to use the latest version of the JSON API, `v1.46`
+ Added new subcontainer `ExternalThreeDS` to container `Authentication`. This affects the following requests: `Transaction/AuthorizeDirect`
+ Updated `AuthorizeDirect` method to use the new `ExternalThreeDS` subcontainer.

## v1.45.01
+ Added `REKA` as alternative payment method to `PaymentPagePaymentMethods`.
272 changes: 82 additions & 190 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,229 +1,121 @@
# SaferPay.NetCore Json Api V1.52
# SaferPay.NetCore (Json Api V1.52)

This repository is an implementation of the [SaferPay.Net](https://github.com/bmbsqd/saferpay-net) library, with updates to use **.NetCore 8.0** and **RestSharp** instead of HttpClient. All methods have been extended with sync and async calls.
An implementation of the [SaferPay.Net](https://github.com/bmbsqd/saferpay-net) library, updated to target **.NET 8.0 / .NET 10.0** and to use **RestSharp** instead of HttpClient. Every method is available in both sync and async form.

The implementation is based on the latest version of the JSON API, **v1.52**, which can be found at the following URL: http://saferpay.github.io/jsonapi/#ChapterTransaction
It tracks the JSON API **v1.52** ([reference](http://saferpay.github.io/jsonapi/#ChapterTransaction)). Test cards and usage are documented on the [SaferPay integration guide](https://docs.saferpay.com/home/integration-guide/testing-and-go-live#visa-and-v-pay).

You can find Test Cards and explanation of usage at: https://docs.saferpay.com/home/integration-guide/testing-and-go-live#visa-and-v-pay
## What's New

### Test Pages
+ Multi-targets `.NET 8.0` and `.NET 10.0`
+ `HttpClient` replaced by `RestSharp`
+ Tracks the latest JSON API, `v1.52`
+ `BaseUri` replaced by a `SandBox` flag (the base URL is derived from it)
+ Simpler constructors and property descriptions taken from the API docs
+ String properties converted to enums
+ Interface channels and extension methods for the most common calls
+ `IsSuccess` and `Error` on every result object
+ Example console app included in the solution

**Create Test Account**
```
https://test.saferpay.com/BO/SignUp
```
## Methods

**Login Test Account**
```
https://test.saferpay.com/BO/Login
```

### What's New
+ Upgrade to `.NetCore 8.0`
+ HttpClient has been replaced by `RestSharp`
+ Updated to use the latest version of the JSON API, `v1.52`
+ Replaced `BaseUri` with `SandBox` mode. BaseUri is now generated based on SandBox mode for testing or live environments.
+ Updated and improved constructors for easier usage.
+ Added descriptions to Properties based on the API documentation.
+ Converted string properties to Enum values.
+ Added Examples and Test Console App in the Solution.
+ Added Interface Channels for ease of usage.
+ Added Extensions for the most used methods for direct use in the client.
+ Added `IsSuccess` and `Error` properties in ResultObject.
+ Updated all enum values, models, and interfaces.

### Methods
Implemented all methods:

+ **Payment Page Methods:** `Initialize`, `Assert`
+ **Transaction Methods:** `Initialize`, `Authorize`, `AuthorizeDirect`, `AuthorizeReferenced`, `Capture`, `MultipartCapture`, `AssertCapture`, `MultipartFinalize`, `Refund`, `AssertRefund`, `RefundDirect`, `Cancel`, `RedirectPayment`, `AssertRedirectPayment`, `Inquire`, `AlternativePayment`, `QueryAlternativePayment`, `DccInquiry`
+ **Payment Page:** `Initialize`, `Assert`
+ **Transaction:** `Initialize`, `Authorize`, `QueryPaymentMeans`, `AdjustAmount`, `AuthorizeDirect`, `AuthorizeReferenced`, `Capture`, `MultipartCapture`, `AssertCapture`, `MultipartFinalize`, `Refund`, `AssertRefund`, `RefundDirect`, `Cancel`, `RedirectPayment`, `AssertRedirectPayment`, `Inquire`, `AlternativePayment`, `QueryAlternativePayment`, `DccInquiry`
+ **Secure Card Data:** `Insert`, `AssertInsert`, `InsertDirect`, `Update`, `Delete`, `Inquire`
+ **Batch:** `Close`
+ **Omni Channel:** `InsertAlias`, `AcquireTransaction`
+ **Saferpay Management API:** `Licensing CustomerLicense`, `PaymentPageConfig GetConfigurations`, `SaferpayFieldsAccessToken CreateAccessToken`, `SaferpayFieldsAccessToken DeleteAccessToken`, `SecurePayGate Create SingleUsePaymentLink`, `SecurePayGate SingleUsePaymentLink`, `SecurePayGate Delete SingleUsePaymentLink`, `Terminal GetTerminal`, `Terminals GetTerminals`, `TransactionReporting GetTransactions`
+ **Management API:** `Licensing CustomerLicense`, `PaymentPageConfig GetConfigurations`, `SaferpayFieldsAccessToken CreateAccessToken`, `SaferpayFieldsAccessToken DeleteAccessToken`, `SecurePayGate Create/Get/Delete SingleUsePaymentLink`, `Terminal GetTerminal`, `Terminals GetTerminals`, `TransactionReporting GetTransactions`

### Global Settings and Usage (With Client Extensions)
## Usage

Define Settings;
```csharp
SaferPay.Config.Settings.Default.Username = "ApiUserName";
SaferPay.Config.Settings.Default.Password = "ApiPassword";
SaferPay.Config.Settings.Default.TerminalId = "TerminalId";
SaferPay.Config.Settings.Default.CustomerId = "CustomerId";
SaferPay.Config.Settings.Default.SandBox = true;
```
### 1. Create a client

Get Client Instance;
```csharp
ISaferPayClient Client = SaferPay.Config.Settings.Client();
```
Either configure the global settings and pull a client from them:

Initialize request for Payment Page;
```csharp
string OrderID = "123456";
SaferPay.Config.Settings.Default.CustomerId = "CustomerId";
SaferPay.Config.Settings.Default.TerminalId = "TerminalId";
SaferPay.Config.Settings.Default.Username = "ApiUserName";
SaferPay.Config.Settings.Default.Password = "ApiPassword";
SaferPay.Config.Settings.Default.SandBox = true;

InitializePaymentPageRequest req = new InitializePaymentPageRequest();
req.TerminalId = TestConfig.TerminalId;
req.Payment = new Payment(123.45M, "TRY", OrderID);
req.ReturnUrl = $"{TestConfig.WebPage}payment-page?orderId={OrderID}";
ISaferPayClient client = SaferPay.Config.Settings.Client();
```

Call Api Async;
```csharp
var result = await Client.InitializePaymentPageAsync(req);
if (result != null && result.IsSuccess)
{
// Success
Console.Write("Response Successful : ");
Console.WriteLine(result.Json());
}
else if (result != null)
{
// Failed
Console.Write("Response Failed : ");
Console.WriteLine(result.Error.Json());
}
else
{
// Error
Console.Write("Error !");
}
```
Or build one directly:

Call Api Sync;
```csharp
var result = Client.InitializePaymentPage(req);
if (result != null && result.IsSuccess)
{
// Success
Console.Write("Response Successful : ");
Console.WriteLine(result.Json());
} else if(result != null)
{
// Failed
Console.Write("Response Failed : ");
Console.WriteLine(result.Error.Json());
} else
{
// Error
Console.Write("Error !");
}
ISaferPayClient client = new SaferPayClient("CustomerId", "TerminalId", "UserName", "Password", sandBox: true);
```


### Basic Usage With Interface Channels
### 2. Build a request


Initialize the ApiClient;
```csharp
ISaferPayClient Client = new SaferPayClient("CustomerId", "TerminalId", "UserName", "PassWord", true);
string orderId = "123456";

var request = new InitializePaymentPageRequest
{
TerminalId = TestConfig.TerminalId,
Payment = new Payment(123.45M, "TRY", orderId),
ReturnUrl = $"{TestConfig.WebPage}payment-page?orderId={orderId}",
};
```

Get Interface Channel to use, example based on Transaction;
### 3. Send it (async or sync)

```csharp
ITransaction payment = Client.Transaction;
var result = await client.InitializePaymentPageAsync(request);
// sync equivalent:
// var result = client.InitializePaymentPage(request);
```

Created Credit Card request;
```csharp
string OrderID = "123456";
### 4. Handle the result

InitializeRequest req = new InitializeRequest(TestConfig.TerminalId, 123.45M, "TRY", OrderID, $"{TestConfig.WebPage}transaction?orderId={OrderID}").SetCard("9010004150000009", 12, 30, "123", "Card Holder Name");
```
Every call returns a result exposing `IsSuccess`, the typed response and an `Error` object:

Call Api Async;
```csharp
var result = await payment.InitializeAsync(req);
if (result != null && result.IsSuccess)
{
// Success
Console.Write("Response Successful : ");
Console.WriteLine(result.Json());
if (result != null && result.IsSuccess) {
Console.WriteLine(result.Json()); // success
}
else if (result != null)
{
// Failed
Console.Write("Response Failed : ");
Console.WriteLine(result.Error.Json());
else if (result != null) {
Console.WriteLine(result.Error.Json()); // API returned an error
}
else
{
// Error
Console.Write("Error !");
else {
Console.WriteLine("Request failed."); // null / transport error
}
```

Call Api Sync;
### Interface channels

Each API group is also reachable as a typed channel on the client, which keeps related calls together:

```csharp
var result = payment.Initialize(req);
if (result != null && result.IsSuccess)
{
// Success
Console.Write("Response Successful : ");
Console.WriteLine(result.Json());
} else if(result != null)
{
// Failed
Console.Write("Response Failed : ");
Console.WriteLine(result.Error.Json());
} else
{
// Error
Console.Write("Error !");
}
ITransaction transaction = client.Transaction;

var request = new InitializeRequest(
TestConfig.TerminalId, 123.45M, "TRY", orderId,
$"{TestConfig.WebPage}transaction?orderId={orderId}")
.SetCard("9010004150000009", 12, 30, "123", "Card Holder Name");

var result = await transaction.InitializeAsync(request);
// sync: transaction.Initialize(request);
```

### Changelog

`v1.52.01`
+ Updated library target framework to `.NET 8.0`
+ Removed unsupported `.NET 6.0` and legacy test runtime targets
+ Improved overall package compatibility with current and future .NET runtimes
+ Fixed recursive `Dispose()` implementation causing `StackOverflowException`
+ Fixed missing `_jsonSerializerSettings` initialization in the 4-argument constructor
+ Improved `RestClient` lifecycle management to prevent socket/resource leaks under load
+ Fixed exception rethrow handling to preserve original stack traces
+ Normalized `CreditCardExpiration` year handling across constructor, setters and parsing
+ Fixed `CreditCardExpiration.Parse()` producing invalid `MMYYYY` values instead of `MMYY`
+ Improved `CreditCardExpiration.ToString()` formatting consistency
+ Updated package metadata and NuGet packaging configuration
+ Improved GitHub Actions build, validation and NuGet publishing workflow
+ Updated package validation and build pipeline for `.NET 8`
+ General reliability, maintainability and runtime compatibility improvements

`v1.52`
+ Updated to use the latest version of the JSON API, `v1.52`
+ Added `Saferpay Management API`.
+ Added `PaymentPage GetConfigurations` method to Saferpay Management API
+ Added `WITH_SUCCESSFUL_THREE_DS_CHALLENGE` as a valid value for the field Condition
+ Added `MastercardTLID` to the `IssuerReference` container in the response
+ removed `PayerId` from the `PayPal` container

`v1.51`
+ Updated to use the latest version of the JSON API, `v1.51`
+ added `PAYPAL` as valid value for field Type in `Alias/Insert`
+ added `ONLINE_CHALLENGED` as valid value for field Type of container `Check` in `Alias/Insert`
+ removed `OK_AUTHENTICATED` as valid value from field `Result` of container `CheckResult`.
+ removed `INVOICE` as valid value from `PaymentMethods` in `PaymentPage/Initialize`
+ added fields `Authenticated` and `AuthenticationType` to container `AuthenticationResult`. Removed field `Result` from container in return.
+ added field `FundingSource` to container `Card`
+ field `CountryCode` in container `ForeignRetailer` is now mandatory.

`v1.50`
+ Updated to use the latest version of the JSON API, `v1.50`
+ Added value `ONLINE_STRONG` to Type in the `Check` container and added new container `ExternalThreeDS` in `Alias/InsertDirect`
+ Added `GIFTCARD` as valid value for the field `PaymentMethods`
+ Introduced a new function to provide Dynamic Currency Conversion (`DCC`) inquiry details for your customer: `Transaction\DccInquiry`
+ The payment methods `GIROPAY`, `PAYDIREKT`, `SOFORT` and `WLCRYPTOPAYMENTS` are no longer supported.
+ `Transaction/AuthorizeDirect` is extended with the new subcontainer `DCC`, which references the response from `Transaction/DccInquiry` and payer's decision whether he accepts or declines `DCC` offer
+ Added `WERO` as valid value for the field `PaymentMethods`
+ Added `HolderName` and `IBAN` to the BankAccount container in `PaymentPage/Assert`
+ `Transaction/RefundDirect` is extended with the new subcontainer `BankAccount`. This is a required container for PostFinance Instant Payout

`v1.46`
+ Updated to use the latest version of the JSON API, `v1.46`
+ Added new subcontainer `ExternalThreeDS` to container `Authentication`. This affects the following requests: `Transaction/AuthorizeDirect`
+ Updated `AuthorizeDirect` method to use the new `ExternalThreeDS` subcontainer.

`v1.45.01`
+ Added `REKA` as alternative payment method to `PaymentPagePaymentMethods`.
The result is handled exactly as shown in step 4.

## Tests

The solution ships two test projects at the repository root:

+ **`SaferPay.Tests`** : automated xUnit suite (`Unit` + sandbox `Integration`). Run it with:

```bash
dotnet test SaferPay.Tests/SaferPay.Tests.csproj
```

Integration tests hit `test.saferpay.com` with the public Viwo sandbox account by default. Override it with the `SAFERPAY_CUSTOMER_ID`, `SAFERPAY_TERMINAL_ID`, `SAFERPAY_USERNAME` and `SAFERPAY_PASSWORD` environment variables, or set `SAFERPAY_SKIP_INTEGRATION=1` for a fully offline run.

+ **`SaferPay.Test`** : interactive console playground that demonstrates the API end to end. See [`SaferPay.Test/README.md`](SaferPay.Test/README.md).

## Changelog

See [CHANGELOG.md](CHANGELOG.md) for the full version history.
2 changes: 1 addition & 1 deletion SaferPay.Test/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Console = Colorful.Console;

Console.WriteAsciiStyled("SaferPay Test Console", new Colorful.StyleSheet(Color.Orange));
Console.WriteLine("Json Api Version: 1.46", System.Drawing.Color.OrangeRed);
Console.WriteLine("Json Api Version: 1.52", System.Drawing.Color.OrangeRed);
Console.WriteLine("By Viwo Dev");
Console.WriteLine("https://github.com/viwodev/SaferPay.NetCore");
Console.WriteLine();
Expand Down
Loading
Loading