다른 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>
84 lines
2.9 KiB
Python
84 lines
2.9 KiB
Python
#!/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')}")
|