Registrar un Service DID
Esta página explica, paso a paso, cómo dar de alta un Service DID bajo tu DID organizativo. Si todavía no sabes qué es un Service DID, empieza por la introducción.
Resumen del proceso
Las claves privadas solo se usan en tu equipo, dentro del CLI. La API nunca las ve.
Requisitos previos
Antes de empezar necesitas:
- Un DID organizativo registrado en el entorno donde vas a dar de alta el servicio. Será el DID paraguas. Si aún no lo tienes, sigue el onboarding del DID.
- El keystore del DID paraguas (por ejemplo,
identity.keystore.json) y su contraseña. Es el fichero que generaste condid-gen keysal crear tu DID. - El CLI
isbe-identity-did-gen, versión 3.0.0 o superior. ⬇ Descargar el CLI (ZIP). - Node.js 20 o superior y npm 10 o superior, para ejecutar el CLI.
- La URL de la Service DID Registry API del entorno. La tienes en Entornos.
En los ejemplos se usa pre-producción (uc-pre). Para producción, usa uc y la URL de producción.
Paso 1 — Instalar el CLI
Descomprime el ZIP que descargaste en los requisitos previos. Se crea una carpeta isbe-identity-did-gen-3.0.0. Entra en ella e instala el CLI:
cd isbe-identity-did-gen-3.0.0
npm ci
npm run build
npm link
npm link deja disponible el comando did-gen en cualquier carpeta. Comprueba que funciona:
did-gen --version
npm link falla con EACCES: permission deniedEs un problema de permisos de la carpeta global de npm, habitual en macOS. El README del CLI explica cómo solucionarlo. También puedes saltarte npm link y ejecutar el CLI desde su carpeta con node dist/index.js en lugar de did-gen.
Paso 2 — Obtener los datos del DID paraguas
Necesitas dos datos de tu DID paraguas: el DID y su EOA (la dirección de la cuenta que firma tus transacciones). Los obtienes a partir de su keystore:
did-gen did --keystore ./identity.keystore.json --modelDeploy uc-pre
Te pide la contraseña del keystore y muestra:
DID:
did:isbe:uc-pre:z1MsSK9H41YvdCrJPmPycEqijYbk
Public Key:
0x04…
Proof:
0x…
EOA: 0xB8172459924a1e81E511D6473f923E531f7B3a5B
Apunta el DID y la EOA.
El --modelDeploy tiene que ser el del entorno donde registraste tu DID: uc-pre en pre-producción. En producción no pongas --modelDeploy (por defecto es uc). Con un entorno equivocado obtendrás un DID distinto, que no es el tuyo.
Paso 3 — Generar la clave del servicio
Genera un par de claves nuevo para el servicio, en un keystore distinto del de tu DID paraguas:
mkdir -p keys
did-gen keys --out ./keys/facturacion.keystore.json
Elige una contraseña para este keystore. El comando muestra, entre otros datos:
Public Key (hex):
0x04ad5f…(130 caracteres en total)
Apunta la Public Key (hex): es la clave que vas a registrar para el servicio.
La clave del servicio tiene que ser distinta de la de tu DID organizativo. Si usas la del paraguas, el alta se rechaza. Puedes reutilizar la clave de otro servicio de tu mismo paraguas, pero nunca la de un DID organizativo ni la de un servicio de otra organización.
Guarda bien facturacion.keystore.json y su contraseña. Es la clave con la que el servicio firmará lo suyo. Para registrar el servicio no la vas a necesitar: el alta la firma el DID paraguas.
Paso 4 — Pedir la transacción de alta
Abre el Swagger de la Service DID Registry API del entorno (ver Entornos) y busca la operación:
POST /api/v1/contract/registerServiceDid
Cuerpo mínimo
{
"controllerDid": "did:isbe:uc-pre:z1MsSK9H41YvdCrJPmPycEqijYbk",
"publicKey": "0x04<clave pública del servicio>",
"publicKeyType": "secp256k1",
"label": "facturacion",
"expiresAt": 0,
"from": "0xB8172459924a1e81E511D6473f923E531f7B3a5B"
}
| Campo | Qué poner |
|---|---|
controllerDid | El DID paraguas del paso 2. |
publicKey | La clave pública del servicio del paso 3. Empieza por 0x04. |
publicKeyType | secp256k1. |
label | Un nombre corto para que tú identifiques el servicio, por ejemplo facturacion. En la cadena se guarda solo su huella (hash), no el texto. |
expiresAt | Fecha de caducidad en segundos Unix. 0 significa que no caduca. |
from | La EOA del DID paraguas del paso 2. |
Cuerpo completo, con campos libres
Cualquier campo que añadas además de los anteriores se guarda en la cadena y aparece en el DID Document del servicio (ver Campos libres). Por ejemplo:
{
"controllerDid": "did:isbe:uc-pre:z1MsSK9H41YvdCrJPmPycEqijYbk",
"publicKey": "0x04<clave pública del servicio>",
"publicKeyType": "secp256k1",
"label": "facturacion-electronica",
"expiresAt": 0,
"from": "0xB8172459924a1e81E511D6473f923E531f7B3a5B",
"name": "Servicio de Facturación Electrónica",
"description": "Emisión y recepción de facturas electrónicas (Facturae y UBL) para clientes empresariales.",
"serviceType": "InvoicingService",
"version": "2.1.0",
"tags": ["facturacion", "facturae", "ubl", "b2b"],
"alsoKnownAs": ["https://facturacion.ejemplo.es"],
"organization": {
"legalName": "Ejemplo Soluciones S.A.",
"taxId": "A12345678",
"country": "ES",
"website": "https://www.ejemplo.es"
},
"contact": {
"email": "soporte.facturacion@ejemplo.es"
},
"service": [
{
"id": "#api",
"type": "InvoicingAPI",
"serviceEndpoint": "https://api.facturacion.ejemplo.es/v2"
},
{
"id": "#openapi",
"type": "OpenAPISpecification",
"serviceEndpoint": "https://api.facturacion.ejemplo.es/v2/openapi.json"
},
{
"id": "#vc-issuer",
"type": "CredentialIssuer",
"serviceEndpoint": "https://facturacion.ejemplo.es/.well-known/openid-credential-issuer"
}
],
"termsOfService": "https://www.ejemplo.es/legal/condiciones-facturacion"
}
Los id de service (#api, #openapi…) son relativos al propio Service DID: #api equivale a did:isbe:svc:…:3#api.
Respuesta
La API devuelve la transacción sin firmar:
{
"to": "0x00000000000000000000000000000000000015Be",
"data": "0x2cc72092…",
"gasLimit": "0x65bc8",
"gasPrice": "0xfa0",
"chainId": "0x…",
"nonce": "0x1",
"value": "0x0",
"from": "0xB8172459924a1e81E511D6473f923E531f7B3a5B"
}
Copia la respuesta entera y guárdala en un fichero unsigned-tx.json, en la carpeta desde la que vas a ejecutar el CLI.
Paso 5 — Firmar la transacción
La transacción la firma el DID paraguas, con su keystore:
did-gen sign-tx --keystore ./identity.keystore.json --tx-file unsigned-tx.json > signed.hex
Te pide la contraseña del keystore del paraguas. Antes de firmar, el CLI comprueba que la transacción es de tu cuenta: si el from no coincide con tu keystore, no la firma.
La transacción firmada queda en signed.hex. Para copiarla sin errores, cópiala desde el fichero en vez de seleccionarla en el terminal:
cat signed.hex | pbcopy
pbcopy es de macOS. En Linux puedes usar xclip -selection clipboard < signed.hex, o abrir el fichero y copiar su contenido.
Si se pierde un solo carácter al copiarla, la API responde invalid BytesLike value y la transacción no se envía. Copiarla desde signed.hex lo evita.
Paso 6 — Enviar la transacción
En el Swagger, busca:
POST /api/v1/transactions/send
Y envía:
{
"signedRawTransaction": "0x01f9…"
}
La respuesta incluye el hash de la transacción (tx_hash) y su recibo (receipt):
- 200: la transacción se ha procesado. Si
receipt.statuses1, el Service DID está registrado. - 206: la transacción se ha enviado, pero el recibo aún no estaba listo. Espera unos segundos y compruébalo en el paso 7.
Paso 7 — Comprobar el Service DID
Encontrar el identificador
Lista los Service DIDs de tu paraguas:
GET /api/v1/service-dids?controller=<DID paraguas>
Si usas curl, codifica el DID en la URL (los : pasan a ser %3A):
curl -s "<API>/api/v1/service-dids?controller=did%3Aisbe%3Auc-pre%3Az1MsSK9H41YvdCrJPmPycEqijYbk"
El servicio nuevo es el que tiene el nonce más alto. Su identificador está en serviceDid:
{
"items": [
{
"serviceDid": "did:isbe:svc:uc-pre:z1MsSK9H41YvdCrJPmPycEqijYbk:3",
"controllerDid": "did:isbe:uc-pre:z1MsSK9H41YvdCrJPmPycEqijYbk",
"signingKeyAddress": "0x…",
"nonce": "3",
"deactivated": false,
…
}
],
"total": "3",
…
}
Resolver el DID Document
GET /api/v1/identifiers/did:isbe:svc:uc-pre:z1MsSK9H41YvdCrJPmPycEqijYbk:3
Comprueba que:
controlleres tu DID paraguas.verificationMethodcontiene la clave del servicio.- Aparecen tus campos libres, si los añadiste.
- No aparece
"deactivated": true.
Errores frecuentes
| Error | Causa | Solución |
|---|---|---|
403 FORBIDDEN — 'from' is not an active controller of 'controllerDid' | La cuenta from no controla el DID paraguas. | Usa la EOA del DID paraguas (paso 2). |
400 — 'controllerDid' is not valid | El DID paraguas está mal escrito o es de otro entorno (por ejemplo, un uc-dev en pre-producción). | Revisa el DID y el --modelDeploy del paso 2. |
400 — The service document cannot set … | Has usado un campo reservado en los campos libres. | Quita o renombra ese campo (ver Campos libres). |
400 — The service document is … bytes; the registry accepts at most 4096. | Los campos libres superan los 4096 bytes. | Reduce los campos libres. |
400 — request/body must have required property … | Falta algún campo obligatorio o tiene un formato incorrecto. | Revisa el cuerpo con la tabla del paso 4. |
500 — invalid BytesLike value | La transacción firmada está incompleta: se perdió algún carácter al copiarla. | Cópiala de nuevo desde signed.hex. |
500 — transaction execution reverted | El contrato ha rechazado el alta. Lo más habitual: la clave del servicio es la del DID paraguas o la de un servicio de otra organización. | Genera una clave nueva para el servicio (paso 3) y repite desde el paso 4. |
500 — Known transaction | Esa transacción ya se había enviado. | Comprueba en el paso 7 si el servicio ya está registrado. |
500 — nonce too low | La transacción se pidió antes de que se procesara otra anterior de la misma cuenta. | Pide una transacción nueva (paso 4) y fírmala otra vez. |
Siguientes pasos
- Gestionar el Service DID — Cambiar sus campos libres, rotar la clave, cambiar la caducidad o desactivarlo.