OrderCloud.Integrations.Payment.BlueSnap
1.0.2-alpha
See the version list below for details.
dotnet add package OrderCloud.Integrations.Payment.BlueSnap --version 1.0.2-alpha
NuGet\Install-Package OrderCloud.Integrations.Payment.BlueSnap -Version 1.0.2-alpha
<PackageReference Include="OrderCloud.Integrations.Payment.BlueSnap" Version="1.0.2-alpha" />
paket add OrderCloud.Integrations.Payment.BlueSnap --version 1.0.2-alpha
#r "nuget: OrderCloud.Integrations.Payment.BlueSnap, 1.0.2-alpha"
// Install OrderCloud.Integrations.Payment.BlueSnap as a Cake Addin #addin nuget:?package=OrderCloud.Integrations.Payment.BlueSnap&version=1.0.2-alpha&prerelease // Install OrderCloud.Integrations.Payment.BlueSnap as a Cake Tool #tool nuget:?package=OrderCloud.Integrations.Payment.BlueSnap&version=1.0.2-alpha&prerelease
OrderCloud.Integrations.Payment.BlueSnap
This project brings payment processing to your ecommerce app using the BlueSnap API. It is published as a nuget code library and conforms to the standard interfaces ICreditCardProcessor
and ICreditCardSaver
published in the base library ordercloud-dotnet-catalyst.
Payment Processing Basics
The OrderCloud API does not have integration points designed specifically for payment proccesing events. Yet secure payments are critical to every Ecommerce solution. Here we will share best practices for payments which are important to understand before using this library.
- As an online retailer, your payments technology needs to be PCI compliant. This will be a much simpler process if you correctly use a payment gateway provider like BlueSnap. Correct use means that your UI for entering card details is an Iframe owned by the payment gateway and that you never save or transmit full card numbers or CVVs. In other words, the code you write should only handle tokens or IDs representing card numbers. These tokens should be generated by the payment gateway's Iframe. Do not put full card numbers in OrderCloud!
- The same rules apply to a user's saved cards. They should be vaulted in the processor's system, and only the Token stored in OrderCloud or your database.
- Once the user enters their payment details and you've seccurely tokenized it, what happens next? For credit cards, you have 2 choices. You can authorize the card - which verifies funds are available and holds them, but is easy to reverse with a void. Or you can authorize and capture - which begins the transfer of funds immediately, but can only be reversed with a refund (which will cost you, the merchant, a processing fee). Incorrectly placed, canceled, or refunded orders are very common in Ecommerce, so it is strongly recommended that you wait to Capture.
- Both the authorization request and the capture request must be made from a secure server-side context. Authorization should take place only after a user has indicated they want to submit the order, but it must succeed before an Order's status should be set to submitted. A pre-webhook endpoint or a proxy endpoint for order submit are the best ways to achieve this.
- There are different valid options for when to Capture, including when the order is shipped, a set time period after the order is placed, or in a nightly batch job.
- If you need to reverse a transaction because of a cancelation or refund, you either Void the authorized transaction or Refund the captured transaction, depending on if capture has taken place.
Table of key credit card events
Description | Integration Method | BlueSnap Documentation | OrderCloud Platform Context |
---|---|---|---|
Request a HostedPaymentFieldToken needed by the FE IFrame |
ICreditCardProcessor.GetIFrameCredentialAsync() | Link | Before the user enters the payment section of checkout, request the token needed for the IFrame from a server-side context. |
Attach the user's card info to the token through the Iframe | None | Link | Save the token and PCI-safe card details (last 4 digits) on a Payment object attached to the Order |
Verify and hold funds | ICreditCardProcessor.AuthorizeOnlyAsync() | Link | Within a pre-webhook or proxy route list Payments, attempt to authorize using the token, set payment accepted true, create a payment transaction, and then submit the Order |
Cancel or refund before capture | ICreditCardProcessor.VoidAuthorizationAsync() | Link | In response to a cancelation, void server-side and create a payment transaction. |
Capture funds | ICreditCardProcessor.CapturePriorAuthorizationAsync() | Link | Catpure when the order is shipped or during a nightly batch job. Create a payment transaction. |
Cancel or refund after capture | ICreditCardProcessor.RefundCaptureAsync() | Link | In response to a cancelation, refund server-side and create a payment transaction. |
Package Installation
This nuget library can be installed in the context of a .NET server-side project. If you already have a .NET project, great. If not, you can follow this guide.
dotnet add package OrderCloud.Integrations.Payment.BlueSnap
Authentication and Injection
You will need these configuration data points to authneticate to the BlueSnap API - BaseUrl, APIUsername, and APIPassword. Follow these steps to get API credentials.
var blueSnapService = new BlueSnapService(new BlueSnapConfig()
{
BaseUrl = "https://sandbox.bluesnap.com" // or https://ws.bluesnap.com
APIUsername = "...",
APIPassword = "...",
});
For efficient use of compute resources and clean code, create 1 BlueSnapService object and make it available throughout your project using inversion of control dependency injection.
services.AddSingleton<ICreditCardProcessor>(blueSnapService);
services.AddSingleton<ICreditCardSaver>(blueSnapService);
Notice that ICreditCardProcessor and ICreditCardSaver are not specific to BlueSnap. They are general to the problem domain and come from the upstream ordercloud-dotnet-catalyst package.
Usage
Inject the interfaces and use them within route logic. Rely on the interfaces whenever you can, not BlueSnapService. The layer of abstraction that ICreditCardProcessor and ICreditCardSaver provide decouples your code from BlueSnap as a specific provider and hides some internal complexity.
public class CreditCardCommand
{
private readonly ICreditCardProcessor _creditCardProcessor;
private readonly ICreditCardSaver _creditCardSaver;
public CheckoutIntegrationEventController(ICreditCardProcessor creditCardProcessor, ICreditCardSaver creditCardSaver)
{
// Inject interface. Implementation will depend on how services were registered, BlueSnapService in this case.
_creditCardProcessor = shipMethodCalculator;
_creditCardSaver = creditCardSaver;
}
...
// Use in pre-submit webhook or proxy route
public async Task<PaymentWithXp> AuthorizeCardPayment(OrderWorksheetWithXp worksheet, PaymentWithXp payment)
{
var authorizeRequest = new AuthorizeCCTransaction()
{
OrderID = worksheet.Order.ID,
Amount = worksheet.Order.Total,
Currency = worksheet.Order.Currency,
AddressVerification = worksheet.Order.BillingAddress,
CustomerIPAddress = "...",
};
var payWithSavedCard = payment?.xp?.SafeCardDetails?.SavedCardID != null;
if (payWithSavedCard)
{
authorizeRequest.SavedCardID = payment.xp.SafeCardDetails.SavedCardID;
authorizeRequest.ProcessorCustomerID = worksheet.Order.FromUser.xp.PaymentProcessorCustomerID;
}
else
{
authorizeRequest.CardToken = payment?.xp?.SafeCardDetails?.Token;
}
CCTransactionResult authorizationResult = await _creditCardProcessor.AuthorizeOnlyAsync(authorizeRequest);
Require.That(authorizationResult.Succeeded, new ErrorCode("Payment.AuthorizeDidNotSucceed", authorizationResult.Message), authorizationResult);
await _oc.Payments.PatchAsync<PaymentWithXp>(OrderDirection.All, worksheet.Order.ID, payment.ID, new PartialPayment { Accepted = true, Amount = authorizeRequest.Amount });
var updatedPayment = await _oc.Payments.CreateTransactionAsync<PaymentWithXp>(OrderDirection.All, worksheet.Order.ID, payment.ID, new PaymentTransactionWithXp()
{
ID = authorizationResult.TransactionID,
Amount = payment.Amount,
DateExecuted = DateTime.Now,
ResultCode = authorizationResult.AuthorizationCode,
ResultMessage = authorizationResult.Message,
Succeeded = authorizationResult.Succeeded,
Type = PaymentTransactionType.Authorization.ToString(),
xp = new PaymentTransactionXp
{
TransactionDetails = authorizationResult,
}
});
return updatedPayment;
}
}
This library also supports more complex cases that require mulitple merchant accounts with different credentials. For example, in a franchise business model where each location is independent but all sell on one ecommerce solution. In that case, still inject one instance of BlueSnapService exactly as above. You can provide empty strings for the credentials. However, when you call methods on the interfaces, provide the optional configOverride
parameter.
BlueSnapConfig configOverride = await FetchPaymentAccountCredentials(supplierID)
var authorize = new AuthorizeCCTransaction();
List<List<ShipMethods> rates = await _creditCardProcessor.AuthorizeOnlyAsynct(authorize, configOverride);
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- ordercloud-dotnet-catalyst (>= 2.1.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
2.3.0 | 379 | 10/31/2022 |
1.0.2-alpha | 186 | 5/17/2022 |
1.0.1-alpha | 200 | 5/4/2022 |