Accepting Payments using LemonSqueezy - Integrating LemonSqueezy into Next.js Tutorial

Atharva Deosthale
6 Feb 202435:54

Summary

TLDR在这个视频中,作者介绍了如何使用Lemon Squeezy这个支付处理平台来销售软件产品。他首先创建了一个测试产品,并使用Next.js框架构建了一个应用程序,该应用程序可以调用Lemon Squeezy的API生成支付链接。用户可以通过这个链接完成支付。视频还演示了如何设置Webhook,以便在订单创建时接收实时通知,从而更新服务和数据库。整个过程清晰易懂,适合开发人员入门使用Lemon Squeezy支付系统。

Takeaways

  • 🔑 Lemon Squeezy是一个专门为软件产品构建的支付处理平台,支持许可证管理、税费计算等功能。
  • 🌐 通过API与Lemon Squeezy集成,可以在自己的应用中销售软件产品。
  • 💻 本教程使用Next.js展示了如何与Lemon Squeezy API交互,创建结账会话(checkout session)。
  • 🔐 Lemon Squeezy使用Webhook通知订单状态变化,确保及时获取付款信息。
  • 🛠 需要配置API密钥、商店ID和Webhook签名密码等重要凭据。
  • 📦 创建产品需要设置定价、税费类别、多个变体等细节。
  • 🔗 通过获取的Checkout URL可以引导用户完成付款流程。
  • ⚙️ 使用ngrok等隧道工具让本地服务器能够接收来自Lemon Squeezy的Webhook通知。
  • ✅ 收到Webhook后,需要验证签名以确保请求合法,然后处理订单信息。
  • 💡 教程中的代码可以作为基础,根据实际需求添加数据库集成、用户认证等功能。

Q & A

  • 这个教程是关于什么的?

    -这个教程展示了如何使用Lemon Squeezy平台在软件产品中集成支付功能。

  • 为什么选择Lemon Squeezy而不是Stripe?

    -Lemon Squeezy是专门为软件产品打造的支付处理平台,提供更简洁的界面管理税费等,而Stripe面向更广泛的应用场景。

  • 如何在Lemon Squeezy中创建产品?

    -可以在Lemon Squeezy的仪表盘上添加新的商店,然后在商店内创建新产品,设置定价模型、税费类别等详细信息。

  • 这个教程使用了什么编程语言和框架?

    -该教程使用JavaScript语言和Next.js框架进行开发。

  • 为什么需要环境变量文件?

    -环境变量文件用于存储Lemon Squeezy API密钥、商店ID和Webhook签名密钥等敏感信息,避免泄露。

  • 我们如何获取结账URL以便重定向用户?

    -通过调用Lemon Squeezy的/checkouts API接口并提交产品ID等相关信息,服务器会返回一个唯一的结账URL供用户支付。

  • 为什么需要使用ngrok进行本地测试?

    -ngrok可以创建一个公共URL指向本地服务器,使得Lemon Squeezy的Webhook能够正确调用我们的API。

  • Webhook在支付流程中起什么作用?

    -Webhook允许Lemon Squeezy在订单创建时通知我们的服务器,提供订单状态和用户自定义数据等信息。

  • 如何验证Webhook请求是否来自Lemon Squeezy?

    -通过使用Lemon Squeezy提供的签名密钥和加密算法,对Webhook请求进行签名验证。

  • 我们能在Webhook中获取哪些有用的数据?

    -Webhook请求中包含订单状态、支付成功与否、用户自定义数据等重要信息,可用于更新本地数据库。

Outlines

00:00

🚀 Lemon Squeezy介绍

这段介绍了Lemon Squeezy作为一个专为软件产品设计的支付处理平台,强调了其相对于Stripe等其他平台的优势,包括更简洁的界面、内置的许可证管理功能以及税务处理的便利性。此外,还指出Lemon Squeezy的易用性,即使是没有创建自己网站的用户也能轻松售卖软件。随后,引导观众进入Lemon Squeezy网站,并展示了如何创建新的商店并添加新产品的过程。

05:00

🔧 创建新应用与产品

这部分详细讲述了如何使用Next.js创建一个新的应用程序来与Lemon Squeezy集成,包括安装必要的包和设置环境变量(如API密钥和商店ID)。介绍了如何通过Axios配置与Lemon Squeezy API交互的基础,并展示了如何创建产品和处理支付的API路由。

10:02

📦 产品和支付处理

这段内容深入讲解了如何定义产品并在Lemon Squeezy上设置售价,包括单次支付和订阅等不同的支付模式。还介绍了如何通过创建API路由处理支付请求,包括验证产品ID并使用Lemon Squeezy API创建结账会话。

15:04

👨‍💻 编码与错误调试

在这一部分,通过一系列编码演示和错误调试,详细说明了如何发送请求以创建结账会话,并如何处理可能出现的问题,例如错误的请求路径或响应处理。

20:04

🌐 前端集成与测试

这段内容聚焦于如何在前端集成支付功能,包括创建触发支付流程的按钮,调用API路由,并处理响应以将用户重定向到支付页面。同时,也展示了如何启动服务器和解决启动过程中遇到的问题。

25:04

🔍 支付完成与Webhook设置

介绍了在用户完成支付后,如何使用Webhook通知服务器。展示了如何在Lemon Squeezy上设置Webhook,并通过NGROK工具将本地开发服务器公开为可从外部访问的服务,以便接收Webhook通知。

30:05

📝 Webhook处理与总结

