새글

    최근 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 토스페이 정기결제 개발
  • 반복 결제가 성공적으로 되었다면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 토스페이 정기결제 개발