@polymorphism-tech/morph-spec 6.0.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +367 -366
- package/docs/CHEATSHEET.md +3 -3
- package/docs/QUICKSTART.md +4 -4
- package/framework/CLAUDE.md +13 -0
- package/framework/MORPH.md +57 -36
- package/framework/agents.json +132 -127
- package/framework/commands/morph-apply.md +4 -21
- package/framework/commands/morph-archive.md +1 -1
- package/framework/commands/morph-proposal.md +2 -0
- package/framework/hooks/claude-code/core/enforce-phase-writes.js +1 -1
- package/framework/hooks/claude-code/core/protect-spec-files.js +1 -1
- package/framework/hooks/claude-code/core/state-sync.js +212 -0
- package/framework/hooks/shared/phase-utils.js +5 -4
- package/framework/hooks/shared/state-reader.js +1 -1
- package/framework/phases.json +1 -1
- package/framework/rubrics/backend.json +41 -36
- package/framework/rules/ai-agents-standards.md +45 -15
- package/framework/rules/morph-workflow.md +15 -34
- package/framework/rules/neon-standards.md +25 -26
- package/framework/schemas/tasks.schema.json +35 -0
- package/framework/skills/core/morph-apply/SKILL.md +154 -0
- package/framework/skills/core/morph-brainstorming/SKILL.md +53 -30
- package/framework/skills/core/morph-implement/SKILL.md +25 -14
- package/framework/skills/core/morph-plan/SKILL.md +91 -23
- package/framework/skills/core/morph-proposal/SKILL.md +137 -0
- package/framework/skills/core/morph-review/SKILL.md +43 -7
- package/framework/skills/core/morph-stack-scan/SKILL.md +40 -1
- package/framework/standards/STANDARDS.json +1729 -1134
- package/framework/standards/ai-agents/agent-session.md +160 -0
- package/framework/standards/ai-agents/batching.md +193 -0
- package/framework/standards/ai-agents/context-providers.md +188 -0
- package/framework/standards/ai-agents/mcp-server.md +250 -0
- package/framework/standards/ai-agents/mcp-tools.md +197 -0
- package/framework/standards/ai-agents/middleware-patterns.md +207 -0
- package/framework/standards/ai-agents/modalities-image-gen.md +173 -0
- package/framework/standards/ai-agents/modalities-speech-to-text.md +171 -0
- package/framework/standards/ai-agents/modalities-text-to-speech.md +181 -0
- package/framework/standards/ai-agents/modalities-vision.md +201 -0
- package/framework/standards/ai-agents/multi-agent-patterns.md +155 -0
- package/framework/standards/ai-agents/production.md +114 -258
- package/framework/standards/ai-agents/prompts-in-db.md +214 -0
- package/framework/standards/ai-agents/providers/model-registry.md +158 -0
- package/framework/standards/ai-agents/rag-custom-pgvector.md +243 -0
- package/framework/standards/ai-agents/service-tier-flex.md +135 -0
- package/framework/standards/ai-agents/setup.md +142 -316
- package/framework/standards/ai-agents/structured-output.md +249 -0
- package/framework/standards/ai-agents/sweet-spot.md +109 -0
- package/framework/standards/ai-agents/workflows.md +114 -284
- package/framework/standards/architecture/vertical-slice/vertical-slice.md +433 -429
- package/framework/standards/backend/api/validation.md +92 -88
- package/framework/standards/backend/database/postgresql/database.md +336 -332
- package/framework/standards/backend/database/vector-search-rag.md +599 -541
- package/framework/standards/backend/dotnet/fluent-validation-vsa.md +4 -0
- package/framework/standards/backend/dotnet/result-pattern.md +4 -0
- package/framework/standards/backend/dotnet/scalar-ui.md +176 -172
- package/framework/standards/backend/dotnet/scrutor.md +4 -0
- package/framework/standards/backend/dotnet/vsa-handler-patterns.md +278 -274
- package/framework/standards/backend/integrations/asaas/asaas-api.md +260 -216
- package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +354 -350
- package/framework/standards/backend/integrations/neon-auth/neon-auth.md +30 -19
- package/framework/standards/backend/integrations/resend/resend-email.md +400 -385
- package/framework/standards/data/nosql/cache/redis.md +106 -97
- package/framework/standards/data/nosql/cosmos-db.md +127 -118
- package/framework/standards/data/vector-search/rag-chunking.md +113 -104
- package/framework/standards/frontend/design-system/ai-image-generation.md +4 -0
- package/framework/standards/frontend/design-system/animations.md +164 -160
- package/framework/standards/frontend/design-system/naming.md +68 -64
- package/framework/standards/frontend/gsap/gsap-core.md +14 -8
- package/framework/standards/frontend/gsap/gsap-plugins.md +26 -21
- package/framework/standards/frontend/gsap/gsap-scrolltrigger.md +9 -7
- package/framework/standards/frontend/nextjs/app-router.md +127 -123
- package/framework/standards/frontend/nextjs/components.md +136 -132
- package/framework/standards/frontend/nextjs/data-fetching.md +130 -126
- package/framework/standards/frontend/nextjs/forms.md +134 -128
- package/framework/standards/frontend/nextjs/motion-patterns.md +328 -322
- package/framework/standards/frontend/nextjs/naming-conventions.md +71 -67
- package/framework/standards/frontend/nextjs/nextjs-patterns.md +229 -225
- package/framework/standards/frontend/nextjs/project-structure.md +106 -102
- package/framework/standards/frontend/nextjs/state-management.md +76 -72
- package/framework/standards/frontend/nextjs/testing.md +115 -111
- package/framework/standards/infrastructure/docker/easypanel-deploy.md +196 -192
- package/framework/standards/infrastructure/neon/neon-pgrag.md +6 -2
- package/framework/standards/infrastructure/neon/neon-pgvector.md +4 -0
- package/framework/standards/infrastructure/neon/neon-setup.md +5 -1
- package/framework/standards/integration/mcp/mcp-tools.md +471 -462
- package/framework/templates/REGISTRY.json +1745 -1239
- package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -0
- package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -0
- package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -0
- package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -0
- package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -0
- package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -0
- package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -0
- package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -0
- package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -0
- package/framework/templates/docs/onboarding.md +4 -4
- package/framework/templates/tasks.template.json +17 -0
- package/package.json +89 -83
- package/src/commands/project/init.js +16 -0
- package/src/commands/validation/validate-feature.js +1 -1
- package/src/core/paths/output-schema.js +6 -6
- package/src/core/state/state-manager.js +1 -1
- package/src/core/templates/template-registry.js +289 -256
- package/src/lib/detectors/design-system-detector.js +1 -1
- package/src/lib/generators/context-generator.js +516 -518
- package/src/lib/generators/scaffold-generator.js +23 -26
- package/src/lib/installers/memory-installer.js +138 -0
- package/src/lib/phase-chain/phase-validator.js +4 -4
- package/src/lib/risk-detector.js +80 -0
- package/src/lib/tasks/tasks-json-parser.js +185 -0
- package/src/scripts/setup-infra.js +25 -0
- package/src/utils/hooks-installer.js +59 -10
- package/framework/standards/infrastructure/neon/neon-semantic-kernel.md +0 -310
- package/framework/templates/integrations/semantic-kernel-neon.cs +0 -125
|
@@ -1,216 +1,260 @@
|
|
|
1
|
-
# Asaas API Integration Standard
|
|
2
|
-
|
|
3
|
-
> **Scope:** universal
|
|
4
|
-
> **Layer:** 2 (on keyword)
|
|
5
|
-
> **Keywords:** asaas, payment, brazilian, pix, boleto, billing
|
|
6
|
-
> **Load When:** asaas or brazilian payment keywords detected
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
1
|
+
# Asaas API Integration Standard
|
|
2
|
+
|
|
3
|
+
> **Scope:** universal
|
|
4
|
+
> **Layer:** 2 (on keyword)
|
|
5
|
+
> **Keywords:** asaas, payment, brazilian, pix, boleto, billing
|
|
6
|
+
> **Load When:** asaas or brazilian payment keywords detected
|
|
7
|
+
|
|
8
|
+
**Verified against:** Asaas REST API v3 (no official Node SDK — direct REST). Last-verified: 2026-05-20.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Brazilian payment gateway integration for PIX, Boleto, and credit card processing.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Overview
|
|
17
|
+
|
|
18
|
+
Asaas is a Brazilian payment service provider offering:
|
|
19
|
+
- PIX instant payments
|
|
20
|
+
- Boleto bancário
|
|
21
|
+
- Credit card processing
|
|
22
|
+
- Subscription billing
|
|
23
|
+
- Split payments
|
|
24
|
+
|
|
25
|
+
**Stack:** .NET Backend
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Core Principles
|
|
30
|
+
|
|
31
|
+
1. **Webhook-First**: All payment state changes via webhooks
|
|
32
|
+
2. **Idempotency**: Use idempotency keys for all POST requests
|
|
33
|
+
3. **Security**: Validate webhook signatures, never store full card data
|
|
34
|
+
4. **Brazil-Specific**: Handle CPF/CNPJ validation, Brazilian tax rules
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## API Configuration
|
|
39
|
+
|
|
40
|
+
### Environment Variables
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# .env.local
|
|
44
|
+
ASAAS_API_KEY=your_api_key_here
|
|
45
|
+
ASAAS_WEBHOOK_SECRET=your_webhook_secret
|
|
46
|
+
ASAAS_ENVIRONMENT=sandbox # or production
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### REST Client Setup
|
|
50
|
+
|
|
51
|
+
Asaas has **no official Node SDK** — integrate against the documented REST API
|
|
52
|
+
directly. The API key goes in the `access_token` header; the base URL switches
|
|
53
|
+
between sandbox and production.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// lib/asaas/client.ts
|
|
57
|
+
const ASAAS_BASE_URL =
|
|
58
|
+
process.env.ASAAS_ENVIRONMENT === 'production'
|
|
59
|
+
? 'https://api.asaas.com/v3'
|
|
60
|
+
: 'https://api-sandbox.asaas.com/v3';
|
|
61
|
+
|
|
62
|
+
export async function asaasFetch<T>(
|
|
63
|
+
path: string,
|
|
64
|
+
init?: RequestInit,
|
|
65
|
+
): Promise<T> {
|
|
66
|
+
const res = await fetch(`${ASAAS_BASE_URL}${path}`, {
|
|
67
|
+
...init,
|
|
68
|
+
headers: {
|
|
69
|
+
'Content-Type': 'application/json',
|
|
70
|
+
access_token: process.env.ASAAS_API_KEY!,
|
|
71
|
+
...init?.headers,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
if (!res.ok) {
|
|
75
|
+
throw new Error(`Asaas ${res.status}: ${await res.text()}`);
|
|
76
|
+
}
|
|
77
|
+
return res.json() as Promise<T>;
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Common Operations
|
|
84
|
+
|
|
85
|
+
### Create PIX Payment
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
// app/api/payments/pix/route.ts
|
|
89
|
+
import { asaasFetch } from '@/lib/asaas/client';
|
|
90
|
+
|
|
91
|
+
export async function POST(req: Request) {
|
|
92
|
+
const { amount, customerId, description } = await req.json();
|
|
93
|
+
|
|
94
|
+
// POST /v3/payments — billingType PIX
|
|
95
|
+
const payment = await asaasFetch<{ id: string }>('/payments', {
|
|
96
|
+
method: 'POST',
|
|
97
|
+
body: JSON.stringify({
|
|
98
|
+
customer: customerId,
|
|
99
|
+
billingType: 'PIX',
|
|
100
|
+
value: amount,
|
|
101
|
+
dueDate: new Date().toISOString().split('T')[0],
|
|
102
|
+
description,
|
|
103
|
+
}),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// GET /v3/payments/{id}/pixQrCode — PIX copy-paste payload + QR image
|
|
107
|
+
const pix = await asaasFetch<{ payload: string; encodedImage: string }>(
|
|
108
|
+
`/payments/${payment.id}/pixQrCode`,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
return Response.json({
|
|
112
|
+
paymentId: payment.id,
|
|
113
|
+
pixCode: pix.payload,
|
|
114
|
+
qrCode: pix.encodedImage,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Webhook Handler
|
|
120
|
+
|
|
121
|
+
Asaas does not HMAC-sign webhooks. Instead, every webhook request carries the
|
|
122
|
+
`authToken` you configured for the webhook in the `asaas-access-token` header —
|
|
123
|
+
compare it against your stored secret. The `authToken` is mandatory: a `POST
|
|
124
|
+
/v3/webhooks` without one makes Asaas auto-generate a high-security token
|
|
125
|
+
(32–255 chars, shown once in the response).
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// app/api/webhooks/asaas/route.ts
|
|
129
|
+
import { headers } from 'next/headers';
|
|
130
|
+
|
|
131
|
+
export async function POST(req: Request) {
|
|
132
|
+
const body = await req.text();
|
|
133
|
+
|
|
134
|
+
// Asaas sends the webhook's authToken in the asaas-access-token header
|
|
135
|
+
const token = headers().get('asaas-access-token');
|
|
136
|
+
if (token !== process.env.ASAAS_WEBHOOK_SECRET) {
|
|
137
|
+
return new Response('Invalid token', { status: 401 });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const event = JSON.parse(body);
|
|
141
|
+
|
|
142
|
+
// Handle payment events
|
|
143
|
+
switch (event.event) {
|
|
144
|
+
case 'PAYMENT_RECEIVED':
|
|
145
|
+
await handlePaymentReceived(event.payment);
|
|
146
|
+
break;
|
|
147
|
+
case 'PAYMENT_CONFIRMED':
|
|
148
|
+
await handlePaymentConfirmed(event.payment);
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return new Response('OK');
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Database Schema (PostgreSQL / Neon)
|
|
159
|
+
|
|
160
|
+
```sql
|
|
161
|
+
-- Store payment records
|
|
162
|
+
create table payments (
|
|
163
|
+
id uuid primary key default gen_random_uuid(),
|
|
164
|
+
user_id uuid references auth.users(id),
|
|
165
|
+
asaas_payment_id text unique not null,
|
|
166
|
+
amount decimal(10,2) not null,
|
|
167
|
+
status text not null, -- pending, confirmed, received
|
|
168
|
+
billing_type text not null, -- PIX, BOLETO, CREDIT_CARD
|
|
169
|
+
created_at timestamptz default now(),
|
|
170
|
+
updated_at timestamptz default now()
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
-- RLS policies
|
|
174
|
+
alter table payments enable row level security;
|
|
175
|
+
|
|
176
|
+
create policy "Users read own payments"
|
|
177
|
+
on payments for select
|
|
178
|
+
using (auth.user_id() = user_id);
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Best Practices
|
|
184
|
+
|
|
185
|
+
### CPF/CNPJ Validation
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
export function validateCPF(cpf: string): boolean {
|
|
189
|
+
cpf = cpf.replace(/[^\d]/g, '');
|
|
190
|
+
if (cpf.length !== 11) return false;
|
|
191
|
+
|
|
192
|
+
// Validation logic...
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function validateCNPJ(cnpj: string): boolean {
|
|
197
|
+
cnpj = cnpj.replace(/[^\d]/g, '');
|
|
198
|
+
if (cnpj.length !== 14) return false;
|
|
199
|
+
|
|
200
|
+
// Validation logic...
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Idempotency Keys
|
|
206
|
+
|
|
207
|
+
Pass a stable idempotency key in the request header so a retried POST does not
|
|
208
|
+
create a duplicate charge:
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
await asaasFetch('/payments', {
|
|
212
|
+
method: 'POST',
|
|
213
|
+
headers: { 'Idempotency-Key': `payment-${userId}-${requestId}` },
|
|
214
|
+
body: JSON.stringify({ /* ... payment data ... */ }),
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Error Handling
|
|
221
|
+
|
|
222
|
+
Asaas returns failures as HTTP 400 with a JSON body shaped `{ errors: [{ code,
|
|
223
|
+
description }] }`. `asaasFetch` throws on non-OK responses — catch and inspect
|
|
224
|
+
the `errors[]` array:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
type AsaasError = { errors: { code: string; description: string }[] };
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
await asaasFetch('/payments', { method: 'POST', body: JSON.stringify(data) });
|
|
231
|
+
} catch (error) {
|
|
232
|
+
// asaasFetch throws `Asaas <status>: <raw body>` — parse the body
|
|
233
|
+
const body = (error as Error).message.replace(/^Asaas \d+: /, '');
|
|
234
|
+
let parsed: AsaasError | null = null;
|
|
235
|
+
try { parsed = JSON.parse(body) as AsaasError; } catch { /* non-JSON */ }
|
|
236
|
+
|
|
237
|
+
const code = parsed?.errors?.[0]?.code;
|
|
238
|
+
if (code === 'invalid_cpfCnpj') {
|
|
239
|
+
return Response.json({ error: 'CPF/CNPJ inválido' }, { status: 400 });
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
console.error('Asaas API error:', body);
|
|
243
|
+
return Response.json({ error: 'Erro no processamento' }, { status: 500 });
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## References
|
|
250
|
+
|
|
251
|
+
- [Asaas API Documentation](https://docs.asaas.com/)
|
|
252
|
+
- [Asaas Webhooks](https://docs.asaas.com/docs/about-webhooks)
|
|
253
|
+
- PIX Specification: Brazilian Central Bank
|
|
254
|
+
|
|
255
|
+
> Asaas publishes **no official Node SDK** — integrate against the REST API
|
|
256
|
+
> directly. Community wrappers exist but are unofficial and vary in maintenance.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
*MORPH-SPEC by Polymorphism Tech*
|