这一部分详细说明了如何编写处理Webhook的代码,验证请求的合法性,并根据Webhook事件更新数据库或执行其他操作。最后,概述了整个视频的内容,强调了使用Lemon Squeezy和Next.js为软件产品处理支付的便利性,并提供了代码资源链接。

Mindmap

Keywords

💡Lemon Squeezy

Lemon Squeezy是一个为软件产品定制的支付处理平台。在视频中,它被强调为一个专为软件销售而设计的解决方案,提供了如许可证管理和税务处理等特殊功能,以简化软件开发者的销售流程。例如,视频中提到Lemon Squeezy处理税务合规性,让用户可以更专注于收入增长,减少头痛事。

💡Stripe

Stripe是一个广泛使用的在线支付处理平台。在视频中,Stripe被用作与Lemon Squeezy进行比较的对象,目的是突出后者在软件产品销售方面的专业性和优势,如更干净的界面和对税务等复杂问题的处理。

💡许可证

许可证在软件销售中扮演着重要的角色,用于控制和管理用户对软件的使用权限。视频中提到Lemon Squeezy提供许可证管理功能,这对于销售需要授权使用的软件产品尤为重要。

💡税务合规

税务合规是指遵守相关税法和规定的过程。视频强调Lemon Squeezy能够处理税务合规问题,减轻软件销售者在税务处理方面的负担,确保交易的合法性和合规性。

💡仪表板

仪表板是一个用户界面,用于展示和管理信息。在视频中,提到用户在Lemon Squeezy平台上的操作是通过仪表板进行的,包括创建新商店、添加产品等操作。这突出了平台的用户友好性和操作的便利性。

💡产品创建

产品创建是在Lemon Squeezy平台上销售软件所必需的步骤之一。视频详细介绍了如何在平台上创建新产品,包括设置定价、选择税务类别和上传产品文件,说明了平台在产品管理方面的灵活性和功能丰富性。

💡Next.js

Next.js是一个基于React的开源Web开发框架,支持服务端渲染和静态网站生成。视频中使用Next.js来开发一个与Lemon Squeezy API交互的应用,展示了如何集成Lemon Squeezy进行支付处理的过程。

💡API路由

API路由是指处理API请求的路径。在视频中,通过创建特定的API路由来处理购买请求和Webhook通知,这是使用Next.js开发Web应用时的一个常见做法,用于处理后端逻辑和与外部服务的交互。

💡Webhook

Webhook是一种Web回调或HTTP推送API的一种实现,用于在特定事件发生时向其他应用程序发送实时信息。视频中演示了如何设置和处理来自Lemon Squeezy的Webhook,用于在用户完成支付时接收通知。

💡环境变量

环境变量是在操作系统中用来指定运行环境设置的动态命名值。视频中提到使用环境变量来存储敏感信息,如API密钥和商店ID,这是一种保护敏感数据不被直接暴露在代码中的常见做法。

Highlights

Introduction to Lemon Squeezy as a payments processing platform specifically for software products.

Advantages of Lemon Squeezy over Stripe, including features like licenses and a cleaner interface for taxes.

Lemon Squeezy's automatic handling of tax compliance for software companies.

Creating a new store on Lemon Squeezy's platform.

Exploring product creation options within Lemon Squeezy, including payment and subscription models.

Using Lemon Squeezy's dashboard for setting up a new product, highlighting the ease of adding product descriptions and pricing.

The process of integrating Lemon Squeezy with a Next.js application for software sales.

Setting up environment variables and API keys for securely connecting to Lemon Squeezy.

Creating an API route in Next.js for handling purchases through Lemon Squeezy.

The importance of passing custom data in transactions for tracking and verification purposes.

Setting up Axios for making HTTP requests to Lemon Squeezy's API within a Next.js app.

Creating a front-end interface in Next.js for users to initiate purchases of software products.

Implementing webhooks from Lemon Squeezy to handle events like order creation and payment success.

Using NGROK to test webhooks locally by creating a public URL that forwards to your localhost.

Summary and invitation for feedback, emphasizing the tutorial's goal to facilitate software sales through Lemon Squeezy.

Transcripts

play00:00

in this video we will look at lemon

play00:01

squeezy lemon squeezy is a payments

play00:02

processing platform which is built

play00:04

specifically for software products so if

play00:06

you're trying to sell some kind of

play00:08

software lemon squeezy is the best

play00:10

platform to do so why would I choose

play00:12

lemon squeezy over something like stripe

play00:14

because it has some cool features such

play00:16

as licenses and a much more cleaner

play00:18

interface than stripe when it comes to

play00:20

taxes and stuff you don't need to figure

play00:22

out a lot of stuff lemon squeezy already

play00:24

has that for you and it's as it's

play00:26

already built for software you do not

play00:28

need to worry about all the different

play00:30

noise which appears in your stripe

play00:32

dashboard it also makes selling software

play00:34

very simpler if you don't want to make

play00:36

create your own website you can just

play00:38

share your around your link and sell

play00:39

your software but if you want you can

play00:41

also go deep and create your own site

play00:43

and do all of that stuff it's pretty

play00:45

interesting so let's get into the

play00:47

tutorial so we at the lemon squeezy site

play00:49

you can see it says payments tax and

play00:51

subscriptions for software companies as

play00:54

a merchant of record we handle a tax

play00:56

compliance burden so you can focus more

play00:58

on revenue and less head headache so

play01:00

it's specifically built for software uh

play01:03

it's it just mentioned here and let's go

play01:05

ahead and click on sign in and let's

play01:08

create our first project I guess or we

play01:12

could call it an organization so it took

play01:14

me to this dashboard so I was doing some

play01:15

testing here so I already have one but

