# 🚀 X OAuth 2.0 - Verification Checklist

**Project:** Bokeplah Video Player  
**Date:** June 12, 2026  
**Feature:** X (Twitter) OAuth 2.0 Publishing

---

## ✅ Pre-Verification

Before testing, verify:

- [ ] Credentials in `.env` file (API Key, Secret, Tokens)
- [ ] X app has "Read and Write" permissions in Twitter Developer Portal
- [ ] Network connectivity to api.twitter.com
- [ ] Laravel queue configured (optional but recommended)
- [ ] Storage directory writable for logs

---

## 🔍 Step 1: Validate Configuration

### Run Validation Command
```bash
php artisan x:test-oauth2 --validate
```

**Expected Output:**
```
✅ Credentials valid
✓ X API credentials (Key/Secret) ✓
✓ OAuth 2.0 Access Token configured ✓
✓ OAuth 2.0 Refresh Token configured ✓
```

**Checklist:**
- [ ] Command runs without errors
- [ ] Shows "Credentials valid"
- [ ] Shows all credentials configured
- [ ] No errors listed

### If Validation Fails
❌ **Error: "Credentials not configured"**
- [ ] Check `.env` has X_API_KEY
- [ ] Check `.env` has X_API_SECRET
- [ ] Check `.env` has X_REFRESH_TOKEN or X_ACCESS_TOKEN
- [ ] Run `php artisan config:clear`

---

## 👤 Step 2: Check User Connection

### Run User Info Command
```bash
php artisan x:test-oauth2 --user-info
```

**Expected Output:**
```
✅ Connected to X API
   - User ID: 1234567890
   - Username: @bokeplah
   - Name: Bokeplah
```

**Checklist:**
- [ ] Command runs without errors
- [ ] Shows "Connected to X API"
- [ ] Shows correct username
- [ ] No "Bearer token" errors

### If Connection Fails
❌ **Error: "Could not retrieve user info"**
- [ ] Check bearer token in `.env` (X_BEARER_TOKEN)
- [ ] Verify X app still exists in Twitter Portal
- [ ] Check network connectivity
- [ ] Try refreshing token (next step)

---

## 🔄 Step 3: Test Token Refresh

### Run Refresh Command
```bash
php artisan x:test-oauth2 --refresh
```

**Expected Output:**
```
✅ Token refreshed successfully
```

**Checklist:**
- [ ] Command runs without errors
- [ ] Shows success message
- [ ] Check logs show token updated
- [ ] X_ACCESS_TOKEN updated in `.env`

### If Refresh Fails
❌ **Error: "Token refresh failed"**
- [ ] Check X_REFRESH_TOKEN in `.env`
- [ ] Verify refresh token not expired (usually 6 months)
- [ ] Regenerate tokens from Twitter Portal
- [ ] Check logs: `tail -f storage/logs/laravel.log | grep "OAuth2"`

---

## 📝 Step 4: Post Test Tweet

### Run Tweet Command
```bash
php artisan x:test-oauth2 --tweet="Test tweet from Bokeplah OAuth 2.0 🚀"
```

**Expected Output:**
```
✅ Tweet posted successfully!
   Tweet ID: 1234567890123456789
   View: https://x.com/i/web/status/1234567890123456789
```

**Checklist:**
- [ ] Command completes without errors
- [ ] Shows success message with tweet ID
- [ ] Tweet ID is numeric
- [ ] Can visit tweet URL in browser
- [ ] Tweet content visible on X

### If Tweet Fails
❌ **Error: "Failed to post tweet"**

**HTTP 401 - Unauthorized:**
- [ ] Run `php artisan x:test-oauth2 --refresh`
- [ ] Check X_ACCESS_TOKEN in `.env`
- [ ] Regenerate tokens if needed

**HTTP 403 - Forbidden:**
- [ ] Check X app permissions (needs "Read and Write")
- [ ] Update permissions in Twitter Developer Portal
- [ ] Regenerate tokens

**HTTP 429 - Rate Limited:**
- [ ] Wait 15 minutes
- [ ] Retry the command

