mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
listen for charge.refunded for stripe
This commit is contained in:
parent
29936d21db
commit
6e57f19598
@ -361,6 +361,24 @@ class Payment extends BaseModel
|
|||||||
return new PaymentService($this);
|
return new PaymentService($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* $data = [
|
||||||
|
'id' => $payment->id,
|
||||||
|
'amount' => 10,
|
||||||
|
'invoices' => [
|
||||||
|
[
|
||||||
|
'invoice_id' => $invoice->id,
|
||||||
|
'amount' => 10,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'date' => '2020/12/12',
|
||||||
|
'gateway_refund' => false,
|
||||||
|
'email_receipt' => false,
|
||||||
|
];
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
public function refund(array $data) :self
|
public function refund(array $data) :self
|
||||||
{
|
{
|
||||||
return $this->service()->refundPayment($data);
|
return $this->service()->refundPayment($data);
|
||||||
|
147
app/PaymentDrivers/Stripe/Jobs/ChargeRefunded.php
Normal file
147
app/PaymentDrivers/Stripe/Jobs/ChargeRefunded.php
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\PaymentDrivers\Stripe\Jobs;
|
||||||
|
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\Payment;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
|
use App\Models\PaymentHash;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use App\Models\CompanyGateway;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use App\PaymentDrivers\Stripe\Utilities;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||||
|
|
||||||
|
class ChargeRefunded implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Utilities;
|
||||||
|
|
||||||
|
public $tries = 1; //number of retries
|
||||||
|
|
||||||
|
public $deleteWhenMissingModels = true;
|
||||||
|
|
||||||
|
public $stripe_request;
|
||||||
|
|
||||||
|
public $company_key;
|
||||||
|
|
||||||
|
private $company_gateway_id;
|
||||||
|
|
||||||
|
public $payment_completed = false;
|
||||||
|
|
||||||
|
public function __construct($stripe_request, $company_key, $company_gateway_id)
|
||||||
|
{
|
||||||
|
$this->stripe_request = $stripe_request;
|
||||||
|
$this->company_key = $company_key;
|
||||||
|
$this->company_gateway_id = $company_gateway_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
MultiDB::findAndSetDbByCompanyKey($this->company_key);
|
||||||
|
nlog($this->stripe_request);
|
||||||
|
|
||||||
|
$company = Company::query()->where('company_key', $this->company_key)->first();
|
||||||
|
|
||||||
|
$source = $this->stripe_request['object'];
|
||||||
|
$charge_id = $source['id'];
|
||||||
|
$amount_refunded = $source['amount_refunded'] ?? 0;
|
||||||
|
|
||||||
|
$payment_hash_key = $source['metadata']['payment_hash'] ?? null;
|
||||||
|
|
||||||
|
$company_gateway = CompanyGateway::query()->find($this->company_gateway_id);
|
||||||
|
$payment_hash = PaymentHash::query()->where('hash', $payment_hash_key)->first();
|
||||||
|
|
||||||
|
$stripe_driver = $company_gateway->driver()->init();
|
||||||
|
|
||||||
|
$stripe_driver->payment_hash = $payment_hash;
|
||||||
|
|
||||||
|
/** @var \App\Models\Payment $payment **/
|
||||||
|
$payment = Payment::query()
|
||||||
|
->withTrashed()
|
||||||
|
->where('company_id', $company->id)
|
||||||
|
->where('transaction_reference', $charge_id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
//don't touch if already refunded
|
||||||
|
if(!$payment || in_array($payment->status_id, [Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stripe_driver->client = $payment->client;
|
||||||
|
|
||||||
|
$amount_refunded = $stripe_driver->convertFromStripeAmount($amount_refunded, $payment->client->currency()->precision, $payment->client->currency());
|
||||||
|
|
||||||
|
if ($payment->status_id == Payment::STATUS_PENDING) {
|
||||||
|
$payment->service()->deletePayment();
|
||||||
|
$payment->status_id = Payment::STATUS_FAILED;
|
||||||
|
$payment->save();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($payment->status_id == Payment::STATUS_COMPLETED) {
|
||||||
|
|
||||||
|
$invoice_collection = $payment->paymentables
|
||||||
|
->where('paymentable_type','invoices')
|
||||||
|
->map(function ($pivot){
|
||||||
|
return [
|
||||||
|
'invoice_id' => $pivot->paymentable_id,
|
||||||
|
'amount' => $pivot->amount - $pivot->refunded
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
if($invoice_collection->count() == 1 && $invoice_collection->first()['amount'] >= $amount_refunded) {
|
||||||
|
//If there is only one invoice- and we are refunding _less_ than the amount of the invoice, we can just refund the payment
|
||||||
|
|
||||||
|
$invoice_collection = $payment->paymentables
|
||||||
|
->where('paymentable_type', 'invoices')
|
||||||
|
->map(function ($pivot) use ($amount_refunded){
|
||||||
|
return [
|
||||||
|
'invoice_id' => $pivot->paymentable_id,
|
||||||
|
'amount' => $amount_refunded
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
elseif($invoice_collection->sum('amount') != $amount_refunded) {
|
||||||
|
//too many edges cases at this point, return early
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoices = $invoice_collection->toArray();
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'id' => $payment->id,
|
||||||
|
'amount' => $amount_refunded,
|
||||||
|
'invoices' => $invoices,
|
||||||
|
'date' => now()->format('Y-m-d'),
|
||||||
|
'gateway_refund' => false,
|
||||||
|
'email_receipt' => false,
|
||||||
|
];
|
||||||
|
|
||||||
|
nlog($data);
|
||||||
|
|
||||||
|
$payment->refund($data);
|
||||||
|
|
||||||
|
$payment->private_notes .= 'Refunded via Stripe';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function middleware()
|
||||||
|
{
|
||||||
|
return [new WithoutOverlapping($this->company_gateway_id)];
|
||||||
|
}
|
||||||
|
}
|
@ -39,6 +39,7 @@ use App\PaymentDrivers\Stripe\FPX;
|
|||||||
use App\PaymentDrivers\Stripe\GIROPAY;
|
use App\PaymentDrivers\Stripe\GIROPAY;
|
||||||
use App\PaymentDrivers\Stripe\iDeal;
|
use App\PaymentDrivers\Stripe\iDeal;
|
||||||
use App\PaymentDrivers\Stripe\ImportCustomers;
|
use App\PaymentDrivers\Stripe\ImportCustomers;
|
||||||
|
use App\PaymentDrivers\Stripe\Jobs\ChargeRefunded;
|
||||||
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentFailureWebhook;
|
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentFailureWebhook;
|
||||||
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentPartiallyFundedWebhook;
|
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentPartiallyFundedWebhook;
|
||||||
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentProcessingWebhook;
|
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentProcessingWebhook;
|
||||||
@ -790,6 +791,12 @@ class StripePaymentDriver extends BaseDriver
|
|||||||
} elseif ($request->data['object']['status'] == "pending") {
|
} elseif ($request->data['object']['status'] == "pending") {
|
||||||
return response()->json([], 200);
|
return response()->json([], 200);
|
||||||
}
|
}
|
||||||
|
} elseif ($request->type === "charge.refunded") {
|
||||||
|
|
||||||
|
ChargeRefunded::dispatch($request->data, $request->company_key, $this->company_gateway->id)->delay(now()->addSeconds(rand(5, 10)));
|
||||||
|
|
||||||
|
return response()->json([], 200);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json([], 200);
|
return response()->json([], 200);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user