mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Store payment after invoice is confirmed paid
This commit is contained in:
parent
5090c963d3
commit
362f197fbb
@ -24,6 +24,7 @@ use App\Models\Filterable;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\GroupSetting;
|
||||
use App\Models\Timezone;
|
||||
use App\Models\User;
|
||||
use App\Utils\Traits\CompanyGatewaySettings;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
@ -137,6 +138,11 @@ class Client extends BaseModel
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function country()
|
||||
{
|
||||
return $this->belongsTo(Country::class);
|
||||
|
@ -19,4 +19,61 @@ class PaymentType extends StaticModel
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
const CREDIT = 1;
|
||||
const ACH = 5;
|
||||
const VISA = 6;
|
||||
const MASTERCARD = 7;
|
||||
const AMERICAN_EXPRESS = 8;
|
||||
const DISCOVER = 9;
|
||||
const DINERS = 10;
|
||||
const EUROCARD = 11;
|
||||
const NOVA = 12;
|
||||
const CREDIT_CARD_OTHER = 13;
|
||||
const PAYPAL = 14;
|
||||
const CARTE_BLANCHE = 17;
|
||||
const UNIONPAY = 18;
|
||||
const JCB = 19;
|
||||
const LASER = 20;
|
||||
const MAESTRO = 21;
|
||||
const SOLO = 22;
|
||||
const SWITCH = 23;
|
||||
const ALIPAY = 28;
|
||||
const SOFORT = 29;
|
||||
const SEPA = 30;
|
||||
const GOCARDLESS = 31;
|
||||
const BITCOIN = 32;
|
||||
|
||||
public static function parseCardType($cardName)
|
||||
{
|
||||
$cardTypes = [
|
||||
'visa' => self::VISA,
|
||||
'americanexpress' => self::AMERICAN_EXPRESS,
|
||||
'amex' => self::AMERICAN_EXPRESS,
|
||||
'mastercard' => self::MASTERCARD,
|
||||
'discover' => self::DISCOVER,
|
||||
'jcb' => self::JCB,
|
||||
'dinersclub' => self::DINERS,
|
||||
'carteblanche' => self::CARTE_BLANCHE,
|
||||
'chinaunionpay' => self::UNIONPAY,
|
||||
'unionpay' => self::UNIONPAY,
|
||||
'laser' => self::LASER,
|
||||
'maestro' => self::MAESTRO,
|
||||
'solo' => self::SOLO,
|
||||
'switch' => self::SWITCH,
|
||||
];
|
||||
|
||||
$cardName = strtolower(str_replace([' ', '-', '_'], '', $cardName));
|
||||
|
||||
if (empty($cardTypes[$cardName]) && 1 == preg_match('/^('.implode('|', array_keys($cardTypes)).')/', $cardName, $matches)) {
|
||||
// Some gateways return extra stuff after the card name
|
||||
$cardName = $matches[1];
|
||||
}
|
||||
|
||||
if (! empty($cardTypes[$cardName])) {
|
||||
return $cardTypes[$cardName];
|
||||
} else {
|
||||
return self::CREDIT_CARD_OTHER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,10 @@
|
||||
namespace App\PaymentDrivers;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\CompanyGateway;
|
||||
use App\Models\GatewayType;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Omnipay\Omnipay;
|
||||
|
||||
|
||||
@ -123,6 +125,16 @@ class BasePaymentDriver
|
||||
|
||||
public function processPaymentResponse($request) {}
|
||||
|
||||
public function getContact()
|
||||
{
|
||||
if($this->invitation)
|
||||
return ClientContact::find($this->invitation->client_contact_id);
|
||||
elseif(auth()->guard('contact')->user())
|
||||
return auth()->user();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/************************************* Omnipay ******************************************
|
||||
authorize($options) - authorize an amount on the customer's card
|
||||
completeAuthorize($options) - handle return from off-site gateways after authorization
|
||||
|
@ -11,34 +11,31 @@
|
||||
|
||||
namespace App\PaymentDrivers;
|
||||
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Models\ClientGatewayToken;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\PaymentType;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Stripe\PaymentIntent;
|
||||
use Stripe\SetupIntent;
|
||||
use Stripe\Stripe;
|
||||
|
||||
class StripePaymentDriver extends BasePaymentDriver
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
protected $refundable = true;
|
||||
|
||||
protected $token_billing = true;
|
||||
|
||||
protected $can_authorise_credit_card = true;
|
||||
protected $can_authorise_credit_card = true;
|
||||
|
||||
protected $customer_reference = 'customerReferenceParam';
|
||||
|
||||
/**
|
||||
* Payments
|
||||
* \Stripe\PaymentIntent::create([
|
||||
'payment_method_types' => ['card'],
|
||||
'amount' => 1099,
|
||||
'currency' => 'aud',
|
||||
'customer' => 'cus_Fow2nmVJX1EsQw',
|
||||
'payment_method' => 'card_1FJIAjKmol8YQE9DxWb9kMpR',
|
||||
]);
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Methods in this class are divided into
|
||||
* two separate streams
|
||||
@ -128,6 +125,14 @@ class StripePaymentDriver extends BasePaymentDriver
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Authorises a credit card for future use
|
||||
* @param array $data Array of variables needed for the view
|
||||
*
|
||||
* @return view The gateway specific partial to be rendered
|
||||
*
|
||||
*/
|
||||
public function authorizeCreditCardView(array $data)
|
||||
{
|
||||
|
||||
@ -137,6 +142,11 @@ class StripePaymentDriver extends BasePaymentDriver
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the gateway response for credti card authorization
|
||||
* @param Request $request The returning request object
|
||||
* @return view Returns the user to payment methods screen.
|
||||
*/
|
||||
public function authorizeCreditCardResponse($request)
|
||||
{
|
||||
|
||||
@ -203,7 +213,7 @@ class StripePaymentDriver extends BasePaymentDriver
|
||||
public function processPaymentView(array $data)
|
||||
{
|
||||
$payment_intent_data = [
|
||||
'amount' => $data['amount_with_fee']*100,
|
||||
'amount' => $this->convertToStripeAmount($data['amount_with_fee'], $this->client->currency->precision),
|
||||
'currency' => $this->client->getCurrencyCode(),
|
||||
'customer' => $this->findOrCreateCustomer(),
|
||||
'description' => $data['invoices']->pluck('id'), //todo more meaningful description here:
|
||||
@ -260,18 +270,40 @@ class StripePaymentDriver extends BasePaymentDriver
|
||||
$payment_method = $server_response->payment_method;
|
||||
$payment_status = $server_response->status;
|
||||
$save_card = $request->input('store_card');
|
||||
$gateway_type_id = $request->input('gateway_type_id');
|
||||
|
||||
$this->init()
|
||||
$gateway_type_id = $request->input('payment_method_id');
|
||||
$hashed_ids = $request->input('hashed_ids');
|
||||
$invoices = Invoice::whereIn('id', $this->transformKeys(explode(",",$hashed_ids)))
|
||||
->whereClientId($this->client->id)
|
||||
->get();
|
||||
/**
|
||||
* Potential statuses that can be returned
|
||||
*
|
||||
* requires_action
|
||||
* processing
|
||||
* canceled
|
||||
* requires_action
|
||||
* requires_confirmation
|
||||
* requires_payment_method
|
||||
*
|
||||
*/
|
||||
|
||||
if($this->getContact()){
|
||||
$client_contact = $this->getContact();
|
||||
}
|
||||
else{
|
||||
$client_contact = $invoices->first()->invitations->first()->contact;
|
||||
}
|
||||
|
||||
$this->init();
|
||||
$payment_intent = \Stripe\PaymentIntent::retrieve($server_response->id);
|
||||
$customer = $payment_intent->customer;
|
||||
|
||||
if($save_card)
|
||||
if($payment_status == 'succeeded')
|
||||
{
|
||||
$this->init()
|
||||
$this->init();
|
||||
$stripe_payment_method = \Stripe\PaymentMethod::retrieve($payment_method);
|
||||
$stripe_payment_method_obj = $stripe_payment_method->jsonSerialize();
|
||||
$stripe_payment_method->attach(['customer' => $customer]);
|
||||
|
||||
$payment_meta = new \stdClass;
|
||||
|
||||
@ -281,8 +313,15 @@ class StripePaymentDriver extends BasePaymentDriver
|
||||
$payment_meta->brand = $stripe_payment_method_obj['card']['brand'];
|
||||
$payment_meta->last4 = $stripe_payment_method_obj['card']['last4'];
|
||||
$payment_meta->type = $stripe_payment_method_obj['type'];
|
||||
|
||||
$payment_type = PaymentType::parseCardType($stripe_payment_method_obj['card']['brand']);
|
||||
}
|
||||
|
||||
if($save_card == 'true')
|
||||
{
|
||||
|
||||
$stripe_payment_method->attach(['customer' => $customer]);
|
||||
|
||||
$cgt = new ClientGatewayToken;
|
||||
$cgt->company_id = $this->client->company->id;
|
||||
$cgt->client_id = $this->client->id;
|
||||
@ -293,16 +332,46 @@ class StripePaymentDriver extends BasePaymentDriver
|
||||
$cgt->meta = $payment_meta;
|
||||
$cgt->save();
|
||||
|
||||
if($is_default == 'true' || $this->client->gateway_tokens->count() == 1)
|
||||
if($this->client->gateway_tokens->count() == 1)
|
||||
{
|
||||
$this->client->gateway_tokens()->update(['is_default'=>0]);
|
||||
|
||||
$cgt->is_default = 1;
|
||||
$cgt->save();
|
||||
}
|
||||
}
|
||||
|
||||
//todo need to fix this to support payment types other than credit card.... sepa etc etc
|
||||
if(!$payment_type)
|
||||
$payment_type = PaymentType::CREDIT_CARD_OTHER;
|
||||
|
||||
$payment = PaymentFactory::create($this->client->company->id, $this->client->user->id);
|
||||
$payment->client_id = $this->client->id;
|
||||
$payment->client_contact_id = $client_contact->id;
|
||||
$payment->company_gateway_id = $this->company_gateway->id;
|
||||
$payment->status_id = Payment::STATUS_COMPLETED;
|
||||
$payment->amount = $this->convertFromStripeAmount($server_response->amount, $this->client->currency->precision);
|
||||
$payment->payment_date = Carbon::now();
|
||||
$payment->payment_type_id = $payment_type;
|
||||
$payment->transaction_reference = $payment_method;
|
||||
$payment->save();
|
||||
|
||||
$payment->invoices()->sync($invoices);
|
||||
$payment->save();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function convertFromStripeAmount($amount, $precision)
|
||||
{
|
||||
return $amount / pow(10, $precision);
|
||||
}
|
||||
|
||||
private function convertToStripeAmount($amount, $precision)
|
||||
{
|
||||
return $amount * pow(10, $precision);
|
||||
}
|
||||
/**
|
||||
* Creates a new String Payment Intent
|
||||
*
|
||||
@ -377,7 +446,7 @@ class StripePaymentDriver extends BasePaymentDriver
|
||||
}
|
||||
|
||||
if(!$customer)
|
||||
throw Exception('Unable to create gateway customer');
|
||||
throw new Exception('Unable to create gateway customer');
|
||||
|
||||
return $customer;
|
||||
}
|
||||
|
@ -76,8 +76,7 @@
|
||||
$("#card-button").removeAttr("disabled");
|
||||
|
||||
} else {
|
||||
// The setup has succeeded. Display a success message.
|
||||
console.log(result);
|
||||
The card has been successfullly stored.
|
||||
postResult(result);
|
||||
}
|
||||
});
|
||||
|
@ -80,6 +80,7 @@
|
||||
$("#card-errors").empty();
|
||||
$("#card-errors").append("<b>" + result.error.message + "</b>");
|
||||
$("#card-button").removeAttr("disabled");
|
||||
$("#store_card").val(0);
|
||||
|
||||
} else {
|
||||
// The setup has succeeded. Display a success message.
|
||||
|
Loading…
x
Reference in New Issue
Block a user