구현 · WooCommerce
WooCommerce try-on 플러그인 만들기
한 줄 요약
WooCommerce 플러그인이 WP-Cron 이벤트에서 일반 HTTP로 Photta API를 호출하고, 다음 틱에서 작업을 폴링한 후, 완성된 이미지를 미디어 라이브러리로 가져옵니다.
- 크레딧: 2K에서 5 크레딧 · 4K에서 6 크레딧
- 일반적인 소요 시간: 1.5–4 min
- 처리 방식: 비동기, 폴링
이 페이지의 모든 수치는 다음 출처를 기반으로 합니다: Photta API 문서 · 확인 완료
PHP SDK는 필요하지 않습니다. WP-Cron이 작업을 제출하고, 다음 틱에서 폴링하며, WP-CLI가 완성된 이미지를 미디어 라이브러리로 가져옵니다.
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/tryon/apparel \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
}')
ID=$(echo "$RESPONSE" | jq -r '.data.id')const res = await fetch("https://api.photta.app/api/v1/tryon/apparel", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
}),
});
const { data } = await res.json(); // data.id, data.statusimport os, requests
res = requests.post(
"https://api.photta.app/api/v1/tryon/apparel",
headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
json={
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": True,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
},
)
data = res.json()["data"] # data["id"], data["status"]동작 원리
cron 틱, 폴링, 그리고 미디어 가져오기
플러그인 기획, 작업 예약, 제출, 다음 틱에서 폴링, 가져오기 순으로 진행됩니다.
단계 1
플러그인 기획하기
대기열 테이블 하나, cron 훅 하나, 키를 입력할 설정 화면 하나면 충분합니다. 페이지 요청 중에는 생성이 절대 일어나지 않으므로 구매자의 작업이 지연될 염려가 없습니다.
단계 2
Photta API 키 발급받기
옵션 테이블에 저장하지 말고 wp-config.php의 환경 변수에서 읽어오도록 하세요. 그래야 데이터베이스를 내보낼 때 인증 자격 증명이 노출되지 않습니다.
단계 3
cron 이벤트 예약하기
반복 훅을 등록하고 실행당 대기 중인 제품을 적당량만 가져오세요. 실제 트래픽이 있는 사이트는 틱이 자주 발생하지만, 트래픽이 적은 사이트는 실제 시스템 cron이 필요합니다.
단계 4
제품 제출하기
cURL 샘플과 동일한 URL, 헤더, JSON 본문으로 wp_remote_post를 통해 제품 이미지를 전송하세요. 반환된 id는 대기열 행에 저장합니다.
단계 5
다음 틱에서 폴링하기
아직 processing 상태인 모든 행의 상태를 확인합니다. 틱 간격이 몇 분 정도이므로 틱당 한 번의 폴링으로 대체로 충분하며, 요청 내부에서 대기 상태(sleep)가 발생하지 않습니다.
단계 6
이미지 가져오기
작업이 완료되면 URL을 미디어 라이브러리로 가져와 제품에 첨부합니다. 다운로드는 WP-CLI가 수행하므로 플러그인이 파일을 직접 버퍼링할 필요가 없습니다.
플러그인의 네 가지 핵심 구성 요소
Photta 호출은 API 문서에 나온 형태 그대로 렌더링됩니다. wp_remote_post도 동일한 URL, 헤더, 본문을 사용합니다.
# wp-config.php holds the key; the plugin reads it with getenv()
# define( 'PHOTTA_API_KEY', getenv( 'PHOTTA_API_KEY' ) );
export PHOTTA_API_KEY="photta_live_xxx"
export PHOTTA_BASE_URL="https://api.photta.app/api/v1"RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/tryon/apparel \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
}')
ID=$(echo "$RESPONSE" | jq -r '.data.id')# $ID is data.id from the POST response. Poll every 3 seconds until status is "completed" or "failed".
for i in $(seq 1 120); do
RESULT=$(curl -s "https://api.photta.app/api/v1/tryon/apparel/$ID" -H "Authorization: Bearer $PHOTTA_API_KEY")
STATUS=$(echo "$RESULT" | jq -r '.data.status')
[ "$STATUS" = "completed" ] && break
[ "$STATUS" = "failed" ] && echo "generation failed" && exit 1
sleep 3
done
echo "$RESULT" | jq -r '.data.output_url'# WP-CLI does the download, so the plugin never buffers the file itself
wp media import "$OUTPUT_URL" \
--post_id="$PRODUCT_ID" \
--title="Virtual try-on" \
--featured_image개발자가 자주 묻는 질문
WordPress 개발자가 자주 묻는 질문
공식 PHP SDK가 있나요?
아닙니다. API는 Bearer 헤더를 사용하는 HTTPS 기반의 일반적인 REST 형식이므로, 업데이트를 관리해야 할 의존성 없이 wp_remote_post만으로 모든 것을 처리할 수 있습니다.
PHP에서는 어떻게 호출하나요?
Authorization 및 Content-Type 헤더와 JSON 본문을 포함하여 wp_remote_post를 사용합니다. 이 페이지의 cURL 샘플과 필드 하나하나까지 정확히 같은 요청입니다.
왜 페이지 로드 시점에 생성하지 않나요?
생성 작업은 단일 페이지 요청보다 오래 걸립니다. 요청 도중에 렌더링을 진행하면 구매자가 대기하게 되고, 타임아웃으로 요청이 중단되더라도 credits는 그대로 차감됩니다.
한 번 실행할 때 몇 개의 제품을 처리해야 하나요?
틱당 적은 양을 처리하여 여러 틱에 걸쳐 대기열이 비워지도록 하세요. 이렇게 하면 각 실행 시간을 짧게 유지할 수 있고 공식 rate limit도 안전하게 준수할 수 있습니다.
실패한 작업은 어떻게 처리되나요?
해당 행을 failed로 표시하고 응답에서 오류 유형을 보관하세요. 실패한 생성에 사용된 credits는 자동으로 환불되므로 재시도해도 비용이 이중으로 청구되지 않습니다.