Skip to content

Commit 7f71cb9

Browse files
Deploy node-storm.com website (removed large video file)
1 parent b7e229a commit 7f71cb9

15 files changed

+545
-26
lines changed

BACKLOG/.DS_Store

6 KB
Binary file not shown.

agents/.dockerignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.git
2+
__pycache__/
3+
*.mov
4+
*.dmg
5+
.vscode
6+
.env

agents/Dockerfile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ WORKDIR /app
99
# Copy the requirements file and install dependencies first
1010
COPY requirements.txt .
1111
RUN apt-get update && apt-get install -y \
12+
build-essential \
13+
gcc \
1214
python3-dev \
1315
libasound2-dev \
1416
libportaudio2 \
1517
libportaudiocpp0 \
18+
portaudio19-dev \
1619
ffmpeg \
1720
libavdevice-dev \
1821
libavfilter-dev \
@@ -24,8 +27,8 @@ RUN apt-get update && apt-get install -y \
2427

2528
RUN pip install --no-cache-dir -r requirements.txt
2629

27-
# Debug with separate test step (temporarily disabled)
28-
# RUN python3 -c "import pygame; import pyaudio"
30+
# Debug with separate test step
31+
RUN python3 -c "import pygame; import pyaudio"
2932

3033
# Now, copy the application code into a subdirectory
3134
COPY core_intelligence ./core_intelligence
Binary file not shown.
Binary file not shown.
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Payment API Server
4+
Backend API to handle payment intent creation for the payment portal
5+
"""
6+
7+
import os
8+
import json
9+
import asyncio
10+
from fastapi import FastAPI, HTTPException, Request
11+
from fastapi.middleware.cors import CORSMiddleware
12+
from fastapi.staticfiles import StaticFiles
13+
from pydantic import BaseModel
14+
from typing import Dict, Any, Optional
15+
import uvicorn
16+
from dotenv import load_dotenv
17+
18+
# Import our universal payment processor
19+
from universal_payment_processor import (
20+
UniversalPaymentProcessor,
21+
PaymentRequest,
22+
ServiceType,
23+
payment_processor
24+
)
25+
26+
# Load environment variables from root config.env
27+
load_dotenv('/Users/joewales/NODE_OUT_Master/config.env')
28+
29+
app = FastAPI(title="NODE OUT Payment API", version="1.0.0")
30+
31+
# Add CORS middleware
32+
app.add_middleware(
33+
CORSMiddleware,
34+
allow_origins=["*"], # In production, specify your domain
35+
allow_credentials=True,
36+
allow_methods=["*"],
37+
allow_headers=["*"],
38+
)
39+
40+
# Serve static files (payment portal HTML)
41+
app.mount("/static", StaticFiles(directory="."), name="static")
42+
43+
class PaymentIntentRequest(BaseModel):
44+
service_type: str
45+
service_name: str
46+
amount: float
47+
currency: str = "usd"
48+
customer_email: str = ""
49+
description: str = ""
50+
metadata: Dict[str, Any] = {}
51+
52+
class PaymentIntentResponse(BaseModel):
53+
client_secret: str
54+
payment_id: str
55+
amount: float
56+
currency: str
57+
status: str
58+
59+
@app.get("/")
60+
async def root():
61+
return {"message": "NODE OUT Payment API", "status": "operational"}
62+
63+
@app.get("/health")
64+
async def health_check():
65+
return {"status": "healthy", "service": "payment_api"}
66+
67+
@app.post("/api/create-payment-intent", response_model=PaymentIntentResponse)
68+
async def create_payment_intent(request: PaymentIntentRequest):
69+
"""
70+
Create a Stripe payment intent for the frontend
71+
"""
72+
try:
73+
# Map service type string to enum
74+
service_type_map = {
75+
'storm_response': ServiceType.STORM_RESPONSE,
76+
'real_estate_content': ServiceType.REAL_ESTATE_CONTENT,
77+
'quote_generation': ServiceType.QUOTE_GENERATION,
78+
'seo_services': ServiceType.SEO_SERVICES,
79+
'ue5_visualization': ServiceType.UE5_VISUALIZATION,
80+
'market_intelligence': ServiceType.MARKET_INTELLIGENCE,
81+
'custom_service': ServiceType.CUSTOM_SERVICE
82+
}
83+
84+
service_type = service_type_map.get(request.service_type, ServiceType.CUSTOM_SERVICE)
85+
86+
# Create payment request
87+
payment_request = PaymentRequest(
88+
service_type=service_type,
89+
service_name=request.service_name,
90+
amount=request.amount,
91+
currency=request.currency,
92+
customer_email=request.customer_email,
93+
description=request.description,
94+
metadata=request.metadata,
95+
agent_id="payment_api"
96+
)
97+
98+
# Process payment through universal processor
99+
result = await payment_processor.create_payment(payment_request)
100+
101+
if result.status.value == "failed":
102+
raise HTTPException(
103+
status_code=400,
104+
detail=f"Payment creation failed: {result.error_message}"
105+
)
106+
107+
return PaymentIntentResponse(
108+
client_secret=result.client_secret,
109+
payment_id=result.payment_id,
110+
amount=result.amount,
111+
currency=result.currency,
112+
status=result.status.value
113+
)
114+
115+
except Exception as e:
116+
print(f"❌ Payment intent creation failed: {str(e)}")
117+
raise HTTPException(status_code=500, detail=str(e))
118+
119+
@app.get("/api/payment-status/{payment_id}")
120+
async def get_payment_status(payment_id: str):
121+
"""
122+
Check the status of a payment
123+
"""
124+
try:
125+
status = await payment_processor.check_payment_status(payment_id)
126+
return {"payment_id": payment_id, "status": status.value}
127+
except Exception as e:
128+
raise HTTPException(status_code=404, detail="Payment not found")
129+
130+
@app.get("/api/revenue-stats")
131+
async def get_revenue_stats(service_type: Optional[str] = None):
132+
"""
133+
Get revenue statistics
134+
"""
135+
try:
136+
service_filter = None
137+
if service_type:
138+
service_type_map = {
139+
'storm_response': ServiceType.STORM_RESPONSE,
140+
'real_estate_content': ServiceType.REAL_ESTATE_CONTENT,
141+
'quote_generation': ServiceType.QUOTE_GENERATION,
142+
'seo_services': ServiceType.SEO_SERVICES,
143+
'ue5_visualization': ServiceType.UE5_VISUALIZATION,
144+
'market_intelligence': ServiceType.MARKET_INTELLIGENCE,
145+
'custom_service': ServiceType.CUSTOM_SERVICE
146+
}
147+
service_filter = service_type_map.get(service_type)
148+
149+
stats = payment_processor.get_revenue_stats(service_filter)
150+
return stats
151+
except Exception as e:
152+
raise HTTPException(status_code=500, detail=str(e))
153+
154+
@app.get("/payment-portal")
155+
async def payment_portal():
156+
"""
157+
Serve the payment portal HTML
158+
"""
159+
with open("payment_portal_glassmorphic.html", "r") as f:
160+
content = f.read()
161+
return content
162+
163+
if __name__ == "__main__":
164+
print("🚀 Starting NODE OUT Payment API Server...")
165+
print("💰 Payment processing ready!")
166+
print("📱 Payment portal: http://localhost:8080/payment-portal")
167+
print("📊 Revenue stats: http://localhost:8080/api/revenue-stats")
168+
169+
uvicorn.run(
170+
app,
171+
host="0.0.0.0",
172+
port=8080,
173+
reload=True
174+
)

agents/business_operations/payment_portal_glassmorphic.html

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -544,35 +544,71 @@ <h3>🎉 Payment Successful!</h3>
544544

545545
let elements;
546546
let paymentElement;
547+
let clientSecret;
547548

548-
// Get URL parameters
549+
// Get service data from URL parameters or use defaults
549550
const urlParams = new URLSearchParams(window.location.search);
550-
const clientSecret = urlParams.get('payment_intent');
551-
const quoteId = urlParams.get('quote_id');
551+
const serviceData = {
552+
service_type: urlParams.get('service') || 'storm_response',
553+
service_name: urlParams.get('name') || 'Storm Response Service',
554+
amount: parseFloat(urlParams.get('amount')) || 299.00,
555+
customer_email: urlParams.get('email') || '',
556+
description: urlParams.get('description') || 'Professional storm response and repair service',
557+
quote_id: urlParams.get('quote_id') || 'QT-' + Date.now()
558+
};
552559

553-
// Enhanced mock quote data with more details
560+
// Mock quote data for display (will be replaced by real service data)
554561
const mockQuoteData = {
555-
quote_id: quoteId || 'Q-STORM-2025',
556-
customer_name: 'Sarah Johnson',
557-
customer_address: '1247 Oak Street, Birmingham, AL 35203',
558-
damage_type: 'Severe Roof Damage',
559-
urgency_level: 'Emergency Service',
560-
amount: 9880.38,
561-
payment_type: 'Emergency Payment',
562-
timeline: 'Same day emergency service'
562+
quote_id: serviceData.quote_id,
563+
customer_name: 'Customer',
564+
customer_address: 'Service Location',
565+
damage_type: serviceData.service_name,
566+
urgency_level: 'Standard',
567+
amount: serviceData.amount,
568+
payment_type: 'Service Payment',
569+
timeline: 'Upon Payment'
563570
};
564571

565572
// Initialize payment form with glassmorphic styling
566573
async function initializePayment() {
567-
if (!clientSecret) {
568-
showError('Invalid payment link. Please contact our support team at (205) 307-9153');
569-
return;
574+
try {
575+
// Create payment intent via backend API
576+
const response = await fetch('/api/create-payment-intent', {
577+
method: 'POST',
578+
headers: {
579+
'Content-Type': 'application/json',
580+
},
581+
body: JSON.stringify({
582+
service_type: serviceData.service_type,
583+
service_name: serviceData.service_name,
584+
amount: serviceData.amount,
585+
currency: 'usd',
586+
customer_email: serviceData.customer_email,
587+
description: serviceData.description,
588+
metadata: {
589+
quote_id: serviceData.quote_id
590+
}
591+
})
592+
});
593+
594+
if (!response.ok) {
595+
throw new Error('Failed to create payment intent');
596+
}
597+
598+
const data = await response.json();
599+
clientSecret = data.client_secret;
600+
601+
if (!clientSecret) {
602+
throw new Error('No client secret received');
603+
}
604+
605+
} catch (error) {
606+
console.error('Payment initialization failed:', error);
607+
// Fallback for testing - remove in production
608+
console.log('Using test mode - payment will not process');
609+
clientSecret = 'pi_test_fallback_secret';
570610
}
571611

572-
// Update UI with quote data
573-
updateQuoteDisplay();
574-
575-
// Create Stripe elements with custom styling
576612
elements = stripe.elements({
577613
clientSecret: clientSecret,
578614
appearance: {

0 commit comments

Comments
 (0)