콘텐츠로 이동
요금문서EN

intent와 권한

intent는 서비스가 지갑에 “이것을 실행해 달라”고 내미는 JSON입니다. 지금 실행할 호출, 그 호출이 쓰는 금액, 그리고 그 호출이 속한 권한(mandate) 을 담습니다. 사용자는 권한을 한 번 승인합니다. 같은 권한 안의 다음 intent와 서비스 청구는 묻지 않고 실행됩니다. AP2의 intent와 mandate 구조를 따릅니다.

action 권한 예
purchase 1회. 상품과 가격을 eq 조건으로 고정. 나중 청구 없음 영화표 한 장
mandate 여러 번. 1회 한도, 전체 한도, 횟수, 기간, 주기 한도 구독, 예매 예약, 검색 이용료, 예금 운용
mandate.update 같은 권한의 한도, 횟수, 기간만 늘림. 범위는 그대로 구독 연장
{
"type": "agentpay.intent",
"version": 1,
"id": "int_8cVd0Hq3pTzR1b2N",
"service": "acme-news",
"action": "mandate",
"summary": "월 구독 월 9,900원, 최대 12개월",
"spend_okrw": 9900,
"prefund_okrw": 9900,
"expires_at": 1792051200,
"calls": [
{ "target": "0x…token", "value": "0", "data": "0x095ea7b3…" },
{ "target": "0x…merchant", "value": "0", "data": "0x…" }
],
"mandate": {
"key": "acme-news:plan",
"label": "Acme 뉴스 월 구독",
"total_okrw": 118800,
"per_okrw": 9900,
"approve_cap_okrw": 9900,
"calls": 12,
"days": 360,
"merchant_charges": true,
"period": { "seconds": 2592000, "max_runs": 1 },
"permissions": [{
"target": "0x…merchant",
"signature": "pay(bytes32,uint256,uint256)",
"predicates": [{ "arg": 1, "op": "eq", "uint": "2" }, { "arg": 2, "op": "lte", "okrw": 9900 }]
}]
}
}
필드 형식 규칙
type, version "agentpay.intent", 1 고정
id int_ + 8 ~ 64자 키트가 만듦
service 서비스 id intent를 가져온 origin의 서비스와 같아야 함
summary 문자열 160자 이하. 승인 화면과 내역에 표시
spend_okrw 정수 지금 호출이 쓰는 금액. per_okrw 이하
prefund_okrw 정수, 선택 지갑이 이 권한을 위해 갖고 있어야 할 잔액 (충전 안내)
expires_at unix 초 지금부터 1시간 이내. 키트 기본은 15분
calls 0 ~ 8개 { target, value: "0", data }. 모두 권한 안에 들어가야 함

금액(*_okrw)은 결제 토큰의 정수 단위입니다. 지갑이 10 ** decimals를 곱해 토큰 최소 단위로 변환합니다.

필드 기본 규칙
key <서비스 id>:로 시작. 같은 key의 살아 있는 권한은 재사용
label 80자 이하. 승인 화면 제목
total_okrw, per_okrw 전체 한도와 1회 한도. per_okrw ≤ total_okrw
approve_cap_okrw 결제 토큰 approve 1회 최대. total_okrw 이하
calls 100 실행 횟수 1 ~ 1000
days 30 유효 기간 1 ~ 365일
valid_after 승인 시각 시작 시각 (예매 예약). 최대 300일 뒤
merchant_charges false 서비스가 나중에 청구할 수 있음. 레지스트리에서 허용된 서비스만
period 없음 { seconds, max_runs?, max_spend_okrw? }. validAfter부터 고정 길이 창
permissions 1 ~ 16개. 등록된 자기 컨트랙트의 함수만

permissions[].predicates는 함수 인자 하나(32바이트 단어)에 거는 조건입니다. permissions 항목 하나에 최대 4개를 지정합니다.

필드 뜻
arg 0부터 세는 인자 위치
op eq(같음) 또는 lte(이하)
값 하나 okrw(토큰 단위, 10 ** decimals를 곱해 변환), uint, bytes32, address

purchase는 최소 하나의 eq 조건으로 상품을 고정해야 합니다.

{ "action": "mandate.update", "spend_okrw": 0, "calls": [],
"mandate": { "key": "acme-news:plan" },
"update": { "add_total_okrw": 29700, "add_calls": 3, "add_days": 90 } }

변경할 때는 호출을 실행하지 않습니다. add_total_okrw, add_calls, add_days는 각 한도를 늘리고, 선택 항목 per_okrw는 1회 한도를 올립니다. 대상 컨트랙트, 함수, 인자 조건과 주기 한도는 바뀌지 않으며 현재 주기의 사용량도 초기화되지 않습니다. 다른 범위나 주기에는 새 권한이 필요합니다. 이용자는 change_mandate로 변경 내용을 확인하고 승인합니다.

사용자가 없는 결제입니다. 서비스가 게이트웨이에 POST /merchant/charges로 보냅니다.

{ "mandate_id": "mnd_…", "charge_id": "sub_123-w1", "summary": "월 구독 2회차",
"spend_okrw": 9900, "calls": [ … ] }
Authorization: AgentPay-Mandate-HMAC id=mcr_…,ts=1792051200,sig=…

서명은 METHOD\npath\nts\nsha256(body)에 대한 HMAC-SHA256입니다. 요청 시각과 검증 시각의 차이는 앞뒤로 최대 300초(5분)까지 허용합니다. 키트의 kit.merchant.charge가 처리합니다.

코드 뜻
INTENT_SERVICE_MISMATCH intent의 service가 가져온 origin의 서비스와 다름
CONTRACT_NOT_REGISTERED 권한 대상이 그 서비스에 등록된 컨트랙트가 아님
INTENT_CALL_OUTSIDE_MANDATE 지금 실행할 호출이 권한 범위 밖
MERCHANT_CHARGES_NOT_ALLOWED 나중 청구가 허용되지 않은 서비스
INTENT_EXPIRED 만료됐거나 1시간보다 길게 잡음
OUTSIDE_MANDATE, OVER_LIMIT, PERIOD_LIMIT 청구가 범위, 한도, 주기 한도를 넘음
MANDATE_REVOKED, MANDATE_RELEASED, MANDATE_EXPIRED 권한이 꺼졌거나 끝남
CHARGE_ID_REUSED 같은 charge_id를 다른 내용으로 다시 보냄