play01:17

I'm going to create a new store here I

play01:19

guess so let's find a way to create a

play01:22

new store yep add new store if you don't

play01:25

already have a store it will

play01:26

automatically ask you to create a new

play01:28

store so I'm just just going to click

play01:30

add new store I'm just going to name it

play01:33

um Aura by

play01:37

store and I'm just going to change my

play01:40

country to India but if you are in

play01:41

different country make sure you set your

play01:44

own country and let's click on create

play01:46

new store perfect now it's going to show

play01:50

all of these settings but we are in test

play01:51

mode so we don't necessarily need to do

play01:54

all of these so let's just go ahead and

play01:57

create our products so to sell some

play01:59

something you need to have a product

play02:01

here so let's create a new product we

play02:03

are just going to create a new test

play02:06

product and we just going to add a

play02:09

description as like um this is my test

play02:11

product perfect and now you can have

play02:13

different kinds of things like single

play02:15

payment subscription pay what you want

play02:18

like they can set the price or even you

play02:20

can set the price at the back end but we

play02:22

are going to use single payment because

play02:24

it's we just have to touch the surface

play02:27

we just have to look at the basics and

play02:29

then you can always look at lemon

play02:30

squeezy documentation and make things

play02:32

work so let's click on single payment

play02:36

and let's select the pricing model so

play02:38

let's look at the options here we have

play02:40

standard and package package I think

play02:43

it's for more than one product so I'm

play02:45

just going to click on standard pricing

play02:47

for the price uh it's in my currency so

play02:49

I'm going to set it to I think so 1,500

play02:53

rupees make sure you respect your

play02:55

currency like uh does like um I mean

play02:58

it's test mode it doesn't really matter

play02:59

so you just do whatever you want then

play03:02

you have tax category I think this would

play03:03

be important in live mode where you have

play03:07

to like sell something so you just have

play03:09

to categorize this so digital goods or

play03:12

services excluding ebooks then we have

play03:13

ebooks as a separate category and then

play03:16

we have S software as a service so I

play03:18

think I'm just going to use digital

play03:20

goods and digital goods or services for

play03:22

this one but make sure you put your

play03:25

category here because in live mode I

play03:26

think this is going to be very important

play03:28

then you will have the media so it says

play03:31

add up to 10 images for your product use

play03:33

to represent your product during

play03:35

checkout we don't need

play03:37

it and upload an unlimited amounts of

play03:40

file to your product your customers will

play03:41

be given access to them after purchase

play03:44

so whatever things you have which you're

play03:46

trying to sell you can simply put them

play03:47

here and yeah uh it will be sent to your

play03:50

customer as soon as they have completed

play03:53

the payments then you will have variants

play03:55

and stuff where you can uh have

play03:57

different kinds of license like size

play04:01

shape and stuff we do you can set it you

play04:03

can set it up we will need the variant

play04:06

variant ID when we are dealing with the

play04:08

code but we can also use the default

play04:10

variant ID so if you want to skip this

play04:12

step feel free to do so but if you want

play04:14

to customize you can go ahead and do so

play04:16

it's not a problem then you will have

play04:18

generate license Keys you can again do

play04:20

so if you want to but I'm just going to

play04:22

keep it disabled for

play04:24

now and yeah show this product on your

play04:27

lemon stor front I guess yeah let's just

play04:30

leave that for email receipt we can

play04:32

enable it uh you can have a thank you

play04:34

node you can have a button link you can

play04:37

have button text and stuff and you can

play04:40

simply publish your product there's a

play04:42

lot of customization here you can simply

play04:44

dig into it and try to find which

play04:47

settings you can play around with to

play04:49

have the best experience for your users

play04:52

we have we just have the basic settings

play04:53

so so that we so that I can show you how

play04:56

the basics work and you can always build

play04:58

on top of that so we have this product

play05:00

right here so if we go into this three

play05:02

dots we will see two different IDs so

play05:05

one is an ID and one is a variant ID so

play05:09

here the variant ID means the specific

play05:11

variant of the product and the ID normal

play05:13

makes the product ID so product can have

play05:16

different variants and different

play05:17

variants will have different IDs so yeah

play05:20

this is how the product system works in

play05:22

lemon squeezy all right so let's create

play05:24

our new application I will be using

play05:26

nextjs because they have support for API

play05:28

routes of the box so if you want to use

play05:31

something like the combination of v and

play05:33

node J feel free to do so but since next

play05:35

J is easy for a tutorial purposes I'm

play05:37

going to do that so I'm going to use

play05:40

pnpm so

play05:42

pnpx create next app and I'm going to

play05:45

name it LS YT stands for lemon squeezy

play05:48

YouTube so I'm just going to hit enter

play05:50

now it will be asked for configuration I

play05:52

will not use typescript for for this

play05:54

tutorial let's leave everything else to

play05:57

default and let's wait for our app

play05:59

installation to complete this should not

play06:01

take a lot of time let's wait perfect

play06:04

now let's go to LS YT and there's only

play06:06

one package we need here you can even

play06:09

eliminate that if you want to but I want

play06:11

to make things simpler so I'm going to

play06:13

install pmpm in we going to install AOS

play06:16

so pnpm install axos AOS is a library to

play06:20

make HTTP requests and we're going to

play06:22

create a config file that sets a base

play06:24

URL for all the stuff and um yeah for

play06:29

all uh interaction with lemon squeezy

play06:32

API and um we also need another package

play06:34

I'm sorry I'm I'm really sorry for this

play06:36

one but we are going to need a package

play06:39

called as server only which makes sure

play06:42

