quantumflow-sdk 0.1.0__py3-none-any.whl

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.
Files changed (60) hide show
  1. api/__init__.py +1 -0
  2. api/auth.py +208 -0
  3. api/main.py +403 -0
  4. api/models.py +137 -0
  5. api/routes/__init__.py +1 -0
  6. api/routes/auth_routes.py +234 -0
  7. api/routes/teleport_routes.py +415 -0
  8. db/__init__.py +15 -0
  9. db/crud.py +319 -0
  10. db/database.py +93 -0
  11. db/models.py +197 -0
  12. quantumflow/__init__.py +47 -0
  13. quantumflow/algorithms/__init__.py +48 -0
  14. quantumflow/algorithms/compression/__init__.py +7 -0
  15. quantumflow/algorithms/compression/amplitude_amplification.py +189 -0
  16. quantumflow/algorithms/compression/qft_compression.py +133 -0
  17. quantumflow/algorithms/compression/token_compression.py +261 -0
  18. quantumflow/algorithms/cryptography/__init__.py +6 -0
  19. quantumflow/algorithms/cryptography/qkd.py +205 -0
  20. quantumflow/algorithms/cryptography/qrng.py +231 -0
  21. quantumflow/algorithms/machine_learning/__init__.py +7 -0
  22. quantumflow/algorithms/machine_learning/qnn.py +276 -0
  23. quantumflow/algorithms/machine_learning/qsvm.py +249 -0
  24. quantumflow/algorithms/machine_learning/vqe.py +229 -0
  25. quantumflow/algorithms/optimization/__init__.py +7 -0
  26. quantumflow/algorithms/optimization/grover.py +223 -0
  27. quantumflow/algorithms/optimization/qaoa.py +251 -0
  28. quantumflow/algorithms/optimization/quantum_annealing.py +237 -0
  29. quantumflow/algorithms/utility/__init__.py +6 -0
  30. quantumflow/algorithms/utility/circuit_optimizer.py +194 -0
  31. quantumflow/algorithms/utility/error_correction.py +330 -0
  32. quantumflow/api/__init__.py +1 -0
  33. quantumflow/api/routes/__init__.py +4 -0
  34. quantumflow/api/routes/billing_routes.py +520 -0
  35. quantumflow/backends/__init__.py +33 -0
  36. quantumflow/backends/base_backend.py +184 -0
  37. quantumflow/backends/braket_backend.py +345 -0
  38. quantumflow/backends/ibm_backend.py +112 -0
  39. quantumflow/backends/simulator_backend.py +86 -0
  40. quantumflow/billing/__init__.py +25 -0
  41. quantumflow/billing/models.py +126 -0
  42. quantumflow/billing/stripe_service.py +619 -0
  43. quantumflow/core/__init__.py +12 -0
  44. quantumflow/core/entanglement.py +164 -0
  45. quantumflow/core/memory.py +147 -0
  46. quantumflow/core/quantum_backprop.py +394 -0
  47. quantumflow/core/quantum_compressor.py +309 -0
  48. quantumflow/core/teleportation.py +386 -0
  49. quantumflow/integrations/__init__.py +107 -0
  50. quantumflow/integrations/autogen_tools.py +501 -0
  51. quantumflow/integrations/crewai_agents.py +425 -0
  52. quantumflow/integrations/crewai_tools.py +407 -0
  53. quantumflow/integrations/langchain_memory.py +385 -0
  54. quantumflow/integrations/langchain_tools.py +366 -0
  55. quantumflow/integrations/mcp_server.py +575 -0
  56. quantumflow_sdk-0.1.0.dist-info/METADATA +190 -0
  57. quantumflow_sdk-0.1.0.dist-info/RECORD +60 -0
  58. quantumflow_sdk-0.1.0.dist-info/WHEEL +5 -0
  59. quantumflow_sdk-0.1.0.dist-info/entry_points.txt +2 -0
  60. quantumflow_sdk-0.1.0.dist-info/top_level.txt +3 -0
