Skip to main content

Integration Guide

Guida pratica per integrare il billing-service con gli altri componenti del sistema.

πŸ”— Integrazione Backend​

Verificare Abbonamento da Altri Servizi​

Il modo piΓΉ semplice per verificare se un utente ha un abbonamento attivo:

import httpx

async def check_user_subscription(user_id: int) -> bool:
"""Check if user has active subscription."""
try:
response = await httpx.AsyncClient().get(
f"http://billing:8088/api/subscriptions/check/{user_id}"
)
data = response.json()
return data.get("is_subscribed", False)
except Exception:
# Fallback: assume not subscribed if billing is down
return False

Consumare Eventi Redis​

Per reagire ai cambi di stato in tempo reale:

import redis
import json

def consume_billing_events():
"""Consume subscription events from Redis stream."""
r = redis.Redis.from_url("redis://redis:6379", decode_responses=True)

# Create consumer group if not exists
try:
r.xgroup_create("billing:events", "my-service-consumers", id='0', mkstream=True)
except redis.ResponseError as e:
if "BUSYGROUP" not in str(e):
raise

while True:
entries = r.xreadgroup(
"my-service-consumers",
"consumer-1",
{"billing:events": '>'},
count=10,
block=5000
)

for stream, messages in entries:
for msg_id, data in messages:
event = json.loads(data['event'])
handle_subscription_event(event)
r.xack("billing:events", "my-service-consumers", msg_id)

def handle_subscription_event(event: dict):
"""Handle subscription state change."""
user_id = int(event['userId'])
new_status = event['newStatus']

if new_status == 'EXPIRED':
disable_premium_features(user_id)
elif new_status == 'ACTIVE':
enable_premium_features(user_id)

πŸ“± Integrazione Mobile​

iOS - StoreKit 2​

Quando crei un acquisto, passa lo user_id come appAccountToken:

// VislaGPS/StoreManager.swift
import StoreKit

func purchase(product: Product, userId: Int) async throws {
// Pass user_id as appAccountToken (UUID format required)
let uuid = UUID(uuidString: String(format: "%08x-0000-0000-0000-000000000000", userId))!

let result = try await product.purchase(options: [
.appAccountToken(uuid)
])

// Handle result...
}

Android - Google Play Billing​

Passa l'ID utente come obfuscatedAccountId:

// SubscriptionManager.kt
import com.android.billingclient.api.*

fun launchPurchase(activity: Activity, productDetails: ProductDetails, userId: String) {
val flowParams = BillingFlowParams.newBuilder()
.setProductDetailsParamsList(listOf(
BillingFlowParams.ProductDetailsParams.newBuilder()
.setProductDetails(productDetails)
.build()
))
.setObfuscatedAccountId(userId) // Pass user ID
.build()

billingClient.launchBillingFlow(activity, flowParams)
}

πŸ’³ Integrazione Stripe (Web)​

Creare Subscription con Metadata​

Quando crei una subscription via Stripe Checkout:

import stripe

def create_checkout_session(user_id: int, price_id: str):
"""Create Stripe checkout session with user metadata."""
session = stripe.checkout.Session.create(
mode="subscription",
line_items=[{"price": price_id, "quantity": 1}],
success_url="https://app.vislagps.com/success",
cancel_url="https://app.vislagps.com/cancel",
client_reference_id=str(user_id),
subscription_data={
"metadata": {
"user_id": str(user_id) # IMPORTANTE!
}
}
)
return session
Importante

Il campo metadata.user_id Γ¨ essenziale. Senza di esso, il billing-service non puΓ² associare la subscription all'utente.


🍎 Configurazione Apple​

App Store Connect​

  1. Vai su App Store Connect β†’ My Apps β†’ La tua app
  2. App Information β†’ App Store Server Notifications
  3. Imposta:
    • Production URL: https://gateway.vislagps.com/webhooks/apple
    • Sandbox URL: https://gateway-dev.vislagps.com/webhooks/apple
    • Version: 2 (v2 S2S)

Generare Shared Secret​

  1. App Store Connect β†’ Users and Access β†’ Keys
  2. Genera una chiave e salva in secrets/apple_shared_secret

πŸ€– Configurazione Google​

Google Cloud Console​

  1. Vai su Google Cloud Console β†’ Pub/Sub
  2. Crea topic per notifiche
  3. Crea subscription push:
    • Endpoint: https://gateway.vislagps.com/webhooks/google

Google Play Console​

  1. Vai su Google Play Console β†’ API access
  2. Collega il progetto Google Cloud
  3. Imposta Real-time developer notifications:
    • Topic: il topic Pub/Sub creato

Service Account​

  1. Crea service account con ruolo Pub/Sub Subscriber
  2. Esporta JSON e salva in secrets/google_service_account_billing.json

⚑ Configurazione Stripe​

Dashboard Stripe​

  1. Vai su Stripe Dashboard β†’ Developers β†’ Webhooks
  2. Aggiungi endpoint:
    • URL: https://gateway.vislagps.com/webhooks/stripe
    • Eventi:
      • customer.subscription.created
      • customer.subscription.updated
      • customer.subscription.deleted
      • invoice.paid
      • invoice.payment_failed
  3. Copia Signing secret e salva in secrets/stripe_webhook_secret

Test Locale con Stripe CLI​

# Installa Stripe CLI
brew install stripe/stripe-cli/stripe

# Login
stripe login

# Forward webhooks a localhost
stripe listen --forward-to localhost:8088/webhooks/stripe

# In altro terminale, trigger eventi di test
stripe trigger customer.subscription.created

πŸ§ͺ Testing​

Test Health Check​

curl http://localhost:8088/health

Test Subscription Check​

curl "http://localhost:8088/api/subscriptions/check/123"

Test Webhook con Payload Mock​

curl -X POST http://localhost:8088/webhooks/stripe \
-H "Content-Type: application/json" \
-H "Stripe-Signature: t=123,v1=xxx" \
-d '{"id": "evt_test", "type": "customer.subscription.created", ...}'
tip

Il signature sarΓ  invalido senza il vero secret. Per test locali, puoi temporaneamente disabilitare la validazione o usare Stripe CLI.