Merge pull request #3838 from beganovich/v2-2306-payments

Improving payments
This commit is contained in:
David Bomba 2020-06-25 07:18:25 +10:00 committed by GitHub
commit a7d64259c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 127 additions and 99 deletions

View File

@ -273,4 +273,16 @@ class CheckoutComPaymentDriver extends BasePaymentDriver
$company_gateway_token->save(); $company_gateway_token->save();
} }
} }
public function refund(Payment $payment, $amount)
{
$payment = new \Checkout\Models\Payments\Refund($payment->transaction_reference);
$payment->amount = $amount;
try {
$refund = $this->gateway->payments()->refund($payment);
} catch (CheckoutHttpException $e) {
// ..
}
}
} }

View File

@ -69,6 +69,10 @@ class PayPalExpressPaymentDriver extends BasePaymentDriver
protected $customer_reference = ''; protected $customer_reference = '';
public function setPaymentMethod($payment_method_id = null)
{
return $this;
}
public function gatewayTypes() public function gatewayTypes()
{ {
@ -283,32 +287,29 @@ class PayPalExpressPaymentDriver extends BasePaymentDriver
->send(); ->send();
if ($response->isSuccessful()) { if ($response->isSuccessful()) {
SystemLogger::dispatch( SystemLogger::dispatch([
[ 'server_response' => $response->getMessage(), 'data' => request()->all(),
'server_response' => $response->getMessage(), ], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_PAYPAL, $this->client);
'data' => request()->all(),
],
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_PAYPAL,
$this->client
);
return true; return [
'transaction_reference' => $response->getData()['REFUNDTRANSACTIONID'],
'transaction_response' => json_encode($response->getData()),
'success' => true,
'description' => $response->getData()['ACK'],
'code' => $response->getCode(),
];
} }
SystemLogger::dispatch( SystemLogger::dispatch([
[ 'server_response' => $response->getMessage(), 'data' => request()->all(),
'server_response' => $response->getMessage(), ], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_PAYPAL, $this->client);
'data' => request()->all(),
],
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_PAYPAL,
$this->client
);
return [
return false; 'transaction_reference' => $response->getData()['CORRELATIONID'],
'transaction_response' => json_encode($response->getData()),
'success' => false,
'description' => $response->getData()['L_LONGMESSAGE0'],
'code' => $response->getData()['L_ERRORCODE0'],
];
} }
} }

View File

@ -49,6 +49,7 @@ class Alipay
'hashed_ids' => implode(",", $data['hashed_ids']), 'hashed_ids' => implode(",", $data['hashed_ids']),
'amount' => $data['amount'], 'amount' => $data['amount'],
'fee' => $data['fee'], 'fee' => $data['fee'],
'payment_method_id' => GatewayType::SOFORT,
]); ]);
} }

View File

@ -162,7 +162,7 @@ class CreditCard
$payment_type = PaymentType::parseCardType($payment_method_object['card']['brand']); $payment_type = PaymentType::parseCardType($payment_method_object['card']['brand']);
if ($state['save_card'] === true) { if ($state['save_card'] == true) {
$this->saveCard($state); $this->saveCard($state);
} }
@ -216,7 +216,7 @@ class CreditCard
$company_gateway_token = new ClientGatewayToken(); $company_gateway_token = new ClientGatewayToken();
$company_gateway_token->company_id = $this->stripe->client->company->id; $company_gateway_token->company_id = $this->stripe->client->company->id;
$company_gateway_token->client_id = $this->stripe->client->id; $company_gateway_token->client_id = $this->stripe->client->id;
$company_gateway_token->token = $state['payment_method']; $company_gateway_token->token = $state['payment_method']->id;
$company_gateway_token->company_gateway_id = $this->stripe->company_gateway->id; $company_gateway_token->company_gateway_id = $this->stripe->company_gateway->id;
$company_gateway_token->gateway_type_id = $state['gateway_type_id']; $company_gateway_token->gateway_type_id = $state['gateway_type_id'];
$company_gateway_token->gateway_customer_reference = $state['customer']; $company_gateway_token->gateway_customer_reference = $state['customer'];

