본문 바로가기

Web Development Tips

Payment Service - Stripe

반응형

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?

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
 

How to create .NET web-API

Setting up development tools When working with .NET, we need tools to create a web application. We can download them at the link below. .NET | Free. Cross-platform. Open Source. (microsoft.com) .NET | Free. Cross-platform. Open Source. .NET is a developer

jin-co.tistory.com

Setting Up a Database
 

Working with SQLite in .NET (Code first)

There are two ways of using the Entity Framework to connect a database to a project. One way is to create the database first which is called the database first approach and the other, of course, is to write code first which is called the code first approac

jin-co.tistory.com

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
 

Angular - How to Use HTTPS in Development

Angular, by default, uses 'HTTP' to run the server in development mode. There is a package called 'mkcert' that provides an easy way to set up a certificate and use 'HTTPS' in a local environment. Setting up mkcert Open the command line as an administrator

jin-co.tistory.com

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

 

Stripe | Payment Processing Platform for the Internet

Stripe is a suite of APIs powering online payment processing and commerce solutions for internet businesses of all sizes. Accept payments and scale faster.

stripe.com

Stripe JS Reference

 

Stripe JS Reference

 

stripe.com

GitHub - stripe/stripe-js: Loading wrapper for Stripe.js

 

GitHub - stripe/stripe-js: Loading wrapper for Stripe.js

Loading wrapper for Stripe.js. Contribute to stripe/stripe-js development by creating an account on GitHub.

github.com

Get started with the Stripe CLI | Stripe Documentation

 

Get started with the Stripe CLI

Build, test, and manage your Stripe integration directly from the command line.

stripe.com

Scoop

 

https://scoop.sh/

 

scoop.sh

How Does Stripe Work? 2023 Guide To Using Stripe Payments (merchantmaverick.com)

 

How Does Stripe Work? The Complete Guide To Stripe For Business

What is Stripe Payments? Learn how Stripe works, what industries the company supports, & whether Stripe is a good choice for your business.

www.merchantmaverick.com

 

 

728x90
반응형

'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