# Stripe API 사용법 (Google Apps Script) ## 개요 Stripe는 온라인 결제를 처리하는 글로벌 결제 플랫폼입니다. Google Apps Script를 통해 Stripe API를 호출하여 결제 데이터를 조회하고 관리할 수 있습니다. ## API 준비사항 1. **Stripe 계정 생성**: https://stripe.com/ 2. **API 키 발급**: - Dashboard > Developers > API keys - Secret Key (sk_live_... 또는 sk_test_...) - Publishable Key (pk_live_... 또는 pk_test_...) ## Google Apps Script 샘플 코드 ### 1. API 키 설정 ```javascript // code.gs // Google Sheet에서 Stripe API 정보 읽기 function getStripeConfig() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('API_Config'); return { secretKey: sheet.getRange('B4').getValue(), // Stripe Secret Key baseUrl: 'https://api.stripe.com/v1' }; } // API 인증 헤더 생성 function getStripeHeaders(secretKey) { const encoded = Utilities.base64Encode(secretKey + ':'); return { 'Authorization': `Basic ${encoded}`, 'Content-Type': 'application/x-www-form-urlencoded' }; } ``` ### 2. 고객 목록 조회 ```javascript // Stripe 고객 목록 조회 function getStripeCustomers(limit = 100) { const config = getStripeConfig(); const url = `${config.baseUrl}/customers?limit=${limit}`; const options = { method: 'GET', headers: getStripeHeaders(config.secretKey), muteHttpExceptions: true }; try { const response = UrlFetchApp.fetch(url, options); const statusCode = response.getResponseCode(); if (statusCode === 200) { const data = JSON.parse(response.getContentText()); Logger.log(`${data.data.length}명의 고객 정보를 가져왔습니다.`); return data.data; } else { Logger.log('에러: ' + statusCode + ' - ' + response.getContentText()); return null; } } catch (error) { Logger.log('API 호출 실패: ' + error.toString()); return null; } } ``` ### 3. 결제 내역 조회 ```javascript // Stripe 결제 내역 조회 (Charges) function getStripeCharges(limit = 100) { const config = getStripeConfig(); const url = `${config.baseUrl}/charges?limit=${limit}`; const options = { method: 'GET', headers: getStripeHeaders(config.secretKey), muteHttpExceptions: true }; try { const response = UrlFetchApp.fetch(url, options); const statusCode = response.getResponseCode(); if (statusCode === 200) { const data = JSON.parse(response.getContentText()); return data.data; } else { Logger.log('에러: ' + statusCode + ' - ' + response.getContentText()); return null; } } catch (error) { Logger.log('API 호출 실패: ' + error.toString()); return null; } } ``` ### 4. 구독 정보 조회 ```javascript // Stripe 구독 목록 조회 function getStripeSubscriptions(limit = 100) { const config = getStripeConfig(); const url = `${config.baseUrl}/subscriptions?limit=${limit}&status=active`; const options = { method: 'GET', headers: getStripeHeaders(config.secretKey), muteHttpExceptions: true }; try { const response = UrlFetchApp.fetch(url, options); const statusCode = response.getResponseCode(); if (statusCode === 200) { const data = JSON.parse(response.getContentText()); return data.data; } else { Logger.log('에러: ' + statusCode + ' - ' + response.getContentText()); return null; } } catch (error) { Logger.log('API 호출 실패: ' + error.toString()); return null; } } ``` ### 5. 특정 기간의 결제 내역 조회 ```javascript // 날짜 범위로 결제 내역 조회 function getStripeChargesByDateRange(startDate, endDate) { const config = getStripeConfig(); // Unix timestamp로 변환 const startTimestamp = Math.floor(startDate.getTime() / 1000); const endTimestamp = Math.floor(endDate.getTime() / 1000); const url = `${config.baseUrl}/charges?limit=100&created[gte]=${startTimestamp}&created[lte]=${endTimestamp}`; const options = { method: 'GET', headers: getStripeHeaders(config.secretKey), muteHttpExceptions: true }; try { const response = UrlFetchApp.fetch(url, options); const statusCode = response.getResponseCode(); if (statusCode === 200) { const data = JSON.parse(response.getContentText()); return data.data; } else { Logger.log('에러: ' + statusCode + ' - ' + response.getContentText()); return null; } } catch (error) { Logger.log('API 호출 실패: ' + error.toString()); return null; } } ``` ### 6. 데이터를 Google Sheet에 저장 ```javascript // 결제 내역을 Sheet에 저장 function saveStripeChargesToSheet() { const charges = getStripeCharges(100); if (!charges || charges.length === 0) { Logger.log('결제 데이터가 없습니다.'); return; } const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('StripeCharges'); if (!sheet) { Logger.log('StripeCharges 시트를 찾을 수 없습니다.'); return; } // 기존 데이터 삭제 (헤더 제외) const lastRow = sheet.getLastRow(); if (lastRow > 1) { sheet.getRange(2, 1, lastRow - 1, sheet.getLastColumn()).clear(); } // 헤더 설정 sheet.getRange(1, 1, 1, 7).setValues([ ['ID', '날짜', '금액', '통화', '상태', '고객 이메일', '설명'] ]); // 데이터 저장 const rows = charges.map(charge => [ charge.id, new Date(charge.created * 1000), // Unix timestamp를 Date로 변환 charge.amount / 100, // 센트를 달러/엔으로 변환 charge.currency.toUpperCase(), charge.status, charge.billing_details ? charge.billing_details.email : '', charge.description || '' ]); if (rows.length > 0) { sheet.getRange(2, 1, rows.length, 7).setValues(rows); } Logger.log(`${rows.length}건의 결제 내역을 저장했습니다.`); } // 구독 정보를 Sheet에 저장 function saveStripeSubscriptionsToSheet() { const subscriptions = getStripeSubscriptions(100); if (!subscriptions || subscriptions.length === 0) { Logger.log('구독 데이터가 없습니다.'); return; } const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('StripeSubscriptions'); if (!sheet) { Logger.log('StripeSubscriptions 시트를 찾을 수 없습니다.'); return; } // 기존 데이터 삭제 const lastRow = sheet.getLastRow(); if (lastRow > 1) { sheet.getRange(2, 1, lastRow - 1, sheet.getLastColumn()).clear(); } // 헤더 설정 sheet.getRange(1, 1, 1, 6).setValues([ ['ID', '고객 ID', '상태', '시작일', '현재 기간 종료일', '플랜 금액'] ]); // 데이터 저장 const rows = subscriptions.map(sub => [ sub.id, sub.customer, sub.status, new Date(sub.start_date * 1000), new Date(sub.current_period_end * 1000), sub.items.data[0].price.unit_amount / 100 ]); if (rows.length > 0) { sheet.getRange(2, 1, rows.length, 6).setValues(rows); } Logger.log(`${rows.length}건의 구독 정보를 저장했습니다.`); } ``` ### 7. 자동 업데이트 설정 ```javascript // Sheet 오픈 시 메뉴 추가 function onOpen() { const ui = SpreadsheetApp.getUi(); ui.createMenu('Stripe') .addItem('결제 내역 업데이트', 'saveStripeChargesToSheet') .addItem('구독 정보 업데이트', 'saveStripeSubscriptionsToSheet') .addItem('전체 업데이트', 'updateAllStripeData') .addToUi(); } // 전체 데이터 업데이트 function updateAllStripeData() { saveStripeChargesToSheet(); saveStripeSubscriptionsToSheet(); SpreadsheetApp.getActiveSpreadsheet().toast('Stripe 데이터가 업데이트되었습니다.', '완료', 3); } ``` ### 8. Webhook 처리 (선택사항) ```javascript // Stripe Webhook을 받기 위한 함수 function doPost(e) { try { const data = JSON.parse(e.postData.contents); const eventType = data.type; Logger.log('Webhook 이벤트: ' + eventType); // 이벤트 타입별 처리 switch(eventType) { case 'charge.succeeded': handleChargeSucceeded(data.data.object); break; case 'customer.subscription.created': handleSubscriptionCreated(data.data.object); break; // 기타 이벤트 처리 } return ContentService.createTextOutput(JSON.stringify({received: true})) .setMimeType(ContentService.MimeType.JSON); } catch (error) { Logger.log('Webhook 처리 실패: ' + error.toString()); return ContentService.createTextOutput(JSON.stringify({error: error.toString()})) .setMimeType(ContentService.MimeType.JSON); } } function handleChargeSucceeded(charge) { Logger.log('결제 성공: ' + charge.id); // 결제 성공 시 처리 로직 } function handleSubscriptionCreated(subscription) { Logger.log('구독 생성: ' + subscription.id); // 구독 생성 시 처리 로직 } ``` ## 주의사항 1. **API 키 보안**: Secret Key는 절대 공개하지 말고 안전하게 보관 2. **Rate Limit**: Stripe는 초당 100개의 요청 제한이 있습니다 3. **금액 단위**: Stripe는 금액을 센트/최소 단위로 저장하므로 100으로 나눠야 합니다 4. **테스트 모드**: 개발 시 Test Key (sk_test_...)를 사용하세요 5. **에러 처리**: 실제 운영 시 더 상세한 에러 처리 필요 ## 참고 링크 - Stripe API Documentation: https://stripe.com/docs/api - Stripe Dashboard: https://dashboard.stripe.com/ - Google Apps Script OAuth2: https://github.com/googleworkspace/apps-script-oauth2