stripe 결제 플랫폼 테스트 코드

2025. 5. 26. 16:55카테고리 없음

반응형

결제승인

 

Stripe는 글로벌 결제 처리 플랫폼으로, 온라인 및 오프라인에서 카드 결제, 간편 결제, 구독, 송금, 정산, 환불 등 다양한 결제 관련 기능을 API로 제공하는 서비스입니다. 개발자 친화적인 설계 덕분에 전 세계적으로 많이 사용됩니다.


🧾 Stripe 플랫폼 개요

항목 설명

주요 기능 카드 결제, 구독, 정기 결제, 결제 대시보드, 웹훅 등
지원 결제 수단 신용/체크카드, Apple Pay, Google Pay, Alipay, 계좌 이체 등
개발자 지원 Node.js, Python, Java, PHP, Ruby, .NET 등 SDK 지원
주요 서비스 지역 미국, 유럽, 아시아 등 대부분 국가 (대한민국 포함)
보안 인증 PCI-DSS, TLS 1.2 이상, 3D Secure 등 지원

✅ Stripe 결제 흐름 요약 (기본 카드 결제)

  1. 클라이언트: 카드 정보 입력
  2. 서버:
    • PaymentIntent 생성 요청
    • 필요 시 3D Secure 인증 처리
  3. Stripe: 결제 처리
  4. 서버: 결제 결과 처리 후 사용자에게 응답

💻 예: Node.js 백엔드에서 Stripe 결제 처리하기

1. Stripe 설치

npm install stripe

2. .env 파일에 Stripe 키 설정

STRIPE_SECRET_KEY=sk_test_1234567890abcdef

3. 서버 코드 예제 (payment.service.ts 또는 controller)

import Stripe from 'stripe';
import { Injectable } from '@nestjs/common';
import * as dotenv from 'dotenv';

dotenv.config();

@Injectable()
export class PaymentService {
  private stripe: Stripe;
  private const defaultCurrency = 'usd';
  
  constructor() {
    this.stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string, {
      apiVersion: '2025-04-30.basil',
    });
  }

  async createPaymentIntent(amount: number, currency: string) {
    try {
      const paymentIntent = await this.stripe.paymentIntents.create({
        amount, // 단위: 센트 (예: ₩1,000 → 100000)
        currency || defaultCurrency,
        payment_method_types: ['card', 'alipay', 'grabpay'],
      });

      return {
        clientSecret: paymentIntent.client_secret,
      };
    } catch (err) {
      console.error('결제 생성 오류:', err);
      throw err;
    }
  }
}

4. 클라이언트 코드 예 (React + Stripe.js)

