콘텐츠로 이동

Stripe 통합 추가

Stripe는 인터넷 비즈니스를 위한 온라인 결제 처리 플랫폼입니다. Stripe를 통합하면 애플리케이션에서 거래, 구독 및 금융 데이터를 안전하게 처리할 수 있습니다.

통합 목록에서 Stripe를 선택하면 구성 모달이 나타납니다. 연결을 설정하려면 Stripe 대시보드에서 다음 자격 증명을 제공해야 합니다.

  • 입력: Secret Key 필드에 개인 Stripe 비밀 키 (일반적으로 sk_로 시작)를 입력하십시오. 이 키를 통해 백엔드가 보안 요청을 인증할 수 있습니다.
  • 입력: Publishable Key 필드에 공용 Stripe 게시 가능 키 (일반적으로 pk_로 시작)를 입력하십시오. 이 키는 프런트엔드 구현에 사용됩니다.
  • 입력: 드롭다운 메뉴에서 적절한 환경 컨텍스트를 선택하십시오 (예: 개발/샌드박스 모드의 경우 Test, 실시간 처리의 경우 Production).

키와 환경이 구성되면:

  1. 상태 표시줄을 확인하십시오 (현재 Not Connected로 표시됨).
  2. 오른쪽 하단의 검은색 Add 버튼을 클릭하여 자격 증명을 저장하고 결제 통합을 활성화하십시오.

Stripe 구성

Stripe 통합


프로젝트 및 환경에 대한 새 Stripe 구성을 생성합니다.

Mutation:

mutation ConfigureStripe (
$input: ConfigureStripeInput!
) {
configureStripe (
input: $input
) {
id
publishableKey
webhookUrl
}
}

Input:

input ConfigureStripeInput {
secretKey: String! # Stripe secret key (sk_test_... or sk_live_...)
publishableKey: String! # Stripe publishable key (pk_test_... or pk_live_...)
environment: StripeEnvironment! # TEST or LIVE
webhookSecret: String # Webhook signing secret (optional)
}

Response:

type ConfigureStripePayload {
id: ID! # Configuration ID
publishableKey: String! # Publishable key
webhookUrl: String! # Generated webhook URL
}

Example:

{
"input": {
"secretKey": "sk_test_...",
"publishableKey": "pk_test_...",
"environment": "TEST",
"webhookSecret": "whsec_..."
}
}

참고:

  • 비밀 키는 저장 전에 AES-256-GCM으로 암호화됩니다.
  • 프로젝트/환경 조합당 하나의 구성만 가능
  • 구성이 이미 존재하는 경우 오류 반환

기존 Stripe 구성을 업데이트합니다.

Mutation:

mutation UpdateStripeConfig (
$input: UpdateStripeConfigInput!
) {
updateStripeConfig (
input: $input
) {
id
publishableKey
webhookUrl
}
}

Input:

input UpdateStripeConfigInput {
secretKey: String # Optional
publishableKey: String # Optional
environment: StripeEnvironment # Optional
webhookSecret: String # Optional
}

Response:

type UpdateStripeConfigPayload {
id: ID!
publishableKey: String!
webhookUrl: String!
}

참고:

  • 모든 필드는 선택 사항입니다.
  • 제공된 필드만 업데이트됩니다.
  • 비밀 키가 제공되면 암호화됩니다.

ID로 단일 고객을 검색합니다.

Query:

query stripe_customer{
stripe_customer(
id: "cus_Ts..."
)
{
id
name
email
phone
description
metadata
object
createdAt
}
}

페이지네이션 및 선택적 필터링을 사용하여 고객을 나열합니다.

Query:

