feat: 개인정보 수집·이용 동의 프로세스 추가
- QR 라벨에 개인정보 동의 안내 문구 추가 (18pt 작은 글씨) - 웹앱에 핀테크 스타일 개인정보 동의 체크박스 추가 - 백엔드 API에서 개인정보 동의 검증 추가 - 개인정보보호법 준수 강화 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
d2ad64ebd8
commit
1717f4c6c2
@ -276,6 +276,7 @@ def api_claim():
|
||||
nonce = data.get('nonce')
|
||||
phone = data.get('phone', '').strip()
|
||||
name = data.get('name', '').strip()
|
||||
privacy_consent = data.get('privacy_consent', False)
|
||||
|
||||
# 입력 검증
|
||||
if not phone or not name:
|
||||
@ -284,6 +285,13 @@ def api_claim():
|
||||
'message': '전화번호와 이름을 모두 입력해주세요.'
|
||||
}), 400
|
||||
|
||||
# 개인정보 동의 검증
|
||||
if not privacy_consent:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'message': '개인정보 수집·이용에 동의해주세요.'
|
||||
}), 400
|
||||
|
||||
# 전화번호 형식 정리 (하이픈 제거)
|
||||
phone = phone.replace('-', '').replace(' ', '')
|
||||
|
||||
|
||||
@ -166,6 +166,72 @@
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.privacy-consent {
|
||||
margin: 24px 0 8px 0;
|
||||
}
|
||||
|
||||
.checkbox-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.checkbox-container input[type="checkbox"] {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.checkmark {
|
||||
position: relative;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background-color: #f8f9fa;
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 6px;
|
||||
transition: all 0.2s ease;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.checkbox-container:hover .checkmark {
|
||||
border-color: #6366f1;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.checkbox-container input:checked ~ .checkmark {
|
||||
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
||||
border-color: #6366f1;
|
||||
}
|
||||
|
||||
.checkmark::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: none;
|
||||
left: 7px;
|
||||
top: 3px;
|
||||
width: 6px;
|
||||
height: 11px;
|
||||
border: solid white;
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.checkbox-container input:checked ~ .checkmark::after {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.consent-text {
|
||||
margin-left: 12px;
|
||||
color: #495057;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
letter-spacing: -0.2px;
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
width: 100%;
|
||||
padding: 18px;
|
||||
@ -382,6 +448,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="privacy-consent">
|
||||
<label class="checkbox-container">
|
||||
<input type="checkbox" id="privacyConsent" required>
|
||||
<span class="checkmark"></span>
|
||||
<span class="consent-text">개인정보 수집·이용 동의</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn-submit" id="btnSubmit">
|
||||
포인트 적립하기
|
||||
</button>
|
||||
@ -442,12 +516,18 @@
|
||||
|
||||
const phone = document.getElementById('phone').value.trim();
|
||||
const name = document.getElementById('name').value.trim();
|
||||
const privacyConsent = document.getElementById('privacyConsent').checked;
|
||||
|
||||
if (!phone || !name) {
|
||||
showAlert('전화번호와 이름을 모두 입력해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!privacyConsent) {
|
||||
showAlert('개인정보 수집·이용에 동의해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
btnSubmit.disabled = true;
|
||||
btnSubmit.textContent = '처리 중...';
|
||||
alertMsg.style.display = 'none';
|
||||
@ -462,7 +542,8 @@
|
||||
transaction_id: tokenInfo.transaction_id,
|
||||
nonce: tokenInfo.nonce,
|
||||
phone: phone,
|
||||
name: name
|
||||
name: name,
|
||||
privacy_consent: true
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@ -92,6 +92,7 @@ def create_qr_receipt_label(qr_url, transaction_id, total_amount, claimable_poin
|
||||
font_amount = ImageFont.truetype(font_path, 40) # 금액 (크게)
|
||||
font_points = ImageFont.truetype(font_path, 36) # 포인트 (강조)
|
||||
font_small = ImageFont.truetype(font_path, 28) # 안내 문구
|
||||
font_tiny = ImageFont.truetype(font_path, 18) # 개인정보 동의 (작게)
|
||||
else:
|
||||
raise IOError("폰트 없음")
|
||||
except (IOError, OSError):
|
||||
@ -101,6 +102,7 @@ def create_qr_receipt_label(qr_url, transaction_id, total_amount, claimable_poin
|
||||
font_amount = ImageFont.load_default()
|
||||
font_points = ImageFont.load_default()
|
||||
font_small = ImageFont.load_default()
|
||||
font_tiny = ImageFont.load_default()
|
||||
|
||||
# 3. QR 코드 생성 (우측 상단) - 크기 및 해상도 개선
|
||||
qr = qrcode.QRCode(
|
||||
@ -162,6 +164,11 @@ def create_qr_receipt_label(qr_url, transaction_id, total_amount, claimable_poin
|
||||
# 안내 문구
|
||||
guide_text = "QR 촬영하고 포인트 받으세요!"
|
||||
draw.text((x_margin, y), guide_text, font=font_small, fill=0)
|
||||
y += 35
|
||||
|
||||
# 개인정보 동의 안내 (작은 글씨)
|
||||
privacy_text = "(QR 스캔 시 개인정보 수집·이용에 동의한 것으로 간주됩니다)"
|
||||
draw.text((x_margin, y), privacy_text, font=font_tiny, fill=0)
|
||||
|
||||
# 5. 테두리 (가위선 스타일)
|
||||
for i in range(2):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user