that a file is always run on the server

play06:45

side so yeah now let's do code Dot and

play06:48

open Visual Studio code perfect let's

play06:51

get this to full screen it's going to

play06:52

lag a bit I really got to replace my

play06:55

machine perfect now first things first

play06:58

we need an envirment variable file so

play07:01

let's create

play07:03

env. loal and now first thing we need is

play07:05

lemon squeezy API

play07:08

key which we will get from the dashboard

play07:11

so let's go to the dashboard and here we

play07:14

are going to go into the

play07:16

settings and in the API section and we

play07:20

will get our API key right here I

play07:24

already have one which is pretty strange

play07:27

I I don't think I had one for this but

play07:30

anyways I'm just going to delete this

play07:31

one and I'm going to create a new one

play07:34

I'm just going to name it by and please

play07:36

do not use my API key I'm I'm I'm going

play07:39

to delete it anyways so don't even try

play07:41

it's just going to waste your time so

play07:44

let's go back to a code and I'm just

play07:45

going to paste this API key right here

play07:47

perfect the second thing we need is the

play07:50

store ID so lemon squeezy this does not

play07:53

need to be private but since we are like

play07:57

abstracting all the payment rated stuff

play07:59

to our back end side so we are just

play08:01

going to make this environment variable

play08:03

private so we are going to have the

play08:05

store ID but if you ever wanted to get

play08:07

this like public you can always do so by

play08:09

prefixing next public so yeah so let's

play08:13

go ahead and uh how do we found our

play08:16

store ID I think it was in general so

play08:18

let's go

play08:19

there H strange so let's find how we can

play08:23

find our store ID I think it was right

play08:26

here all right so it was in the stores

play08:28

Tab and we have all my stores here and

play08:31

the store we are looking for is this one

play08:33

Aur it store I'm just going to copy the

play08:35

ID without the hash and we're just going

play08:37

to paste it here now there is one more

play08:40

thing we require which is the Web book

play08:42

signature so whenever somebody tries to

play08:45

make a payment on a website and whenever

play08:48

it is successful or even fail or I would

play08:51

rather say when an order is created

play08:52

lemon squeezy will try to Ping our

play08:55

endpoint to tell us that hey this a

play08:59

person has tried to create an order and

play09:01

the way to verify if the request has

play09:05

been sent ledged by Lemon squee and not

play09:07

by an attacker is by verifying the

play09:10

signature that lemon squeezy sent us so

play09:12

how does this work we have a secret uh

play09:15

which is basically a password which only

play09:18

you and lemon squeezy knows and using

play09:20

that password you can make sure that the

play09:23

request has been sent by lemon squeezy

play09:24

or not so yeah let's just have a

play09:26

password Here we will go into the

play09:29

details lat so we are going to have

play09:31

lemon

play09:32

squeezy uh web hook signature oops I

play09:35

can't

play09:36

type and we going to have anything you

play09:38

can literally have anything I'm just

play09:40

going to have the most secret secret

play09:42

yeah like it it it just works we will

play09:45

deal with web books later but first

play09:46

let's make this thing work all right now

play09:49

let's go into the SSC folder and let's

play09:51

create a new folder inside the SRC

play09:53

folder and I'm going to call it utils

play09:56

and inside utils I'm going to create a

play09:58

new file file called axios

play10:02

JS and this will contain our AOS uh

play10:05

configuration so I'm just going to

play10:07

import axos

play10:09

here import axos auto complete thank you

play10:13

and now we can start creating our

play10:15

instance but first of all we need an

play10:17

base endpoint so lemon squeezy has this

play10:20

endpoint which we can always contact so

play10:22

I'm just going to say export const

play10:25

exporting just because we might need it

play10:27

later but um it's fine if we don't so

play10:30

lemon squeezy

play10:34

endpoint and the endpoint is https not

play10:38

the one which is suggested by co- parate

play10:40

but yeah uh api. lemon

play10:46

squeezy slv1 perfect now this is the API

play10:50

key sorry this is the API URL which we

play10:53

are going to call in every single

play10:54

request we make to lemon squeezy so

play10:56

let's create the instance so I'm just

play10:58

going to say

play10:59

export const instance actually I'm going

play11:02

to name it lemon squeezy API

play11:08

instance to be more specific about this

play11:11

so we are going to create a new instance

play11:13

using axes. Create oops I can't type

play11:17

today and we going to have the base URL

play11:20

here hello autocomplete yeah uh lemon

play11:24

squeezy end point I just wanted to make

play11:26

sure that the base URL is like the URL

play11:28

is all uper case not yeah now we also

play11:31

need some headers which are provided in

play11:33

the documentation I'm just going to save

play11:35

a lot of effort from your side I'm just

play11:37

going to copy and

play11:39

paste these things so yeah the accept

play11:42

and content type headers are something

play11:44

that lemon squeezy requires and uh

play11:48

authorization this contains your API key

play11:51

uh which we pulling in from our

play11:53

environment variables so yeah perfect

play11:55

all right now we are going to create a

play11:57

new API route which will handle

play11:59

the purchasing for us we will look at

play12:02

the UI after this so in app we are using

play12:05

the app directory for next just if

play12:07

you're using Pages directory make sure

play12:08

you follow that format but uh since we

play12:11

using App directory we are going to

play12:12

create a new folder here I'm going to

play12:14

call it API uh it should be named API by

play12:17

the way I'm sorry if I said that I'm

play12:19

going to call it API it literally should

play12:21

be called as API now we can call some

play12:23

folder so yeah now I'm going to call it

play12:26

purchase product and inside this I am

