@polymorphism-tech/morph-spec 2.2.0 → 2.4.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/CLAUDE.md +314 -1673
- package/LICENSE +72 -72
- package/README.md +515 -516
- package/bin/detect-agents.js +225 -225
- package/bin/morph-spec.js +358 -173
- package/bin/render-template.js +302 -302
- package/bin/semantic-detect-agents.js +246 -246
- package/bin/task-manager.js +429 -0
- package/bin/validate-agents-skills.js +251 -251
- package/bin/validate-agents.js +69 -69
- package/bin/validate-phase.js +263 -263
- package/bin/validate.js +369 -0
- package/content/.azure/README.md +293 -293
- package/content/.azure/docs/azure-devops-setup.md +454 -454
- package/content/.azure/docs/branch-strategy.md +398 -398
- package/content/.azure/docs/local-development.md +515 -515
- package/content/.azure/pipelines/pipeline-variables.yml +34 -34
- package/content/.azure/pipelines/prod-pipeline.yml +319 -319
- package/content/.azure/pipelines/staging-pipeline.yml +234 -234
- package/content/.azure/pipelines/templates/build-dotnet.yml +75 -75
- package/content/.azure/pipelines/templates/deploy-app-service.yml +94 -94
- package/content/.azure/pipelines/templates/deploy-container-app.yml +120 -120
- package/content/.azure/pipelines/templates/infra-deploy.yml +90 -90
- package/content/.claude/commands/morph-apply.md +221 -158
- package/content/.claude/commands/morph-archive.md +79 -79
- package/content/.claude/commands/morph-infra.md +209 -209
- package/content/.claude/commands/morph-preflight.md +227 -0
- package/content/.claude/commands/morph-proposal.md +122 -101
- package/content/.claude/commands/morph-status.md +86 -86
- package/content/.claude/commands/morph-troubleshoot.md +122 -0
- package/content/.claude/settings.local.json +15 -15
- package/content/.claude/skills/checklists/code-review.md +226 -0
- package/content/.claude/skills/checklists/morph-checklist.md +117 -0
- package/content/.claude/skills/checklists/simulation-checklist.md +77 -0
- package/content/.claude/skills/infra/bicep-architect.md +126 -419
- package/content/.claude/skills/infra/container-specialist.md +131 -437
- package/content/.claude/skills/infra/devops-engineer.md +119 -405
- package/content/.claude/skills/integrations/asaas-financial.md +130 -333
- package/content/.claude/skills/integrations/azure-identity.md +142 -309
- package/content/.claude/skills/integrations/clerk-auth.md +108 -290
- package/content/.claude/skills/integrations/resend-email.md +119 -0
- package/content/.claude/skills/specialists/ai-system-architect.md +192 -604
- package/content/.claude/skills/specialists/azure-architect.md +142 -142
- package/content/.claude/skills/specialists/code-analyzer.md +235 -0
- package/content/.claude/skills/specialists/dotnet-senior.md +287 -0
- package/content/.claude/skills/specialists/ef-modeler.md +113 -200
- package/content/.claude/skills/specialists/hangfire-orchestrator.md +126 -245
- package/content/.claude/skills/specialists/ms-agent-expert.md +109 -263
- package/content/.claude/skills/specialists/po-pm-advisor.md +197 -197
- package/content/.claude/skills/specialists/standards-architect.md +156 -78
- package/content/.claude/skills/specialists/testing-specialist.md +126 -0
- package/content/.claude/skills/specialists/ui-ux-designer.md +191 -1060
- package/content/.claude/skills/stacks/dotnet-blazor.md +210 -588
- package/content/.claude/skills/stacks/dotnet-nextjs.md +154 -402
- package/content/.claude/skills/workflows/morph-replicate.md +213 -0
- package/content/.claude/{commands/morph-clarify.md → skills/workflows/phase-clarify.md} +5 -58
- package/content/.claude/{commands/morph-design.md → skills/workflows/phase-design.md} +16 -86
- package/content/.claude/{commands/morph-setup.md → skills/workflows/phase-setup.md} +9 -17
- package/content/.claude/skills/workflows/phase-tasks.md +164 -0
- package/content/.claude/{commands/morph-uiux.md → skills/workflows/phase-uiux.md} +15 -88
- package/content/.morph/.morphversion +5 -5
- package/content/.morph/archive/.gitkeep +25 -25
- package/content/.morph/config/agents.json +378 -242
- package/content/.morph/config/config.template.json +89 -108
- package/content/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +392 -392
- package/content/.morph/docs/workflows/design-impl.md +37 -0
- package/content/.morph/docs/workflows/fast-track.md +29 -0
- package/content/.morph/docs/workflows/full-morph.md +76 -0
- package/content/.morph/docs/workflows/standard.md +44 -0
- package/content/.morph/docs/workflows/ui-refresh.md +39 -0
- package/content/.morph/examples/api-nextjs/README.md +241 -241
- package/content/.morph/examples/api-nextjs/contracts.ts +307 -307
- package/content/.morph/examples/api-nextjs/spec.md +399 -399
- package/content/.morph/examples/api-nextjs/tasks.md +168 -168
- package/content/.morph/examples/micro-saas/README.md +125 -125
- package/content/.morph/examples/micro-saas/contracts.cs +358 -358
- package/content/.morph/examples/micro-saas/decisions.md +246 -246
- package/content/.morph/examples/micro-saas/spec.md +236 -236
- package/content/.morph/examples/micro-saas/tasks.md +150 -150
- package/content/.morph/examples/multi-agent/README.md +309 -309
- package/content/.morph/examples/multi-agent/contracts.cs +433 -433
- package/content/.morph/examples/multi-agent/spec.md +479 -479
- package/content/.morph/examples/multi-agent/tasks.md +185 -185
- package/content/.morph/examples/scheduled-reports/decisions.md +158 -0
- package/content/.morph/examples/scheduled-reports/proposal.md +95 -0
- package/content/.morph/examples/scheduled-reports/spec.md +267 -0
- package/content/.morph/examples/state-v3.json +188 -0
- package/content/.morph/features/.gitkeep +25 -25
- package/content/.morph/hooks/README.md +190 -239
- package/content/.morph/hooks/pre-commit-agents.sh +24 -24
- package/content/.morph/hooks/pre-commit-all.sh +48 -48
- package/content/.morph/hooks/pre-commit-specs.sh +49 -49
- package/content/.morph/hooks/pre-commit-tests.sh +60 -60
- package/content/.morph/project.md +160 -160
- package/content/.morph/schemas/agent.schema.json +296 -296
- package/content/.morph/schemas/tasks.schema.json +220 -0
- package/content/.morph/specs/.gitkeep +20 -20
- package/content/.morph/standards/agent-framework-blazor-ui.md +359 -0
- package/content/.morph/standards/agent-framework-production.md +410 -0
- package/content/.morph/standards/agent-framework-setup.md +413 -453
- package/content/.morph/standards/agent-framework-workflows.md +349 -0
- package/content/.morph/standards/architecture.md +325 -325
- package/content/.morph/standards/azure.md +605 -379
- package/content/.morph/standards/coding.md +377 -377
- package/content/.morph/standards/dotnet10-migration.md +520 -494
- package/content/.morph/standards/fluent-ui-setup.md +590 -590
- package/content/.morph/standards/migration-guide.md +514 -514
- package/content/.morph/standards/passkeys-auth.md +423 -423
- package/content/.morph/standards/vector-search-rag.md +536 -536
- package/content/.morph/state.json +17 -17
- package/content/.morph/templates/FluentDesignTheme.cs +149 -149
- package/content/.morph/templates/MudTheme.cs +281 -281
- package/content/.morph/templates/agent.cs +163 -172
- package/content/.morph/templates/clarify-questions.md +159 -0
- package/content/.morph/templates/component.razor +239 -239
- package/content/.morph/templates/contracts/Commands.cs +74 -0
- package/content/.morph/templates/contracts/Entities.cs +25 -0
- package/content/.morph/templates/contracts/Queries.cs +74 -0
- package/content/.morph/templates/contracts/README.md +74 -0
- package/content/.morph/templates/contracts.cs +217 -217
- package/content/.morph/templates/decisions.md +123 -106
- package/content/.morph/templates/design-system.css +226 -226
- package/content/.morph/templates/infra/.dockerignore.example +89 -89
- package/content/.morph/templates/infra/Dockerfile.example +82 -82
- package/content/.morph/templates/infra/README.md +286 -286
- package/content/.morph/templates/infra/app-insights.bicep +63 -63
- package/content/.morph/templates/infra/app-service.bicep +164 -164
- package/content/.morph/templates/infra/container-app-env.bicep +49 -49
- package/content/.morph/templates/infra/container-app.bicep +156 -156
- package/content/.morph/templates/infra/deploy-checklist.md +426 -0
- package/content/.morph/templates/infra/deploy.ps1 +229 -229
- package/content/.morph/templates/infra/deploy.sh +208 -208
- package/content/.morph/templates/infra/key-vault.bicep +91 -91
- package/content/.morph/templates/infra/main.bicep +189 -189
- package/content/.morph/templates/infra/parameters.dev.json +29 -29
- package/content/.morph/templates/infra/parameters.prod.json +29 -29
- package/content/.morph/templates/infra/parameters.staging.json +29 -29
- package/content/.morph/templates/infra/sql-database.bicep +103 -103
- package/content/.morph/templates/infra/storage.bicep +106 -106
- package/content/.morph/templates/integrations/asaas-client.cs +387 -387
- package/content/.morph/templates/integrations/asaas-webhook.cs +351 -351
- package/content/.morph/templates/integrations/azure-identity-config.cs +288 -288
- package/content/.morph/templates/integrations/clerk-config.cs +258 -258
- package/content/.morph/templates/job.cs +171 -171
- package/content/.morph/templates/migration.cs +83 -83
- package/content/.morph/templates/proposal.md +141 -155
- package/content/.morph/templates/recap.md +94 -105
- package/content/.morph/templates/repository.cs +141 -141
- package/content/.morph/templates/saas/subscription.cs +347 -347
- package/content/.morph/templates/saas/tenant.cs +338 -338
- package/content/.morph/templates/service.cs +139 -139
- package/content/.morph/templates/simulation.md +353 -0
- package/content/.morph/templates/spec.md +149 -148
- package/content/.morph/templates/sprint-status.yaml +68 -68
- package/content/.morph/templates/state.template.json +222 -222
- package/content/.morph/templates/story.md +143 -143
- package/content/.morph/templates/tasks.md +257 -235
- package/content/.morph/templates/test.cs +239 -239
- package/content/.morph/templates/ui-components.md +362 -276
- package/content/.morph/templates/ui-design-system.md +286 -286
- package/content/.morph/templates/ui-flows.md +336 -336
- package/content/.morph/templates/ui-mockups.md +133 -133
- package/content/.morph/test-infra/example.bicep +59 -59
- package/content/CLAUDE.md +150 -442
- package/content/README.md +79 -79
- package/detectors/config-detector.js +223 -223
- package/detectors/conversation-analyzer.js +163 -163
- package/detectors/index.js +84 -84
- package/detectors/standards-generator.js +275 -275
- package/detectors/structure-detector.js +245 -250
- package/docs/README.md +144 -149
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +977 -977
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1048 -1048
- package/docs/api/scripts/collapse.js +38 -38
- package/docs/api/scripts/commonNav.js +28 -28
- package/docs/api/scripts/linenumber.js +25 -25
- package/docs/api/scripts/nav.js +12 -12
- package/docs/api/scripts/polyfill.js +3 -3
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -202
- package/docs/api/scripts/prettify/lang-css.js +2 -2
- package/docs/api/scripts/prettify/prettify.js +28 -28
- package/docs/api/scripts/search.js +98 -98
- package/docs/api/styles/jsdoc.css +776 -776
- package/docs/api/styles/prettify.css +80 -80
- package/docs/examples.md +328 -328
- package/docs/getting-started.md +301 -302
- package/docs/installation.md +361 -361
- package/docs/templates.md +418 -418
- package/docs/validation-checklist.md +265 -266
- package/package.json +80 -80
- package/scripts/postinstall.js +132 -132
- package/src/commands/advance-phase.js +183 -0
- package/src/commands/analyze-blazor-concurrency.js +193 -0
- package/src/commands/create-story.js +351 -351
- package/src/commands/detect-agents.js +139 -0
- package/src/commands/detect.js +104 -104
- package/src/commands/doctor.js +356 -280
- package/src/commands/generate.js +149 -149
- package/src/commands/init.js +258 -245
- package/src/commands/lint-fluent.js +352 -0
- package/src/commands/rollback-phase.js +185 -0
- package/src/commands/session-summary.js +291 -0
- package/src/commands/shard-spec.js +224 -224
- package/src/commands/sprint-status.js +250 -250
- package/src/commands/state.js +333 -333
- package/src/commands/sync.js +167 -167
- package/src/commands/task.js +78 -0
- package/src/commands/troubleshoot.js +222 -0
- package/src/commands/update.js +192 -159
- package/src/commands/validate-blazor-state.js +210 -0
- package/src/commands/validate-blazor.js +156 -0
- package/src/commands/validate-css.js +84 -0
- package/src/commands/validate-phase.js +221 -0
- package/src/lib/blazor-concurrency-analyzer.js +288 -0
- package/src/lib/blazor-state-validator.js +291 -0
- package/src/lib/blazor-validator.js +374 -0
- package/src/lib/complexity-analyzer.js +441 -292
- package/src/lib/continuous-validator.js +421 -0
- package/src/lib/css-validator.js +352 -0
- package/src/lib/decision-constraint-loader.js +109 -0
- package/src/lib/design-system-generator.js +298 -298
- package/src/lib/learning-system.js +520 -0
- package/src/lib/mockup-generator.js +366 -0
- package/src/lib/recap-generator.js +205 -0
- package/src/lib/state-manager.js +397 -340
- package/src/lib/troubleshoot-grep.js +194 -0
- package/src/lib/troubleshoot-index.js +144 -0
- package/src/lib/ui-detector.js +350 -0
- package/src/lib/validation-runner.js +231 -0
- package/src/lib/validators/architecture-validator.js +387 -0
- package/src/lib/validators/contract-compliance-validator.js +273 -0
- package/src/lib/validators/package-validator.js +360 -0
- package/src/lib/validators/ui-contrast-validator.js +422 -0
- package/src/utils/file-copier.js +179 -139
- package/src/utils/logger.js +32 -32
- package/src/utils/version-checker.js +175 -175
- package/content/.claude/commands/morph-costs.md +0 -206
- package/content/.claude/commands/morph-tasks.md +0 -319
- package/content/.claude/skills/specialists/cost-guardian.md +0 -110
- package/content/.claude/skills/stacks/shopify.md +0 -445
- package/content/.morph/config/azure-pricing.json +0 -70
- package/content/.morph/config/azure-pricing.schema.json +0 -50
- package/content/.morph/hooks/pre-commit-costs.sh +0 -91
- package/docs/api/cost-calculator.js.html +0 -513
- package/docs/api/design-system-generator.js.html +0 -382
- package/docs/api/global.html +0 -5263
- package/docs/api/index.html +0 -96
- package/docs/api/state-manager.js.html +0 -423
- package/src/commands/cost.js +0 -181
- package/src/commands/update-pricing.js +0 -206
- package/src/lib/cost-calculator.js +0 -429
|
@@ -1,333 +1,130 @@
|
|
|
1
|
-
# Asaas Financial
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
public
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
##
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
[JsonPropertyName("phone")]
|
|
132
|
-
public string? Phone { get; init; }
|
|
133
|
-
|
|
134
|
-
[JsonPropertyName("mobilePhone")]
|
|
135
|
-
public string? MobilePhone { get; init; }
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Models/Asaas/CreatePaymentRequest.cs
|
|
139
|
-
public record CreatePaymentRequest
|
|
140
|
-
{
|
|
141
|
-
[JsonPropertyName("customer")]
|
|
142
|
-
public required string Customer { get; init; } // Asaas customer ID
|
|
143
|
-
|
|
144
|
-
[JsonPropertyName("billingType")]
|
|
145
|
-
public required string BillingType { get; init; } // BOLETO, PIX, CREDIT_CARD
|
|
146
|
-
|
|
147
|
-
[JsonPropertyName("value")]
|
|
148
|
-
public required decimal Value { get; init; }
|
|
149
|
-
|
|
150
|
-
[JsonPropertyName("dueDate")]
|
|
151
|
-
public required string DueDate { get; init; } // yyyy-MM-dd
|
|
152
|
-
|
|
153
|
-
[JsonPropertyName("description")]
|
|
154
|
-
public string? Description { get; init; }
|
|
155
|
-
|
|
156
|
-
[JsonPropertyName("externalReference")]
|
|
157
|
-
public string? ExternalReference { get; init; } // Seu ID interno
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Models/Asaas/AsaasPayment.cs
|
|
161
|
-
public record AsaasPayment
|
|
162
|
-
{
|
|
163
|
-
[JsonPropertyName("id")]
|
|
164
|
-
public string Id { get; init; } = "";
|
|
165
|
-
|
|
166
|
-
[JsonPropertyName("customer")]
|
|
167
|
-
public string Customer { get; init; } = "";
|
|
168
|
-
|
|
169
|
-
[JsonPropertyName("value")]
|
|
170
|
-
public decimal Value { get; init; }
|
|
171
|
-
|
|
172
|
-
[JsonPropertyName("status")]
|
|
173
|
-
public string Status { get; init; } = ""; // PENDING, RECEIVED, CONFIRMED, OVERDUE...
|
|
174
|
-
|
|
175
|
-
[JsonPropertyName("billingType")]
|
|
176
|
-
public string BillingType { get; init; } = "";
|
|
177
|
-
|
|
178
|
-
[JsonPropertyName("invoiceUrl")]
|
|
179
|
-
public string? InvoiceUrl { get; init; }
|
|
180
|
-
|
|
181
|
-
[JsonPropertyName("bankSlipUrl")]
|
|
182
|
-
public string? BankSlipUrl { get; init; } // URL do boleto
|
|
183
|
-
|
|
184
|
-
[JsonPropertyName("pixQrCode")]
|
|
185
|
-
public AsaasPixQrCode? PixQrCode { get; init; }
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
public record AsaasPixQrCode
|
|
189
|
-
{
|
|
190
|
-
[JsonPropertyName("encodedImage")]
|
|
191
|
-
public string? EncodedImage { get; init; } // Base64 QR Code
|
|
192
|
-
|
|
193
|
-
[JsonPropertyName("payload")]
|
|
194
|
-
public string? Payload { get; init; } // PIX copia-e-cola
|
|
195
|
-
}
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
## Webhooks
|
|
199
|
-
|
|
200
|
-
```csharp
|
|
201
|
-
// Controllers/AsaasWebhookController.cs
|
|
202
|
-
[ApiController]
|
|
203
|
-
[Route("api/webhooks/asaas")]
|
|
204
|
-
public class AsaasWebhookController : ControllerBase
|
|
205
|
-
{
|
|
206
|
-
private readonly IPaymentService _paymentService;
|
|
207
|
-
private readonly ILogger<AsaasWebhookController> _logger;
|
|
208
|
-
|
|
209
|
-
public AsaasWebhookController(
|
|
210
|
-
IPaymentService paymentService,
|
|
211
|
-
ILogger<AsaasWebhookController> logger)
|
|
212
|
-
{
|
|
213
|
-
_paymentService = paymentService;
|
|
214
|
-
_logger = logger;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
[HttpPost]
|
|
218
|
-
public async Task<IActionResult> HandleWebhook([FromBody] AsaasWebhookPayload payload)
|
|
219
|
-
{
|
|
220
|
-
_logger.LogInformation("Received Asaas webhook: {Event} for payment {PaymentId}",
|
|
221
|
-
payload.Event, payload.Payment?.Id);
|
|
222
|
-
|
|
223
|
-
try
|
|
224
|
-
{
|
|
225
|
-
switch (payload.Event)
|
|
226
|
-
{
|
|
227
|
-
case "PAYMENT_CONFIRMED":
|
|
228
|
-
case "PAYMENT_RECEIVED":
|
|
229
|
-
await _paymentService.ConfirmPaymentAsync(payload.Payment!.Id);
|
|
230
|
-
break;
|
|
231
|
-
|
|
232
|
-
case "PAYMENT_OVERDUE":
|
|
233
|
-
await _paymentService.MarkOverdueAsync(payload.Payment!.Id);
|
|
234
|
-
break;
|
|
235
|
-
|
|
236
|
-
case "PAYMENT_REFUNDED":
|
|
237
|
-
await _paymentService.RefundPaymentAsync(payload.Payment!.Id);
|
|
238
|
-
break;
|
|
239
|
-
|
|
240
|
-
default:
|
|
241
|
-
_logger.LogWarning("Unhandled webhook event: {Event}", payload.Event);
|
|
242
|
-
break;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
return Ok();
|
|
246
|
-
}
|
|
247
|
-
catch (Exception ex)
|
|
248
|
-
{
|
|
249
|
-
_logger.LogError(ex, "Error processing webhook");
|
|
250
|
-
return StatusCode(500);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
public record AsaasWebhookPayload
|
|
256
|
-
{
|
|
257
|
-
[JsonPropertyName("event")]
|
|
258
|
-
public string Event { get; init; } = "";
|
|
259
|
-
|
|
260
|
-
[JsonPropertyName("payment")]
|
|
261
|
-
public AsaasPayment? Payment { get; init; }
|
|
262
|
-
}
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
## Assinaturas Recorrentes
|
|
266
|
-
|
|
267
|
-
```csharp
|
|
268
|
-
// Models/Asaas/CreateSubscriptionRequest.cs
|
|
269
|
-
public record CreateSubscriptionRequest
|
|
270
|
-
{
|
|
271
|
-
[JsonPropertyName("customer")]
|
|
272
|
-
public required string Customer { get; init; }
|
|
273
|
-
|
|
274
|
-
[JsonPropertyName("billingType")]
|
|
275
|
-
public required string BillingType { get; init; }
|
|
276
|
-
|
|
277
|
-
[JsonPropertyName("value")]
|
|
278
|
-
public required decimal Value { get; init; }
|
|
279
|
-
|
|
280
|
-
[JsonPropertyName("nextDueDate")]
|
|
281
|
-
public required string NextDueDate { get; init; }
|
|
282
|
-
|
|
283
|
-
[JsonPropertyName("cycle")]
|
|
284
|
-
public required string Cycle { get; init; } // MONTHLY, WEEKLY, BIWEEKLY, YEARLY
|
|
285
|
-
|
|
286
|
-
[JsonPropertyName("description")]
|
|
287
|
-
public string? Description { get; init; }
|
|
288
|
-
|
|
289
|
-
[JsonPropertyName("externalReference")]
|
|
290
|
-
public string? ExternalReference { get; init; }
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Criar assinatura
|
|
294
|
-
var subscription = await _asaasClient.CreateSubscriptionAsync(new()
|
|
295
|
-
{
|
|
296
|
-
Customer = customerId,
|
|
297
|
-
BillingType = "PIX",
|
|
298
|
-
Value = 49.90m,
|
|
299
|
-
NextDueDate = DateTime.Today.AddDays(1).ToString("yyyy-MM-dd"),
|
|
300
|
-
Cycle = "MONTHLY",
|
|
301
|
-
Description = "Plano Pro",
|
|
302
|
-
ExternalReference = $"plan_{planId}"
|
|
303
|
-
});
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
## Ambientes
|
|
307
|
-
|
|
308
|
-
| Ambiente | Base URL |
|
|
309
|
-
|----------|----------|
|
|
310
|
-
| Sandbox | `https://sandbox.asaas.com/api/v3` |
|
|
311
|
-
| Produção | `https://www.asaas.com/api/v3` |
|
|
312
|
-
|
|
313
|
-
## Documentação de Referência
|
|
314
|
-
|
|
315
|
-
- [Asaas API Documentation](https://docs.asaas.com/)
|
|
316
|
-
- [Webhooks](https://docs.asaas.com/reference/webhooks)
|
|
317
|
-
- [Cobranças](https://docs.asaas.com/reference/criar-nova-cobranca)
|
|
318
|
-
- [Assinaturas](https://docs.asaas.com/reference/criar-nova-assinatura)
|
|
319
|
-
|
|
320
|
-
## Checklist de Integração
|
|
321
|
-
|
|
322
|
-
- [ ] API Key configurada (não hardcoded)
|
|
323
|
-
- [ ] HttpClient com retry policy (Polly)
|
|
324
|
-
- [ ] Webhook endpoint configurado
|
|
325
|
-
- [ ] Validação de webhook signature
|
|
326
|
-
- [ ] Logs estruturados
|
|
327
|
-
- [ ] Tratamento de erros Asaas
|
|
328
|
-
- [ ] Testes com sandbox
|
|
329
|
-
- [ ] ExternalReference para reconciliação
|
|
330
|
-
|
|
331
|
-
---
|
|
332
|
-
|
|
333
|
-
*MORPH-SPEC by Polymorphism Tech*
|
|
1
|
+
# Asaas Financial
|
|
2
|
+
|
|
3
|
+
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** asaas, payment, pix, boleto, cobranca, subscription, billing, pagamento
|
|
4
|
+
|
|
5
|
+
Integração com Asaas para pagamentos no Brasil. API REST, sem SDK .NET oficial. Suporta PIX, Boleto, Cartão.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
```csharp
|
|
10
|
+
// appsettings.json
|
|
11
|
+
{ "Asaas": { "BaseUrl": "https://sandbox.asaas.com/api/v3", "ApiKey": "${ASAAS_API_KEY}" } }
|
|
12
|
+
|
|
13
|
+
// Program.cs
|
|
14
|
+
builder.Services.Configure<AsaasOptions>(builder.Configuration.GetSection("Asaas"));
|
|
15
|
+
builder.Services.AddHttpClient<IAsaasClient, AsaasClient>((sp, client) =>
|
|
16
|
+
{
|
|
17
|
+
var options = sp.GetRequiredService<IOptions<AsaasOptions>>().Value;
|
|
18
|
+
client.BaseAddress = new Uri(options.BaseUrl);
|
|
19
|
+
client.DefaultRequestHeaders.Add("access_token", options.ApiKey);
|
|
20
|
+
client.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
|
|
21
|
+
});
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Client Interface
|
|
25
|
+
|
|
26
|
+
```csharp
|
|
27
|
+
public interface IAsaasClient
|
|
28
|
+
{
|
|
29
|
+
Task<AsaasCustomer> CreateCustomerAsync(CreateCustomerRequest request);
|
|
30
|
+
Task<AsaasPayment> CreatePaymentAsync(CreatePaymentRequest request);
|
|
31
|
+
Task<AsaasPayment> GetPaymentAsync(string paymentId);
|
|
32
|
+
Task<AsaasSubscription> CreateSubscriptionAsync(CreateSubscriptionRequest request);
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Implementation: standard `HttpClient.PostAsJsonAsync` / `GetAsync` + `ReadFromJsonAsync` pattern. Log errors, throw `AsaasException` on failure.
|
|
37
|
+
|
|
38
|
+
## DTOs (all use `[JsonPropertyName]`)
|
|
39
|
+
|
|
40
|
+
```csharp
|
|
41
|
+
public record CreateCustomerRequest
|
|
42
|
+
{
|
|
43
|
+
[JsonPropertyName("name")] public required string Name { get; init; }
|
|
44
|
+
[JsonPropertyName("cpfCnpj")] public required string CpfCnpj { get; init; } // REQUIRED even in sandbox
|
|
45
|
+
[JsonPropertyName("email")] public string? Email { get; init; }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public record CreatePaymentRequest
|
|
49
|
+
{
|
|
50
|
+
[JsonPropertyName("customer")] public required string Customer { get; init; }
|
|
51
|
+
[JsonPropertyName("billingType")] public required string BillingType { get; init; } // BOLETO, PIX, CREDIT_CARD
|
|
52
|
+
[JsonPropertyName("value")] public required decimal Value { get; init; }
|
|
53
|
+
[JsonPropertyName("dueDate")] public required string DueDate { get; init; } // yyyy-MM-dd
|
|
54
|
+
[JsonPropertyName("description")] public string? Description { get; init; }
|
|
55
|
+
[JsonPropertyName("externalReference")] public string? ExternalReference { get; init; }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public record AsaasPayment
|
|
59
|
+
{
|
|
60
|
+
[JsonPropertyName("id")] public string Id { get; init; } = "";
|
|
61
|
+
[JsonPropertyName("status")] public string Status { get; init; } = ""; // PENDING, RECEIVED, CONFIRMED, OVERDUE
|
|
62
|
+
[JsonPropertyName("invoiceUrl")] public string? InvoiceUrl { get; init; }
|
|
63
|
+
[JsonPropertyName("bankSlipUrl")] public string? BankSlipUrl { get; init; }
|
|
64
|
+
[JsonPropertyName("pixQrCode")] public AsaasPixQrCode? PixQrCode { get; init; }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public record AsaasPixQrCode
|
|
68
|
+
{
|
|
69
|
+
[JsonPropertyName("encodedImage")] public string? EncodedImage { get; init; } // Base64
|
|
70
|
+
[JsonPropertyName("payload")] public string? Payload { get; init; } // PIX copia-e-cola
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Follow same pattern for `CreateSubscriptionRequest` (add `cycle`: MONTHLY/WEEKLY/YEARLY, `nextDueDate`).
|
|
75
|
+
|
|
76
|
+
## Webhooks
|
|
77
|
+
|
|
78
|
+
```csharp
|
|
79
|
+
[ApiController, Route("api/webhooks/asaas")]
|
|
80
|
+
public class AsaasWebhookController(IPaymentService payments, ILogger<AsaasWebhookController> logger) : ControllerBase
|
|
81
|
+
{
|
|
82
|
+
[HttpPost]
|
|
83
|
+
public async Task<IActionResult> Handle([FromBody] AsaasWebhookPayload payload)
|
|
84
|
+
{
|
|
85
|
+
logger.LogInformation("Asaas webhook: {Event} payment {Id}", payload.Event, payload.Payment?.Id);
|
|
86
|
+
switch (payload.Event)
|
|
87
|
+
{
|
|
88
|
+
case "PAYMENT_CONFIRMED": case "PAYMENT_RECEIVED":
|
|
89
|
+
await payments.ConfirmPaymentAsync(payload.Payment!.Id); break;
|
|
90
|
+
case "PAYMENT_OVERDUE":
|
|
91
|
+
await payments.MarkOverdueAsync(payload.Payment!.Id); break;
|
|
92
|
+
case "PAYMENT_REFUNDED":
|
|
93
|
+
await payments.RefundPaymentAsync(payload.Payment!.Id); break;
|
|
94
|
+
}
|
|
95
|
+
return Ok();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Environments
|
|
101
|
+
|
|
102
|
+
| Environment | Base URL |
|
|
103
|
+
|-------------|----------|
|
|
104
|
+
| Sandbox | `https://sandbox.asaas.com/api/v3` |
|
|
105
|
+
| Production | `https://www.asaas.com/api/v3` |
|
|
106
|
+
|
|
107
|
+
## Gotchas
|
|
108
|
+
|
|
109
|
+
| Issue | Fix |
|
|
110
|
+
|-------|-----|
|
|
111
|
+
| PIX QR Code returns Base64, NOT URL | `$"data:image/png;base64,{response.EncodedImage}"` |
|
|
112
|
+
| CPF required even in sandbox | Always include `cpfCnpj` in CreateCustomer |
|
|
113
|
+
| Missing `User-Agent` header | Add to HttpClient defaults |
|
|
114
|
+
| Date format must be `yyyy-MM-dd` | `DateTime.Today.AddDays(1).ToString("yyyy-MM-dd")` |
|
|
115
|
+
|
|
116
|
+
## Checklist
|
|
117
|
+
|
|
118
|
+
- [ ] API Key configured (not hardcoded)
|
|
119
|
+
- [ ] HttpClient with retry policy (Polly)
|
|
120
|
+
- [ ] Headers: `access_token` + `User-Agent`
|
|
121
|
+
- [ ] CPF/CNPJ always included for customers
|
|
122
|
+
- [ ] PIX QR Code → data URI conversion
|
|
123
|
+
- [ ] Dates in `yyyy-MM-dd` format
|
|
124
|
+
- [ ] Webhook endpoint + signature validation
|
|
125
|
+
- [ ] ExternalReference for reconciliation
|
|
126
|
+
- [ ] Tests with sandbox
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
*MORPH-SPEC by Polymorphism Tech*
|