function PaymentOptions({ clientSecret }) {
  const stripe = useStripe();
  const elements = useElements();
  const [method, setMethod] = useState('card'); // 사용자가 선택

  const handleSubmit = async (e) => {
    e.preventDefault();

    if (method === 'card') {
      await stripe.confirmCardPayment(clientSecret, {
        payment_method: {
          card: elements.getElement(CardElement),
        },
      });
    } else if (method === 'alipay') {
      await stripe.confirmAlipayPayment(clientSecret, {
        return_url: 'https://yourdomain.com/payment-complete',
      });
    } else if (method === 'grabpay') {
      await stripe.confirmGrabPayPayment(clientSecret, {
        return_url: 'https://yourdomain.com/payment-complete',
      });
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <select onChange={(e) => setMethod(e.target.value)} value={method}>
        <option value="card">카드 결제</option>
        <option value="alipay">Alipay</option>
        <option value="grabpay">GrabPay</option>
      </select>
      {method === 'card' && <CardElement />}
      <button type="submit">결제하기</button>
    </form>
  );
}

🛠 통합 팁

  • 금액은 센트 단위 (₩1,000 → 100000)로 요청
  • 웹훅(webhook)을 통해 성공/실패 알림 처리 가능
  • 카드 정보는 절대 서버로 전달하지 말 것! → Stripe.js로 직접 Stripe에 전송

🧩 예시: 회사 시스템에서 API 호출 흐름

📌 시나리오

고객이 골프 예약을 하고, 카드로 결제를 완료해야 함.

🔄 서버 처리 흐름

  1. 고객이 예약 → 프론트에서 결제 버튼 클릭
  2. 서버에서 /create-payment-intent API 호출
  3. 생성된 client_secret을 프론트로 전달
  4. Stripe.js로 카드 입력 → Stripe 서버와 통신
  5. 결제 완료 → 서버에서 Stripe 웹훅 또는 confirm 후 처리

📎 문서 링크


 

 

 

제공 UI 사용 방법

 

좋아요! Stripe에서 제공하는 기본 UI 방식인 Stripe Elements + Payment Element는 Stripe가 다양한 결제 수단을 자동으로 사용자에게 보여주고 처리까지 해주는 통합 컴포넌트입니다.

목표: 프론트에서 별도 결제 수단 선택 UI를 만들 필요 없이,
Stripe가 카드, Alipay, GrabPay 등 활성화된 결제 수단을 자동으로 표시하고 처리까지 해줍니다.


🧩 Stripe Payment Element란?

Stripe Payment Element는 다음을 통합한 컴포넌트입니다:

포함 요소 설명

카드 입력 폼 카드 번호, 만료일, CVC 등
간편결제 버튼 Apple Pay, Google Pay
로컬 결제 옵션 Alipay, GrabPay 등
자동 결제 수단 표시 사용자의 국가, 디바이스, 설정된 payment_method_types에 따라 자동

🛠️ 기본 구성 흐름 (프론트 + 백엔드)

1️⃣ 백엔드: PaymentIntent 생성

// NestJS나 Express 기준
const paymentIntent = await stripe.paymentIntents.create({
  amount: 5000, // 50.00 USD
  currency: 'usd',
  automatic_payment_methods: {
    enabled: true, // 필수! → 여러 결제수단 자동 지원
  },
});

return { clientSecret: paymentIntent.client_secret };

✅ automatic_payment_methods: { enabled: true } 설정 시,
Stripe가 카드, Alipay, GrabPay 등 자동으로 적용 가능한 결제 수단을 판단합니다.


2️⃣ 프론트엔드: Stripe.js + React 등에서 Elements 설정

👉 1. Stripe.js 초기화

import { loadStripe } from '@stripe/stripe-js';
import { Elements } from '@stripe/react-stripe-js';

const stripePromise = loadStripe('pk_test_...'); // 퍼블릭 키

👉 2. Elements 구성

<Elements stripe={stripePromise} options={{ clientSecret }}>
  <CheckoutForm />
</Elements>

3️⃣ 프론트엔드: PaymentElement 컴포넌트 사용

import { PaymentElement, useStripe, useElements } from '@stripe/react-stripe-js';

const CheckoutForm = () => {
  const stripe = useStripe();
  const elements = useElements();

  const handleSubmit = async (event) => {
    event.preventDefault();

    const result = await stripe.confirmPayment({
      elements,
      confirmParams: {
        return_url: 'https://yourdomain.com/payment-complete',
      },
    });

    if (result.error) {
      console.error(result.error.message);
    } else {
      console.log("결제 완료");
    }
  };

  return (
{/* Stripe가 제공하는 결제 UI */} ); };

💡 자동 포함되는 결제 수단 예

결제 수단 포함 여부 (자동)

💳 카드 결제 기본 포함
💼 Apple Pay / Google Pay 사용자의 디바이스에 따라 자동 노출
🌏 Alipay / GrabPay / FPX 등 백엔드에서 활성화되어 있고 사용자 위치가 지원되면 자동 표시

🎨 디자인 커스터마이징도 가능

const options = {
  clientSecret,
  appearance: {
    theme: 'stripe', // 또는 'night', 'flat' 등
    labels: 'floating',
  },
};

✅ 테마, 글꼴, 폼 스타일 등 일부 커스터마이징 가능


📦 장점 vs 단점

장점 단점

✅ UI 구현 거의 불필요 ❌ 디자인 커스터마이징 제한
✅ 다양한 결제 방식 자동 표시 ❌ 완전한 UX 제어는 어려움
✅ 3D Secure 자동 처리 ❌ 결제 방식 고정 불가 (무조건 자동 노출)

📌 결론

Stripe Payment Element는 가장 빠르고 안전하게 결제 시스템을 구축하는 방법입니다.

  • 서버에서 automatic_payment_methods: true 설정
  • 프론트에서 <PaymentElement />로 자동 UI 렌더링
  • 사용자는 카드/간편결제 등을 선택하고 결제
  • 결제 완료 후 return_url로 이동

👇 원하시면:

  • Next.js/React 프로젝트 통합 예제
  • return_url에서 결제 결과 처리 방법
  • 백엔드 NestJS 또는 Express 연동 코드

제공해드릴 수 있어요. 사용 중인 프레임워크를 알려주세요!

 

 

제공하는 UI 적용 - HTML

 


✅ 순수 HTML + JavaScript 환경에서 Stripe Payment Element 사용 방법

1️⃣ Stripe.js 스크립트 로드

HTML에 Stripe 라이브러리를 추가:

<script src="https://js.stripe.com/v3/"></script>

2️⃣ 백엔드에서 PaymentIntent 생성 → client_secret 반환

// 예: Node.js 서버에서
const paymentIntent = await stripe.paymentIntents.create({
  amount: 5000,
  currency: 'usd',
  automatic_payment_methods: {
    enabled: true,
  },
});

res.json({ clientSecret: paymentIntent.client_secret });

3️⃣ 프론트엔드에 Payment Element 삽입

<form id="payment-form">
  <div id="payment-element"><!-- Stripe 결제 UI 렌더링됨 --></div>
  <button id="submit">결제하기</button>
  <div id="error-message"></div>
</form>

<script>
  const stripe = Stripe("pk_test_..."); // 퍼블릭 키
  const clientSecret = "서버에서 받아온 client_secret";

  const elements = stripe.elements({ clientSecret });

  const paymentElement = elements.create("payment");
  paymentElement.mount("#payment-element");

  const form = document.getElementById("payment-form");

  form.addEventListener("submit", async (event) => {
    event.preventDefault();

    const { error } = await stripe.confirmPayment({
      elements,
      confirmParams: {
        return_url: "https://yourdomain.com/payment-complete",
      },
    });

    if (error) {
      document.getElementById("error-message").textContent = error.message;
    }
  });
</script>

🧩 실제로 자동으로 보여주는 예

사용자가 결제 페이지에 접근하면 Stripe는 자동으로:

  • 카드 입력 UI
  • Apple Pay / Google Pay 버튼
  • Alipay, GrabPay, FPX 등 로컬 결제 수단

자동으로 판단해서 보여줍니다.


📦 이 방식의 장점

장점 설명

✅ 프레임워크 없이 가능 React/Next.js 없이도 Stripe 결제 구현 가능
✅ 다양한 결제 수단 자동 지원 사용자의 디바이스와 위치에 따라 알맞은 결제 수단 자동 표시
✅ 가장 빠른 구현 방법 UI, 인증, 보안 Stripe가 모두 관리

🧪 참고: 테스트 카드

  • 카드 번호: 4242 4242 4242 4242
  • 유효기간: 아무 미래 날짜
  • CVC: 아무 숫자

✅ 결론

Stripe Payment Element는 일반 자바스크립트만으로도 쉽게 적용 가능하며,
결제 수단 선택 UI도 Stripe가 자동으로 구성해주기 때문에 별도 UI 없이도 구현할 수 있는 매우 편리한 방식입니다.

필요하다면:

  • Node.js + HTML 예제 프로젝트 구조
  • 서버 없는 클라이언트 테스트 코드 (정적 HTML 기반)
  • 한국 결제 수단 대응 여부

도와드릴 수 있어요. 추가로 원하시면 알려주세요!

 

 

 제공하는 UI 적용 - flutter

 

 

✅ Stripe Payment Sheet이란?

Stripe가 제공하는 모든 결제 수단을 자동으로 감지하고 하나의 UI로 통합해서 보여주는 표준 결제 창입니다.

예시 화면:

  • 카드 정보 입력 필드
  • Google Pay / Apple Pay 버튼
  • Alipay, GrabPay 등 지역 결제 수단
  • UI 및 보안, UX Stripe가 전담

✅ Flutter에서 Payment Sheet 띄우는 흐름

1️⃣ 서버에서 PaymentIntent 생성

백엔드(Node.js 등)에서 다음처럼 생성합니다:

const paymentIntent = await stripe.paymentIntents.create({
  amount: 5000,
  currency: 'usd',
  automatic_payment_methods: { enabled: true },
});

res.json({ clientSecret: paymentIntent.client_secret });

2️⃣ Flutter 앱에서 Stripe Payment Sheet 띄우기


앱 시작
  ↓
서버에서 publishableKey 요청
  ↓
Stripe.publishableKey 설정 → applySettings()
  ↓
결제 시점에 server에서 clientSecret 요청
  ↓
initPaymentSheet → presentPaymentSheet


import 'package:flutter/material.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 퍼블릭 키를 서버에서 받아오기
  final response = await http.get(Uri.parse('http://yourserver.com/stripe/publishable-key'));

  if (response.statusCode == 200) {
    final data = json.decode(response.body);
    final publishableKey = data['publishableKey'];

    // Stripe 초기화
    Stripe.publishableKey = publishableKey;
    await Stripe.instance.applySettings();

    runApp(MyApp());
  } else {
    throw Exception('❌ 퍼블릭 키를 불러올 수 없습니다');
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Stripe 결제 테스트')),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              await payWithStripe();
            },
            child: Text('결제하기'),
          ),
        ),
      ),
    );
  }
}

