Try to fix
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
dvirlabs 2026-05-13 21:17:56 +03:00
parent f3537a66b2
commit 97a0932e67
3 changed files with 206 additions and 14 deletions

View File

@ -4,7 +4,7 @@ sqlalchemy>=2.0.23
psycopg2-binary>=2.9.9
pydantic[email]>=2.5.0
httpx>=0.25.2
certifi>=2024.0.0
certifi>=2023.7.22
python-dotenv>=1.0.0
python-multipart>=0.0.7
openpyxl>=3.1.2

View File

@ -0,0 +1,185 @@
"""
SSL/TLS Connection Test for Meta WhatsApp API
==============================================
This script tests SSL/TLS connectivity to Meta's API to diagnose
handshake failures.
"""
import asyncio
import ssl
import certifi
import httpx
import sys
import os
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from dotenv import load_dotenv
load_dotenv()
async def test_ssl_methods():
"""Test different SSL configuration methods"""
test_url = "https://graph.facebook.com/v20.0/me"
token = os.getenv("WHATSAPP_ACCESS_TOKEN", "")
if not token:
print("❌ WHATSAPP_ACCESS_TOKEN not set in .env")
return
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
print("="*80)
print("Testing SSL/TLS Connection to Meta's API")
print("="*80)
print(f"\nTest URL: {test_url}")
print(f"Token: ***{token[-8:]}")
print()
# Method 1: Using certifi
print("Method 1: Using certifi CA bundle")
print("-" * 80)
try:
async with httpx.AsyncClient(
verify=certifi.where(),
timeout=10.0
) as client:
response = await client.get(test_url, headers=headers)
print(f"✅ SUCCESS! Status: {response.status_code}")
print(f" Response: {response.text[:200]}")
except Exception as e:
print(f"❌ FAILED: {e}")
print()
# Method 2: Using system certificates
print("Method 2: Using system certificates (verify=True)")
print("-" * 80)
try:
async with httpx.AsyncClient(
verify=True,
timeout=10.0
) as client:
response = await client.get(test_url, headers=headers)
print(f"✅ SUCCESS! Status: {response.status_code}")
print(f" Response: {response.text[:200]}")
except Exception as e:
print(f"❌ FAILED: {e}")
print()
# Method 3: Custom SSL context with TLS 1.2+
print("Method 3: Custom SSL context (TLS 1.2+)")
print("-" * 80)
try:
ssl_context = ssl.create_default_context(cafile=certifi.where())
ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
ssl_context.check_hostname = True
async with httpx.AsyncClient(
verify=ssl_context,
timeout=10.0
) as client:
response = await client.get(test_url, headers=headers)
print(f"✅ SUCCESS! Status: {response.status_code}")
print(f" Response: {response.text[:200]}")
except Exception as e:
print(f"❌ FAILED: {e}")
print()
# Method 4: Custom SSL context with relaxed settings
print("Method 4: Custom SSL context (relaxed cipher suite)")
print("-" * 80)
try:
ssl_context = ssl.create_default_context(cafile=certifi.where())
ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
ssl_context.check_hostname = True
ssl_context.set_ciphers('DEFAULT:@SECLEVEL=1')
async with httpx.AsyncClient(
verify=ssl_context,
timeout=10.0
) as client:
response = await client.get(test_url, headers=headers)
print(f"✅ SUCCESS! Status: {response.status_code}")
print(f" Response: {response.text[:200]}")
except Exception as e:
print(f"❌ FAILED: {e}")
print()
# Method 5: No verification (INSECURE - for testing only)
print("Method 5: No SSL verification (INSECURE - testing only)")
print("-" * 80)
try:
async with httpx.AsyncClient(
verify=False,
timeout=10.0
) as client:
response = await client.get(test_url, headers=headers)
print(f"✅ SUCCESS! Status: {response.status_code}")
print(f" Response: {response.text[:200]}")
print(" ⚠️ WARNING: This method is INSECURE. Do not use in production!")
except Exception as e:
print(f"❌ FAILED: {e}")
print()
# System info
print("="*80)
print("System Information")
print("="*80)
print(f"Python SSL version: {ssl.OPENSSL_VERSION}")
print(f"Certifi CA bundle location: {certifi.where()}")
print(f"httpx version: {httpx.__version__}")
# Check if CA bundle exists
import os.path
ca_bundle = certifi.where()
if os.path.exists(ca_bundle):
file_size = os.path.getsize(ca_bundle)
print(f"✅ CA bundle exists ({file_size:,} bytes)")
else:
print(f"❌ CA bundle not found at {ca_bundle}")
async def main():
print("\n" + "="*80)
print("WhatsApp Cloud API - SSL/TLS Connectivity Test")
print("="*80)
print("""
This script tests different SSL/TLS configuration methods to identify
which one works with Meta's API on your system.
It will try:
1. Certifi CA bundle
2. System certificates
3. Custom SSL context with TLS 1.2+
4. Relaxed cipher suites
5. No verification (insecure, for comparison)
""")
await test_ssl_methods()
print("\n" + "="*80)
print("Recommendation")
print("="*80)
print("""
Look at the results above and use the first method that succeeded.
If only Method 5 (no verification) worked:
- Your system certificates may be outdated
- Update certifi: pip install --upgrade certifi
- Update OpenSSL on your system
If Methods 1-4 all failed:
- Check your firewall/proxy settings
- Ensure you can reach graph.facebook.com
- Verify WHATSAPP_ACCESS_TOKEN is correct
""")
if __name__ == "__main__":
asyncio.run(main())

View File

@ -17,18 +17,25 @@ logger = logging.getLogger(__name__)
async def create_http_client() -> httpx.AsyncClient:
"""
Create an httpx client with proper certificate verification.
Uses certifi for CA bundle and explicit TLS 1.2+ negotiation.
"""
import ssl
# Create a default SSL context that prefers TLS 1.2 and higher
ssl_context = ssl.create_default_context(cafile=certifi.where())
ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
ssl_context.check_hostname = True
Uses certifi CA bundle for Meta's WhatsApp Cloud API.
Falls back to system certificates if certifi fails.
"""
try:
# Try using certifi's CA bundle first (most reliable)
return httpx.AsyncClient(
verify=ssl_context,
verify=certifi.where(),
timeout=httpx.Timeout(30.0, connect=10.0),
http2=False, # Disable HTTP/2 to avoid compatibility issues
http2=False, # Disable HTTP/2 for better compatibility
limits=httpx.Limits(max_keepalive_connections=5, max_connections=10)
)
except Exception as e:
logger.warning(f"[WhatsApp] Certifi SSL setup failed, using system certs: {e}")
# Fallback: use system default certificates
return httpx.AsyncClient(
verify=True, # Use system certificates
timeout=httpx.Timeout(30.0, connect=10.0),
http2=False,
limits=httpx.Limits(max_keepalive_connections=5, max_connections=10)
)