zoho-api
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseZoho API Integration
Zoho API集成
Quick Reference
快速参考
| API | Base URL |
|---|---|
| Zoho Inventory | |
| Zoho Books | |
Organization ID:
748369814| API | 基础URL |
|---|---|
| Zoho Inventory | |
| Zoho Books | |
组织ID:
748369814Code Files
代码文件
| File | Purpose |
|---|---|
| OAuth client, token caching, |
| Products, stock extraction |
| Price list constants and fetching |
| Customer lookup by email |
| Sales orders |
| Invoices |
| Payments |
| Credit notes |
| 文件 | 用途 |
|---|---|
| OAuth客户端、令牌缓存、 |
| 产品、库存提取 |
| 价格列表常量与获取 |
| 通过邮箱查找客户 |
| 销售订单 |
| 发票 |
| 付款 |
| 贷项通知单 |
Using zohoFetch
使用zohoFetch
typescript
import { zohoFetch } from '@/lib/zoho/client';
// GET request
const data = await zohoFetch('/inventory/v1/items', {
params: {
organization_id: process.env.ZOHO_ORGANIZATION_ID,
page: 1,
per_page: 100,
},
});
// Single item with locations
const item = await zohoFetch(`/inventory/v1/items/${itemId}`, {
params: { organization_id: process.env.ZOHO_ORGANIZATION_ID },
});typescript
import { zohoFetch } from '@/lib/zoho/client';
// GET请求
const data = await zohoFetch('/inventory/v1/items', {
params: {
organization_id: process.env.ZOHO_ORGANIZATION_ID,
page: 1,
per_page: 100,
},
});
// 包含库存位置的单个商品
const item = await zohoFetch(`/inventory/v1/items/${itemId}`, {
params: { organization_id: process.env.ZOHO_ORGANIZATION_ID },
});Token Caching (CRITICAL)
令牌缓存(至关重要)
Memory Cache → Upstash Redis → Zoho OAuth Refresh
(50-min TTL) (rate limit: 10s guard)If all prices show "Contact for price", check:
- Upstash env vars in Vercel
- and
UPSTASH_REDIS_REST_URLUPSTASH_REDIS_REST_TOKEN - Run:
curl https://www.tsh.sale/api/debug/token
内存缓存 → Upstash Redis → Zoho OAuth刷新
(50分钟TTL) (速率限制:10秒防护)如果所有商品都显示“联系我们获取价格”,请检查:
- Vercel中的Upstash环境变量
- 和
UPSTASH_REDIS_REST_URLUPSTASH_REDIS_REST_TOKEN - 运行:
curl https://www.tsh.sale/api/debug/token
Common Endpoints
常用端点
Inventory API
Inventory API
GET /items # List products
GET /items/{id} # Single product (includes locations)
GET /categories # List categories
GET /pricebooks/{id} # Pricebook with itemsGET /items # 列出产品
GET /items/{id} # 单个产品(包含库存位置)
GET /categories # 列出分类
GET /pricebooks/{id} # 包含商品的价格手册Books API
Books API
GET /contacts # List customers
GET /salesorders # Sales orders
GET /invoices # Invoices
GET /customerpayments # Payments
GET /creditnotes # Credit notesGET /contacts # 列出客户
GET /salesorders # 销售订单
GET /invoices # 发票
GET /customerpayments # 客户付款
GET /creditnotes # 贷项通知单Caching with unstable_cache
使用unstable_cache进行缓存
typescript
import { unstable_cache } from 'next/cache';
const getCachedProducts = unstable_cache(
async () => await fetchProducts(),
['products'],
{ revalidate: 3600, tags: ['products'] }
);Revalidate cache:
bash
curl "https://www.tsh.sale/api/revalidate?tag=products&secret=tsh-revalidate-2024"typescript
import { unstable_cache } from 'next/cache';
const getCachedProducts = unstable_cache(
async () => await fetchProducts(),
['products'],
{ revalidate: 3600, tags: ['products'] }
);刷新缓存:
bash
curl "https://www.tsh.sale/api/revalidate?tag=products&secret=tsh-revalidate-2024"Error Handling Pattern
错误处理模式
typescript
try {
const data = await zohoFetch('/inventory/v1/items', { ... });
} catch (error) {
if (error.message.includes('401')) {
// Token expired - auto-refreshes
} else if (error.message.includes('429')) {
// Rate limited - wait and retry
}
}typescript
try {
const data = await zohoFetch('/inventory/v1/items', { ... });
} catch (error) {
if (error.message.includes('401')) {
// 令牌过期 - 自动刷新
} else if (error.message.includes('429')) {
// 速率受限 - 等待并重试
}
}Creating New API Route
创建新API路由
typescript
// src/app/api/zoho/[resource]/route.ts
import { NextResponse } from 'next/server';
import { zohoFetch } from '@/lib/zoho/client';
export async function GET(request: Request) {
const data = await zohoFetch('/inventory/v1/items', {
params: {
organization_id: process.env.ZOHO_ORGANIZATION_ID,
},
});
return NextResponse.json(data);
}typescript
// src/app/api/zoho/[resource]/route.ts
import { NextResponse } from 'next/server';
import { zohoFetch } from '@/lib/zoho/client';
export async function GET(request: Request) {
const data = await zohoFetch('/inventory/v1/items', {
params: {
organization_id: process.env.ZOHO_ORGANIZATION_ID,
},
});
return NextResponse.json(data);
}Rate Limits
速率限制
| API | Limit |
|---|---|
| OAuth Refresh | ~100/minute |
| Inventory API | 100/minute |
| Books API | 100/minute |
| API | 限制 |
|---|---|
| OAuth刷新 | ~100次/分钟 |
| Inventory API | 100次/分钟 |
| Books API | 100次/分钟 |
Debug Commands
调试命令
bash
undefinedbash
undefined