// ✅ 서버에서 PaymentIntent 생성 후 clientSecret을 받아오는 함수
Future<String> fetchClientSecretFromServer() async {
  final response = await http.post(Uri.parse('http://yourserver.com/create-payment-intent'));

  if (response.statusCode == 200) {
    final data = json.decode(response.body);
    return data['clientSecret']; // 서버에서 받은 clientSecret 반환
  } else {
    throw Exception('❌ clientSecret 요청 실패');
  }
}

// ✅ Stripe 결제 흐름
Future<void> payWithStripe() async {
  try {
    // 1. 서버에서 PaymentIntent 생성 후 clientSecret 받기
    final clientSecret = await fetchClientSecretFromServer();

    // 2. Stripe PaymentSheet 초기화
    await Stripe.instance.initPaymentSheet(
      paymentSheetParameters: SetupPaymentSheetParameters(
        paymentIntentClientSecret: clientSecret,
        merchantDisplayName: 'Your Company',
        style: ThemeMode.light,
      ),
    );

    // 3. 결제 UI 띄우기 (Stripe 제공 화면)
    await Stripe.instance.presentPaymentSheet();

    // 4. 결제 성공 처리
    print('✅ 결제 성공!');
  } catch (e) {
    print('❌ 결제 실패: $e');
  }
}