play12:30

going to need to add a route. TS file uh

play12:33

sorry we are not using typescript I

play12:35

almost forget every single time oops

play12:38

it's hard it's hard at the JavaScript

play12:41

yeah anyways now first thing first we

play12:44

need to export a variable so export cons

play12:48

Dynamic and we this the value needs to

play12:50

be Force Dynamic this tells next just

play12:53

that uh there is no caching involved at

play12:56

all so don't ever cache the response and

play12:58

next thing we are going to have is the

play13:01

actual request Handler so we are going

play13:03

to make this a post Handler so post it

play13:06

it is going to only handle post request

play13:08

so let's do that so export asnc

play13:11

function post and it will have a request

play13:14

object and let's open the function now

play13:16

we can do a try cat block right here and

play13:19

we can do console do error Whenever

play13:22

there is an um error in this block we

play13:25

don't know what it is so we just going

play13:27

to return that it's an internal server

play13:29

error so let's do response and U since

play13:34

using next sh uh this is just the uh way

play13:37

of sending responses but if you're using

play13:39

Express you might have like a response

play13:43

variable inside of your Handler or

play13:45

something but here we are just doing

play13:47

response. Json and we're just going to

play13:50

say message and error ORD and the next

play13:54

thing we are going to have is a status

play13:56

which we are going to pass in 500 uh um

play13:59

mentioning that it's a internal server

play14:01

error now we can work with stuff now

play14:04

let's get the data from the post request

play14:07

so con data request data and then we

play14:10

going to have request. uh request

play14:13

dojason I hate when these handlers do

play14:16

not uh yeah when these handlers do not

play14:20

have any like types in JavaScript you

play14:22

need to like just figure out things if

play14:25

it works or not and it's pretty bad if

play14:27

you're using typescript it's going to be

play14:29

much easier but um this is how it works

play14:32

here so in JavaScript so you just say

play14:35

request. Json and all of your body will

play14:37

be converted into an object and will be

play14:39

set

play14:41

into request data whatever I named it

play14:43

anyways now the first thing we want to

play14:45

check if there is a product ID provided

play14:48

so this is going to be a very Dynamic

play14:50

route so if that uh you can just pass

play14:53

you can just call this endpoint and just

play14:55

pass in your product ID and it will just

play14:58

return you with with an URL which you

play14:59

can make payment with but uh yeah

play15:03

so uh if there is no product ID provided

play15:06

we must throw an error so let's do

play15:09

that request data dot um I guess product

play15:16

ID GitHub co-pilot is being too annoy

play15:19

right now so yeah the then we need to

play15:22

return a response so return response.

play15:25

Json and we are going to have a message

play15:30

product ID is required thank you get up

play15:32

co-pilot for once hello what happened

play15:35

yeah the status should be 400 as in bad

play15:38

request perfect and now we can make our

play15:41

request to lemon squeezy thing so how do

play15:44

we do that so let's go to the

play15:46

documentation so this is the

play15:47

documentation API reference for lemon

play15:49

squeezy they have two different

play15:51

documentations one is help documentation

play15:53

and one is an API reference I will have

play15:55

the API reference in the uh description

play15:58

below this is what you will need I think

play16:00

the documentations is a little confusing

play16:02

I think they can improve a lot here but

play16:04

yeah now what you need to do is click on

play16:07

read the developer guide and we can go

play16:09

on taking payments and we can get uh

play16:13

gist of what we need to send to lemon

play16:15

squeezy so if you're using a post

play16:18

request to then if you want to get a

play16:20

checkout checkout and point so creating

play16:23

checkouts with API you just need to use

play16:25

this request I would have liked if they

play16:27

had buttons to change languages but it's

play16:29

fine we can still work with it so we

play16:32

need to send this data so first of all

play16:34

let's Port all this data to a

play16:36

code and we need to send it to/

play16:39

checkouts right so we already have these

play16:41

datas so let's not worry about it we

play16:43

need to send it to/ checkouts so let's

play16:45

go um I'm sorry let's go back to our

play16:48

code and let's go beneath this line of

play16:52

code and let's say uh con

play16:56

response is equal to a wait Lon squeezy

play16:59

instance. post and we are going to post

play17:01

to/ checkout since we already have the

play17:03

base URL we do not need to have the

play17:06

entire URL and now we will have

play17:10

the data so in the data we are just

play17:14

going to pass and we just going to paste

play17:16

it in and we're just going to save it

play17:18

now this is the data we are going to

play17:19

send I know this is this does not look

play17:22

pretty at all but what this means is

play17:25

that uh in data you are passing in all

play17:27

the things and um which is related to

play17:30

your request and the type of this

play17:33

request is checkouts in relationships

play17:36

you need to pass in all the data of your

play17:39

specific lemon lemon

play17:41

squeezy um instances like your store ID

play17:46

uh and your variants but instead we need

play17:48

to edit it here so for stores we need to

play17:51

have a store ID so let's have process.

play17:56

EnV do let's go here and copy the store

play18:00

ID uh perfect and now we can

play18:03

have in the variant uh we are treating

play18:07

the variant as a product ID here because

play18:09

typically you will have different kind

play18:11

of variants with different anyways if

play18:13

you want to rename this to variant ID

play18:15

feel fre to do so I'm just going to let

play18:17

it be product ID so we are going to

play18:20

replace this with the uh variant ID so

play18:24

which is actually the product ID here so

play18:26

let's do that uh we are going to do

play18:28

request

play18:30

data do product ID and since this is

play18:32

going to be an integer we are going to

play18:35

convert it to string I also have doubt