**Other Errors:**
- [ ] Check logs: `grep "tweet\|OAuth\|error" storage/logs/laravel.log | tail -20`
- [ ] Read error message carefully
- [ ] Refer to X_OAUTH2_SETUP.md troubleshooting

---

## 🧪 Step 5: Test from Code

### Test in Tinker
```bash
php artisan tinker
```

Then run:
```php
$x = app(\App\Services\XPublishService::class);

// Validate
$status = $x->validateCredentials();
dd($status);

// Get auth info
$auth = $x->getAuthInfo();
dd($auth);

// Post tweet
$tweetId = $x->postSimpleTweet('Tinker test tweet 📱');
echo "Posted: {$tweetId}";
```

**Checklist:**
- [ ] Service initializes without errors
- [ ] validateCredentials returns valid: true
- [ ] getAuthInfo shows configured tokens
- [ ] postSimpleTweet returns numeric ID
- [ ] Tweet visible on X

---

## 📤 Step 6: Test Job Queue

### Create Test PublishLog
```bash
php artisan tinker
```

```php
$video = \App\Models\Video::first();
if (!$video) {
    dd("No videos found");
}

$publishLog = \App\Models\PublishLog::create([
    'video_id' => $video->id,
    'platform' => 'x',
    'publish_title' => 'Job test tweet from Bokeplah',
    'status' => 'pending',
]);

dispatch(new \App\Jobs\XPublishJob($publishLog));
echo "Job dispatched: " . $publishLog->id;
```

### Process Queue
```bash
php artisan queue:work
```

**Checklist:**
- [ ] Job dispatched successfully
- [ ] Queue worker picks up job
- [ ] Job completes without errors
- [ ] Tweet posted to X
- [ ] PublishLog status updated to "published"
- [ ] Logs show success message

---

## 🔍 Step 7: Check Logs

### View Recent Logs
```bash
tail -50 storage/logs/laravel.log
```

**Look For:**
```
✓ "X publish successful"
✓ "X tweet posted successfully"
✓ "X_ACCESS_TOKEN updated in .env"
✓ "X OAuth2 access token refreshed"
```

**Checklist:**
- [ ] Log file exists and is readable
- [ ] Recent entries show X operations
- [ ] No "ERROR" or "CRITICAL" entries
- [ ] Can see operation timeline

### Search Specific Events
```bash
# Tweet posts
grep "tweet posted" storage/logs/laravel.log | tail -5

# Token refreshes
grep "access token refreshed" storage/logs/laravel.log | tail -5

# Authentication
grep "OAuth2\|authorization" storage/logs/laravel.log | tail -5

# Errors
grep "ERROR.*X\|error.*OAuth" storage/logs/laravel.log | tail -5
```

**Checklist:**
- [ ] Can find recent tweet posting
- [ ] Can find token refresh events
- [ ] No repeated auth errors
- [ ] No "permission denied" messages

---

## 🚨 Step 8: Error Scenarios

### Scenario A: Token Expires
**What happens:**
1. Next tweet post gets 401
2. Service auto-refreshes token
3. Retry succeeds
4. `.env` updated with new token

**How to verify:**
- [ ] Post tweet after 2+ hours
- [ ] Should post successfully (auto-refresh)
- [ ] Check logs for "Token refreshed"

### Scenario B: Network Failure
**What happens:**
1. Request fails with connection error
2. Job retries (after configured delay)
3. Eventually succeeds

**How to verify:**
- [ ] Disconnect network
- [ ] Try to post tweet
- [ ] Reconnect network
- [ ] Tweet should eventually succeed

### Scenario C: Invalid Credentials
**What happens:**
1. Service initialization fails
2. Clear error message shown
3. Cannot proceed

**How to verify:**
- [ ] Temporarily remove X_API_KEY from `.env`
- [ ] Try to initialize service
- [ ] Should show "API Key not configured"
- [ ] Restore X_API_KEY

---

## ✨ Step 9: Full Integration Test