💡 장점

항목 설명

✅ 완전한 Stripe UI 사용 카드 입력부터 간편결제 버튼까지
✅ 여러 결제 수단 자동 지원 카드, Apple Pay, Google Pay, Alipay 등
✅ Flutter에서도 그대로 사용 가능 React Native 수준으로 지원
✅ UX, 보안, 인증 모두 Stripe가 처리 직접 구현할 필요 없음

📷 예시 화면

사용 환경 보여주는 결제 수단

iPhone Apple Pay + 카드 UI
Android Google Pay + 카드 UI
동남아 GrabPay, FPX 등 로컬 결제
한국 카드 (Stripe가 계약된 카드사 기준)

🛠️ 정리

Stripe의 Payment Sheet는 Flutter에서도 공식 지원되며,
Stripe가 만든 결제 UI를 그대로 앱 안에서 띄우고 사용할 수 있습니다.


 

 

flutter로 stripe에서 지원하는 결제 UI 실행하여 결제하기


✅ Stripe Payment Sheet이란?

Stripe가 제공하는 모든 결제 수단을 자동으로 감지하고 하나의 UI로 통합해서 보여주는 표준 결제 창입니다.

예시 화면:

  • 카드 정보 입력 필드
  • Google Pay / Apple Pay 버튼
  • Alipay, GrabPay 등 지역 결제 수단
  • UI 및 보안, UX Stripe가 전담

✅ Flutter에서 Payment Sheet 띄우는 흐름

1️⃣ 서버에서 PaymentIntent 생성

백엔드(Node.js 등)에서 다음처럼 생성합니다:

const paymentIntent = await stripe.paymentIntents.create({
  amount: 5000,
  currency: 'usd',
  automatic_payment_methods: { enabled: true },
});

res.json({ clientSecret: paymentIntent.client_secret });

2️⃣ Flutter 앱에서 Stripe Payment Sheet 띄우기

import 'package:flutter_stripe/flutter_stripe.dart';