play18:37

that this might be an integer so let's

play18:38

convert it to string because lemon

play18:40

squeezy only accepts string Zer perfect

play18:44

and now when we have the response uh we

play18:47

will need to console log it out um to

play18:50

check it out so let's do

play18:53

console.log response perfect now let's

play18:57

try to figure things out let's uh create

play19:01

a new request here so we will go to our

play19:04

Thunder cland we will create a new

play19:06

request we don't need the release notes

play19:09

and uh we will make a request to http

play19:12

Local

play19:17

Host 3,000 SL API slash what was it

play19:22

again it was purchase product perfect

play19:25

and now we need to pass in all the

play19:26

headers and stuff uh

play19:28

actually we do not because we are

play19:30

handling it internally so we need to

play19:32

only pass in the body uh we need this

play19:35

needs to be a post request and it needs

play19:37

to be adjacent so we need to pass in a

play19:40

product ID let's get our variant ID from

play19:43

there so let's go to store let's go to

play19:46

products let's copy the variant ID I'm

play19:48

treating this as a separate product

play19:50

that's why I had named a product ID so

play19:52

yeah hello yep paste it let's send this

play19:56

request connection was was refused by

play19:59

the server let's go to the terminal and

play20:01

see what's wrong here oops we haven't

play20:04

even started it yeah classic Dev mode

play20:06

yeah all this time we have been coding

play20:08

and we haven't even started the server

play20:10

it's like crazy let's wait there will be

play20:13

actually no response but we got in 500

play20:16

that means something is wrong oh yeah

play20:18

that's because we didn't send any

play20:20

response but uh even the request failed

play20:23

which is interesting let's see what's

play20:25

wrong here bad requests oops

play20:29

404 H oh it it should be checkouts yeah

play20:32

dumb mistake so let's go back let's send

play20:35

this request again 500 again I wonder

play20:38

what it is now all right yeah the thing

play20:41

was it wasn't really an error I was

play20:43

trying to log the entire response thing

play20:45

but we only needed the actual data that

play20:48

was returned back to us so what I did

play20:50

was uh took out the check out URL which

play20:53

we will see the structure right now and

play20:55

I just console loog the respons of data

play20:57

so let's look at the response of data uh

play20:59

where is my terminal so yeah this is the

play21:01

response we get so we have the data

play21:04

inside it and then we have the

play21:06

attributes which has a lot of different

play21:07

things and we have the product options

play21:10

check out options but the main thing we

play21:12

need here is the URL so this is the

play21:14

unique URL which your user will use to

play21:17

pay and we will pass this to the front

play21:20

end uh for them to make the payment the

play21:23

cool thing why we the thing with here is

play21:25

why we are using this uh because because

play21:28

uh we need to pass in custom data so

play21:31

like what traditionally you can do is

play21:32

you can simply go to the dashboard for

play21:34

11 squeezy and generate a URL and share

play21:36

it but what we want to do is we want to

play21:38

attach custom data with this specific

play21:40

session and we will get that data back

play21:43

when the user completes the transaction

play21:45

so how do we uh pass in custom data here

play21:49

we can do that by adding a new

play21:51

attributes section

play21:53

here attributes I cannot type today and

play21:58

then we can have okay let me give you

play22:00

give it a comma and then we can have

play22:02

custom data oh actually this needs to be

play22:05

check out data and then we will have it

play22:07

so check out

play22:12

data and we will have custom here this

play22:15

is the format you need to follow and

play22:16

then you can have any key value pair

play22:18

here so for example if you have uh

play22:20

authentication session active you can

play22:22

find your user ID and you can just plug

play22:24

it in here so yeah uh but in this case

play22:27

I'm just going to hardcode it because we

play22:29

don't really have a customer ID here or

play22:33

user ID here because we haven't implied

play22:35

authentication or something but just

play22:37

feel free to do it it's just going to be

play22:39

like just plug in the actual user ID and

play22:42

you will get the user ID at the webbook

play22:44

S side when the uh order is completed

play22:48

perfect so this is done now we can

play22:50

simply go ahead and try again let's send

play22:54

it we will get oops we are getting some

play22:57

error oh yeah I know why we are getting

play22:59

an error because this should be a string

play23:00

key value pass the value should be a

play23:03

string in this case and let's send it

play23:04

again now we have the checkout URL which

play23:06

we will be passing to the front end now

play23:08

let's also check the terminal for One

play23:10

Last Time

play23:12

oopsie yep now we will also have this

play23:15

checkout data which is an object which

play23:17

contains everything which we have which

play23:19

is user ID it's not printing it out I

play23:22

just want to show you that the checkout

play23:23

data is here so that means that it has

play23:26

accepted it so perfect now we can

play23:29

actually make payments now we are also

play23:31

passing using response. Json and we

play23:34

passing the checkout URL now let's

play23:36

enable the front end to make calls to

play23:38

this API and uh make the actual payment

play23:42

so what we are going to do is we are

play23:44

going to use the

play23:46

page.js file we're not going to go into

play23:49

a lot of details but I'm just going to

play23:51

remove everything from here we do not

play23:53

need everything we just need the main

play23:55

tag and I'm going to have a button here

play23:59

I'm I just going to I'm just going to

play24:00

copy paste we do not need to focus a lot

play24:03

uh it's just going to perform a by

play24:05

product one uh function which we are

play24:07

making right now so let's create a new

play24:10

function C by product

play24:13

[Applause]

play24:15

one

play24:18

async function and my typing speed has

play24:22

been so bad lately this also will have a

play24:24

TR catch block and uh we will also have

play24:28

