로그인
회원가입
클래스(강좌)
클래스 게시판
클래스 자료 게시판
GPT - 프롬프트
주니어 클래스
패밀리 클래스
열혈 클래스
커뮤니티
최신 뉴스
질문답변
공지사항
FAQ
1:1 문의
새글
최근 30일 이내 등록된 새글 이에요.
전체
글
댓글
비메오 테스트
#vimeoWrap{ position: relative; padding-top: 30px; /* IE6 workaround*/ height: 0; overflow: hidden; margin: 0; } #vimeoWrap iframe, #vimeoWrap object, #vimeoWrap embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
최고관리자 2025-05-12
토스페이 정기결제 개발
정기 결제 중복 체크 - 같은 상품을 정기결제 하려고 할 때 사전 안내
쿠키페이 폴더에 파일을 만들어 체크아웃에 인클루드 형태로 해주세요.<?php// checkout_header.php 등에 포함// 1. 공통 로드 (영카트 환경)include_once('../shop/_common.php');// 2. 로그인 회원 확인if (!$member['mb_id']) { // 비로그인 시 검사를 건너뜁니다 return;}// 3. 현재 상품코드 가져오기// 실제 checkout 페이지에서 PRODUCTCODE 입력필드나 변수를 사용하세요.$productCode = isset($_REQUEST['PRODUCTCODE']) ? clean_xss_tags($_REQUEST['PRODUCTCODE'], 1, 1) : '';// 4. 같은 상품 구독 중인지 확인$sql = " SELECT COUNT(*) AS cnt FROM cookiepay_pg_result WHERE BUYERID = '".sql_real_escape_string($member['mb_id'])."' AND PRODUCTCODE = '".sql_real_escape_string($productCode)."' AND pay_status = 1 /* 1: 활성(구독 중) 상태 */";$row = sql_fetch($sql);// 5. 중복 구독 시 팝업 안내if ($row['cnt'] > 0) { echo '<script> alert("이미 이 상품을 구독 중입니다.\\n마이페이지에서 구독 상태를 확인해 주세요."); history.back(); </script>'; exit;}// (이후 기존 체크아웃 로직 이어서 실행)?>
최고관리자 2025-04-27
토스페이 정기결제 개발
구독 취소 코딩 - 마이페이지 삽입 부분 + 정기결제 등록 취소
<?php// 마이페이지: 사용자의 활성 구독 조회$sql = " SELECT DISTINCT RESERVE_ID, BILLKEY, PRODUCTCODE FROM cookiepay_pg_result WHERE mb_id = '{$member['mb_id']}' AND pay_status = 1";$result = sql_query($sql);if (sql_num_rows($result) > 0) { echo '<h3>내 구독 목록</h3><ul>'; while ($row = sql_fetch_array($result)) { $rid = $row['RESERVE_ID']; $bkey = $row['BILLKEY']; $pcode = $row['PRODUCTCODE']; // 테이블에 컬럼명이 다르다면 수정 echo '<li>'; echo '상품코드: '.htmlspecialchars($pcode).' '; // POST 방식 폼 + confirm 창 echo '<form method="POST" action="'.G5_URL.'/cookiepay_cancel.php" style="display:inline;">'; echo '<input type="hidden" name="reserve_id" value="'.htmlspecialchars($rid).'">'; echo '<input type="hidden" name="billkey" value="'.htmlspecialchars($bkey).'">'; echo '<button type="submit" onclick="return confirm(\'정기구독을 정말 취소하시겠습니까?\');">'; echo '구독 취소'; echo '</button>'; echo '</form>'; echo '</li>'; } echo '</ul>';} else { echo '<p>활성 구독이 없습니다.</p>';}?><?php/** * cookiepay_cancel.php * * 영카트 마이페이지에서 호출되는 정기결제(구독) 취소 핸들러 */// 1. 공통 설정 로드include_once('../shop/_common.php');require_once G5_PATH . "/cookiepay/cookiepay.lib.php";// 2. 로그인 회원 확인if (!$member['mb_id']) { alert('로그인이 필요합니다.'); exit;}// 3. GET/POST로 전달된 변수 취득$reserveId = isset($_REQUEST['reserve_id']) ? trim($_REQUEST['reserve_id']) : '';$billKey = isset($_REQUEST['billkey']) ? trim($_REQUEST['billkey']) : '';// 4. 필수 파라미터 체크if (!$reserveId || !$billKey) { alert("유효하지 않은 접근입니다.\n정기결제 예약ID와 빌링키가 필요합니다."); exit;}// 5. 소유권 확인: 해당 예약이 현재 로그인 회원의 것인지 검증$row = sql_fetch(" SELECT mb_id FROM " . COOKIEPAY_PG_RESULT . " WHERE RESERVE_ID = '$reserveId' AND BILLKEY = '$billKey' LIMIT 1");if (!$row || $row['mb_id'] !== $member['mb_id']) { alert('권한이 없습니다.'); exit;}// 6. JS confirm()을 통한 최종 확인은 링크/폼에서 처리// 7. 쿠키페이 API 호출 준비$apiAccount = cookiepay_get_api_account_info($default, 1);$pay2_id = $apiAccount['api_id'];$pay2_key = $apiAccount['api_key'];$cancelUrl = "https://sandbox.cookiepayments.com/Subscribe/recurrence_schedule_cancel";$payload = [ 'API_ID' => $pay2_id, 'RESERVE_ID'=> $reserveId, 'BILLKEY' => $billKey,];$headers = [ "Content-Type: application/json; charset=utf-8", "ApiKey: {$pay2_key}"];// 8. cURL로 취소 요청 전송$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $cancelUrl);curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload, JSON_UNESCAPED_UNICODE));curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);curl_setopt($ch, CURLOPT_TIMEOUT, 20);curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);$response = curl_exec($ch);curl_close($ch);// 9. 응답 처리$result = json_decode($response, true);if (isset($result['RESULTCODE']) && $result['RESULTCODE'] === '0000') { // 10. DB 업데이트: cookiepay_pg_result 취소 상태 반영 $sql = " UPDATE " . COOKIEPAY_PG_RESULT . " SET pay_status = 2 /* 2: 결제취소 */ WHERE RESERVE_ID = '$reserveId' AND BILLKEY = '$billKey'"; sql_query($sql); // 11. 사용자 알림 및 리다이렉트 alert("구독이 정상적으로 취소되었습니다."); goto_url(G5_URL . "/shop/mypage.php");} else { $msg = $result['RESULTMSG'] ?? 'API 통신 오류'; alert("구독 취소 실패: {$msg}"); exit;}?>
최고관리자 2025-04-27
토스페이 정기결제 개발
noti 페이지 정리
[댓글]
최고관리자 2025-04-26
토스페이 정기결제 개발
noti 페이지 정리
반복 결제가 성공적으로 되었다면cookiepay_pg_result 테이블에START_DATE, END_DATE, RESERVE_START_PAY_CNT, RESERVE_NEXT_PAY_DATE 값이 업데이트 되고 BILLKEY와 RESERVE_ID 값이 같은 필드가 UPDATE 되게 하면 됩니다 그리고 cookiepay_shop_order 테이블에 주문서 생성을 해주면 됩니다
최고관리자 2025-04-26
토스페이 정기결제 개발
정기 결제 갱신날짜
[댓글]
쿠키페이의 통지전문(Noti) 페이로드에는 초기 빌링키 발급과 정기결제(갱신) 알림을 구분해 주는 전용 “type” 필드는 없지만, 포함되는 파라미터로 다음과 같이 구분할 수 있습니다. 초기 빌링키 발급(Noti 없음 또는 단일 결제 Noti) 빌링키 생성(채번) API 호출에 대한 응답은 쇼핑몰→쿠키페이로 요청하고, 쿠키페이→쇼핑몰(Noti) 으로 별도 전송되지 않습니다. 만약 단일 결제(카드 최초 과금) 결과가 Noti로 온다면, 페이로드에 RESERVE_ID 등의 반복결제 관련 필드가 전혀 포함되지 않습니다. 포함 필드 예시: ORDERNO, AMOUNT, TID, ACCEPT_DATE, ACCEPT_NO, BILLKEY 등(반복 관련 항목 없음) cookiepayments.com 정기결제(갱신) 알림(Noti) 예약된 주기에 따라 자동결제가 실행된 후 쿠키페이→쇼핑몰으로 Server→Server POST 통지(Noti)가 전송됩니다. 이때 페이로드에 RESERVE_ID, PAY_CNT(회차), LAST_PAY_CNT, TRY_CNT, NEXT_PAY_DATE(다음 결제 예정일) 등의 반복결제 전용 필드가 포함되어 있습니다. 이 필드들이 존재하면 “정기결제 갱신 알림”으로 판단할 수 있습니다. cookiepayments.com 요약 RESERVE_ID 등 반복결제 스케줄 관련 필드의 존재 유무로 없으면 “초기 빌링키 발급/단일 결제”, 있으면 “정기결제 갱신(Noti)” 를 구분할 수 있습니다.
최고관리자 2025-04-26
토스페이 정기결제 개발
정기 결제 갱신날짜
cookiepay_pg_result 테이블에 구독 기간 START_DATE, END_DATE,다음 결제일 RESERVE_NEXT_PAY_DATE
최고관리자 2025-04-26
토스페이 정기결제 개발
쿠키페이 정기결제 등록
cookiepay.pay.php 혹은 복호화·저장 로직의 마지막 성공 블록(// 정기결제 빌링키 저장 및 갱신 성공 로그 직후)에 넣으시면 됩니다.RECURRENCE_TYPE: "M"은 매월, "W"는 매주 반복 PAY_DAY: 매월 몇 일에 결제할지 (01~31 또는 "00"=말일) START_PAY_CNT: 몇 회차부터 예약할지 (1회차는 빌링키 발급 시 이미 처리된 경우 2부터 시작) LAST_PAY_CNT: 총 몇 회 반복할지 (0이면 무제한) 위 코드를 빌링키 저장 및 갱신 성공 로그(cookiepay_payment_log("정기결제 빌링키 저장 및 갱신 성공", ...)) 바로 아래에 넣으시면, 발급된 빌링키로 **정기결제 예약(스케줄링)**까지 자동으로 처리됩니다.<?php// (앞부분: 빌링키 복호화·저장 로직까지 생략)// ─────────────────────────────────────────────────────// 빌링키와 최초 결제 정보가 성공적으로 DB에 저장된 이후 이 부분을 삽입// ─────────────────────────────────────────────────────// 빌링키, 주문번호, 금액 변수 (복호화 결과에서 가져온 값)$billingKey = $result_array['BILLKEY']; // 복호화된 빌링키$orderNo = $result_array['ORDERNO']; // 주문번호$amount = $result_array['AMOUNT']; // 결제금액// 쿠키페이 정기결제 예약 API 엔드포인트$recUrl = "https://sandbox.cookiepayments.com/Subscribe/recurrence_schedule_reserve";// 예약할 정기결제 설정$recData = [ 'API_ID' => $pay2_id, // API 아이디 'BILLKEY' => $billingKey, // 발급받은 빌링키 'AMOUNT' => $amount, // 결제금액 'RECURRENCE_TYPE' => 'M', // 주기 (M: 매월, W: 매주) 'PAY_DAY' => date('d'), // 매월 결제일 (오늘 기준 일자 사용) 'START_PAY_CNT' => 2, // 다음 회차부터 시작 (1회차는 빌링키 발급 시 이미 결제됨) 'LAST_PAY_CNT' => 0, // 0이면 무제한];// HTTP 헤더$headers = [ "Content-Type: application/json; charset=utf-8", "ApiKey: {$pay2_key}"];// cURL로 예약 요청 전송$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $recUrl);curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($recData, JSON_UNESCAPED_UNICODE));curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);curl_setopt($ch, CURLOPT_TIMEOUT, 20);curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);$recResponse = curl_exec($ch);if ($recResponse === false) { $err = curl_error($ch); @cookiepay_payment_log("정기결제 예약 API 호출 실패", $err, 3);} else { $recResult = json_decode($recResponse, true); @cookiepay_payment_log("정기결제 예약 API 응답", $recResponse, 3); // 예약 성공 여부 확인 if (isset($recResult['RESULTCODE']) && $recResult['RESULTCODE'] === '0000') { @cookiepay_payment_log("정기결제 예약 성공", "RESERVE_ID={$recResult['RESERVE_ID']}", 3); } else { @cookiepay_payment_log("정기결제 예약 실패", $recResponse, 3); }}curl_close($ch);// (이후 로직 계속...)
최고관리자 2025-04-26
토스페이 정기결제 개발
Guest
로그인
회원가입
클래스(강좌)
클래스 게시판
클래스 자료 게시판
GPT - 프롬프트
주니어 클래스
패밀리 클래스
열혈 클래스
커뮤니티
최신 뉴스
질문답변
공지사항
FAQ
1:1 문의