#!/usr/bin/env bash # Test integrazione billing (senza emissione fatture Aruba API) set -euo pipefail BASE="${BASE_URL:-http://localhost:3000}" COOKIES=$(mktemp) trap 'rm -f "$COOKIES"' EXIT pass=0 fail=0 ok() { echo "OK $1"; pass=$((pass+1)); } ko() { echo "FAIL $1"; fail=$((fail+1)); } login() { curl -sf -c "$COOKIES" "$BASE/login" -o /tmp/login.html T=$(grep -oP 'name="authenticity_token" value="\K[^"]+' /tmp/login.html | head -1) curl -sf -c "$COOKIES" -b "$COOKIES" -X POST "$BASE/login" \ -d "authenticity_token=$T" \ -d "email=coach@matchlivetv.test" \ -d "password=password123" -o /dev/null } login CLUB_ID=$(docker compose -f "$(dirname "$0")/../infra/docker-compose.yml" exec -T rails bundle exec rails runner "puts Club.first.id" 2>/dev/null | tail -1) # Health curl -sf "$BASE/up" >/dev/null && ok "/up" || ko "/up" # Billing page BODY=$(curl -sf -b "$COOKIES" "$BASE/clubs/$CLUB_ID/billing") echo "$BODY" | grep -q "Pagamenti effettuati" && ok "billing: sezione pagamenti" || ko "billing: sezione pagamenti" echo "$BODY" | grep -q ">Fatture/dev/null 2>&1 CODE=$(curl -s -o /dev/null -w "%{http_code}" -L -b "$COOKIES" "$BASE/clubs/$CLUB_ID/checkout?plan=premium_light") [[ "$CODE" == "200" ]] && ok "checkout redirect senza dati fiscali" || ko "checkout senza dati fiscali ($CODE)" # Record payment via runner docker compose -f "$(dirname "$0")/../infra/docker-compose.yml" exec -T rails bundle exec rails runner " require 'ostruct' club = Club.first inv = OpenStruct.new( id: 'in_integration_test', subscription: club.subscription&.stripe_subscription_id, metadata: { 'club_id' => club.id }, amount_paid: 4000, currency: 'eur', status: 'paid', description: 'Test', payment_intent: 'pi_t', charge: 'ch_t', invoice_pdf: nil, hosted_invoice_url: 'https://stripe.com/test', status_transitions: OpenStruct.new(paid_at: Time.current.to_i), lines: OpenStruct.new(data: [OpenStruct.new(description: 'Premium Light')]), subscription_details: nil ) Billing::Stripe::RecordPayment.call(stripe_invoice: inv, club: club) puts Billing::Payment.last.stripe_invoice_id " >/dev/null 2>&1 && ok "RecordPayment runner" || ko "RecordPayment runner" BODY2=$(curl -sf -b "$COOKIES" "$BASE/clubs/$CLUB_ID/billing") echo "$BODY2" | grep -q "in_integration_test\|Premium Light\|40,00" && ok "pagamento visibile in billing" || ko "pagamento visibile in billing" # Webhook invoice.paid (mock event structure) docker compose -f "$(dirname "$0")/../infra/docker-compose.yml" exec -T rails bundle exec rails runner " require 'ostruct' club = Club.first event = OpenStruct.new( type: 'invoice.paid', data: OpenStruct.new(object: OpenStruct.new( id: \"in_webhook_test_#{Time.now.to_i}\", subscription: club.subscription&.stripe_subscription_id, metadata: { 'club_id' => club.id }, amount_paid: 5000, currency: 'eur', status: 'paid', description: 'Webhook test', payment_intent: 'pi_w', charge: 'ch_w', invoice_pdf: nil, hosted_invoice_url: nil, status_transitions: OpenStruct.new(paid_at: Time.current.to_i), lines: OpenStruct.new(data: []), subscription_details: nil )) ) Billing::Stripe::WebhookHandler.call(event) " >/dev/null 2>&1 && ok "WebhookHandler invoice.paid" || ko "WebhookHandler invoice.paid" # Draft invoice (no PDF) - admin-side model only docker compose -f "$(dirname "$0")/../infra/docker-compose.yml" exec -T rails bundle exec rails runner " club = Club.first club.billing_invoices.find_or_create_by!(number: 'TEST/2026') do |i| i.issued_on = Date.current i.amount_cents = 4000 i.status = 'draft' end " >/dev/null 2>&1 && ok "fattura draft creata" || ko "fattura draft creata" BODY3=$(curl -sf -b "$COOKIES" "$BASE/clubs/$CLUB_ID/billing") echo "$BODY3" | grep -q "TEST/2026" && ok "fattura draft in elenco" || ko "fattura draft in elenco" echo "" echo "Risultato: $pass OK, $fail FAIL" [[ "$fail" -eq 0 ]]