View File

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Invoice Ninja (https://invoiceninja.com) * Invoice Ninja (https://invoiceninja.com)
* *
@ -21,6 +22,10 @@ use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\PaymentType; use App\Models\PaymentType;
use App\Models\SystemLog; use App\Models\SystemLog;
use App\PaymentDrivers\Stripe\ACH;
use App\PaymentDrivers\Stripe\Alipay;
use App\PaymentDrivers\Stripe\CreditCard;
use App\PaymentDrivers\Stripe\SOFORT;
use App\PaymentDrivers\Stripe\Utilities; use App\PaymentDrivers\Stripe\Utilities;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@ -43,6 +48,15 @@ class StripePaymentDriver extends BasePaymentDriver
protected $payment_method; protected $payment_method;
public static $methods = [
GatewayType::CREDIT_CARD => CreditCard::class,
GatewayType::BANK_TRANSFER => ACH::class,
GatewayType::ALIPAY => Alipay::class,
GatewayType::SOFORT => SOFORT::class,
GatewayType::APPLE_PAY => 1,
GatewayType::SEPA => 1,
];
/** /**
* Methods in this class are divided into * Methods in this class are divided into
* two separate streams * two separate streams
@ -60,16 +74,16 @@ class StripePaymentDriver extends BasePaymentDriver
* Initializes the Stripe API * Initializes the Stripe API
* @return void * @return void
*/ */
public function init() :void public function init(): void
{ {
Stripe::setApiKey($this->company_gateway->getConfigField('apiKey')); Stripe::setApiKey($this->company_gateway->getConfigField('apiKey'));
} }
public function setPaymentMethod(string $method) public function setPaymentMethod($payment_method_id)
{ {
// Example: setPaymentMethod('App\\PaymentDrivers\\Stripe\\CreditCard'); $class = self::$methods[$payment_method_id];
$this->payment_method = new $method($this); $this->payment_method = new $class($this);
return $this; return $this;
} }
@ -77,7 +91,7 @@ class StripePaymentDriver extends BasePaymentDriver
/** /**
* Returns the gateway types * Returns the gateway types
*/ */
public function gatewayTypes() :array public function gatewayTypes(): array
{ {
$types = [ $types = [
GatewayType::CREDIT_CARD, GatewayType::CREDIT_CARD,
@ -208,7 +222,7 @@ class StripePaymentDriver extends BasePaymentDriver
return $this->payment_method->paymentResponse($request); return $this->payment_method->paymentResponse($request);
} }
public function createPayment($data, $status = Payment::STATUS_COMPLETED) :Payment public function createPayment($data, $status = Payment::STATUS_COMPLETED): Payment
{ {
$payment = parent::createPayment($data, $status); $payment = parent::createPayment($data, $status);
@ -230,7 +244,7 @@ class StripePaymentDriver extends BasePaymentDriver
* @param array $data The data array to be passed to Stripe * @param array $data The data array to be passed to Stripe
* @return PaymentIntent The Stripe payment intent object * @return PaymentIntent The Stripe payment intent object
*/ */
public function createPaymentIntent($data) :?\Stripe\PaymentIntent public function createPaymentIntent($data): ?\Stripe\PaymentIntent
{ {
$this->init(); $this->init();
@ -243,7 +257,7 @@ class StripePaymentDriver extends BasePaymentDriver
* *
* @return \Stripe\SetupIntent * @return \Stripe\SetupIntent
*/ */
public function getSetupIntent() :\Stripe\SetupIntent public function getSetupIntent(): \Stripe\SetupIntent
{ {
$this->init(); $this->init();
@ -255,7 +269,7 @@ class StripePaymentDriver extends BasePaymentDriver
* Returns the Stripe publishable key * Returns the Stripe publishable key
* @return NULL|string The stripe publishable key * @return NULL|string The stripe publishable key
*/ */
public function getPublishableKey() :?string public function getPublishableKey(): ?string
{ {
return $this->company_gateway->getPublishableKey(); return $this->company_gateway->getPublishableKey();
} }
@ -265,7 +279,7 @@ class StripePaymentDriver extends BasePaymentDriver
* *
* @return NULL|\Stripe\Customer A Stripe customer object * @return NULL|\Stripe\Customer A Stripe customer object
*/ */
public function findOrCreateCustomer() :?\Stripe\Customer public function findOrCreateCustomer(): ?\Stripe\Customer
{ {
$customer = null; $customer = null;
@ -298,36 +312,34 @@ class StripePaymentDriver extends BasePaymentDriver
$this->gateway(); $this->gateway();
$response = $this->gateway $response = $this->gateway
->refund(['transactionReference'=>$payment->transaction_reference, 'amount' => $amount, 'currency' => $payment->client->getCurrencyCode()]) ->refund(['transactionReference' => $payment->transaction_reference, 'amount' => $amount, 'currency' => $payment->client->getCurrencyCode()])
->send(); ->send();
if ($response->isSuccessful()) { if ($response->isSuccessful()) {
SystemLogger::dispatch( SystemLogger::dispatch([
[ 'server_response' => $response->getMessage(), 'data' => request()->all(),
'server_response' => $response->getMessage(), ], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_STRIPE, $this->client);
'data' => request()->all(),
],
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_PAYPAL,
$this->client
);
return true; return [
'transaction_reference' => $response->getData()['id'],
'transaction_response' => json_encode($response->getData()),
'success' => $response->getData()['refunded'],
'description' => $response->getData()['description'],
'code' => $response->getCode(),
];
} }
SystemLogger::dispatch( SystemLogger::dispatch([
[ 'server_response' => $response->getMessage(), 'data' => request()->all(),
'server_response' => $response->getMessage(), ], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->client);
'data' => request()->all(),
],
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_PAYPAL,
$this->client
);
return false; return [
'transaction_reference' => null,
'transaction_response' => json_encode($response->getData()),
'success' => false,
'description' => $response->getData()['error']['message'],
'code' => $response->getData()['error']['code'],
];
} }
public function verificationView(ClientGatewayToken $payment_method) public function verificationView(ClientGatewayToken $payment_method)

View File

@ -24,6 +24,8 @@ class RefundPayment
private $gateway_refund_status; private $gateway_refund_status;
private $activity_repository;
public function __construct($payment, $refund_data) public function __construct($payment, $refund_data)
{ {
$this->payment = $payment; $this->payment = $payment;
@ -33,6 +35,8 @@ class RefundPayment
$this->total_refund = 0; $this->total_refund = 0;
$this->gateway_refund_status = false; $this->gateway_refund_status = false;
$this->activity_repository = new ActivityRepository();
} }
/** /**
@ -54,27 +58,35 @@ class RefundPayment
private function processGatewayRefund() private function processGatewayRefund()
{ {
if ($this->refund_data['gateway_refund'] !== false && $this->total_refund > 0) { if ($this->refund_data['gateway_refund'] !== false && $this->total_refund > 0) {
$gateway = CompanyGateway::first();
$gateway = CompanyGateway::find($this->payment->company_gateway_id);
if ($gateway) { if ($gateway) {
$response = $gateway->driver($this->payment->client)->refund($this->payment, $this->total_refund); $response = $gateway->driver($this->payment->client)->refund($this->payment, $this->total_refund);
if (!$response) { if ($response['success']) {
throw new PaymentRefundFailed(); throw new PaymentRefundFailed();
} }
info(print_r($response,1));
//todo
//need to check the gateway response has successfully be transacted.
//if a credit has been generated I think this is the correct section to fix the balance of the credit $this->payment->refunded = $this->total_refund;
$activity = [
'payment_id' => $this->payment->id,
'user_id' => $this->payment->user->id,
'company_id' => $this->payment->company->id,
'activity_type_id' => Activity::REFUNDED_PAYMENT,
'credit_id' => 1, // ???
'notes' => $response,
];
/** Persist activiy to database. */
// $this->activity_repository->save($activity, ??);
/** Substract credit amount from the refunded value. */
} }
} } else {
else
$this->payment->refunded += $this->total_refund; $this->payment->refunded += $this->total_refund;
}
return $this; return $this;
} }
@ -105,7 +117,7 @@ class RefundPayment
private function calculateTotalRefund() private function calculateTotalRefund()
{ {
if(isset($this->refund_data['invoices']) && count($this->refund_data['invoices']) > 0) if (isset($this->refund_data['invoices']) && count($this->refund_data['invoices']) > 0)
$this->total_refund = collect($this->refund_data['invoices'])->sum('amount'); $this->total_refund = collect($this->refund_data['invoices'])->sum('amount');
else else
$this->total_refund = $this->refund_data['amount']; $this->total_refund = $this->refund_data['amount'];
@ -145,10 +157,8 @@ class RefundPayment
{ {
$ledger_string = ''; $ledger_string = '';
if(isset($this->refund_data['invoices']) && count($this->refund_data['invoices']) > 0) if (isset($this->refund_data['invoices']) && count($this->refund_data['invoices']) > 0) {
{ foreach ($this->refund_data['invoices'] as $invoice) {
foreach ($this->refund_data['invoices'] as $invoice)
{
$inv = Invoice::find($invoice['invoice_id']); $inv = Invoice::find($invoice['invoice_id']);
@ -164,9 +174,7 @@ class RefundPayment
$line_items[] = $credit_line_item; $line_items[] = $credit_line_item;
} }
} } else {
else
{
$credit_line_item = InvoiceItemFactory::create(); $credit_line_item = InvoiceItemFactory::create();
$credit_line_item->quantity = 1; $credit_line_item->quantity = 1;
@ -188,20 +196,16 @@ class RefundPayment
private function updatePaymentables() private function updatePaymentables()
{ {
if(isset($this->refund_data['invoices']) && count($this->refund_data['invoices']) > 0) if (isset($this->refund_data['invoices']) && count($this->refund_data['invoices']) > 0) {
{
$this->payment->invoices->each(function ($paymentable_invoice) { $this->payment->invoices->each(function ($paymentable_invoice) {
collect($this->refund_data['invoices'])->each(function ($refunded_invoice) use($paymentable_invoice){ collect($this->refund_data['invoices'])->each(function ($refunded_invoice) use ($paymentable_invoice) {
if($refunded_invoice['invoice_id'] == $paymentable_invoice->id) if ($refunded_invoice['invoice_id'] == $paymentable_invoice->id) {
{
$paymentable_invoice->pivot->refunded += $refunded_invoice['amount']; $paymentable_invoice->pivot->refunded += $refunded_invoice['amount'];
$paymentable_invoice->pivot->save(); $paymentable_invoice->pivot->save();
} }
}); });
}); });
} }
@ -248,8 +252,7 @@ class RefundPayment
{ {
$adjustment_amount = 0; $adjustment_amount = 0;
if(isset($this->refund_data['invoices']) && count($this->refund_data['invoices']) > 0) if (isset($this->refund_data['invoices']) && count($this->refund_data['invoices']) > 0) {
{
foreach ($this->refund_data['invoices'] as $refunded_invoice) { foreach ($this->refund_data['invoices'] as $refunded_invoice) {
$invoice = Invoice::find($refunded_invoice['invoice_id']); $invoice = Invoice::find($refunded_invoice['invoice_id']);
@ -277,7 +280,6 @@ class RefundPayment
$this->payment->client->paid_to_date -= $this->refund_data['amount']; $this->payment->client->paid_to_date -= $this->refund_data['amount'];
$this->payment->client->save(); $this->payment->client->save();
} }
return $this; return $this;