Table of Contents


Stripe Recurring Payments

This document outlines how you can process a recurring payment via Credit Card or SEPA Debit Subscription.

Recurring Payment via Credit Card

In addition to populating the ChargeInfo data, you will also need to populate another data class called “SubscriptionInfo”, via this object you can pass more info about the nature of the recurring payment you want to collect. 

var chargeInfo = new ChargeInfo() {
	Firstname = "Jane",
	Lastname = "Doe",
	Amount = 1500.00M,
	Currency = "USD",
	Country = "US",
	CardNumber = "4242424242424242",
	ExpMonth = 3, 
	ExpYear = 2030, 
	CardCvc = "123", 
	Email = "test@magentrix.com",
	City = "Toronto",
	Street1 = "Main Street",
	ZipCode = "A1A1A1",
	State = "Ontario",
	Description = "Testing Credit Card Subscription"
};


var subscriptionInfo = new SubscriptionInfo() {
	StripeTaxId = "<TaxID>",
	Description = "Testing Subscription CC",
    Interval = "month",
    IntervalCount = 12,
	CancelAt = DateTime.Now.AddDays(7).AddYears(3),
	RedirectUrl = "/aspx/payment3DSConfirmation"
};


var stripe = new Stripe2.StripeHelper('<STRIPE_CONNECTED_APP>'); 
var subscription = stripe.ProcessCreditCardSubscription(chargeInfo, subscriptionInfo);

 

Notes:      
“RedirectUrl” should be provided if 3D Secure authentication is required. You can pass any parameter required, for example: $"/aspx/Payment3DSConfirmation?oppId={oppId}&option={option}"        

“TAX_RATE_ID” create the TaxRate in Stripe Dashboard or via API. Populate the subscriptionInfo.StripeTaxId with the ID. It’s not a required field. Tax will be automatically calculated.

BillingSchemeper_unitDescribes how to compute the price per period. Either per_unit or tiered. 
TaxBehaviorexclusiveIf exclusive: On The Tax Rate, the field inclusive must be set to false, If inclusive: On The Tax Rate, the field inclusive must be set to true 
IntervalyearThe frequency at which a subscription is billed. One of: day, week, month or year
IntervalCount1For example, interval=month and interval_count=3 bills every 3 months
CollectionMethodcharge_automatically 

 

Items (products) associated with the Subscription are required (see PrepareLineItems example below).  

var stripe = new Stripe2.StripeHelper('<STRIPE_CONNECTED_APP>');
var subscription = stripe.ProcessCreditCardSubscription(chargeInfo, subscriptionInfo);
 
//Subscription with Status different to active were processed incorrectly or will be updated off-line. Use webhooks in order for you to receive notifications of status changes on PaymentIntent and Charge objects.if (subscription.Status != "active")
{
	//3D Secure authentication is requiredif (!IsEmpty(subscription.RedirectToUrl))
         return Redirect(subscription.RedirectToUrl);
        	    
    ModelState.AddModelError($"The Transaction's Status is {subscription.Status}.");
   	      
	return View(chargeInfo);
}

 

PrepareLineItems example code: 

private List<ChargeInfoLineItem> PrepareLineItems(string oppId)
{
   var lineItems = new List<ChargeInfoLineItem>();
   var oppLineItems = Database.Query<Force__OpportunityLineItem>()
	                   .Where(f => f.OpportunityId == oppId)
	                   .Include(f => f.Product2, f => new { f.Id, f.Name, f.Descriptionn })
	                   .ToListAsAdmin();
	                       
   foreach (var item in oppLineItems)
   {
      var chargeInfoLineItem = new ChargeInfoLineItem {
	      ItemId = item.Product2.Id,
	      Name = item.Product2.Name,
	      Description = item.Product2.Description,
	      Quantity = (int)item.Quantity.Value,
	      Price = item.UnitPrice.Value,
      };
	        
      lineItems.Add(chargeInfoLineItem);
   }
	    
   return lineItems;                    
}

 

Stripe SEPA Debit Subscription

SEPA Direct Debit is used to debit bank accounts within the Single Euro Payments Area (SEPA) region.  

In order to debit an account, businesses must collect their customer’s name and bank account number in IBAN format. During the payment flow, customers must accept a mandate that gives the business an authorization to debit the account. Stripe is able to generate this mandate for businesses to present to their customers.

SEPA Direct Debit payments are an asynchronous method, so funds are not immediately available. A charge created from a SEPA Direct Debit source can remain in a pending state for up to 14 business days from its creation, though the average time is around five business days. Once the charge is confirmed, its status is updated to succeed. Your integration must use webhooks in order for you to receive notifications of status changes on PaymentIntent and Charge objects.
 