### Test Complete Workflow
```bash
# 1. Validate
php artisan x:test-oauth2 --validate

# 2. Check connection
php artisan x:test-oauth2 --user-info

# 3. Post tweet
php artisan x:test-oauth2 --tweet="Full integration test 🎯"

# 4. Refresh token
php artisan x:test-oauth2 --refresh

# 5. Check logs
tail -20 storage/logs/laravel.log | grep "X\|OAuth"
```

**Checklist:**
- [ ] All 4 operations complete successfully
- [ ] All logs show success
- [ ] No error messages
- [ ] Can see tweets on X

---

## 📊 Expected Results

### Successful Configuration
```
Command                           Expected Result
─────────────────────────────────────────────────────────────
validate                          ✅ Credentials valid
user-info                         ✅ Connected to X API
tweet="Test message"              ✅ Tweet posted successfully
refresh                           ✅ Token refreshed successfully
```

### Successful Logs
```
✓ X publish successful
✓ X tweet posted successfully
✓ X media upload successful
✓ X_ACCESS_TOKEN updated in .env
✓ X OAuth2 access token refreshed
```

### Successful Queue
```
✓ Job dispatched
✓ Job processing...
✓ X publish successful
✓ PublishLog status updated to published
```

---

## ❌ Troubleshooting Guide

### Issue: "API Key not configured"
**Cause:** X_API_KEY missing from `.env`  
**Solution:**
1. Add X_API_KEY to `.env`
2. Run `php artisan config:clear`
3. Retry test command

### Issue: "HTTP 401 Unauthorized"
**Cause:** Invalid or expired access token  
**Solution:**
1. Run `php artisan x:test-oauth2 --refresh`
2. Check X_REFRESH_TOKEN in `.env`
3. If still fails, regenerate from Twitter Portal

### Issue: "HTTP 403 Forbidden"
**Cause:** X app missing "Read and Write" permissions  
**Solution:**
1. Go to Twitter Developer Portal
2. Edit app permissions to "Read and Write"
3. Regenerate tokens
4. Update `.env`

### Issue: "No valid authentication token"
**Cause:** All auth tokens missing  
**Solution:**
1. Check `.env` has at least one token
2. Verify token format (should start with specific prefixes)
3. Add missing tokens from Twitter Portal

### Issue: "Failed to connect to api.twitter.com"
**Cause:** Network or DNS issue  
**Solution:**
1. Check internet connection
2. Verify DNS: `nslookup api.twitter.com`
3. Check firewall rules
4. Retry after network restored

---

## 🎯 Success Criteria

✅ **All of the following must be true:**

- [ ] `php artisan x:test-oauth2 --validate` passes
- [ ] `php artisan x:test-oauth2 --user-info` returns username
- [ ] `php artisan x:test-oauth2 --tweet="..."` posts tweet
- [ ] Tweets are visible on X.com
- [ ] Logs show success messages
- [ ] No repeated error messages
- [ ] Queue jobs complete successfully
- [ ] `.env` file updates with new tokens
- [ ] No 401/403/429 errors in logs
- [ ] Can post multiple tweets without issues

---

## 📝 Sign-Off

### Verification Completed By
- Name: ________________
- Date: ________________
- Time: ________________

### Status
- [ ] ✅ All tests passed - Ready for production
- [ ] ⚠️ Some tests passed - Needs review
- [ ] ❌ Tests failed - Not ready

### Notes
```
_________________________________________________________________
_________________________________________________________________
_________________________________________________________________
```

---

## 📚 Help & Support

- **Quick Start:** [X_QUICK_START.md](X_QUICK_START.md)
- **Setup Guide:** [X_OAUTH2_SETUP.md](X_OAUTH2_SETUP.md)
- **API Reference:** [X_API_REFERENCE.md](X_API_REFERENCE.md)
- **Test Script:** `php test_x_oauth2_setup.php`
- **Logs:** `storage/logs/laravel.log`

---

**Verification Checklist Complete!**

For additional help, refer to the documentation files or contact the development team.
