Files
2026-05-16 23:00:37 -05:00

196 lines
6.2 KiB
PHP

<?php
/**
* Tom's Java Jive - Twilio SMS Service
*
* Handles all SMS notifications using Twilio API
*/
class TwilioSMS {
private string $accountSid;
private string $authToken;
private string $fromNumber;
public function __construct() {
// Load from settings or config
$this->accountSid = getSetting('twilio_account_sid', 'YOUR_TWILIO_ACCOUNT_SID');
$this->authToken = getSetting('twilio_auth_token', 'YOUR_TWILIO_AUTH_TOKEN');
$this->fromNumber = getSetting('twilio_phone_number', '+1234567890');
}
/**
* Send SMS via Twilio API
*/
public function send(string $to, string $message): array {
// Ensure phone number is in E.164 format
$to = $this->formatPhoneNumber($to);
if (!$to) {
return ['success' => false, 'error' => 'Invalid phone number'];
}
$url = "https://api.twilio.com/2010-04-01/Accounts/{$this->accountSid}/Messages.json";
$data = [
'To' => $to,
'From' => $this->fromNumber,
'Body' => $message
];
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_USERPWD => "{$this->accountSid}:{$this->authToken}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
return ['success' => false, 'error' => $error];
}
$result = json_decode($response, true);
if ($httpCode >= 200 && $httpCode < 300) {
return [
'success' => true,
'sid' => $result['sid'] ?? null,
'status' => $result['status'] ?? 'queued'
];
}
return [
'success' => false,
'error' => $result['message'] ?? 'Failed to send SMS',
'code' => $result['code'] ?? $httpCode
];
}
/**
* Format phone number to E.164 format
*/
private function formatPhoneNumber(string $phone): ?string {
// Remove all non-numeric characters except +
$phone = preg_replace('/[^0-9+]/', '', $phone);
// If already in E.164 format
if (preg_match('/^\+[1-9]\d{1,14}$/', $phone)) {
return $phone;
}
// US number without country code
if (preg_match('/^1?\d{10}$/', $phone)) {
$phone = preg_replace('/^1?/', '', $phone);
return '+1' . $phone;
}
return null;
}
/**
* Send order confirmation SMS
*/
public function sendOrderConfirmation(array $order, string $phone): array {
$message = "Tom's Java Jive: Your order #{$order['order_number']} has been confirmed! " .
"Total: " . formatCurrency($order['total']) . ". " .
"Thank you for your purchase!";
return $this->send($phone, $message);
}
/**
* Send shipping notification SMS
*/
public function sendShippingNotification(array $order, string $phone): array {
$message = "Tom's Java Jive: Your order #{$order['order_number']} has shipped! " .
"Tracking: {$order['tracking_number']}. " .
"Track at: " . ($order['tracking_url'] ?? SITE_URL);
return $this->send($phone, $message);
}
/**
* Send delivery notification SMS
*/
public function sendDeliveryNotification(array $order, string $phone): array {
$message = "Tom's Java Jive: Great news! Your order #{$order['order_number']} " .
"has been delivered. Enjoy your coffee!";
return $this->send($phone, $message);
}
/**
* Send password reset SMS
*/
public function sendPasswordResetCode(string $phone, string $code): array {
$message = "Tom's Java Jive: Your password reset code is {$code}. " .
"This code expires in 15 minutes. Don't share it with anyone.";
return $this->send($phone, $message);
}
/**
* Send OTP verification SMS
*/
public function sendVerificationCode(string $phone, string $code): array {
$message = "Tom's Java Jive: Your verification code is {$code}. " .
"Valid for 10 minutes.";
return $this->send($phone, $message);
}
/**
* Send promotional SMS (with opt-out info)
*/
public function sendPromotion(string $phone, string $promoMessage): array {
$message = "Tom's Java Jive: {$promoMessage} " .
"Reply STOP to unsubscribe.";
return $this->send($phone, $message);
}
/**
* Send order ready for pickup SMS
*/
public function sendReadyForPickup(array $order, string $phone): array {
$message = "Tom's Java Jive: Your order #{$order['order_number']} is ready for pickup! " .
"Show this message at the counter.";
return $this->send($phone, $message);
}
/**
* Send low wallet balance alert
*/
public function sendLowBalanceAlert(string $phone, float $balance): array {
$message = "Tom's Java Jive: Your wallet balance is " . formatCurrency($balance) . ". " .
"Top up now to continue enjoying fast checkout!";
return $this->send($phone, $message);
}
/**
* Send loyalty tier upgrade notification
*/
public function sendTierUpgrade(string $phone, string $tierName): array {
$message = "Tom's Java Jive: Congratulations! You've reached {$tierName} status! " .
"Enjoy your new benefits and rewards. Thank you for being a loyal customer!";
return $this->send($phone, $message);
}
}
// Helper function for easy access
function sendSMS(): TwilioSMS {
static $instance = null;
if ($instance === null) {
$instance = new TwilioSMS();
}
return $instance;
}