- Created complete documentation in docs/ directory - Added PROJECT_OVERVIEW.md with feature highlights and getting started guide - Added ARCHITECTURE.md with system design and technical details - Added SECURITY.md with comprehensive security implementation guide - Added DEVELOPMENT.md with development workflows and best practices - Added DEPLOYMENT.md with production deployment instructions - Added API.md with complete REST API documentation - Added CONTRIBUTING.md with contribution guidelines - Added CHANGELOG.md with version history and migration notes - Reorganized all documentation files into docs/ directory for better organization - Updated README.md with proper documentation links and quick navigation - Enhanced project structure with professional documentation standards
175 lines
6.5 KiB
PHP
175 lines
6.5 KiB
PHP
<?php
|
|
namespace Donations;
|
|
|
|
use Square\SquareClient;
|
|
use Square\Environment;
|
|
use Square\Models\CreatePaymentRequest;
|
|
use Square\Models\Money;
|
|
|
|
class DonationHandler {
|
|
private $square_client;
|
|
private $config;
|
|
|
|
public function __construct() {
|
|
global $square_config;
|
|
$this->config = $square_config;
|
|
|
|
// Initialize Square client
|
|
$this->square_client = new SquareClient([
|
|
'accessToken' => $this->config['square']['access_token'],
|
|
'environment' => $this->config['square']['environment'] === 'production' ? Environment::PRODUCTION : Environment::SANDBOX
|
|
]);
|
|
}
|
|
|
|
public function createDonation($streamer_id, $amount, $donor_name = '', $message = '') {
|
|
try {
|
|
$this->validateAmount($amount);
|
|
|
|
$payment = $this->createSquarePayment($streamer_id, $amount, $donor_name, $message);
|
|
|
|
if ($payment->isSuccess()) {
|
|
$this->recordDonation($streamer_id, $amount, $donor_name, $message, $payment->getResult()->getPayment()->getId());
|
|
|
|
return [
|
|
'success' => true,
|
|
'payment_id' => $payment->getResult()->getPayment()->getId(),
|
|
'message' => 'Donation processed successfully'
|
|
];
|
|
}
|
|
|
|
return [
|
|
'success' => false,
|
|
'message' => 'Failed to process donation: ' . $payment->getErrors()[0]->getDetail()
|
|
];
|
|
} catch (\Exception $e) {
|
|
return [
|
|
'success' => false,
|
|
'message' => 'Error processing donation: ' . $e->getMessage()
|
|
];
|
|
}
|
|
}
|
|
|
|
private function validateAmount($amount) {
|
|
if ($amount < $this->config['square']['min_donation'] ||
|
|
$amount > $this->config['square']['max_donation']) {
|
|
throw new \Exception('Invalid donation amount');
|
|
}
|
|
}
|
|
|
|
private function createSquarePayment($streamer_id, $amount, $donor_name, $message) {
|
|
$money = new Money();
|
|
$money->setAmount($amount * 100); // Convert to cents
|
|
$money->setCurrency($this->config['square']['currency']);
|
|
|
|
$payment_request = new CreatePaymentRequest();
|
|
$payment_request->setSourceId('EXTERNAL');
|
|
$payment_request->setAmountMoney($money);
|
|
$payment_request->setLocationId($this->config['square']['location_id']);
|
|
|
|
// Add metadata
|
|
$payment_request->setMetadata([
|
|
'streamer_id' => $streamer_id,
|
|
'donor_name' => $donor_name,
|
|
'message' => $message
|
|
]);
|
|
|
|
return $this->square_client->getPaymentsApi()->createPayment($payment_request);
|
|
}
|
|
|
|
private function recordDonation($streamer_id, $amount, $donor_name, $message, $payment_id) {
|
|
$sql = "INSERT INTO donations (
|
|
streamer_id, amount, donor_name, message, payment_id, status, created_at
|
|
) VALUES (?, ?, ?, ?, ?, 'completed', NOW())";
|
|
|
|
$params = [$streamer_id, $amount, $donor_name, $message, $payment_id];
|
|
db()->executeQuery($sql, $params);
|
|
|
|
// Update streamer's balance
|
|
$sql = "UPDATE users SET donation_balance = donation_balance + ? WHERE user_id = ?";
|
|
db()->executeQuery($sql, [$amount, $streamer_id]);
|
|
}
|
|
|
|
public function getStreamerBalance($streamer_id) {
|
|
$sql = "SELECT donation_balance FROM users WHERE user_id = ?";
|
|
$result = db()->getRow($sql, [$streamer_id]);
|
|
return $result['donation_balance'] ?? 0;
|
|
}
|
|
|
|
public function requestPayout($streamer_id) {
|
|
try {
|
|
$balance = $this->getStreamerBalance($streamer_id);
|
|
|
|
if ($balance < $this->config['streamer']['min_balance']) {
|
|
return [
|
|
'success' => false,
|
|
'message' => 'Insufficient balance for payout'
|
|
];
|
|
}
|
|
|
|
$payout = $this->createSquarePayout($streamer_id, $balance);
|
|
|
|
if ($payout->isSuccess()) {
|
|
$this->recordPayout($streamer_id, $balance, $payout->getResult()->getPayout()->getId());
|
|
|
|
return [
|
|
'success' => true,
|
|
'message' => 'Payout processed successfully',
|
|
'amount' => $balance
|
|
];
|
|
}
|
|
|
|
return [
|
|
'success' => false,
|
|
'message' => 'Failed to process payout: ' . $payout->getErrors()[0]->getDetail()
|
|
];
|
|
} catch (\Exception $e) {
|
|
return [
|
|
'success' => false,
|
|
'message' => 'Error processing payout: ' . $e->getMessage()
|
|
];
|
|
}
|
|
}
|
|
|
|
private function createSquarePayout($streamer_id, $amount) {
|
|
// Calculate fees
|
|
$fee_amount = ($amount * ($this->config['streamer']['payout_fee'] / 100)) + $this->config['streamer']['payout_fee_fixed'];
|
|
$payout_amount = $amount - $fee_amount;
|
|
|
|
return $this->square_client->getPayoutsApi()->createPayout([
|
|
'amount_money' => [
|
|
'amount' => $payout_amount * 100, // Convert to cents
|
|
'currency' => $this->config['square']['currency']
|
|
],
|
|
'location_id' => $this->config['square']['location_id']
|
|
]);
|
|
}
|
|
|
|
private function recordPayout($streamer_id, $amount, $payout_id) {
|
|
// Calculate fees
|
|
$fee_amount = ($amount * ($this->config['streamer']['payout_fee'] / 100)) + $this->config['streamer']['payout_fee_fixed'];
|
|
$payout_amount = $amount - $fee_amount;
|
|
|
|
// Record payout
|
|
$sql = "INSERT INTO payouts (
|
|
streamer_id, amount, fee, payout_id, status, created_at
|
|
) VALUES (?, ?, ?, ?, 'completed', NOW())";
|
|
|
|
$params = [$streamer_id, $payout_amount, $fee_amount, $payout_id];
|
|
db()->executeQuery($sql, $params);
|
|
|
|
// Reset streamer's balance
|
|
$sql = "UPDATE users SET donation_balance = 0 WHERE user_id = ?";
|
|
db()->executeQuery($sql, [$streamer_id]);
|
|
}
|
|
|
|
public function getDonationHistory($streamer_id, $limit = 10) {
|
|
$sql = "SELECT d.*, u.username as streamer_name
|
|
FROM donations d
|
|
JOIN users u ON d.streamer_id = u.user_id
|
|
WHERE d.streamer_id = ?
|
|
ORDER BY d.created_at DESC
|
|
LIMIT ?";
|
|
|
|
return db()->getRows($sql, [$streamer_id, $limit]);
|
|
}
|
|
}
|