OrderCloud.Integrations.Payment.Stripe
1.0.1-alpha
See the version list below for details.
dotnet add package OrderCloud.Integrations.Payment.Stripe --version 1.0.1-alpha
NuGet\Install-Package OrderCloud.Integrations.Payment.Stripe -Version 1.0.1-alpha
<PackageReference Include="OrderCloud.Integrations.Payment.Stripe" Version="1.0.1-alpha" />
paket add OrderCloud.Integrations.Payment.Stripe --version 1.0.1-alpha
#r "nuget: OrderCloud.Integrations.Payment.Stripe, 1.0.1-alpha"
// Install OrderCloud.Integrations.Payment.Stripe as a Cake Addin #addin nuget:?package=OrderCloud.Integrations.Payment.Stripe&version=1.0.1-alpha&prerelease // Install OrderCloud.Integrations.Payment.Stripe as a Cake Tool #tool nuget:?package=OrderCloud.Integrations.Payment.Stripe&version=1.0.1-alpha&prerelease
OrderCloud.Integrations.Payment.Stripe
This project brings payment processing to your ecommerce app using the Stripe API. It will be 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 Stripe. 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 transaction or Refund, depending on if capture has taken place.
Table of key credit card events
Card details are collected via Stripe.js in the client. Once details are collected, a Payment Method will need to be created either in the client or in your hosted server. Once a Payment Method is created, you will use that ID in your request body to ICreditCardProcessor.AuthorizeOnlyAsync().
Description | Integration Method | Stripe Documentation | OrderCloud Platform Context |
---|---|---|---|
Request an authnetication cred for the IFrame | ICreditCardProcessor.GetIFrameCredentialAsync() | Link | Stripe publishable key is set in a config and forwarded to the front end. |
Tokenize the user's card details with Stripe Payment Element | 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.Stripe
Authentication and Injection
You will need a SecretKey configured to authneticate to the Stripe API. Click here to learn more about Stripe's API keys.
var stripeService = new StripeService(new StripeConfig()
{
SecretKey = "sk_123456...."
});
For efficient use of compute resources and clean code, create 1 StripeService object and make it available throughout your project using inversion of control dependency injection.
services.AddSingleton<ICreditCardProcessor>(stripeService);
services.AddSingleton<ICreditCardSaver>(stripeService);
Notice that ICreditCardProcessor and ICreditCardSaver are not specific to Stripe. 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 StripeService. The layer of abstraction that ICreditCardProcessor and ICreditCardSaver provide decouples your code from Stripe 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, StripeService 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 StripeService exactly as above. You can provide empty strings for the credentials. However, when you call methods on the interfaces, provide the optional configOverride
parameter.
StripeConfig 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)
- Stripe.net (>= 39.105.0)
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.4.0 | 89 | 11/27/2024 |
2.3.0 | 9,569 | 10/31/2022 |
1.0.3-alpha | 212 | 5/27/2022 |
1.0.2-alpha | 2,051 | 5/17/2022 |
1.0.1-alpha | 185 | 5/17/2022 |