@@ -0,0 +1,619 @@
1
+ """
2
+ Stripe Billing Service for QuantumFlow.
3
+
4
+ Handles:
5
+ - Customer management
6
+ - Subscription lifecycle (create, update, cancel)
7
+ - Usage-based billing (metered API calls)
8
+ - Webhook processing
9
+ - Invoice management
10
+ """
11
+
12
+ import os
13
+ from datetime import datetime
14
+ from enum import Enum
15
+ from typing import Optional
16
+ import stripe
17
+
18
+ from quantumflow.billing.models import (
19
+ Customer,
20
+ Subscription,
21
+ Invoice,
22
+ UsageRecord,
23
+ SubscriptionStatus,
24
+ PaymentStatus,
25
+ PriceInfo,
26
+ )
27
+
28
+
29
+ class SubscriptionTier(str, Enum):
30
+ """Available subscription tiers."""
31
+ FREE = "free"
32
+ PRO = "pro"
33
+ ENTERPRISE = "enterprise"
34
+
35
+
36
+ # Tier configuration
37
+ TIER_LIMITS = {
38
+ SubscriptionTier.FREE: {
39
+ "api_calls_monthly": 1_000,
40
+ "max_qubits": 20,
41
+ "backends": ["simulator"],
42
+ "support": "community",
43
+ "rate_limit_per_minute": 10,
44
+ },
45
+ SubscriptionTier.PRO: {
46
+ "api_calls_monthly": 50_000,
47
+ "max_qubits": 100,
48
+ "backends": ["simulator", "ibm", "aws"],
49
+ "support": "email",
50
+ "rate_limit_per_minute": 100,
51
+ },
52
+ SubscriptionTier.ENTERPRISE: {
53
+ "api_calls_monthly": 1_000_000,
54
+ "max_qubits": 156,
55
+ "backends": ["simulator", "ibm", "aws", "dedicated"],
56
+ "support": "24/7",
57
+ "rate_limit_per_minute": 1000,
58
+ },
59
+ }
60
+
61
+ # Stripe product IDs (set in environment)
62
+ STRIPE_PRODUCTS = {
63
+ SubscriptionTier.FREE: os.getenv("STRIPE_PRODUCT_FREE", "prod_TsZuC9LFEZGZ6v"),
64
+ SubscriptionTier.PRO: os.getenv("STRIPE_PRODUCT_PRO", "prod_TsZujvgfFU5BFj"),
65
+ SubscriptionTier.ENTERPRISE: os.getenv("STRIPE_PRODUCT_ENTERPRISE", "prod_TsZudz3o7YX9t0"),
66
+ }
67
+
68
+ # Stripe price IDs (set these in environment or Stripe dashboard)
69
+ TIER_PRICES = {
70
+ SubscriptionTier.FREE: PriceInfo(
71
+ tier="free",
72
+ stripe_price_id=os.getenv("STRIPE_PRICE_FREE", ""), # Will be fetched from product
73
+ stripe_product_id=STRIPE_PRODUCTS[SubscriptionTier.FREE],
74
+ amount=0,
75
+ api_calls_included=1_000,
76
+ overage_price_per_call=0.01,
77
+ ),
78
+ SubscriptionTier.PRO: PriceInfo(
79
+ tier="pro",
80
+ stripe_price_id=os.getenv("STRIPE_PRICE_PRO", ""), # Will be fetched from product
81
+ stripe_product_id=STRIPE_PRODUCTS[SubscriptionTier.PRO],
82
+ amount=4900, # $49/month
83
+ api_calls_included=50_000,
84
+ overage_price_per_call=0.005,
85
+ ),
86
+ SubscriptionTier.ENTERPRISE: PriceInfo(
87
+ tier="enterprise",
88
+ stripe_price_id=os.getenv("STRIPE_PRICE_ENTERPRISE", ""), # Will be fetched from product
89
+ stripe_product_id=STRIPE_PRODUCTS[SubscriptionTier.ENTERPRISE],
90
+ amount=19900, # $199/month
91
+ api_calls_included=1_000_000,
92
+ overage_price_per_call=0.001, # $0.00001 per call
93
+ ),
94
+ }
95
+
96
+
97
+ class StripeService:
98
+ """Service for managing Stripe billing operations."""
99
+
100
+ def __init__(self, api_key: Optional[str] = None):
101
+ """
102
+ Initialize Stripe service.
103
+
104
+ Args:
105
+ api_key: Stripe secret key. Defaults to STRIPE_SECRET_KEY env var.
106
+ """
107
+ self.api_key = api_key or os.getenv("STRIPE_SECRET_KEY")
108
+ if not self.api_key:
109
+ raise ValueError("Stripe API key not configured. Set STRIPE_SECRET_KEY.")
110
+
111
+ stripe.api_key = self.api_key
112
+ self.webhook_secret = os.getenv("STRIPE_WEBHOOK_SECRET")
113
+ self._price_cache = {} # Cache for price IDs
114
+
115
+ def get_price_id_for_tier(self, tier: SubscriptionTier) -> str:
116
+ """Get the Stripe price ID for a tier, fetching from product if needed."""
117
+ price_info = TIER_PRICES[tier]
118
+
119
+ # If price ID is set in env, use it
120
+ if price_info.stripe_price_id:
121
+ return price_info.stripe_price_id
122
+
123
+ # Check cache
124
+ if tier in self._price_cache:
125
+ return self._price_cache[tier]
126
+
127
+ # Fetch from product
128
+ product_id = price_info.stripe_product_id
129
+ if not product_id:
130
+ raise ValueError(f"No product ID configured for tier {tier}")
131
+
132
+ # Get the default price for this product
133
+ prices = stripe.Price.list(product=product_id, active=True, limit=1)
134
+ if not prices.data:
135
+ raise ValueError(f"No active price found for product {product_id}")
136
+
137
+ price_id = prices.data[0].id
138
+ self._price_cache[tier] = price_id
139
+ return price_id
140
+
141
+ # ==================== Customer Management ====================
142
+
143
+ def create_customer(
144
+ self,
145
+ email: str,
146
+ name: Optional[str] = None,
147
+ user_id: Optional[str] = None,
148
+ metadata: Optional[dict] = None,
149
+ ) -> Customer:
150
+ """Create a new Stripe customer."""
151
+ customer_data = {
152
+ "email": email,
153
+ "metadata": metadata or {},
154
+ }
155
+ if name:
156
+ customer_data["name"] = name
157
+ if user_id:
158
+ customer_data["metadata"]["user_id"] = user_id
159
+
160
+ stripe_customer = stripe.Customer.create(**customer_data)
161
+
162
+ return Customer(
163
+ id=user_id or stripe_customer.id,
164
+ email=email,
165
+ name=name,
166
+ stripe_customer_id=stripe_customer.id,
167
+ metadata=stripe_customer.metadata,
168
+ )
169
+
170
+ def get_customer(self, stripe_customer_id: str) -> Optional[Customer]:
171
+ """Retrieve a customer from Stripe."""
172
+ try:
173
+ stripe_customer = stripe.Customer.retrieve(stripe_customer_id)
174
+ return Customer(
175
+ id=stripe_customer.metadata.get("user_id", stripe_customer.id),
176
+ email=stripe_customer.email,
177
+ name=stripe_customer.name,
178
+ stripe_customer_id=stripe_customer.id,
179
+ default_payment_method=stripe_customer.invoice_settings.default_payment_method,
180
+ metadata=dict(stripe_customer.metadata),
181
+ )
182
+ except stripe.error.StripeError:
183
+ return None
184
+
185
+ def update_customer(
186
+ self,
187
+ stripe_customer_id: str,
188
+ email: Optional[str] = None,
189
+ name: Optional[str] = None,
190
+ metadata: Optional[dict] = None,
191
+ ) -> Customer:
192
+ """Update customer details."""
193
+ update_data = {}
194
+ if email:
195
+ update_data["email"] = email
196
+ if name:
197
+ update_data["name"] = name
198
+ if metadata:
199
+ update_data["metadata"] = metadata
200
+
201
+ stripe_customer = stripe.Customer.modify(stripe_customer_id, **update_data)
202
+
203
+ return Customer(
204
+ id=stripe_customer.metadata.get("user_id", stripe_customer.id),
205
+ email=stripe_customer.email,
206
+ name=stripe_customer.name,
207
+ stripe_customer_id=stripe_customer.id,
208
+ metadata=dict(stripe_customer.metadata),
209
+ )
210
+
211
+ # ==================== Subscription Management ====================
212
+
213
+ def create_subscription(
214
+ self,
215
+ customer_id: str,
216
+ tier: SubscriptionTier,
217
+ trial_days: int = 0,
218
+ payment_method_id: Optional[str] = None,
219
+ ) -> Subscription:
220
+ """
221
+ Create a new subscription for a customer.
222
+
223
+ Args:
224
+ customer_id: Stripe customer ID
225
+ tier: Subscription tier
226
+ trial_days: Number of trial days (0 for no trial)
227
+ payment_method_id: Payment method to use
228
+ """
229
+ price_id = self.get_price_id_for_tier(tier)
230
+
231
+ subscription_data = {
232
+ "customer": customer_id,
233
+ "items": [{"price": price_id}],
234
+ "metadata": {"tier": tier.value},
235
+ }
236
+
237
+ if trial_days > 0:
238
+ subscription_data["trial_period_days"] = trial_days
239
+
240
+ if payment_method_id:
241
+ subscription_data["default_payment_method"] = payment_method_id
242
+
243
+ # For free tier, skip payment requirement
244
+ if tier == SubscriptionTier.FREE:
245
+ subscription_data["payment_behavior"] = "default_incomplete"
246
+
247
+ stripe_sub = stripe.Subscription.create(**subscription_data)
248
+
249
+ return self._stripe_sub_to_model(stripe_sub)
250
+
251
+ def get_subscription(self, stripe_subscription_id: str) -> Optional[Subscription]:
252
+ """Retrieve subscription details."""
253
+ try:
254
+ stripe_sub = stripe.Subscription.retrieve(stripe_subscription_id)
255
+ return self._stripe_sub_to_model(stripe_sub)
256
+ except stripe.error.StripeError:
257
+ return None
258
+
259
+ def update_subscription_tier(
260
+ self,
261
+ stripe_subscription_id: str,
262
+ new_tier: SubscriptionTier,
263
+ prorate: bool = True,
264
+ ) -> Subscription:
265
+ """
266
+ Upgrade or downgrade a subscription.
267
+
268
+ Args:
269
+ stripe_subscription_id: Current subscription ID
270
+ new_tier: New tier to switch to
271
+ prorate: Whether to prorate the change
272
+ """
273
+ stripe_sub = stripe.Subscription.retrieve(stripe_subscription_id)
274
+ new_price_id = self.get_price_id_for_tier(new_tier)
275
+
276
+ # Update the subscription item
277
+ stripe.Subscription.modify(
278
+ stripe_subscription_id,
279
+ items=[{
280
+ "id": stripe_sub["items"]["data"][0].id,
281
+ "price": new_price_id,
282
+ }],
283
+ proration_behavior="create_prorations" if prorate else "none",
284
+ metadata={"tier": new_tier.value},
285
+ )
286
+
287
+ updated_sub = stripe.Subscription.retrieve(stripe_subscription_id)
288
+ return self._stripe_sub_to_model(updated_sub)
289
+
290
+ def cancel_subscription(
291
+ self,
292
+ stripe_subscription_id: str,
293
+ at_period_end: bool = True,
294
+ ) -> Subscription:
295
+ """
296
+ Cancel a subscription.
297
+
298
+ Args:
299
+ stripe_subscription_id: Subscription to cancel
300
+ at_period_end: If True, cancel at end of billing period
301
+ """
302
+ if at_period_end:
303
+ stripe_sub = stripe.Subscription.modify(
304
+ stripe_subscription_id,
305
+ cancel_at_period_end=True,
306
+ )
307
+ else:
308
+ stripe_sub = stripe.Subscription.delete(stripe_subscription_id)
309
+
310
+ return self._stripe_sub_to_model(stripe_sub)
311
+
312
+ def reactivate_subscription(self, stripe_subscription_id: str) -> Subscription:
313
+ """Reactivate a subscription scheduled for cancellation."""
314
+ stripe_sub = stripe.Subscription.modify(
315
+ stripe_subscription_id,
316
+ cancel_at_period_end=False,
317
+ )
318
+ return self._stripe_sub_to_model(stripe_sub)
319
+
320
+ # ==================== Usage-Based Billing ====================
321
+
322
+ def report_usage(
323
+ self,
324
+ subscription_item_id: str,
325
+ quantity: int,
326
+ timestamp: Optional[datetime] = None,
327
+ idempotency_key: Optional[str] = None,
328
+ ) -> UsageRecord:
329
+ """
330
+ Report API usage for metered billing.
331
+
332
+ Args:
333
+ subscription_item_id: The subscription item for metered billing
334
+ quantity: Number of API calls to report
335
+ timestamp: When the usage occurred (defaults to now)
336
+ idempotency_key: Prevent duplicate reporting
337
+ """
338
+ usage_data = {
339
+ "quantity": quantity,
340
+ "action": "increment",
341
+ }
342
+
343
+ if timestamp:
344
+ usage_data["timestamp"] = int(timestamp.timestamp())
345
+
346
+ kwargs = {}
347
+ if idempotency_key:
348
+ kwargs["idempotency_key"] = idempotency_key
349
+
350
+ record = stripe.SubscriptionItem.create_usage_record(
351
+ subscription_item_id,
352
+ **usage_data,
353
+ **kwargs,
354
+ )
355
+
356
+ return UsageRecord(
357
+ id=record.id,
358
+ subscription_id=record.subscription_item,
359
+ quantity=record.quantity,
360
+ timestamp=datetime.fromtimestamp(record.timestamp),
361
+ )
362
+
363
+ def get_usage_summary(
364
+ self,
365
+ subscription_item_id: str,
366
+ ) -> dict:
367
+ """Get usage summary for current billing period."""
368
+ records = stripe.SubscriptionItem.list_usage_record_summaries(
369
+ subscription_item_id,
370
+ limit=1,
371
+ )
372
+
373
+ if records.data:
374
+ summary = records.data[0]
375
+ return {
376
+ "total_usage": summary.total_usage,
377
+ "period_start": datetime.fromtimestamp(summary.period.start),
378
+ "period_end": datetime.fromtimestamp(summary.period.end),
379
+ }
380
+
381
+ return {"total_usage": 0, "period_start": None, "period_end": None}
382
+
383
+ # ==================== Payment Methods ====================
384
+
385
+ def create_setup_intent(self, customer_id: str) -> dict:
386
+ """Create a SetupIntent for adding a payment method."""
387
+ intent = stripe.SetupIntent.create(
388
+ customer=customer_id,
389
+ payment_method_types=["card"],
390
+ )
391
+ return {
392
+ "client_secret": intent.client_secret,
393
+ "setup_intent_id": intent.id,
394
+ }
395
+
396
+ def attach_payment_method(
397
+ self,
398
+ customer_id: str,
399
+ payment_method_id: str,
400
+ set_default: bool = True,
401
+ ) -> str:
402
+ """Attach a payment method to a customer."""
403
+ stripe.PaymentMethod.attach(payment_method_id, customer=customer_id)
404
+
405
+ if set_default:
406
+ stripe.Customer.modify(
407
+ customer_id,
408
+ invoice_settings={"default_payment_method": payment_method_id},
409
+ )
410
+
411
+ return payment_method_id
412
+
413
+ def list_payment_methods(self, customer_id: str) -> list[dict]:
414
+ """List customer's payment methods."""
415
+ methods = stripe.PaymentMethod.list(customer=customer_id, type="card")
416
+ return [
417
+ {
418
+ "id": pm.id,
419
+ "brand": pm.card.brand,
420
+ "last4": pm.card.last4,
421
+ "exp_month": pm.card.exp_month,
422
+ "exp_year": pm.card.exp_year,
423
+ }
424
+ for pm in methods.data
425
+ ]
426
+
427
+ # ==================== Invoices ====================
428
+
429
+ def list_invoices(
430
+ self,
431
+ customer_id: str,
432
+ limit: int = 10,
433
+ ) -> list[Invoice]:
434
+ """List customer invoices."""
435
+ invoices = stripe.Invoice.list(customer=customer_id, limit=limit)
436
+ return [self._stripe_invoice_to_model(inv) for inv in invoices.data]
437
+
438
+ def get_upcoming_invoice(self, customer_id: str) -> Optional[Invoice]:
439
+ """Get the upcoming invoice for a customer."""
440
+ try:
441
+ invoice = stripe.Invoice.upcoming(customer=customer_id)
442
+ return self._stripe_invoice_to_model(invoice)
443
+ except stripe.error.InvalidRequestError:
444
+ return None
445
+
446
+ # ==================== Webhooks ====================
447
+
448
+ def construct_webhook_event(
449
+ self,
450
+ payload: bytes,
451
+ signature: str,
452
+ ) -> stripe.Event:
453
+ """
454
+ Verify and construct a webhook event.
455
+
456
+ Args:
457
+ payload: Raw request body
458
+ signature: Stripe-Signature header
459
+
460
+ Returns:
461
+ Verified Stripe event
462
+ """
463
+ if not self.webhook_secret:
464
+ raise ValueError("Webhook secret not configured")
465
+
466
+ return stripe.Webhook.construct_event(
467
+ payload,
468
+ signature,
469
+ self.webhook_secret,
470
+ )
471
+
472
+ def handle_webhook_event(self, event: stripe.Event) -> dict:
473
+ """
474
+ Process a webhook event.
475
+
476
+ Returns action to take based on event type.
477
+ """
478
+ event_type = event.type
479
+ data = event.data.object
480
+
481
+ handlers = {
482
+ "customer.subscription.created": self._handle_subscription_created,
483
+ "customer.subscription.updated": self._handle_subscription_updated,
484
+ "customer.subscription.deleted": self._handle_subscription_deleted,
485
+ "invoice.paid": self._handle_invoice_paid,
486
+ "invoice.payment_failed": self._handle_payment_failed,
487
+ "customer.created": self._handle_customer_created,
488
+ }
489
+
490
+ handler = handlers.get(event_type)
491
+ if handler:
492
+ return handler(data)
493
+
494
+ return {"action": "ignored", "event_type": event_type}
495
+
496
+ # ==================== Checkout Sessions ====================
497
+
498
+ def create_checkout_session(
499
+ self,
500
+ customer_id: str,
501
+ tier: SubscriptionTier,
502
+ success_url: str,
503
+ cancel_url: str,
504
+ ) -> dict:
505
+ """Create a Stripe Checkout session for subscription."""
506
+ # Get price ID (fetches from product if not in env)
507
+ price_id = self.get_price_id_for_tier(tier)
508
+
509
+ session = stripe.checkout.Session.create(
510
+ customer=customer_id,
511
+ payment_method_types=["card"],
512
+ line_items=[{
513
+ "price": price_id,
514
+ "quantity": 1,
515
+ }],
516
+ mode="subscription",
517
+ success_url=success_url,
518
+ cancel_url=cancel_url,
519
+ metadata={"tier": tier.value},
520
+ )
521
+
522
+ return {
523
+ "session_id": session.id,
524
+ "url": session.url,
525
+ }
526
+
527
+ def create_billing_portal_session(
528
+ self,
529
+ customer_id: str,
530
+ return_url: str,
531
+ ) -> dict:
532
+ """Create a Stripe Billing Portal session."""
533
+ session = stripe.billing_portal.Session.create(
534
+ customer=customer_id,
535
+ return_url=return_url,
536
+ )
537
+ return {"url": session.url}
538
+
539
+ # ==================== Helper Methods ====================
540
+
541
+ def _stripe_sub_to_model(self, stripe_sub) -> Subscription:
542
+ """Convert Stripe subscription to our model."""
543
+ return Subscription(
544
+ id=stripe_sub.metadata.get("user_id", stripe_sub.id),
545
+ customer_id=stripe_sub.customer,
546
+ stripe_subscription_id=stripe_sub.id,
547
+ tier=stripe_sub.metadata.get("tier", "free"),
548
+ status=SubscriptionStatus(stripe_sub.status),
549
+ current_period_start=datetime.fromtimestamp(stripe_sub.current_period_start),
550
+ current_period_end=datetime.fromtimestamp(stripe_sub.current_period_end),
551
+ cancel_at_period_end=stripe_sub.cancel_at_period_end,
552
+ canceled_at=datetime.fromtimestamp(stripe_sub.canceled_at) if stripe_sub.canceled_at else None,
553
+ trial_end=datetime.fromtimestamp(stripe_sub.trial_end) if stripe_sub.trial_end else None,
554
+ metadata=dict(stripe_sub.metadata),
555
+ )
556
+
557
+ def _stripe_invoice_to_model(self, stripe_inv) -> Invoice:
558
+ """Convert Stripe invoice to our model."""
559
+ return Invoice(
560
+ id=stripe_inv.id,
561
+ customer_id=stripe_inv.customer,
562
+ stripe_invoice_id=stripe_inv.id,
563
+ subscription_id=stripe_inv.subscription,
564
+ amount_due=stripe_inv.amount_due,
565
+ amount_paid=stripe_inv.amount_paid,
566
+ currency=stripe_inv.currency,
567
+ status=PaymentStatus(stripe_inv.status) if stripe_inv.status else PaymentStatus.DRAFT,
568
+ invoice_pdf=stripe_inv.invoice_pdf,
569
+ hosted_invoice_url=stripe_inv.hosted_invoice_url,
570
+ period_start=datetime.fromtimestamp(stripe_inv.period_start) if stripe_inv.period_start else None,
571
+ period_end=datetime.fromtimestamp(stripe_inv.period_end) if stripe_inv.period_end else None,
572
+ )
573
+
574
+ # Webhook handlers
575
+ def _handle_subscription_created(self, data) -> dict:
576
+ return {
577
+ "action": "subscription_created",
578
+ "subscription_id": data.id,
579
+ "customer_id": data.customer,
580
+ "tier": data.metadata.get("tier", "free"),
581
+ }
582
+
583
+ def _handle_subscription_updated(self, data) -> dict:
584
+ return {
585
+ "action": "subscription_updated",
586
+ "subscription_id": data.id,
587
+ "status": data.status,
588
+ "tier": data.metadata.get("tier", "free"),
589
+ }
590
+
591
+ def _handle_subscription_deleted(self, data) -> dict:
592
+ return {
593
+ "action": "subscription_deleted",
594
+ "subscription_id": data.id,
595
+ "customer_id": data.customer,
596
+ }
597
+
598
+ def _handle_invoice_paid(self, data) -> dict:
599
+ return {
600
+ "action": "invoice_paid",
601
+ "invoice_id": data.id,
602
+ "customer_id": data.customer,
603
+ "amount_paid": data.amount_paid,
604
+ }
605
+
606
+ def _handle_payment_failed(self, data) -> dict:
607
+ return {
608
+ "action": "payment_failed",
609
+ "invoice_id": data.id,
610
+ "customer_id": data.customer,
611
+ "attempt_count": data.attempt_count,
612
+ }
613
+
614
+ def _handle_customer_created(self, data) -> dict:
615
+ return {
616
+ "action": "customer_created",
617
+ "customer_id": data.id,
618
+ "email": data.email,
619
+ }
@@ -0,0 +1,12 @@
1
+ """QuantumFlow Core - Quantum computing primitives and algorithms."""
2
+
3
+ from quantumflow.core.quantum_compressor import QuantumCompressor, CompressedResult
4
+ from quantumflow.core.entanglement import Entangler
5
+ from quantumflow.core.memory import QuantumMemory
6
+
7
+ __all__ = [
8
+ "QuantumCompressor",
9
+ "CompressedResult",
10
+ "Entangler",
11
+ "QuantumMemory",
12
+ ]