Validate Square payment arguments - #625
Conversation
Greptile SummaryThis PR adds input validation to the Square payment adapter: amounts are checked to be positive integers, currency codes are normalized and validated, and
Confidence Score: 3/5Not safe to merge without fixing the refund amount_money shape and the silent currency default. The refund path sends Both changed files warrant attention: Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[build called] --> B{SQUARE_ACCESS_TOKEN set?}
B -- No --> C[throw Error]
B -- Yes --> D{command}
D -- create --> E[requirePositiveInteger amount]
E --> F[requireCurrency currency]
F --> G[requireText sourceId]
G --> H[POST /v2/payments]
H --> I[return artifact: square-payment-create]
D -- get --> J[requireText paymentId]
J --> K[GET /v2/payments/:id]
K --> L[return artifact: square-payment-get]
D -- cancel --> M[requireText paymentId]
M --> N[POST /v2/payments/:id/cancel]
N --> O[return artifact: square-payment-cancel]
D -- list --> P[GET /v2/payments]
P --> Q[return artifact: square-payment-list]
D -- refund --> R[requireText paymentId]
R --> S["POST /v2/refunds\namount_money: args.amount ⚠️ bare number"]
S --> T[return artifact: square-payment-refund]
D -- other --> U[throw Unknown command]
style S fill:#ffcccc,stroke:#cc0000
Reviews (1): Last reviewed commit: "Validate Square payment arguments" | Re-trigger Greptile |
| function requireCurrency(value: unknown): string { | ||
| const currency = typeof value === 'string' ? value.trim().toUpperCase() : 'USD'; | ||
| if (!/^[A-Z]{3}$/.test(currency)) throw new Error('currency must be a three-letter ISO code'); | ||
| return currency; | ||
| } |
There was a problem hiding this comment.
requireCurrency silently defaults instead of rejecting
When value is not a string — e.g. undefined, null, or a number — the function substitutes 'USD' and passes the ^[A-Z]{3}$ check without throwing. Every other require* helper in this file throws on an invalid/missing input, so callers expecting a validation error when they forget to supply currency (or pass the wrong type) will silently receive a USD charge instead. The inconsistency also means the function name "require" is misleading; a missing currency is accepted rather than rejected.
| @@ -85,7 +103,7 @@ export default defineTarget<Config>({ | |||
| reason: (config.args?.reason as string) || 'requested_by_customer', | |||
| }), | |||
| }); | |||
There was a problem hiding this comment.
Refund
amount_money sends a bare number instead of a { amount, currency } object
Square's refund endpoint expects amount_money to be an object shaped { amount: number, currency: string }. The current code passes config.args?.amount directly — a bare integer like 1500 — so any partial-refund request will fail with a Square API validation error. When amount is omitted the field becomes undefined, which JSON.stringify drops entirely (triggering a full refund), so the bug surfaces only for partial refunds. Currency is also never threaded through to the refund body.
| const data = await sq('/refunds', { | |
| method: 'POST', | |
| body: JSON.stringify({ | |
| idempotency_key: `sh1pt-${Date.now()}`, | |
| payment_id: id, | |
| ...(config.args?.amount !== undefined && { | |
| amount_money: { | |
| amount: requirePositiveInteger(config.args.amount, 'amount'), | |
| currency: requireCurrency(config.args?.currency), | |
| }, | |
| }), | |
| reason: (config.args?.reason as string) || 'requested_by_customer', | |
| }), | |
| }); |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
10 similar comments
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
Fixes #624.
Changes:
Validation: