DATA/UPBIT/daemon/target/upbit_api.class.php
<?php
class Upbit {
    private $access_key;
    private $secret_key;
    private $api_url = 'https://api.upbit.com';

    public function __construct($access_key, $secret_key) {
        $this->access_key = $access_key;
        $this->secret_key = $secret_key;
    }

    // [핵심] 업비트 서버로 신호 보내는 함수 (복잡한 건 여기서 다 처리해!)
    public function request($method, $path, $params = []) {
        $query_string = '';
        if (!empty($params)) {
            $query_string = http_build_query($params);
        }

        // JWT 인증 토큰 만들기 (업비트가 요구하는 암호표)
        $payload = [
            'access_key' => $this->access_key,
            'nonce' => uniqid(),
        ];

        if (!empty($params)) {
            $payload['query_hash'] = hash('sha512', $query_string, false);
            $payload['query_hash_alg'] = 'SHA512';
        }

        $jwt_token = $this->generate_jwt($payload, $this->secret_key);
        $authorization_token = "Bearer {$jwt_token}";

        // 진짜 통신 시작 (cURL)
        $url = $this->api_url . $path;
        if ($method === 'GET' && !empty($query_string)) {
            $url .= '?' . $query_string;
        }

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            "Content-Type: application/json",
            "Authorization: {$authorization_token}"
        ]);

        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
        } else if ($method === 'DELETE') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
        }

        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        // 결과 반환 (배열로 변환해서 줌)
        return json_decode($response, true);
    }

    // [JWT 생성기] 외부 라이브러리 없이 순수 코드로 제작 (가볍고 빠름)
    private function generate_jwt($payload, $secret) {
        $header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);
        $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
        $base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode(json_encode($payload)));
        $signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, $secret, true);
        $base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
        return $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;
    }

    // -----------------------------------------------------------
    // ★ 오빠가 사용하는 기능들 (주문 넣기)
    // -----------------------------------------------------------

    // 1. [뉴자지용] 시장가 매수 (돈만 입력하면 알아서 사줌)
    public function buy_market_order($market, $price) {
        $params = [
            'market' => $market,
            'side' => 'bid', // 매수
            'ord_type' => 'price', // 시장가(가격)
            'price' => (string)$price,
        ];
        return $this->request('POST', '/v1/orders', $params);
    }

    // 2. [옛날자지용] 지정가 주문 (가격, 수량 지정)
    public function order($params) {
        return $this->request('POST', '/v1/orders', $params);
    }
}

// -----------------------------------------------------------
// ★ [호환성 패치] 오빠가 옛날 코드(day_target_code.php)에서 쓰는 함수
// 이 함수가 없으면 day_target_code.php가 에러 남!
// -----------------------------------------------------------
function upbit_place_order_local($params) {
    global $upbit_access, $upbit_secret; // 몸통 파일에 있는 키를 가져옴

    if (!$upbit_access || !$upbit_secret) {
        return ['error' => 'API Key가 설정되지 않았습니다.'];
    }

    $upbit = new Upbit($upbit_access, $upbit_secret);
    return $upbit->order($params);
}
?>