전제 조건
Dodo Payments API를 통합하려면 다음이 필요합니다:
Dodo Payments 상인 계정
대시보드에서 API 자격 증명 (API 키 및 웹훅 비밀 키)
대시보드 설정
Dodo Payments 대시보드 로 이동합니다.
제품을 생성합니다 (일회성 결제 또는 구독)
API 키를 생성합니다:
개발자 > API로 이동합니다.
상세 가이드
env에 DODO_PAYMENTS_API_KEY라는 이름으로 API 키를 복사합니다.
웹훅을 구성합니다:
개발자 > 웹훅으로 이동합니다.
결제 알림을 위한 웹훅 URL을 생성합니다.
env에 웹훅 비밀 키를 복사합니다.
결제 링크
사용 사례에 맞는 통합 경로를 선택합니다:
체크아웃 세션(추천) : 대부분의 통합에 가장 적합합니다. 서버에서 세션을 생성하고 고객을 안전한 호스팅 체크아웃으로 리디렉션합니다.
오버레이 체크아웃(임베디드) : 사이트에 호스팅된 체크아웃을 임베드하여 페이지 내 경험이 필요할 때 사용합니다.
정적 결제 링크 : 코드 없이 즉시 공유 가능한 URL로 빠른 결제 수집을 위한 것입니다.
동적 결제 링크 : 프로그래밍 방식으로 생성된 링크입니다. 그러나 체크아웃 세션이 추천되며 더 많은 유연성을 제공합니다.
1. 체크아웃 세션
체크아웃 세션을 사용하여 일회성 결제 또는 구독을 위한 안전한 호스팅 체크아웃 경험을 생성합니다. 서버에서 세션을 생성한 후, 고객을 반환된 checkout_url로 리디렉션합니다.
체크아웃 세션은 기본적으로 24시간 유효합니다. confirm=true를 전달하면 세션은 15분 동안 유효하며 모든 필수 필드를 제공해야 합니다.
체크아웃 세션 생성
선호하는 SDK를 선택하거나 REST API를 호출합니다. Node.js SDK
Python SDK
REST API
import DodoPayments from 'dodopayments' ;
const client = new DodoPayments ({
bearerToken: process . env . DODO_PAYMENTS_API_KEY ,
environment: 'test_mode' , // defaults to 'live_mode'
});
const session = await client . checkoutSessions . create ({
product_cart: [{ product_id: 'prod_123' , quantity: 1 }],
customer: { email: '[email protected] ' , name: 'John Doe' },
return_url: 'https://yourapp.com/checkout/success' ,
});
import os
from dodopayments import DodoPayments
client = DodoPayments(
bearer_token = os.environ.get( "DODO_PAYMENTS_API_KEY" ),
environment = "test_mode" , # defaults to "live_mode"
)
session = client.checkout_sessions.create(
product_cart = [{ "product_id" : "prod_123" , "quantity" : 1 }],
customer = { "email" : "[email protected] " , "name" : "John Doe" },
return_url = "https://yourapp.com/checkout/success" ,
)
const response = await fetch ( 'https://test.dodopayments.com/checkouts' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'Authorization' : `Bearer ${ process . env . DODO_PAYMENTS_API_KEY } ` ,
},
body: JSON . stringify ({
product_cart: [{ product_id: 'prod_123' , quantity: 1 }],
customer: { email: '[email protected] ' , name: 'John Doe' },
return_url: 'https://yourapp.com/checkout/success' ,
}),
});
const session = await response . json ();
고객을 체크아웃으로 리디렉션
세션 생성 후, checkout_url로 리디렉션하여 호스팅 흐름을 시작합니다. // Example in a browser context
window . location . href = session . checkout_url ;
가장 빠르고 신뢰할 수 있는 결제 수집 방법으로 체크아웃 세션을 선호하세요. 고급 사용자 정의를 원하시면 전체 체크아웃 세션 가이드 와 API 참조 를 참조하세요.
2. 오버레이 체크아웃
매끄러운 페이지 내 체크아웃 경험을 위해 고객이 웹사이트를 떠나지 않고 결제를 완료할 수 있는 오버레이 체크아웃 통합을 탐색하세요.
3. 정적 결제 링크
정적 결제 링크를 사용하면 간단한 URL을 공유하여 빠르게 결제를 수락할 수 있습니다. 쿼리 매개변수를 전달하여 고객 세부 정보를 미리 채우고, 양식 필드를 제어하며, 사용자 정의 메타데이터를 추가하여 체크아웃 경험을 사용자 정의할 수 있습니다.
결제 링크 구성
기본 URL로 시작하고 제품 ID를 추가합니다: https://checkout.dodopayments.com/buy/{productid}
고객 정보 미리 채우기(선택 사항)
체크아웃을 간소화하기 위해 고객 또는 청구 필드를 쿼리 매개변수로 추가합니다.
고객의 전체 이름 (firstName 또는 lastName이 제공된 경우 무시됨).
양식 필드 제어(선택 사항)
특정 필드를 비활성화하여 고객이 읽기 전용으로 만들 수 있습니다. 이는 고객의 세부 정보가 이미 있는 경우(예: 로그인한 사용자) 유용합니다.
필드를 비활성화하려면 해당 값을 제공하고 해당 disable… 플래그를 true로 설정합니다: 필드 비활성화 플래그 필수 매개변수 전체 이름 disableFullNamefullName이름 disableFirstNamefirstName성 disableLastNamelastName이메일 disableEmailemail국가 disableCountrycountry주소 disableAddressLineaddressLine도시 disableCitycity주 disableStatestateZIP 코드 disableZipCodezipCode
필드를 비활성화하면 우발적인 변경을 방지하고 데이터 일관성을 보장하는 데 도움이 됩니다.
showDiscounts=false를 설정하면 체크아웃 양식에서 할인 섹션이 비활성화되고 숨겨집니다. 고객이 체크아웃 중 쿠폰 또는 프로모션 코드를 입력하지 못하도록 하려면 이 옵션을 사용하세요.
고급 제어 추가(선택 사항)
결제 통화를 지정합니다. 기본적으로 청구 국가의 통화로 설정됩니다.
센트 단위의 금액 (Pay What You Want 가격 책정 전용).
사용자 정의 메타데이터 필드 (예: metadata_orderId=123).
링크 공유
완료된 결제 링크를 고객에게 전송합니다. 고객이 방문하면 모든 쿼리 매개변수가 수집되어 세션 ID와 함께 저장됩니다. 그런 다음 URL은 세션 매개변수만 포함하도록 단순화됩니다 (예: ?session=sess_1a2b3c4d). 저장된 정보는 페이지 새로 고침을 통해 지속되며 체크아웃 과정 전반에 걸쳐 접근할 수 있습니다. 고객의 체크아웃 경험이 이제 매개변수에 따라 간소화되고 개인화되었습니다.
4. 동적 결제 링크
대부분의 사용 사례에 대해 체크아웃 세션을 선호하세요. 더 많은 유연성과 제어를 제공합니다.
API 호출 또는 고객 세부 정보를 사용하여 SDK를 통해 생성됩니다. 예를 들어:
동적 결제 링크를 생성하는 두 가지 API가 있습니다:
아래 가이드는 일회성 결제 링크 생성을 위한 것입니다.
구독 통합에 대한 자세한 지침은 구독 통합 가이드 를 참조하세요.
결제 링크를 얻으려면 payment_link = true를 전달하고 있는지 확인하세요.
Node.js SDK
Python SDK
Go SDK
API 참조
import DodoPayments from 'dodopayments' ;
const client = new DodoPayments ({
bearerToken: process . env [ 'DODO_PAYMENTS_API_KEY' ], // This is the default and can be omitted
environment: 'test_mode' , // defaults to 'live_mode'
});
async function main () {
const payment = await client . payments . create ({
payment_link: true ,
billing: { city: 'city' , country: 'AF' , state: 'state' , street: 'street' , zipcode: 0 },
customer: { email: '[email protected] ' , name: 'name' },
product_cart: [{ product_id: 'product_id' , quantity: 0 }],
});
console . log ( payment . payment_id );
}
main ();
import os
from dodopayments import DodoPayments
client = DodoPayments(
bearer_token = os.environ.get( "DODO_PAYMENTS_API_KEY" ), # This is the default and can be omitted (if using same name `DODO_PAYMENTS_API_KEY`)
environment = "test_mode" , # defaults to "live_mode"
)
payment = client.payments.create(
payment_link = True ,
billing = {
"city" : "city" ,
"country" : "AF" ,
"state" : "state" ,
"street" : "street" ,
"zipcode" : 0 ,
},
customer = {
"email" : "[email protected] " ,
"name" : "name" ,
},
product_cart = [{
"product_id" : "product_id" ,
"quantity" : 0 ,
}],
)
print (payment.payment_link)
package main
import (
" context "
" fmt "
" github.com/dodopayments/dodopayments-go "
" github.com/dodopayments/dodopayments-go/option "
)
func main () {
client := dodopayments . NewClient (
option . WithBearerToken ( "My Bearer Token" ), // defaults to os.LookupEnv("DODO_PAYMENTS_API_KEY")
)
payment , err := client . Payments . New ( context . TODO (), dodopayments . PaymentNewParams {
PaymentLink : dodopayments . F ( true ),
Billing : dodopayments . F ( dodopayments . PaymentNewParamsBilling {
City : dodopayments . F ( "city" ),
Country : dodopayments . F ( dodopayments . CountryCodeAf ),
State : dodopayments . F ( "state" ),
Street : dodopayments . F ( "street" ),
Zipcode : dodopayments . F ( int64 ( 0 )),
}),
Customer : dodopayments . F ( dodopayments . PaymentNewParamsCustomer {
Email : dodopayments . F ( "email" ),
Name : dodopayments . F ( "name" ),
}),
ProductCart : dodopayments . F ([] dodopayments . PaymentNewParamsProductCart { dodopayments . PaymentNewParamsProductCart {
ProductID : dodopayments . F ( "product_id" ),
Quantity : dodopayments . F ( int64 ( 0 )),
}}),
})
if err != nil {
panic ( err . Error ())
}
fmt . Printf ( " %+v \n " , payment . PaymentLink )
}
import { NextRequest , NextResponse } from "next/server" ;
export async function POST ( request : NextRequest ) {
try {
const body = await request . json ();
const { formData , cartItems } = paymentRequestSchema . parse ( body );
const response = await fetch ( ` ${ process . env . NEXT_PUBLIC_DODO_TEST_API } /payments` , {
method: "POST" ,
headers: {
"Content-Type" : "application/json" ,
Authorization: `Bearer ${ process . env . DODO_API_KEY } ` , // Replace with your API secret key generated from the Dodo Payments Dashboard
},
body: JSON . stringify ({
billing: {
city: formData . city ,
country: formData . country ,
state: formData . state ,
street: formData . addressLine ,
zipcode: parseInt ( formData . zipCode ),
},
customer: {
email: formData . email ,
name: ` ${ formData . firstName } ${ formData . lastName } ` ,
phone_number: formData . phoneNumber || undefined ,
},
payment_link: true ,
product_cart: cartItems . map (( id ) => ({
product_id: id ,
quantity: 1 ,
})),
return_url: process . env . NEXT_PUBLIC_RETURN_URL ,
}),
});
if ( ! response . ok ) {
const errorData = await response . json (). catch (() => null );
return NextResponse . json (
{ error: "Payment link creation failed" , details: errorData },
{ status: response . status }
);
}
const data = await response . json ();
return NextResponse . json ({ paymentLink: data . payment_link });
} catch ( err ) {
console . error ( "Payment error:" , err );
return NextResponse . json (
{
error: err instanceof Error ? err . message : "An unknown error occurred" ,
},
{ status: 500 }
);
}
}
결제 링크를 생성한 후, 고객이 결제를 완료하도록 리디렉션하세요.
웹훅 구현
결제 알림을 수신할 API 엔드포인트를 설정합니다. 다음은 Next.js를 사용하는 예입니다:
import { Webhook } from "standardwebhooks" ;
import { headers } from "next/headers" ;
import { WebhookPayload } from "@/types/api-types" ;
const webhook = new Webhook ( process . env . DODO_WEBHOOK_KEY ! ); // Replace with your secret key generated from the Dodo Payments Dashboard
export async function POST ( request : Request ) {
const headersList = headers ();
const rawBody = await request . text ();
const webhookHeaders = {
"webhook-id" : headersList . get ( "webhook-id" ) || "" ,
"webhook-signature" : headersList . get ( "webhook-signature" ) || "" ,
"webhook-timestamp" : headersList . get ( "webhook-timestamp" ) || "" ,
};
await webhook . verify ( rawBody , webhookHeaders );
const payload = JSON . parse ( rawBody ) as WebhookPayload ;
// Process the payload according to your business logic
}
우리의 웹훅 구현은 표준 웹훅 사양을 따릅니다. 웹훅 유형 정의에 대해서는 웹훅 이벤트 가이드 를 참조하세요.
Next.js와 TypeScript를 사용한 데모 구현이 포함된 이 프로젝트를 GitHub 에서 참조할 수 있습니다.
실제 구현을 여기 에서 확인할 수 있습니다.