You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
| List Payment Links |`GET`|`/api/v1/billing/payment-links`| Admin (X-Admin-Secret) |
120
+
| Deactivate Payment Link |`POST`|`/api/v1/billing/payment-links/{id}/deactivate`| Admin (X-Admin-Secret) |
121
+
122
+
Implementation: `src/api/v1/billing/admin.py`
95
123
96
124
### Key Differences from Commerce Charges
97
125
@@ -132,14 +160,86 @@ No schema changes required — the `credits_ledger` table already supports both
132
160
133
161
---
134
162
135
-
## 8. Testing Checklist
163
+
## 8. User Identification in Payment Flow
164
+
165
+
The `metadata` field on the payment link is used to pass the user identifier through the Coinbase payment flow. Coinbase treats metadata as an opaque key-value store and returns it verbatim in webhook payloads.
The authenticated user's `cognito_user_id` is **automatically injected** into `metadata.user_id` server-side. The caller cannot override this — it is set from the JWT-authenticated session.
171
+
172
+
```json
173
+
// Sent to Coinbase API:
174
+
{
175
+
"amount": "10.00",
176
+
"currency": "USDC",
177
+
"metadata": {
178
+
"user_id": "<cognito_user_id>"
179
+
}
180
+
}
181
+
```
182
+
183
+
2.**Webhook** (`POST /api/v1/webhooks/coinbase`):
184
+
Coinbase sends the `metadata` back in the event payload. The webhook handler reads `metadata.user_id` to look up the user and credit their account.
185
+
186
+
```json
187
+
// Received from Coinbase:
188
+
{
189
+
"id": "69163c762331ed43dc64a6ef",
190
+
"eventType": "payment_link.payment.success",
191
+
"amount": "10.00",
192
+
"currency": "USDC",
193
+
"metadata": {
194
+
"user_id": "<cognito_user_id>"
195
+
},
196
+
...
197
+
}
198
+
```
199
+
200
+
3.**Credit**: The webhook service looks up the user by `cognito_user_id`, validates the amount, and creates a purchase ledger entry.
-[ ] Verify sandbox webhook events are received and processed correctly
136
235
137
236
### Pre-deployment
138
237
-[ ] Verify JWT signing works with test CDP key
139
-
-[ ] Create a test payment link via admin endpoint
140
-
-[ ] Verify webhook signature verification with test payload
238
+
-[ ] Create a test payment link via `POST /api/v1/billing/coinbase/payment-links`
239
+
-[ ] Verify webhook signature verification with test payload (both formats)
141
240
-[ ] Test idempotency (same webhook delivered twice)
142
241
-[ ] Test expired/failed webhook handling
242
+
-[ ] Verify legacy Commerce webhooks still work during transition
143
243
144
244
### Post-deployment
145
245
-[ ] Create a real payment link and complete payment
@@ -153,38 +253,58 @@ Coinbase provides a [Postman collection](https://docs.cdp.coinbase.com/coinbase-
153
253
154
254
---
155
255
156
-
## 9. Rollback Plan
256
+
## 11. Rollback Plan
157
257
158
258
If issues are discovered after deployment:
159
259
160
-
1. The webhook endpoint only accepts`X-Hook0-Signature`— if you need to revert, restore the legacy `verify_legacy_commerce_signature` function from git history
161
-
2. CDP API key credentials can coexist with Commerce API keys during transition
162
-
3.The`COINBASE_COMMERCE_WEBHOOK_SECRET`config was removed from code but the env var can remain set harmlessly
260
+
1. The webhook endpoint supports both`X-Hook0-Signature`and `X-CC-Webhook-Signature` — legacy Commerce continues to work without code changes
261
+
2. CDP API key credentials coexist with Commerce API keys during transition
262
+
3.Both`COINBASE_COMMERCE_WEBHOOK_SECRET`and `COINBASE_PAYMENT_LINK_WEBHOOK_SECRET`can be set simultaneously
163
263
164
264
---
165
265
166
-
## 10. IP Allowlisting
266
+
## 12. Post-Migration Cleanup (after transition)
267
+
268
+
Once all Commerce charges have settled and new system is confirmed working:
269
+
270
+
-[ ] Remove `COINBASE_COMMERCE_WEBHOOK_SECRET` from config
271
+
-[ ] Remove `_detect_webhook_format()` and `verify_legacy_commerce_signature()` from webhook handler
272
+
-[ ] Remove `_handle_legacy_commerce_webhook()` from webhook handler
273
+
-[ ] Remove legacy event types and `handle_charge_confirmed()` from webhook service
274
+
-[ ] Update webhook endpoint to only accept `X-Hook0-Signature`
275
+
276
+
---
277
+
278
+
## 13. IP Allowlisting
167
279
168
280
-[ ] If using CDP API key IP allowlisting, ensure all API server IPs are added
169
281
-[ ] If behind a load balancer, verify the outbound IP (NAT gateway) is allowlisted
170
282
171
283
---
172
284
173
-
## 11. Monitoring & Alerting
285
+
## 14. Monitoring & Alerting
174
286
175
287
Ensure alerts are configured for these log event types:
0 commit comments