an error here so we can

play24:30

simply pass in this code and we will

play24:33

just alert when there is an error we

play24:35

will do this Tri tribe block right now

play24:38

so we are going to do const response the

play24:40

difference here is that we are making an

play24:42

API call to our own API which is the

play24:45

next ch's API route so we going to do a

play24:47

wait axios we are going to import axos

play24:51

axios

play24:54

dopost slash API SL which is product the

play24:59

data we are going to pass here is

play25:00

product ID so let's go ahead and get the

play25:04

variant we are going to copy the variant

play25:06

ID and we're going to pass in it here as

play25:10

a product ID yeah let's just do it fine

play25:13

I was thinking about something else but

play25:15

I think it's just fine let's just

play25:16

console log it uh for personal thing if

play25:19

there is some kind of error we can

play25:21

easily debug it but the next thing we

play25:23

want to do is when you want to redirect

play25:25

the user to the checkout URL to complete

play25:28

the payment so we can do window.

play25:32

open and we can say response. data.

play25:36

checkout URL and we will pass in blank

play25:37

so that it opens in a new tab perfect

play25:40

now whenever this button is clicked uh

play25:43

new tab will be opened where the where

play25:45

the customer can do his payment and yeah

play25:48

and if you have any pro if you have

play25:50

anything set in your product like

play25:53

sending through email those things will

play25:55

be sent directly to their emails so yeah

play25:59

this is how it works let's go let's go

play26:01

to a browser and test it out so we will

play26:03

go to local 3000 waiting for it it's

play26:06

going to take some time H oh yeah this

play26:09

needs to be a client component so we are

play26:12

going to use use client I want to make

play26:14

an entire video on this uh use client

play26:17

stuff react server component in the next

play26:19

JS I think it deserves a video of it so

play26:21

on but yeah let's go back and we will

play26:24

have this button so let's click this

play26:27

let's see what happens now a new tab has

play26:29

been opened it's loading perfect test

play26:32

mode has been currently enabled now it

play26:34

has a email ID because we are logged in

play26:36

here but if not they will get an email

play26:39

ID prompt here now for card number uh

play26:42

anyways I think I can blur it out so I'm

play26:44

just going to type 42 42 42 42 42 42 42

play26:47

which is the same as stripe so uh yeah

play26:51

4242 42 and then we are going to

play26:55

have 2 42 42 I'm just going to have some

play26:57

some random stuff here I think 4 digit

play26:59

it works and uh yeah uh let's proceed

play27:02

with the payment

play27:06

processing perfect continue now the

play27:09

thing is that the payment has been

play27:10

completed but how does your website know

play27:12

how does your servers know that the

play27:14

payment is completed of course you can

play27:16

have like a crw job which like fetches

play27:18

every single every five minutes to see

play27:21

if a payment is done or not but it's

play27:23

really not that good so like if a person

play27:26

makes a payment right now the person

play27:28

might potentially have to wait 5 minutes

play27:30

to uh see his or her payment reflected

play27:33

and that sucks really so there is one

play27:36

good thing you can create web hooks that

play27:38

means that lemon squeezy will call your

play27:40

API and will inform you that the payment

play27:42

is successful and that you can enable

play27:45

their services their paid services so

play27:47

yeah let's do that so let's go to GL

play27:50

squeezy dashboard let's go ahead and

play27:53

click on settings let's go to web hooks

play27:56

let's create a new web hook

play27:58

now we need to pass in an URL now this

play28:00

is a very difficult thing right because

play28:02

we are in Local Host we cannot just pass

play28:04

in Local Host here because it doesn't

play28:06

know what our Local Host is so the thing

play28:08

is that we need to use some kind of

play28:10

tunnel so I'm going to use NG Rock so

play28:13

I'm going to leave a tutorial about how

play28:15

to use ngok in the comments like you

play28:17

need to have an API key and stuff but I

play28:19

already have all of it configured

play28:21

because it's more of os related thing

play28:23

how to install it so go ahead and check

play28:26

it out but but uh what we going to do is

play28:29

we are going to use NG Rock um HTTP uh

play28:34

HTTP local 3000 let me tell you the

play28:37

reason why we are using this what this

play28:38

will do is it will give us a link uh

play28:41

which will be a public link if we pass

play28:43

into to the web hook thing it will

play28:45

automatically call our Local Host so if

play28:48

ngok uses the link which is provided

play28:51

here this will forward all the requests

play28:53

to a local Host this is how it works and

play28:55

it's called a tunnel so if you notice

play28:57

Tel you know what I'm doing right here

play28:59

so yeah let's pass this URL here for the

play29:02

signing secret we need to pass in the

play29:04

same one which we passed here in our

play29:07

environment variables make sure you just

play29:09

have some really good one not some goofy

play29:11

one right like I have right here you

play29:14

will choose some events here but for

play29:17

this video I think event order created

play29:20

should be enough so I'm just going to

play29:21

save the web hook perfect now I'm just

play29:24

going to click on Cross perfect now the

play29:28

Web book is done now let's try to make

play29:30

the payment again don't worry if

play29:32

whenever you want to try it out you

play29:34

don't need to make uh the payments a lot

play29:36

of time to just just to debug the

play29:38

webbook uh you can always uh resend the

play29:40

webbook event from L squeezy so I'll

play29:43

show you what I mean so let's try to

play29:45

make this payment once and we do not

play29:46

need to make it again and

play29:50

again

play29:52

um does this work yeah perfect uh yeah

play29:57

now we can go back to our

play30:00

dashboard and uh we can reload this

play30:04

page and we will say that we have the