query stripe_customers (
$first: Int,
$after: String,
$customerId: String
) {
stripe_customers (
first: $first,
after: $after,
customerId: $customerId
) {
edges {
node {
id
name
email
phone
description
createdAt
}
cursor
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}

Parameters:

  • first: 반환할 항목 수 (기본값: 10)
  • after: 페이지네이션용 커서
  • customerId: 고객 ID로 필터링 (선택 사항)

새 고객을 생성합니다.

Mutation:

mutation stripe_createCustomer {
stripe_createCustomer (
input: {
name: "Customer",
email: "example@archie.com",
phone: "+573001230001",
description: "Description Example"
metadata: {
data1: "Example data1",
data2: "Example data2"
}
}
)
{
id
name
email
phone
description
metadata
object
createdAt
}
}

기존 고객을 업데이트합니다.

Mutation:

mutation stripe_updateCustomer {
stripe_updateCustomer(
id: "cus_Ts...",
input: {
name: "Customer",
email: "example@archie.com",
phone: "+573001230001",
description:"Description Example",
metadata: {
data1: "Example data1 updated",
data2: "Example data2 updated"
}
}
)
{
id
name
email
phone
description
metadata
object
createdAt
}
}

참고:

  • 모든 필드는 선택 사항입니다.
  • 제공된 필드만 업데이트됩니다.

고객을 삭제합니다.

Mutation:

mutation stripe_deleteCustomer {
stripe_deleteCustomer (
id: "cus_Ts...")
}

Response:

  • 성공 시 true 반환
  • 고객을 찾을 수 없는 경우 오류 반환

ID로 단일 결제 의도를 검색합니다.

Query:

query stripe_paymentIntent {
stripe_paymentIntent (
id: "pi_3Su..."
)
{
id
customerId
paymentMethodId
currency
amount
status
metadata
object
clientSecret
createdAt
}
}

페이지네이션 및 선택적 필터링을 사용하여 결제 의도를 나열합니다.

Query:

query stripe_paymentIntents (
$first: Int,
$after: String,
$customerId: String
) {
stripe_paymentIntents (
first: $first,
after: $after,
customerId: $customerId
) {
edges {
node {
id
customerId
paymentMethodId
currency
amount
status
metadata
object
clientSecret
createdAt
}
cursor
}
pageInfo {
hasPreviousPage
hasNextPage
startCursor
endCursor
}
}
}

Parameters:

  • first: 반환할 항목 수 (기본값: 10)
  • after: 페이지네이션용 커서
  • customerId: 고객 ID로 필터링 (선택 사항)

새 결제 의도를 생성합니다.

Mutation:

mutation stripe_createPaymentIntent {
stripe_createPaymentIntent (
input: {
amount: 12.35,
currency: "usd",
customerId: "cus_Ts...",
paymentMethodId: "pm_1Su...",
automaticPaymentMethods: true
}
)
{
id
customerId
paymentMethodId
currency
amount
status
metadata
object
clientSecret
createdAt
}
}

참고:

  • clientSecret은 프런트엔드 확인을 위해 반환됩니다.
  • Stripe.js와의 통합을 위해 automaticPaymentMethods: true를 사용하십시오.

확인 전에 결제 의도를 업데이트합니다.

Mutation:

mutation stripe_updatePaymentIntent{
stripe_updatePaymentIntent(
id: "pi_3S...",
input: {
amount: 36.92,
currency: "usd",
paymentMethodId: "pm_1Su..."
metadata:{
data1: "Example data1"
}
}
) {
id
customerId
paymentMethodId
currency
amount
status
metadata
object
clientSecret
createdAt
}
}

참고:

  • 확인 전에만 업데이트할 수 있습니다.
  • 모든 필드는 선택 사항입니다.

결제 의도를 확인합니다.

Mutation:

mutation stripe_confirmPaymentIntent{
stripe_confirmPaymentIntent(
id: "pi_3Su..."
input: {
paymentMethodId: "pm_1Su...",
returnUrl: "http://localhost:3000/successful-payment"
}
) {
id
customerId
paymentMethodId
currency
amount
status
metadata
object
clientSecret
createdAt
}
}

참고:

  • 결제를 완료하려면 필수입니다.
  • 3D Secure 인증이 필요할 수 있습니다.
  • 업데이트된 상태 (succeeded, requires_action 등)를 반환합니다.

결제 의도를 취소합니다.

Mutation:

mutation stripe_cancelPaymentIntent {
stripe_cancelPaymentIntent(
id: "pi_3Su..."
) {
id
customerId
paymentMethodId
currency
amount
status
metadata
object
clientSecret
createdAt
}
}

참고:

  • 성공하지 않았거나 취소되지 않은 결제 의도만 취소할 수 있습니다.
  • 상태가 “canceled”로 변경됩니다.

ID로 단일 구독을 검색합니다.

Query:

query stripe_subscription {
stripe_subscription(id: "sub_1Su...") {
id
customerId
status
currentPeriodStart
currentPeriodEnd
createdAt
cancelAtPeriodEnd
metadata
object
items {
data {
id
priceId
quantity
}
}
}
}

페이지네이션 및 선택적 필터링을 사용하여 구독을 나열합니다.

Query:

query stripe_subscriptions (
$first: Int,
$after: String,
$customerId: String
) {
stripe_subscriptions (
first: $first,
after: $after,
customerId: $customerId
) {
edges {
node {
id
customerId
status
currentPeriodStart
currentPeriodEnd
createdAt
cancelAtPeriodEnd
metadata
object
items {
data {
id
priceId
quantity
}
}
}
cursor
}
pageInfo {
hasPreviousPage
hasNextPage
startCursor
endCursor
}
}
}

Parameters:

  • first: 반환할 항목 수 (기본값: 10)
  • after: 페이지네이션용 커서
  • customerId: 고객 ID로 필터링 (선택 사항)
  • status: 상태로 필터링 (선택 사항)

새 구독을 생성합니다.

Mutation:

mutation stripe_createSubscription {
stripe_createSubscription (
input: {
customerId: "cus_TsQ...",
items: {
priceId: "price_1Su...",
quantity: 1
},
metadata: {
data1: "Example data1"
},
trialPeriodDays: 0
}
) {
id
customerId
status
currentPeriodStart
currentPeriodEnd
createdAt
cancelAtPeriodEnd
metadata
object
items {
data {
id
priceId
quantity
}
}
}
}

참고:

  • paymentBehavior는 결제 방법이 필요한 구독에 대해 “default_incomplete”일 수 있습니다.
  • 평가 기간은 일 단위로 지정됩니다.
  • 최신 인보이스 및 결제 의도가 자동으로 확장됩니다.

기존 구독을 업데이트합니다.

Mutation:

mutation stripe_updateSubscription {
stripe_updateSubscription(
id: "sub_1Sv..."
input: {
cancelAtPeriodEnd: false
metadata: {
data2: "Example data2"
}
}
) {
id
customerId
status
currentPeriodStart
currentPeriodEnd
createdAt
cancelAtPeriodEnd
metadata
object
items {
data {
id
priceId
quantity
}
}
}
}

구독을 취소합니다.

Mutation:

mutation stripe_cancelSubscription {
stripe_cancelSubscription (
cancelAtPeriodEnd: true,
id: "sub_1Sv..."
) {
id
customerId
status
currentPeriodStart
currentPeriodEnd
createdAt
cancelAtPeriodEnd
metadata
object
items {
data {
id
priceId
quantity
}
}
}
}

Parameters:

  • id: 구독 ID (필수)
  • cancelAtPeriodEnd: true인 경우 기간 종료 시 취소, false인 경우 즉시 취소 (기본값: false)

참고:

  • 즉시 취소: 구독이 지금 종료됩니다.
  • 기간 종료 시 취소: 구독이 현재 기간이 끝날 때까지 계속됩니다.

페이지네이션을 사용하여 제품을 나열합니다.

Query:

query stripe_products (
$first: Int,
$after: String
) {
stripe_products (
first: $first,
after: $after
) {
edges {
node {
id
name
description
active
metadata
object
createdAt
}
cursor
}
pageInfo {
hasPreviousPage
hasNextPage
startCursor
endCursor
}
}
}

새 제품을 생성합니다.

Mutation:

mutation stripe_createProduct {
stripe_createProduct (
input: {
name: "Product 01",
description: "Description product 01",
metadata: {
data1: "Example data1"
}
}
) {
id
name
description
active
metadata
object
createdAt
}
}

페이지네이션 및 선택적 필터링을 사용하여 가격을 나열합니다.

Query:

query stripe_prices (
$first: Int,
$after: String,
$productId: String
) {
stripe_prices (
first: $first,
after: $after,
productId: $productId
) {
edges {
node {
id
productId
active
currency
unitAmount
object
metadata
createdAt
recurring {
interval
intervalCount
}
}
cursor
}
pageInfo {
hasPreviousPage
hasNextPage
startCursor
endCursor
}
}
}

Parameters:

  • first: 반환할 항목 수 (기본값: 10)
  • after: 페이지네이션용 커서
  • productId: 제품 ID로 필터링 (선택 사항)

새 가격을 생성합니다.

Mutation:

mutation stripe_createPrice {
stripe_createPrice (
input: {
productId: "prod_Tst...",
unitAmount: 25.85,
currency: "usd",
recurring: {
interval: "month",
intervalCount: 1
},
metadata: {
data1: "Example data1"
}
}
) {
id
productId
currency
unitAmount
active
object
createdAt
metadata
recurring {
interval
intervalCount
}
}
}

참고:

  • 일회성 가격의 경우 recurring을 생략하십시오.
  • interval은 “day”, “week”, “month”, “year” 중 하나여야 합니다.

ID로 단일 인보이스를 검색합니다.

Query:

query stripe_invoice {
stripe_invoice (
id: "in_1Su..."
) {
id
customerId
subscriptionId
currency
amountPaid
amountDue
status
object
metadata
createdAt
lineItems {
data {
id
description
currency
amount
quantity
}
}
}
}

참고:

  • 구독 ID는 가능한 경우 API 확장을 통해 채워집니다.

페이지네이션 및 선택적 필터링을 사용하여 인보이스를 나열합니다.

Query:

query stripe_invoices (
$first: Int,
$after: String,
$customerId: String,
$status: String
) {
stripe_invoices (
first: $first,
after: $after,
customerId: $customerId,
status: $status
) {
edges {
node {
id
customerId
subscriptionId
currency
amountPaid
amountDue
status
object
metadata
createdAt
lineItems {
data {
id
description
currency
amount
quantity
}
}
}
cursor
}
pageInfo {
hasPreviousPage
hasNextPage
startCursor
endCursor
}
}
}

Parameters:

  • first: 반환할 항목 수 (기본값: 10)
  • after: 페이지네이션용 커서
  • customerId: 고객 ID로 필터링 (선택 사항)
  • status: 상태로 필터링 (선택 사항)

프로그래밍 방식으로 인보이스를 결제합니다.

Mutation:

mutation stripe_payInvoice {
stripe_payInvoice (
id: "in_1Sv..."
) {
id
customerId
subscriptionId
currency
amountPaid
amountDue
status
object
metadata
createdAt
lineItems {
data {
id
description
currency
amount
quantity
}
}
}
}

참고:

  • 고객의 기본 결제 방법을 사용하여 인보이스 결제를 시도합니다.
  • 결제가 실패하면 오류를 반환합니다.
  • 성공 시 인보이스 상태를 “paid”로 업데이트합니다.

페이지네이션 및 선택적 필터링을 사용하여 환불을 나열합니다.

Query:

query stripe_refunds (
$first: Int,
$after: String,
$paymentIntentId: String
) {
stripe_refunds (
first: $first,
after: $after,
paymentIntentId: $paymentIntentId
) {
edges {
node {
id
paymentIntentId
reason
status
currency
amount
metadata
object
createdAt
}
cursor
}
pageInfo {
hasPreviousPage
hasNextPage
startCursor
endCursor
}
}
}

Parameters:

  • first: 반환할 항목 수 (기본값: 10)
  • after: 페이지네이션용 커서
  • paymentIntentId: 결제 의도 ID로 필터링 (선택 사항)

결제 의도에 대한 환불을 생성합니다.

Mutation:

mutation stripe_createRefund {
stripe_createRefund (
input: {
paymentIntentId: "pi_3Sv...",
amount: 200,
reason: "requested_by_customer"
}
) {
id
reason
paymentIntentId
status
currency
amount
object
metadata
createdAt
}
}

참고:

  • 전액 환불의 경우 amount를 생략하십시오.
  • reason은 “duplicate”, “fraudulent”, “requested_by_customer” 중 하나일 수 있습니다.
  • 환불 상태는 “pending”으로 시작하여 “succeeded” 또는 “failed”로 업데이트됩니다.

페이지네이션 및 선택적 필터링을 사용하여 결제 방법을 나열합니다.

Query:

query stripe_paymentMethods (
$first: Int,
$after: String,
$customerId: String
) {
stripe_paymentMethods(
first: $first,
after: $after,
customerId: $customerId
) {
edges {
node {
id
customerId
type
object
metadata
createdAt
card {
brand
expMonth
expYear
last4
}
}
cursor
}
pageInfo {
hasPreviousPage
hasNextPage
startCursor
endCursor
}
}
}

Parameters:

  • first: 반환할 항목 수 (기본값: 10)
  • after: 페이지네이션용 커서
  • customerId: 고객 ID로 필터링 (선택 사항)

참고:

  • 안전한 카드 정보 (마지막 4자리, 브랜드, 만료일)만 반환됩니다.
  • 전체 카드 번호는 절대 노출되지 않습니다.

고객에게 결제 방법을 연결합니다.

Mutation:

mutation stripe_attachPaymentMethod {
stripe_attachPaymentMethod (
id: "pm_1Sv...",
input: {
customerId: "cus_Ts4..."
}
) {
id
customerId
type
card {
brand
expMonth
expYear
last4
}
metadata
object
createdAt
}
}

참고:

  • 결제 방법은 먼저 생성되어야 합니다 (일반적으로 Stripe.js를 통해).
  • 연결된 결제 방법은 구독 및 결제에 사용할 수 있습니다.

고객에게서 결제 방법을 분리합니다.

Mutation:

mutation stripe_detachPaymentMethod {
stripe_detachPaymentMethod (
id: "pm_1Sv..."
) {
id
customerId
type
card {
brand
expYear
expMonth
last4
}
metadata
object
createdAt
}
}

참고:

  • 분리된 결제 방법은 더 이상 결제에 사용할 수 없습니다.
  • customerId가 null로 설정된 결제 방법을 반환합니다.

서비스에서 수신한 Webhook 이벤트를 나열합니다.

Query:

query ListWebhookEvents (
$first: Int,
$after: String
) {
stripe_webhookEvents (
first: $first,
after: $after
) {
edges {
node {
id
type
data
processed
createdAt
}
cursor
}
pageInfo {
hasNextPage
hasPreviousPage
endCursor
}
}
}

Response:

type StripeWebhookEvent {
id: ID!
type: String! # Event type (e.g., "payment_intent.succeeded")
data: String! # JSON string of event data
processed: Boolean! # Whether event has been processed
createdAt: Time!
}

Parameters:

  • first: 반환할 항목 수 (기본값: 10)
  • after: 페이지네이션용 커서

참고:

  • 이벤트는 Webhook 엔드포인트를 통해 자동으로 수신됩니다.
  • 이벤트는 서명 확인 후 저장됩니다.
  • data 필드에는 전체 이벤트 페이로드가 JSON 문자열로 포함됩니다.

모든 목록 쿼리는 Relay 연결 패턴을 사용하는 커서 기반 페이지네이션을 지원합니다.

type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
query ListCustomers (
$first: Int,
$after: String
) {
stripe_customers (
first: $first,
after: $after
) {
edges {
node {
id
email
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
}
}

페이지네이션 흐름:

  1. 초기 요청: first: 10, after: null
  2. 응답의 pageInfo.endCursor를 다음 요청의 after로 사용
  3. hasNextPage를 확인하여 더 많은 페이지가 있는지 확인

기본값:

  • first: 제공되지 않은 경우 기본값 10
  • after: 제공되지 않은 경우 처음부터 시작

모든 작업은 사용자 친화적인 메시지와 함께 GraphQL 오류를 반환합니다. 오류는 명확한 피드백을 제공하기 위해 Stripe API 오류에서 매핑됩니다.

구성 오류:

  • 400: 잘못된 Stripe 키 형식
  • 404: 프로젝트 또는 구성을 찾을 수 없음
  • 400: 구성이 이미 존재함

고객 오류:

  • 404: 고객을 찾을 수 없음
  • 400: 잘못된 고객 데이터

결제 의도 오류:

  • 404: 결제 의도를 찾을 수 없음
  • 400: 잘못된 금액 또는 통화
  • 402: 결제 실패 (카드 거부, 잔액 부족 등)

구독 오류:

  • 404: 구독을 찾을 수 없음
  • 400: 잘못된 구독 매개변수
  • 400: 취소된 구독을 업데이트할 수 없음

Stripe 오류 코드: 일반적인 Stripe 오류 코드는 사용자 친화적인 메시지로 매핑됩니다.

  • card_declined: “카드가 거부되었습니다”
  • insufficient_funds: “잔액이 부족합니다”
  • invalid_number: “잘못된 카드 번호입니다”
  • expired_card: “카드가 만료되었습니다”
  • incorrect_cvc: “잘못된 CVC 코드입니다”
{
"errors": [
{
"message": "Customer not found",
"extensions": {
"code": "NOT_FOUND",
"stripeErrorCode": "resource_missing"
}
}
],
"data": null
}

enum StripeEnvironment {
TEST # Test mode
LIVE # Live/production mode
}

Map 스칼라 유형은 키-값 맵을 나타냅니다.

  • 키는 문자열입니다.
  • 값은 문자열, 숫자, 부울 또는 중첩된 맵일 수 있습니다.
  • 메타데이터 필드에 사용됩니다.

예:

{
"metadata": {
"order_id": "12345",
"user_id": "67890",
"premium": true
}
}

Time 스칼라 유형은 ISO 8601 형식의 타임스탬프를 나타냅니다.

예: "2025-11-16T00:28:48.081Z"