var chargeInfo = new ChargeInfo() {
  AccountNumber = "IT40S0542811101000000123456",
  NameOnAccount = "Jane Doe",
  Amount = 25.00M,
  Currency = "EUR",
  Country = "IT",
  Email = "test@magentrix.com",
  City = "Toronto",
  Street1 = "Main Street",
  ZipCode = "A1A1A1",
  State = "Ontario",
  Description = "Testing SEPA Debit Subscription"
};

var subscriptionInfo = new SubscriptionInfo() {
  StripeTaxId = StripeApp.TAX_RATE_ID,
  Description = "Testing Subscription CC",
  CancelAt = DateTime.Now.AddDays(7).AddYears(3),
};


TAX_RATE_ID: Create the TaxRate in Stripe Dashboard or via API. Populate the subscriptionInfo.StripeTaxId with the ID. It’s not a required field. Tax will be automatically calculated.  
See Stripe - Credit Card Subscription to get more details about the SubscriptionInfo Object.   

NOTE: SEPA Credit Payment required Users consent to create a mandate. So, consider adding the verbiage below on your UI, Users can read and agree with it before Submitting the request.  

“By providing your IBAN and confirming this payment, you are authorizing COMPANY_NAME and Stripe, our payment service provider, to send instructions to your bank to debit your account and your bank to debit your account in accordance with those instructions. You are entitled to a refund from your bank under the  terms and conditions of your agreement with your bank. A refund must be claimed within 8 weeks starting from the date on which your account was debited.”

var lineItems = new List<ChargeInfoLineItem>();
chargeInfo.LineItems = PrepareLineItems(oppId);

var stripe = new Stripe2.StripeHelper('<STRIPE_CONNECTED_APP>');
var paymentIntent = stripe.ProcessSepaDebitSubscription(chargeInfo, subscriptionInfo);

//PaymentIntent with Status equal to processing will be updated off-line, requires WebHookif (paymentIntent.Status != "succeeded")
{
    if (paymentIntent.Status == "processing")
       return View("Message", new { 
             Title = "Thank You", 
             Message = "Your payment is being processed. You will receive an email if the Payment is successful." 
       });

     ModelState.AddModelError($"The Transaction's Status is {paymentIntent.Status}. Please, try again using the same or another Credit Card.");
            	      
     return View(chargeInfo);
}

The paymentIntent above will provide you with the following sample data:

{
	"id": "pi_3Mj5m6BP3jFzD6fq16WbWT18",
	"object": "payment_intent",
	"client_secret": "pi_3Mj5m6BP3jFzD6fq16WbWT18_secret_L0GhI7GZOpfuMJOCsPea5QGu0",
	"payment_method": "pm_1Mj5m4BP3jFzD6fqZsTRaKS3",
	"customer": "cus_NU3tnSWGMjoe7r",
	"currency": "eur",
	"amount": 16950,
	"next_action": null,
	"description": "Subscription creation",
	"latest_charge": "py_3Mj5m6BP3jFzD6fq1JRSnzto",
	"status": "processing",
	"SubscriptionId": "sub_1Mj5m6BP3jFzD6fqW82RZ5lg",
	"RedirectToUrl": null,
	"AutomaticPaymentMethods": false
}

To fully Test your integration, consider testing all possible scenarios:

The charge status transitions from pending to succeed: 
AccountNumber = “IT40S0542811101000000123456”
 

The charge status transitions from pending to fail.
AccountNumber = “IT60X0542811101000000123456”
 

The charge status transitions from pending to succeeded, but a dispute is immediately created.         AccountNumber = “IT83S0542811101000000123458”


How to get details about Subscriptions created?

The sample codes below shows how you can get Payment Intent, Subscription information, the Invoice or Charge details from Stripe.
 

var stripe = new Stripe2.StripeHelper('<STRIPE_CONNECTED_APP>');

// get payment intent using Id
Stripe2.PaymentIntent paymentIntent = stripe.GetPaymentIntent(paymentIntentId); 

// get subscription details
Stripe2.Subscription subscription = stripe.GetSubscription(subscriptionId);

// get invoice
Stripe2.Invoice invoice = stripe.GetInvoice(invoiceId);

// get Charge
Stripe2.Charge charge = stripe.GetCharge(chargeId);

 

Here is complete example:

var striper = new Stripe2.StripeHelper('<STRIPE_CONNECTED_APP>'); 
var subscription = stripe.ProcessCreditCardSubscription(chargeInfo, subscriptionInfo);

if (subscription != null)
{ 
   Stripe2.Invoice invoice = stripe.GetInvoice(subscription.LatestInvoice);
}

Here is an example response:

{
   "id": "in_1Mj5QmBP3jFzD6fqCz20YOkf", 
   "object": "invoice", 
   "payment_intent": "pi_3Mj5QmBP3jFzD6fq1sUUilCo", 
   "charge": "ch_3Mj5QmBP3jFzD6fq1FXE0wmK",
   "subscription": "sub_1Mj5QlBP3jFzD6fqQJlV1Ecp", 
   "status": "paid" 
}