Payment service is one of the major features that cannot be left out when creating an e-commerce website. But the thing is that since it requires lots of sensitive information from the users, developing a fully-fledged payment service takes a lot of work and time. For this reason, many applications choose to use payment services. Stripe is one of the many payment services and in this writing, we will see how we can cooperate with applications.
List of Contents
- Stripe?
-
Using Stripe with Applications
-
Angular & .NET Web API
-
.NET
- Creating .NET Web API
- Setting Up a Database
- HTTPS Set Up
- Installing Packages
- Using Environment Variables
- Creating Entities
- Adding an Intent Interface
- Implementing the Intent Interface
- Registering the Intent Interface as a Service
- Adding a Repository Interface
- Implementing the Repository Interface
- Registering the Repository Interface as a Service
- Adding a Controller
- Run
- Angular
- Stripe Events Testing
-
.NET
-
Angular & .NET Web API
Stripe?
Stripe is a Payment Service System(PSP) that helps the process of payment between the customer and web providers. The service is reliable and used by Google, Zoom, Shopify, Amazon, etc. It is highly customizable and has good documentation so it is a favored choice among developers. It also does not charge unless you earn money from the service which makes it a good fit for a trial.
Payment Process
There are two types of payment processes, normal and enhanced processes.
▶ Normal Process
In the normal process, Stripe sends a token to a user when the user orders from a server. Then the user sends the token back to Stripe through the server to get a confirmation.
▶ Enhanced Process
In the enhanced process, an intent and client secret are created when a user starts the purchase process. And when the user purchases the server the client secret is sent to Stripe to check if the user is the same person and Stripe returns a confirmation. Since the confirmation is sent from Stripe to the user directly, the server uses events that are emitted by Stripe to confirm the payment.
Creating a Stripe Account
Go to Stripe and create an account. Create a project in the test mode.
Now we can use the service in our application.
Using Stripe with Applications
Angular & .NET Web API
Let's see how we can use the service in .NET and Angular applications with the enhanced process.
.NET
Creating .NET Web API
Setting Up a Database
HTTPS Set Up
Since we are dealing with sensitive information, we need to use the certified domain. .NET, by default, runs both on HTTP and HTTPS. But for convenience, we will delete the HTTP
And leave only one address in the HTTPS
Installing Packages
Open the Nuget gallery and install the package below.
Stripe.net
Using Environment Variables
To link the application to Stripe, we need an API key. Go to the Stripe account -> developers -> 'API keys'. Copy the public key and the secret key
Go to the application and paste both in the appsettings file ('appsetting.Development.json' or 'appsetting.json' both are fine but 'appsetting.json' provides better security)
Creating Entities
We need an entity to track the necessary information. Add an entity class and add properties. Payment Id and client secret properties are a must to track the payment and confirm the payment.
Adding an Intent Interface
Add an interface to manage payment
Implementing the Intent Interface
Implement the interface and add a constructor. Inject what is necessary (IConfiguration is needed to use the environment variables).
Update the methods
public async Task<Payment> UpdatePaymentIntent(int id)
{
StripeConfiguration.ApiKey = _config["Stripe:SecretKey"];
var payment = await _payRepo.GetPayByIdAsync(id);
var service = new PaymentIntentService();
PaymentIntent intent;
if (string.IsNullOrEmpty(payment.PaymentIntentId))
{
var options = new PaymentIntentCreateOptions
{
Amount = (long) (100),
Currency = "usd",
PaymentMethodTypes = new List<string> { "card" }
};
intent = await service.CreateAsync(options);
payment.PaymentIntentId = intent.Id;
payment.ClientSecret = intent.ClientSecret;
}
else
{
var options = new PaymentIntentUpdateOptions
{
Amount = (long) (100),
};
await service.UpdateAsync(payment.PaymentIntentId, options);
}
return payment;
}
Registering the Intent Interface as a Service
Go to the Program.cs file and register the interface as a service.
Adding a Repository Interface
Add another interface for dealing with the data
Implementing the Repository Interface
Implement the interface and inject context class.
Update the methods
Registering the Repository Interface as a Service
Go to the Program.cs file and register the interface as a service.
Adding a Controller
Add a controller to set up endpoints. Inject the both interfaces we created earlier
Set up the endpoints
Run
Go to the API folder
cd /API
Run the command below
dotnet watch
Send a POST request and if you see the client secret and payment ID are returned. The first part is completed
Angular
In the root, open the console and create an Angular project.
Install a certificate to use HTTPS
Adding HTTPS
Using Stripe JS
In the Angular project, run the command below.
npm install @stripe/stripe-js
Adding Components
Add components
Fill in the template file with the code below (The attribute variables are used to link to the Stripe JS elements).
<!-- pay.component.html -->
<div>
<div type="text" class="form-control" #cardNum></div>
<div type="text" class="form-control" #cardExp></div>
<div type="text" class="form-control" #cardCvc></div>
<button class="btn" (click)="onSubmit()">Submit</button>
</div>
<span class="text-danger">
{{stripeErrors}}
</span>
Use ViewChild to get the element from the template. And link them to the Stripe JS element as shown below.
// pay.component.ts
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import {
Stripe,
StripeCardCvcElement,
StripeCardExpiryElement,
StripeCardNumberElement,
StripeElementChangeEvent,
loadStripe,
} from '@stripe/stripe-js';
@Component({
selector: 'app-pay',
templateUrl: './pay.component.html',
styleUrls: ['./pay.component.css'],
})
export class PayComponent implements OnInit {
@ViewChild('cardNum') cardNumEl?: ElementRef;
@ViewChild('cardExp') cardExpEl?: ElementRef;
@ViewChild('cardCvc') cardCvcEl?: ElementRef;
stripe: Stripe | null = null;
cardNum?: StripeCardNumberElement;
cardExp?: StripeCardExpiryElement;
cardCvc?: StripeCardCvcElement;
stripeErrors: any;
clientSecret: string = '<clientSecret>';
constructor() {}
ngOnInit(): void {
loadStripe(
'<publicSecretKey>'
).then((stripe) => {
this.stripe = stripe;
const el = stripe?.elements();
if (el) {
this.cardNum = el.create('cardNumber');
this.cardNum.mount(this.cardNumEl?.nativeElement);
this.showStripeError(this.cardNum);
this.cardExp = el.create('cardExpiry');
this.cardExp.mount(this.cardExpEl?.nativeElement);
this.showStripeError(this.cardExp);
this.cardCvc = el.create('cardCvc');
this.cardCvc.mount(this.cardCvcEl?.nativeElement);
this.showStripeError(this.cardCvc);
}
});
}
showStripeError(el: any) {
el.on('change', (e: StripeElementChangeEvent) => {
if (e.error) {
this.stripeErrors = e.error.message;
} else {
this.stripeErrors = null;
}
});
}
onSubmit() {
console.log('card num: ', this.cardNum);
this.stripe
?.confirmCardPayment(this.clientSecret, {
payment_method: {
card: this.cardNum!,
},
})
.then((result) => {
console.log(result);
});
}
}
Replace the <publicSecretKey> with the API public key from your Stripe account
Run the app and you will see some similar to this.
Payment Testing
To test, copy the client secret and replace it with <clientSecret> and submit. For testing, we can use the card number 4242...
Go to the Stripe account and you will see the completed payment.
Stripe Events Testing
Let's see how we can test events coming from Stripe.
Stripe -> developer -> Wep hook -> add an endpoint
Select 'select events'
Open the payment intent box
Check any event you want to track and click Add events
Cilck add endpoint
Go to the test number and it says we need Stipe CLI to test (How to install Stripe CLI)
For window users, open the power shell and type in the command below
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
irm get.scoop.sh | iex
Run the command line as an admin
scoop bucket add stripe https://github.com/stripe/scoop-stripe-cli.git
scoop install stripe --global
Open the project console and check if the Stripe CLI is installed
stripe --version
Log in to Stripe
stripe login
Open the browser (Try a different browser if you cannot open it) and grant access.
If you see this, it is done
stripe listen --forward-to <url>
private const string Secret = "whsec_3711bc92b2c6a9d9ed";
[HttpPost("webhook")]
public async Task<ActionResult> StripeWebhook()
{
var json = await new StreamReader(Request.Body).ReadToEndAsync();
var stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], Secret);
PaymentIntent intent;
Order order;
switch (stripeEvent.Type)
{
case "payment_intent.succeeded":
intent = (PaymentIntent)stripeEvent.Data.Object;
break;
case "payment_intent.payment_failed":
intent = (PaymentIntent)stripeEvent.Data.Object;
break;
}
return new EmptyResult();
}
In this writing, we have seen how to use Stripe.
References
Stripe | Payment Processing Platform for the Internet
GitHub - stripe/stripe-js: Loading wrapper for Stripe.js
Get started with the Stripe CLI | Stripe Documentation
How Does Stripe Work? 2023 Guide To Using Stripe Payments (merchantmaverick.com)
'Web Development Tips' 카테고리의 다른 글
Logistics Delivery Status (Lotte, Post Office) (0) | 2023.12.19 |
---|---|
Adding Open With a Program (0) | 2023.09.01 |
Deprecated (12) | 2023.07.12 |
Environment Variables (2) | 2023.05.31 |
Asynchronous VS Synchronous (1) | 2023.03.27 |