docs: 약학정보원 JSON API 정답 경로 추가 (로컬 BLOB 우회 해법)

다른 AI가 로컬 BLOB(DrugImg) 매칭키에서 막힌 부분을, 운영 POS에
실제 구현·검증한 약정원 JSON API 경로로 보강. 혼동 방지용 결정 문서.

- docs/healthkr-json-api-SOLVED.md: 정답 경로 단일 진입점.
  · 연결고리 = CD_GOODS.BARCODE → CD_BARCODE.DIK_CODE (CD_GOODS.DIK
    직접 14/19, 바코드 경로 18/19. 용각산(대) 실증).
  · 정답 엔드포인트 = ajax_result_drug2.asp (JSON 64필드+이미지URL).
    result_drug_simple.asp는 사람용 HTML, zoom.asp 파싱 불필요.
  · 로컬 BLOB 안 씀 → 44자 base64 image key 문제 자체가 사라짐.
- README: 핵심결론 최상단에 SOLVED 문서 포인터.
- scripts/probe_healthkr_json.py: 정답 경로 재현 스크립트(비번 CHANGEME).

기존 drugimg-key-findings.md(BLOB 분석)는 보존 — "BLOB 쓸 때의 문제"로
관계 명시.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-29 10:22:26 +09:00
parent c0a673d20a
commit 659e9d5880
3 changed files with 174 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
#!/usr/bin/env python3
"""약학정보원 JSON API 정답 경로 재현 스크립트.
DrugCode → CD_GOODS.BARCODE → CD_BARCODE.DIK_CODE → health.kr JSON + 이미지.
실측 환경: 192.168.0.69\\PM2014 (PIT3000). DB 접속정보는 환경에 맞게 수정.
이 저장소의 다른 스크립트(probe_drugimg_keys.py)는 로컬 BLOB 매칭키 분석용.
이 스크립트는 그 BLOB을 우회하는 '정답' 경로(약정원 JSON)를 재현한다.
"""
import sys
import json
import ssl
import urllib.request
try:
import pyodbc
except ImportError:
pyodbc = None
DRIVER = 'SQL Server Native Client 11.0' # 또는 'ODBC Driver 17/18 for SQL Server'
SERVER = r'192.168.0.69\PM2014'
UID, PWD = 'sa', 'CHANGEME' # ← 환경에 맞게
_CTX = ssl.create_default_context()
_CTX.check_hostname = False
_CTX.verify_mode = ssl.CERT_NONE
_HDR = {'User-Agent': 'Mozilla/5.0 Chrome/120', 'Referer': 'https://health.kr/'}
JSON_API = 'https://health.kr/searchDrug/ajax/ajax_result_drug2.asp?drug_cd={dik}'
def q(sql, params=None, db='PM_DRUG'):
cs = (f"DRIVER={{{DRIVER}}};SERVER={SERVER};DATABASE={db};UID={UID};"
f"PWD={PWD};Encrypt=no;TrustServerCertificate=yes;"
f"Connection Timeout=15;")
c = pyodbc.connect(cs)
cur = c.cursor()
cur.execute(sql, params) if params else cur.execute(sql)
cols = [d[0] for d in cur.description]
rows = [dict(zip(cols, r)) for r in cur.fetchall()]
c.close()
return rows
def resolve_dik(drugcode):
"""DrugCode → 마스터바코드 → CD_BARCODE.DIK_CODE (정답 경로 A)."""
rows = q("""
SELECT TOP 1 b.DIK_CODE
FROM PM_DRUG..CD_GOODS g
JOIN PM_DRUG..CD_BARCODE b ON g.BARCODE = b.BARCODE
WHERE g.DrugCode = ? AND ISNULL(b.DIK_CODE,'') <> ''
""", (drugcode,))
return rows[0]['DIK_CODE'] if rows else None
def fetch_json(dik):
url = JSON_API.format(dik=urllib.parse.quote(dik))
req = urllib.request.Request(url, headers=_HDR)
with urllib.request.urlopen(req, timeout=12, context=_CTX) as r:
body = r.read().decode('utf-8', 'replace').strip()
if not body:
return None
data = json.loads(body)
return data[0] if isinstance(data, list) and data else None
if __name__ == '__main__':
import urllib.parse
drugcode = sys.argv[1] if len(sys.argv) > 1 else 'LB000000169' # 용각산(대)
dik = resolve_dik(drugcode)
print(f"DrugCode={drugcode} → DIK_CODE={dik}")
if not dik:
print("DIK 없음(의약품 아님/바코드 없음).")
sys.exit()
d = fetch_json(dik)
if not d:
print("약정원 미등록.")
sys.exit()
print(f" drug_name = {d.get('drug_name')} / {d.get('drug_enm')}")
print(f" company = {(d.get('upso_name') or '').split('|')[0]}")
print(f" cls/form = {d.get('cls_code')} / {d.get('drug_form')}")
print(f" drug_pic = {d.get('drug_pic')}")
print(f" pack_img = {d.get('pack_img')}")