@@ -22,4 +22,8 @@ export const billingApi = {
|
|||||||
resume() {
|
resume() {
|
||||||
return http.post('/billing/resume')
|
return http.post('/billing/resume')
|
||||||
},
|
},
|
||||||
|
// 구매 복원 (기기 변경·재설치)
|
||||||
|
restore() {
|
||||||
|
return http.post('/billing/restore')
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,25 @@ async function resumeSub() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function restoreSub() {
|
||||||
|
if (subBusy.value) return
|
||||||
|
subBusy.value = 'restore'; subMsg.value = ''; subErr.value = ''
|
||||||
|
try {
|
||||||
|
sub.value = await billingApi.restore()
|
||||||
|
await auth.refreshProfile()
|
||||||
|
subMsg.value = sub.value?.premium ? '구매가 복원되었습니다.' : '복원할 결제 내역이 없습니다.'
|
||||||
|
} catch (e) {
|
||||||
|
subErr.value = e.response?.data?.message || '복원에 실패했습니다.'
|
||||||
|
} finally {
|
||||||
|
subBusy.value = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 포인트 기프트콘 교환 — 업데이트 예정
|
||||||
|
function exchangeGiftcon() {
|
||||||
|
dialog.alert('포인트 기프트콘 교환은 업데이트 예정입니다. 조금만 기다려 주세요!')
|
||||||
|
}
|
||||||
|
|
||||||
// 플랜 구독/변경 — Android 만 결제, PC 는 업그레이드(앱 안내) 화면으로
|
// 플랜 구독/변경 — Android 만 결제, PC 는 업그레이드(앱 안내) 화면으로
|
||||||
async function choosePlan(product) {
|
async function choosePlan(product) {
|
||||||
if (!isNative) {
|
if (!isNative) {
|
||||||
@@ -265,6 +284,10 @@ async function withdraw() {
|
|||||||
<span class="point-more">내역 ›</span>
|
<span class="point-more">내역 ›</span>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button type="button" class="row row-point" @click="exchangeGiftcon">
|
||||||
|
<span class="k">기프트콘 교환</span>
|
||||||
|
<span class="v"><span class="soon">업데이트 예정</span></span>
|
||||||
|
</button>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- 정기결제 관리 -->
|
<!-- 정기결제 관리 -->
|
||||||
@@ -331,6 +354,12 @@ async function withdraw() {
|
|||||||
<p v-if="!isNative" class="sub-note">📱 구독 결제·변경은 모바일 앱에서 진행됩니다.</p>
|
<p v-if="!isNative" class="sub-note">📱 구독 결제·변경은 모바일 앱에서 진행됩니다.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="restore-row">
|
||||||
|
<button type="button" class="link-btn muted" :disabled="!!subBusy" @click="restoreSub">
|
||||||
|
{{ subBusy === 'restore' ? '복원 중…' : '구매 복원' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p v-if="subMsg" class="sub-ok">{{ subMsg }}</p>
|
<p v-if="subMsg" class="sub-ok">{{ subMsg }}</p>
|
||||||
<p v-if="subErr" class="sub-errmsg">{{ subErr }}</p>
|
<p v-if="subErr" class="sub-errmsg">{{ subErr }}</p>
|
||||||
</section>
|
</section>
|
||||||
@@ -431,6 +460,19 @@ async function withdraw() {
|
|||||||
color: hsla(160, 100%, 37%, 1);
|
color: hsla(160, 100%, 37%, 1);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
.soon {
|
||||||
|
font-size: 0.74rem;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 0.1rem 0.45rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: var(--color-background-mute);
|
||||||
|
color: var(--color-text);
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
.restore-row {
|
||||||
|
padding: 0.4rem 1.1rem 0.2rem;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
.row-point {
|
.row-point {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user