play30:08

response of 200 and this data was sent

play30:10

to us and we can actually get we can

play30:14

actually use this data to find out the

play30:17

state of the user if you can go here we

play30:19

will actually find in the last meta

play30:21

object you will have the custom data

play30:22

which we passed when we created the

play30:24

checkout which is pretty cool uh but

play30:27

this's one thing we need to modify we

play30:29

simply passed in the domain here but

play30:31

which is not good we need to pass in/

play30:33

API SL webbook which this is the route

play30:36

we are going to create right now so yeah

play30:38

let's save this one perfect now yeah

play30:41

let's work on getting the endpoint thing

play30:44

up so I'm just going to create a new

play30:47

folder here under API which is going to

play30:49

be called as web hook reflecting on what

play30:53

we passed in on Lemon Squeezy and we are

play30:55

going to create a new file called route

play30:57

JS let me get the code from there we do

play31:00

not want to waste a lot of time here um

play31:04

this is the entire code for this file uh

play31:08

actually I coded in typescript first so

play31:10

I need to remove everything which is

play31:11

related to typescript

play31:14

here yep so what we are doing here is

play31:17

first of all we are cloning the request

play31:19

because we want the request as text

play31:22

first because we are passing it for

play31:25

verification of signatures and then we

play31:27

are also getting the event name from our

play31:29

request which is the original request

play31:31

not the cloned one so we are getting the

play31:33

oops we getting the header uh which has

play31:36

the event name which is basically what

play31:38

event what event is so basically for

play31:41

example we enabled order created if you

play31:43

have multiple of those enabled you would

play31:46

get the exact event name here then we

play31:48

have the body of the

play31:51

actual actual content of the request

play31:54

then this part is copied from lemon

play31:56

squeezy you do not need need to focus

play31:57

how it works it's a lot of cryptography

play32:00

stuff but in short this is just trying

play32:03

to uh verify if the request is really

play32:07

coming from lemon squeezy or Not by

play32:10

using the secret so make sure you keep

play32:13

the secret very private and not share it

play32:15

with anyone else because if they have it

play32:17

they can probably get around this and

play32:19

pass malicious request to you and after

play32:22

this point after this uh block of code

play32:25

this request is legit and you can trust

play32:27

anything the data says so if the you can

play32:30

check if the event type is order created

play32:32

you can get out the get the user ID from

play32:35

here and you can get if the payment is

play32:37

successful by checking the status if

play32:39

it's paid or not I'm not going in detail

play32:42

of this file because we don't have a

play32:44

database we don't not have um specific

play32:48

data to work on but if you have a

play32:51

database you can simply plug in your

play32:52

database logic here to make sure that

play32:55

the that your customers plan is edited

play32:58

so yeah uh you can simply check out all

play33:00

these data like U you can check which

play33:03

where is useful for you and you can fill

play33:07

that in your database or you know what

play33:09

you can simply get all of the data from

play33:11

here and just fill it in your database

play33:13

for later use and you can simply do the

play33:15

recent thing and it will work out

play33:18

oh H so let's click on resent and we

play33:22

should have it in our terminal so if we

play33:25

see the data here uh oops there is some

play33:28

kind of error there is no kind of

play33:30

response oh yeah we do not have a

play33:32

response yet so what we will do is uh we

play33:35

are just going to do

play33:37

response. Json web hook received and I

play33:41

think this is important for many web

play33:42

hooks because if you do not have a 200

play33:44

response they will try to send it again

play33:46

and again which is very problematic but

play33:49

yeah so it's very always it's always

play33:51

good to have a response to a web hook so

play33:55

yeah now if you send it again

play33:58

uh we will have we most likely will have

play34:01

all the data here we all we have a error

play34:04

again H which is pretty H this is this

play34:08

is strange let's try it out

play34:11

again going to click

play34:15

resend because we are sending a response

play34:18

I know for sure no response is written

play34:21

from Route

play34:22

Handler ensure that you have a response

play34:26

we do have response of course we console

play34:29

logging it out and we are sending a

play34:32

response using response. Json so yeah I

play34:35

figured it out it should have been

play34:36

returned we do not need to do this in

play34:38

Express but uh apparently this one

play34:41

requires it so you need to have return

play34:43

before this so yeah and it works if we

play34:45

go back and if we see if we resend it we

play34:49

can check our terminal and we will have

play34:52

only data and not the errors because we

play34:55

actually have console loged the body

play34:56

here and if you go ahead and reload it

play34:59

first we only have 1 200 and now we have

play35:02

two 200s which we just have and we we we

play35:05

also see the response which our web hook

play35:06

replied with so if you have like some

play35:08

kind of things logs and stuff you can

play35:11

always pass it through the webbook

play35:13

response and you will see it here so

play35:16

yeah this is how you can work with lemon

play35:18

squeezy you can the opportunities are

play35:20

endless here you can do literally

play35:22

anything you want to uh I will have the

play35:24

code in the description below though uh

play35:26

in the GitHub repository so yeah that's

play35:28

it for this video in this video we saw

play35:30

how you can use lemon squeezy for

play35:32

payments for your software products very

play35:34

easily using nextjs so yeah if you have

play35:37

any suggestions make sure you leave them

play35:39

in the comments below and uh please hit

play35:41

the like button hit the Subscribe button

play35:43

share this video with your friends and

play35:45

leave some comment below to support me

play35:47

and promote my videos in the algorithm

play35:49

so yeah that's it for this video I'll

play35:51

see you guys in the next one bye

Rate This

5.0 / 5 (0 votes)

Do you need a summary in English?