도매상 API 통합 가이드
작성일: 2026-03-06
버전: 1.0
📦 패키지 구조
pharmacy-wholesale-api/ # 별도 리포지토리
├── wholesale/
│ ├── __init__.py # SooinSession, GeoYoungSession 노출
│ ├── base.py # WholesaleSession 공통 인터페이스
│ ├── sooin.py # 수인약품 API
│ └── geoyoung.py # 지오영 API
└── docs/
└── SOOIN.md # 수인약품 상세 문서
pharmacy-pos-qr-system/backend/ # 기존 프로젝트
├── wholesale_path.py # 패키지 경로 설정
├── sooin_api.py # Flask Blueprint (wholesale 사용)
└── geoyoung_api.py # Flask Blueprint (wholesale 사용)
🔌 도매상별 API 특성
| 항목 |
지오영 |
수인약품 |
| 웹사이트 |
gwn.geoweb.kr |
sooinpharm.co.kr |
| 인증 방식 |
Playwright → requests |
Playwright → requests |
| 세션 유효시간 |
30분 |
30분 |
| 검색 코드 |
보험코드 (KD) |
KD코드 + 내부코드 (pc) |
| 장바구니 추가 |
productCode 필요 |
internal_code (pc) 필요 |
| 개별 삭제 |
❌ 없음 |
✅ 체크박스 soft delete |
| 장바구니 조회 |
PartialProductCart |
Bag.asp |
🔑 핵심 발견: 코드 체계
지오영
보험코드 (KD코드) → 검색 → productCode (내부) → 장바구니 추가
수인약품
KD코드 → 검색 → internal_code (pc) → 장바구니 추가
↓
PhysicInfo.asp?pc=32495 에서 추출
⚠️ 중요: internal_code가 없으면 장바구니 추가 불가!
🛒 수인약품 개별 취소 (Soft Delete)
발견 과정
kind=delOne API 존재하지만 작동 안 함
- 체크박스가 실제 "취소" 역할
ControlBag.asp AJAX 엔드포인트 발견
API 사용법
from wholesale import SooinSession
session = SooinSession()
session.login()
# 장바구니 조회 (체크 상태 포함)
cart = session.get_cart()
# cart['items'][0]['checked'] = False (활성)
# cart['items'][0]['active'] = True
# 항목 취소 (체크)
session.cancel_item(row_index=0)
# 또는
session.cancel_item(product_code="32495")
# 취소 복원 (체크 해제)
session.restore_item(row_index=0)
내부 동작
POST /Service/Order/ControlBag.asp
Content-Type: application/x-www-form-urlencoded; charset=euc-kr
X-Requested-With: XMLHttpRequest
vc=50911 (거래처코드)
pc=32495 (내부 제품코드)
f=true (true=취소, false=복원)
pg= (제품구분, 빈값)
pdno= (제품번호, 빈값)
tmdt= (기한, 빈값)
📊 SQLite 스키마 연동
order_context (AI 학습용)
-- 새로 추가된 필드 (2026-03-06)
wholesaler_id TEXT, -- 'geoyoung' 또는 'sooin'
wholesaler_price INTEGER, -- 도매상 가격
internal_code TEXT, -- 도매상 내부 코드
was_cancelled BOOLEAN, -- 취소 여부 (수인 soft delete)
도매상별 주문 시 기록할 데이터
order_context = {
'drug_code': 'D12345',
'product_name': '아세탑정',
'wholesaler_id': 'sooin',
'internal_code': '32495', # 수인 내부코드
'ordered_spec': '30T',
'ordered_qty': 2,
'wholesaler_price': 4800,
'available_specs': '["30T", "500T"]',
'spec_stocks': '{"30T": 0, "500T": 0}', # 재고 상황
'selection_reason': 'only_option',
'was_cancelled': False
}
🔄 Flask API 엔드포인트
수인약품 (/api/sooin/*)
| 메서드 |
경로 |
설명 |
| GET |
/stock |
재고 검색 |
| GET |
/cart |
장바구니 조회 |
| POST |
/order |
장바구니 추가 |
| POST |
/cart/clear |
장바구니 비우기 |
| POST |
/cart/cancel |
항목 취소 (soft delete) |
| POST |
/cart/restore |
항목 복원 |
| POST |
/confirm |
주문 전송 |
지오영 (/api/geoyoung/*)
| 메서드 |
경로 |
설명 |
| GET |
/stock |
재고 검색 |
| GET |
/cart |
장바구니 조회 |
| POST |
/order |
장바구니 추가 |
| POST |
/cart/clear |
장바구니 비우기 |
| POST |
/cart/cancel |
항목 삭제 (hard delete) |
| POST |
/cart/restore |
❌ NOT_SUPPORTED |
| POST |
/confirm |
주문 전송 |
개별 삭제 API 차이
| 도매상 |
cancel 동작 |
restore 가능 |
내부 API |
| 수인 |
체크박스 soft delete |
✅ 가능 |
ControlBag.asp |
| 지오영 |
완전 삭제 |
❌ 불가 |
DataCart/del |
📁 관련 문서
| 문서 |
위치 |
내용 |
| AI ERP 자동주문 기획 |
docs/AI_ERP_AUTO_ORDER_SYSTEM.md |
전체 시스템 설계 |
| 지오영 API 분석 |
docs/GEOYOUNG_API_REVERSE_ENGINEERING.md |
지오영 리버스 엔지니어링 |
| 수인 API 분석 |
pharmacy-wholesale-api/docs/SOOIN.md |
수인 리버스 엔지니어링 |
| 사용량 조회 가이드 |
docs/RX_USAGE_GEOYOUNG_GUIDE.md |
처방 사용량 조회 |
✅ 체크리스트
완료
진행 예정
업데이트: 2026-03-06 by 용림 🐉