File size: 16,075 Bytes
4e3c158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
"""
Stripe Integration Setup Script
Comprehensive setup and configuration script for Stripe payment processing integration
"""

from datetime import datetime
import json
import logging
import os
import subprocess
import sys
import time
from typing import Any, Dict, List, Optional
import requests

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    handlers=[logging.FileHandler("stripe_setup.log"), logging.StreamHandler()],
)
logger = logging.getLogger(__name__)


class StripeIntegrationSetup:
    """Comprehensive setup class for Stripe integration"""

    def __init__(self):
        self.base_dir = os.path.dirname(os.path.abspath(__file__))
        self.integrations_dir = os.path.join(self.base_dir, "integrations")
        self.python_api_dir = os.path.join(self.base_dir, "python-api-service")
        self.env_file = os.path.join(self.base_dir, ".env")
        self.setup_results = {
            "timestamp": datetime.now().isoformat(),
            "steps": [],
            "success": True,
            "environment_configured": False,
        }

    def log_step(self, step_name: str, success: bool, details: str = ""):
        """Log setup step result"""
        status = "✅ SUCCESS" if success else "❌ FAILED"
        step_result = {
            "step": step_name,
            "status": status,
            "details": details,
            "timestamp": datetime.now().isoformat(),
        }
        self.setup_results["steps"].append(step_result)

        print(f"{status} {step_name}")
        if details:
            print(f"   Details: {details}")

        if not success:
            self.setup_results["success"] = False

    def check_prerequisites(self) -> bool:
        """Check system prerequisites"""
        print("\n🔍 Checking Prerequisites...")

        # Check Python version
        try:
            python_version = sys.version_info
            if python_version.major >= 3 and python_version.minor >= 8:
                self.log_step(
                    "Python Version Check",
                    True,
                    f"Python {python_version.major}.{python_version.minor}.{python_version.micro}",
                )
            else:
                self.log_step(
                    "Python Version Check",
                    False,
                    f"Python 3.8+ required, found {python_version.major}.{python_version.minor}",
                )
                return False
        except Exception as e:
            self.log_step("Python Version Check", False, f"Error: {str(e)}")
            return False

        # Check required directories
        required_dirs = [self.integrations_dir, self.python_api_dir]
        for dir_path in required_dirs:
            if os.path.exists(dir_path):
                self.log_step(f"Directory Check: {os.path.basename(dir_path)}", True)
            else:
                self.log_step(
                    f"Directory Check: {os.path.basename(dir_path)}",
                    False,
                    "Directory not found",
                )
                return False

        # Check if Stripe files exist
        stripe_files = [
            os.path.join(self.integrations_dir, "stripe_routes.py"),
            os.path.join(self.python_api_dir, "stripe_service.py"),
            os.path.join(self.integrations_dir, "test_stripe_integration.py"),
        ]

        for file_path in stripe_files:
            if os.path.exists(file_path):
                self.log_step(f"File Check: {os.path.basename(file_path)}", True)
            else:
                self.log_step(
                    f"File Check: {os.path.basename(file_path)}",
                    False,
                    "File not found",
                )
                return False

        return True

    def install_dependencies(self) -> bool:
        """Install required Python dependencies"""
        print("\n📦 Installing Dependencies...")

        dependencies = [
            "stripe>=8.0.0",
            "fastapi>=0.100.0",
            "uvicorn>=0.23.0",
            "requests>=2.31.0",
            "loguru>=0.7.0",
            "pydantic>=2.0.0",
            "python-multipart>=0.0.6",
            "python-jose[cryptography]>=3.3.0",
            "passlib[bcrypt]>=1.7.4",
        ]

        try:
            import importlib
            import pkg_resources

            for dep in dependencies:
                package_name = dep.split(">=")[0].split("[")[0]
                try:
                    importlib.import_module(package_name.replace("-", "_"))
                    self.log_step(
                        f"Dependency: {package_name}", True, "Already installed"
                    )
                except ImportError:
                    self.log_step(f"Dependency: {package_name}", False, "Not installed")
                    return False

            self.log_step(
                "All Dependencies", True, "All required packages are available"
            )
            return True

        except Exception as e:
            self.log_step("Dependency Check", False, f"Error: {str(e)}")
            return False

    def setup_environment(self, stripe_config: Dict[str, str]) -> bool:
        """Setup environment configuration"""
        print("\n⚙️  Setting Up Environment...")

        try:
            # Check if .env file exists
            if os.path.exists(self.env_file):
                self.log_step("Environment File", True, ".env file already exists")
            else:
                # Create .env file from template
                template_path = os.path.join(self.base_dir, ".env.template")
                if os.path.exists(template_path):
                    with open(template_path, "r") as f:
                        template_content = f.read()

                    # Replace template values with actual configuration
                    env_content = template_content
                    for key, value in stripe_config.items():
                        env_content = env_content.replace(f"your_{key}_here", value)

                    with open(self.env_file, "w") as f:
                        f.write(env_content)

                    self.log_step(
                        "Environment File", True, "Created .env file from template"
                    )
                else:
                    self.log_step("Environment File", False, "Template file not found")
                    return False

            # Set environment variables
            for key, value in stripe_config.items():
                os.environ[key] = value

            self.setup_results["environment_configured"] = True
            self.log_step("Environment Variables", True, "Environment variables set")
            return True

        except Exception as e:
            self.log_step("Environment Setup", False, f"Error: {str(e)}")
            return False

    def test_integration(self) -> bool:
        """Test Stripe integration functionality"""
        print("\n🧪 Testing Integration...")

        try:
            # Run the integration tests
            test_script = os.path.join(
                self.integrations_dir, "test_stripe_integration.py"
            )

            if not os.path.exists(test_script):
                self.log_step("Integration Test", False, "Test script not found")
                return False

            # Run the test script
            result = subprocess.run(
                [sys.executable, test_script],
                cwd=self.integrations_dir,
                capture_output=True,
                text=True,
                timeout=60,
            )

            if result.returncode == 0:
                self.log_step("Integration Test", True, "All tests passed")

                # Parse test results
                try:
                    results_file = os.path.join(
                        self.integrations_dir, "stripe_integration_test_results.json"
                    )
                    if os.path.exists(results_file):
                        with open(results_file, "r") as f:
                            test_results = json.load(f)
                        passed = test_results["test_run"]["passed_tests"]
                        total = test_results["test_run"]["total_tests"]
                        self.log_step(
                            "Test Results", True, f"{passed}/{total} tests passed"
                        )
                except Exception as e:
                    logger.warning(f"Could not parse test results: {e}")

                return True
            else:
                self.log_step(
                    "Integration Test", False, f"Tests failed: {result.stderr}"
                )
                return False

        except subprocess.TimeoutExpired:
            self.log_step("Integration Test", False, "Test execution timed out")
            return False
        except Exception as e:
            self.log_step("Integration Test", False, f"Error: {str(e)}")
            return False

    def verify_api_integration(self) -> bool:
        """Verify API integration with main application"""
        print("\n🔗 Verifying API Integration...")

        try:
            # Check if Stripe routes are imported in main API
            main_api_file = os.path.join(self.base_dir, "main_api_app.py")

            if not os.path.exists(main_api_file):
                self.log_step("API Integration", False, "Main API file not found")
                return False

            with open(main_api_file, "r") as f:
                content = f.read()

            # Check for Stripe integration imports
            if "stripe_routes" in content and "STRIPE_AVAILABLE" in content:
                self.log_step(
                    "API Integration", True, "Stripe routes integrated in main API"
                )
            else:
                self.log_step(
                    "API Integration", False, "Stripe routes not found in main API"
                )
                return False

            # Test API health endpoint
            try:
                # Start the API server in background for testing
                import threading
                import uvicorn

                def run_server():
                    uvicorn.run(
                        "main_api_app:app",
                        host="0.0.0.0",
                        port=8000,
                        log_level="error",
                        access_log=False,
                    )

                server_thread = threading.Thread(target=run_server, daemon=True)
                server_thread.start()

                # Wait for server to start
                time.sleep(3)

                # Test health endpoint
                response = requests.get(
                    "http://localhost:8000/stripe/health", timeout=10
                )
                if response.status_code == 200:
                    self.log_step(
                        "API Health Check", True, "Stripe health endpoint responding"
                    )
                else:
                    self.log_step(
                        "API Health Check",
                        False,
                        f"Health endpoint returned {response.status_code}",
                    )
                    return False

            except Exception as e:
                self.log_step("API Health Check", False, f"Error: {str(e)}")
                # This might be expected if server is already running or can't start

            return True

        except Exception as e:
            self.log_step("API Integration", False, f"Error: {str(e)}")
            return False

    def create_setup_summary(self):
        """Create comprehensive setup summary"""
        print("\n📋 Setup Summary")
        print("=" * 50)

        total_steps = len(self.setup_results["steps"])
        successful_steps = sum(
            1 for step in self.setup_results["steps"] if "SUCCESS" in step["status"]
        )

        print(f"Total Steps: {total_steps}")
        print(f"Successful: {successful_steps}")
        print(f"Failed: {total_steps - successful_steps}")
        print(f"Success Rate: {(successful_steps / total_steps) * 100:.1f}%")

        # Save detailed results
        summary_file = os.path.join(self.base_dir, "stripe_setup_summary.json")
        with open(summary_file, "w") as f:
            json.dump(self.setup_results, f, indent=2)

        print(f"\n📄 Detailed summary saved to: {summary_file}")

        if self.setup_results["success"]:
            print("\n🎉 Stripe Integration Setup Completed Successfully!")
            print("\nNext Steps:")
            print("1. Configure your Stripe account in the Stripe Dashboard")
            print("2. Update the .env file with your production credentials")
            print("3. Run production tests: python test_stripe_production.py")
            print("4. Deploy to your production environment")
        else:
            print(
                "\n⚠️  Setup completed with errors. Please review the failed steps above."
            )

    def run_complete_setup(self, stripe_config: Dict[str, str] = None):
        """Run complete setup process"""
        print("🚀 Starting Stripe Integration Setup")
        print("=" * 60)
        print(f"Start Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print("=" * 60)

        # Default configuration for testing
        if stripe_config is None:
            stripe_config = {
                "STRIPE_CLIENT_ID": "ca_test_123456789",
                "STRIPE_CLIENT_SECRET": "sk_test_123456789",
                "STRIPE_REDIRECT_URI": "http://localhost:3000/auth/stripe/callback",
                "STRIPE_PUBLISHABLE_KEY": "pk_test_123456789",
                "STRIPE_SECRET_KEY": "sk_test_123456789",
                "STRIPE_WEBHOOK_SECRET": "whsec_test_123456789",
            }

        # Run all setup steps
        steps = [
            ("Prerequisites Check", self.check_prerequisites),
            ("Dependencies Check", self.install_dependencies),
            ("Environment Setup", lambda: self.setup_environment(stripe_config)),
            ("Integration Testing", self.test_integration),
            ("API Integration", self.verify_api_integration),
        ]

        for step_name, step_function in steps:
            if not step_function():
                print(f"\n❌ Setup failed at: {step_name}")
                break

        # Create final summary
        self.create_setup_summary()

        return self.setup_results["success"]


def main():
    """Main setup execution function"""
    import argparse

    parser = argparse.ArgumentParser(description="Stripe Integration Setup")
    parser.add_argument("--client-id", help="Stripe Client ID")
    parser.add_argument("--client-secret", help="Stripe Client Secret")
    parser.add_argument("--redirect-uri", help="Stripe Redirect URI")
    parser.add_argument("--publishable-key", help="Stripe Publishable Key")
    parser.add_argument("--secret-key", help="Stripe Secret Key")
    parser.add_argument("--webhook-secret", help="Stripe Webhook Secret")

    args = parser.parse_args()

    # Build configuration from command line arguments
    stripe_config = {}
    if args.client_id:
        stripe_config["STRIPE_CLIENT_ID"] = args.client_id
    if args.client_secret:
        stripe_config["STRIPE_CLIENT_SECRET"] = args.client_secret
    if args.redirect_uri:
        stripe_config["STRIPE_REDIRECT_URI"] = args.redirect_uri
    if args.publishable_key:
        stripe_config["STRIPE_PUBLISHABLE_KEY"] = args.publishable_key
    if args.secret_key:
        stripe_config["STRIPE_SECRET_KEY"] = args.secret_key
    if args.webhook_secret:
        stripe_config["STRIPE_WEBHOOK_SECRET"] = args.webhook_secret

    setup = StripeIntegrationSetup()
    success = setup.run_complete_setup(stripe_config)

    return 0 if success else 1


if __name__ == "__main__":
    exit_code = main()
    sys.exit(exit_code)