Future<void> payWithStripe() async {
  // 1. 서버에서 PaymentIntent 생성 후 clientSecret 받기
  final clientSecret = await fetchClientSecretFromServer();

  // 2. Stripe PaymentSheet 초기화
  await Stripe.instance.initPaymentSheet(
    paymentSheetParameters: SetupPaymentSheetParameters(
      paymentIntentClientSecret: clientSecret,
      merchantDisplayName: 'Your Company',
      style: ThemeMode.light, // 다크 모드 등 가능
    ),
  );

  // 3. 결제 UI 띄우기 (Stripe가 제공하는 화면)
  await Stripe.instance.presentPaymentSheet();

  // 4. 성공 시 처리
  print('결제 성공!');
}

💡 장점

항목 설명

✅ 완전한 Stripe UI 사용 카드 입력부터 간편결제 버튼까지
✅ 여러 결제 수단 자동 지원 카드, Apple Pay, Google Pay, Alipay 등
✅ Flutter에서도 그대로 사용 가능 React Native 수준으로 지원
✅ UX, 보안, 인증 모두 Stripe가 처리 직접 구현할 필요 없음

📷 예시 화면

사용 환경 보여주는 결제 수단

iPhone Apple Pay + 카드 UI
Android Google Pay + 카드 UI
동남아 GrabPay, FPX 등 로컬 결제
한국 카드 (Stripe가 계약된 카드사 기준)

🛠️ 정리

Stripe의 Payment Sheet는 Flutter에서도 공식 지원되며,
Stripe가 만든 결제 UI를 그대로 앱 안에서 띄우고 사용할 수 있습니다.


필요하다면:

  • Flutter 전체 결제 예제 프로젝트
  • 테스트용 카드 번호/에러 시나리오 처리
  • 서버 연동 코드 (Node.js / NestJS 등)

도움드릴 수 있어요. 추가로 궁금한 부분 있으신가요?

결제취소

 

좋습니다! Stripe에서는 결제 취소(취소 또는 환불)를 두 가지 방식으로 처리할 수 있어요:


✅ Stripe 결제 취소의 두 가지 방법

방법 설명 API

결제 취소(Cancel PaymentIntent) 결제가 아직 완료되지 않은 상태에서 중단 paymentIntents.cancel()
환불(Refund) 결제가 완료된 후, 전액 또는 일부 환불 refunds.create()

🧭 상황에 따라 사용하는 방식

상황 처리 방법

사용자가 결제 도중 창을 닫았거나 → 미승인 상태 paymentIntent.cancel()로 취소
사용자가 결제 완료 후, 결제 취소 요청 refunds.create()로 환불 처리

💳 환불 처리 (가장 일반적인 방법)

🛠️ Node.js 예시

const refund = await stripe.refunds.create({
  payment_intent: 'pi_1NX3lq2eZvKYlo2CdqR8XXXX', // 결제된 PaymentIntent ID
  amount: 5000, // 환불할 금액 (센트 기준, optional. 전액이면 생략 가능)
});

✔️ 설명

  • payment_intent: 결제할 때 받은 ID (pi_...)
  • amount: 생략 시 전체 환불, 넣으면 부분 환불

🔁 결제 취소 (아직 승인 전일 때)

await stripe.paymentIntents.cancel('pi_1NX3lq2eZvKYlo2CdqR8XXXX');

status가 requires_payment_method, requires_confirmation일 때만 취소 가능


✅ 환불 관련 참고 사항

항목 설명

환불 처리 시간 일반적으로 5~10 영업일 (카드사에 따라 다름)
🧾 부분 환불 가능 금액 지정 가능 (예: $50 중 $20만 환불)
📥 환불 상태 확인 Stripe Dashboard나 API로 refund.status 조회 가능
결제 수수료 환불 여부 기본적으로 수수료는 환불되지 않습니다 (국가 및 약관에 따라 다름)

🧠 정리

기능 메서드 언제 사용하나요?

❌ 결제 취소 paymentIntents.cancel() 결제 완료 에 취소할 때
💸 환불 refunds.create() 결제 완료 에 환불할 때

필요하다면:

  • 환불 처리 흐름 전체 예제 (NestJS / Express)
  • 사용자 요청으로 결제 내역 조회 및 취소 UI 처리
  • Flutter 앱에서 결제 취소 시 연동 방법

도움드릴 수 있어요. 알려주세요!

반응형