# Customer Portal (/guides/portal)





Customer Portal [#customer-portal]

Customer Portal 是一個託管的自助服務頁面，讓您的客戶可以管理他們的訂閱，而無需您開發額外的 UI。

功能概覽 [#功能概覽]

Customer Portal 提供以下功能：

* **查看訂閱** - 顯示當前訂閱方案、價格、下次扣款日期
* **更新付款方式** - 安全地更新或新增信用卡
* **取消訂閱** - 客戶可自行取消訂閱
* **查看帳單歷史** - 瀏覽過去的付款記錄

<Callout type="info">
  Portal 的外觀會自動套用您在後台設定的品牌樣式，包括 Logo 和主題顏色。
</Callout>

運作流程 [#運作流程]

```
1. 客戶在您的網站點擊「管理訂閱」
   ↓
2. 您的後端呼叫 POST /portal/sessions
   ↓
3. Recur 返回 Portal Session URL
   ↓
4. 前端導向該 URL
   ↓
5. 客戶在 Portal 管理訂閱
   ↓
6. 完成後重新導向回 returnUrl
```

整合方式 [#整合方式]

<Cards>
  <Card title="後端整合（Server SDK）" description="使用 Recur Server SDK 在後端建立 Portal Session" href="/guides/portal/server-integration" />

  <Card title="前端整合（Web Component）" description="使用 <recur-portal> 按鈕快速整合" href="/guides/portal/client-integration" />
</Cards>

快速開始 [#快速開始]

1\. 安裝 SDK [#1-安裝-sdk]

```bash
npm install recur-tw
```

2\. 後端建立 Portal Session [#2-後端建立-portal-session]

```typescript
// app/api/portal/create/route.ts
import { Recur } from 'recur-tw/server';
import { NextRequest, NextResponse } from 'next/server';
import { getSession } from '@/lib/auth'; // 您的認證函數

const recur = new Recur(process.env.RECUR_SECRET_KEY!);

export async function POST(request: NextRequest) {
  // 驗證用戶身份
  const session = await getSession();
  if (!session) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  // 取得用戶對應的 Recur Customer ID
  const customerId = session.user.recurCustomerId;

  // 建立 Portal Session
  const portalSession = await recur.portal.sessions.create({
    customer: customerId,
    returnUrl: `${process.env.NEXT_PUBLIC_URL}/account`,
  });

  return NextResponse.json({ url: portalSession.url });
}
```

3\. 前端按鈕 [#3-前端按鈕]

```tsx
// components/ManageSubscriptionButton.tsx
'use client';

export function ManageSubscriptionButton() {
  const handleClick = async () => {
    const response = await fetch('/api/portal/create', {
      method: 'POST',
    });

    const { url } = await response.json();
    window.location.href = url;
  };

  return (
    <button onClick={handleClick}>
      管理訂閱
    </button>
  );
}
```

或使用 Web Component：

```html
<recur-portal api-endpoint="/api/portal/create">
  管理訂閱
</recur-portal>
```

安全性 [#安全性]

<Callout type="warning">
  **重要**：Portal Session 必須在後端建立。

  * Portal API 需要 Secret Key 認證
  * 建立 Session 前務必驗證用戶身份
  * 確保用戶只能存取自己的 Customer Portal
</Callout>

下一步 [#下一步]

<Cards>
  <Card title="Portal Sessions API" description="完整的 API 參考文件" href="/api/portal" />

  <Card title="Webhook 整合" description="接收訂閱變更通知" href="/guides/webhooks" />
</Cards>
