Deep UX: 2-column automations, visible appeal cards, platform education, strip model refs
Automations: - 2-column layout: WhatsApp phone LEFT, education RIGHT - Right column: 'How it works' (5 numbered steps), performance stats, timing controls, reply commands, tips - Hero spans full width with photo+dark panel - Improvement CTA is a prominent card, not floating text - No misalignment — phone fills left column naturally Collect: - Appeals shown as visible gap-px grid cards (not hidden dropdown) - Each card shows name, platform, amount raised, pledge count, collection rate - Active appeal has border-l-2 blue indicator - Platform integration clarity: shows 'Donors redirected to JustGiving' etc - Educational section: 'Where to share your link' + 'How payment works' - Explains bank transfer vs JustGiving vs card payment inline AI model: Stripped all model name comments from code (no user-facing references existed)
This commit is contained in:
157
temp_files/care/StripeRefundService.php
Normal file
157
temp_files/care/StripeRefundService.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Stripe\Exception\ApiErrorException;
|
||||
use Stripe\StripeClient;
|
||||
|
||||
/**
|
||||
* Centralised Stripe refund & payment-method management.
|
||||
*
|
||||
* Every action is logged. Every response is a simple array so callers
|
||||
* can show user-friendly notifications without catching exceptions.
|
||||
*/
|
||||
class StripeRefundService
|
||||
{
|
||||
private StripeClient $stripe;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->stripe = new StripeClient(config('paisa.gateways.stripe.secret_key'));
|
||||
}
|
||||
|
||||
// ── Refund a PaymentIntent (full or partial) ────────────────
|
||||
|
||||
public function refundPaymentIntent(string $paymentIntentId, ?int $amountInPence = null, string $reason = ''): array
|
||||
{
|
||||
try {
|
||||
$params = [
|
||||
'payment_intent' => $paymentIntentId,
|
||||
'reason' => 'requested_by_customer',
|
||||
];
|
||||
|
||||
if ($amountInPence !== null && $amountInPence > 0) {
|
||||
$params['amount'] = $amountInPence;
|
||||
}
|
||||
|
||||
$refund = $this->stripe->refunds->create($params);
|
||||
|
||||
Log::info('Stripe refund created', [
|
||||
'refund_id' => $refund->id,
|
||||
'payment_intent' => $paymentIntentId,
|
||||
'amount' => $refund->amount,
|
||||
'status' => $refund->status,
|
||||
'reason' => $reason,
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'refund_id' => $refund->id,
|
||||
'amount' => $refund->amount,
|
||||
'status' => $refund->status,
|
||||
];
|
||||
} catch (ApiErrorException $e) {
|
||||
Log::error('Stripe refund failed', [
|
||||
'payment_intent' => $paymentIntentId,
|
||||
'error' => $e->getMessage(),
|
||||
'reason' => $reason,
|
||||
]);
|
||||
|
||||
return ['success' => false, 'error' => $e->getMessage()];
|
||||
}
|
||||
}
|
||||
|
||||
// ── Detach payment method from a SetupIntent ────────────────
|
||||
// This is how we "cancel" recurring: remove the card so no
|
||||
// future charges can be made.
|
||||
|
||||
public function detachPaymentMethod(string $setupIntentId): array
|
||||
{
|
||||
try {
|
||||
$si = $this->stripe->setupIntents->retrieve($setupIntentId);
|
||||
|
||||
if (! $si->payment_method) {
|
||||
return ['success' => true, 'message' => 'No payment method attached'];
|
||||
}
|
||||
|
||||
$pmId = is_string($si->payment_method)
|
||||
? $si->payment_method
|
||||
: $si->payment_method->id;
|
||||
|
||||
$this->stripe->paymentMethods->detach($pmId);
|
||||
|
||||
Log::info('Stripe payment method detached', [
|
||||
'setup_intent' => $setupIntentId,
|
||||
'payment_method' => $pmId,
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => "Payment method {$pmId} detached",
|
||||
'payment_method' => $pmId,
|
||||
];
|
||||
} catch (ApiErrorException $e) {
|
||||
Log::error('Failed to detach payment method', [
|
||||
'setup_intent' => $setupIntentId,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return ['success' => false, 'error' => $e->getMessage()];
|
||||
}
|
||||
}
|
||||
|
||||
// ── Retrieve PaymentIntent details for display ──────────────
|
||||
|
||||
public function getPaymentDetails(string $paymentIntentId): ?array
|
||||
{
|
||||
try {
|
||||
$pi = $this->stripe->paymentIntents->retrieve($paymentIntentId, [
|
||||
'expand' => ['latest_charge'],
|
||||
]);
|
||||
|
||||
$charge = $pi->latest_charge;
|
||||
|
||||
return [
|
||||
'id' => $pi->id,
|
||||
'status' => $pi->status,
|
||||
'amount' => $pi->amount,
|
||||
'currency' => strtoupper($pi->currency),
|
||||
'created' => date('d M Y H:i', $pi->created),
|
||||
'refunded' => $charge?->refunded ?? false,
|
||||
'amount_refunded' => $charge?->amount_refunded ?? 0,
|
||||
'card_brand' => $charge?->payment_method_details?->card?->brand ?? null,
|
||||
'card_last4' => $charge?->payment_method_details?->card?->last4 ?? null,
|
||||
];
|
||||
} catch (ApiErrorException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Retrieve SetupIntent details for display ────────────────
|
||||
|
||||
public function getSetupIntentDetails(string $setupIntentId): ?array
|
||||
{
|
||||
try {
|
||||
$si = $this->stripe->setupIntents->retrieve($setupIntentId, [
|
||||
'expand' => ['payment_method'],
|
||||
]);
|
||||
|
||||
$pm = $si->payment_method;
|
||||
|
||||
return [
|
||||
'id' => $si->id,
|
||||
'status' => $si->status,
|
||||
'created' => date('d M Y H:i', $si->created),
|
||||
'payment_method_id' => is_string($pm) ? $pm : ($pm?->id ?? null),
|
||||
'card_brand' => is_object($pm) ? ($pm->card?->brand ?? null) : null,
|
||||
'card_last4' => is_object($pm) ? ($pm->card?->last4 ?? null) : null,
|
||||
'card_exp_month' => is_object($pm) ? ($pm->card?->exp_month ?? null) : null,
|
||||
'card_exp_year' => is_object($pm) ? ($pm->card?->exp_year ?? null) : null,
|
||||
'customer_id' => $si->customer,
|
||||
];
|
||||
} catch (ApiErrorException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user