mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-08 13:34:29 -04:00
Merge pull request #5853 from beganovich/v5-2805-tracking-campaign-source
(v5) Passing campaign data into payment flow
This commit is contained in:
commit
c61a94f2d1
@ -162,6 +162,13 @@ class BillingPortalPurchase extends Component
|
|||||||
*/
|
*/
|
||||||
public $passwordless_login_btn = false;
|
public $passwordless_login_btn = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Campaign reference.
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
public $campaign;
|
||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
$this->price = $this->subscription->price;
|
$this->price = $this->subscription->price;
|
||||||
@ -182,8 +189,8 @@ class BillingPortalPurchase extends Component
|
|||||||
$this->validate();
|
$this->validate();
|
||||||
|
|
||||||
$contact = ClientContact::where('email', $this->email)
|
$contact = ClientContact::where('email', $this->email)
|
||||||
->where('company_id', $this->subscription->company_id)
|
->where('company_id', $this->subscription->company_id)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($contact && $this->steps['existing_user'] === false) {
|
if ($contact && $this->steps['existing_user'] === false) {
|
||||||
return $this->steps['existing_user'] = true;
|
return $this->steps['existing_user'] = true;
|
||||||
@ -272,8 +279,8 @@ class BillingPortalPurchase extends Component
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((int)$this->subscription->price == 0)
|
if ((int)$this->subscription->price == 0)
|
||||||
$this->steps['payment_required'] = false;
|
$this->steps['payment_required'] = false;
|
||||||
else
|
else
|
||||||
$this->steps['fetched_payment_methods'] = true;
|
$this->steps['fetched_payment_methods'] = true;
|
||||||
@ -332,7 +339,7 @@ class BillingPortalPurchase extends Component
|
|||||||
|
|
||||||
$is_eligible = $this->subscription->service()->isEligible($this->contact);
|
$is_eligible = $this->subscription->service()->isEligible($this->contact);
|
||||||
|
|
||||||
if ($is_eligible['exception']['message'] != 'Success') {
|
if (is_array($is_eligible) && $is_eligible['exception']['message'] != 'Success') {
|
||||||
$this->steps['not_eligible'] = true;
|
$this->steps['not_eligible'] = true;
|
||||||
$this->steps['not_eligible_message'] = $is_eligible['exception']['message'];
|
$this->steps['not_eligible_message'] = $is_eligible['exception']['message'];
|
||||||
$this->steps['show_loading_bar'] = false;
|
$this->steps['show_loading_bar'] = false;
|
||||||
@ -341,13 +348,13 @@ class BillingPortalPurchase extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
Cache::put($this->hash, [
|
Cache::put($this->hash, [
|
||||||
'subscription_id' => $this->subscription->id,
|
'subscription_id' => $this->subscription->id,
|
||||||
'email' => $this->email ?? $this->contact->email,
|
'email' => $this->email ?? $this->contact->email,
|
||||||
'client_id' => $this->contact->client->id,
|
'client_id' => $this->contact->client->id,
|
||||||
'invoice_id' => $this->invoice->id,
|
'invoice_id' => $this->invoice->id,
|
||||||
'context' => 'purchase',
|
'context' => 'purchase',
|
||||||
now()->addMinutes(60)]
|
'campaign' => $this->campaign,
|
||||||
);
|
], now()->addMinutes(60));
|
||||||
|
|
||||||
$this->emit('beforePaymentEventsCompleted');
|
$this->emit('beforePaymentEventsCompleted');
|
||||||
}
|
}
|
||||||
@ -370,7 +377,7 @@ class BillingPortalPurchase extends Component
|
|||||||
public function handlePaymentNotRequired()
|
public function handlePaymentNotRequired()
|
||||||
{
|
{
|
||||||
|
|
||||||
$is_eligible = $this->subscription->service()->isEligible($this->contact);
|
$is_eligible = $this->subscription->service()->isEligible($this->contact);
|
||||||
|
|
||||||
if ($is_eligible['status_code'] != 200) {
|
if ($is_eligible['status_code'] != 200) {
|
||||||
$this->steps['not_eligible'] = true;
|
$this->steps['not_eligible'] = true;
|
||||||
|
@ -244,6 +244,10 @@ class BaseDriver extends AbstractPaymentDriver
|
|||||||
if (property_exists($this->payment_hash->data, 'billing_context')) {
|
if (property_exists($this->payment_hash->data, 'billing_context')) {
|
||||||
$billing_subscription = \App\Models\Subscription::find($this->payment_hash->data->billing_context->subscription_id);
|
$billing_subscription = \App\Models\Subscription::find($this->payment_hash->data->billing_context->subscription_id);
|
||||||
|
|
||||||
|
// To access campaign hash => $this->payment_hash->data->billing_context->campaign;
|
||||||
|
// To access campaign data => Cache::get(CAMPAIGN_HASH)
|
||||||
|
// To access utm data => session()->get('utm-' . CAMPAIGN_HASH);
|
||||||
|
|
||||||
(new SubscriptionService($billing_subscription))->completePurchase($this->payment_hash);
|
(new SubscriptionService($billing_subscription))->completePurchase($this->payment_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +52,8 @@ class SubscriptionService
|
|||||||
$this->subscription = $subscription;
|
$this->subscription = $subscription;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Performs the initial purchase of a
|
Performs the initial purchase of a
|
||||||
one time or recurring product
|
one time or recurring product
|
||||||
*/
|
*/
|
||||||
public function completePurchase(PaymentHash $payment_hash)
|
public function completePurchase(PaymentHash $payment_hash)
|
||||||
@ -184,13 +184,13 @@ class SubscriptionService
|
|||||||
/**
|
/**
|
||||||
* Returns an upgrade price when moving between plans
|
* Returns an upgrade price when moving between plans
|
||||||
*
|
*
|
||||||
* However we only allow people to move between plans
|
* However we only allow people to move between plans
|
||||||
* if their account is in good standing.
|
* if their account is in good standing.
|
||||||
*
|
*
|
||||||
* @param RecurringInvoice $recurring_invoice
|
* @param RecurringInvoice $recurring_invoice
|
||||||
* @param Subscription $target
|
* @param Subscription $target
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function calculateUpgradePrice(RecurringInvoice $recurring_invoice, Subscription $target) :?float
|
public function calculateUpgradePrice(RecurringInvoice $recurring_invoice, Subscription $target) :?float
|
||||||
{
|
{
|
||||||
@ -210,7 +210,7 @@ class SubscriptionService
|
|||||||
->where('client_id', $recurring_invoice->client_id)
|
->where('client_id', $recurring_invoice->client_id)
|
||||||
->where('is_deleted', 0)
|
->where('is_deleted', 0)
|
||||||
->orderBy('id', 'desc')
|
->orderBy('id', 'desc')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($outstanding->count() == 0){
|
if ($outstanding->count() == 0){
|
||||||
//nothing outstanding
|
//nothing outstanding
|
||||||
@ -232,15 +232,15 @@ class SubscriptionService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* We refund unused days left.
|
* We refund unused days left.
|
||||||
*
|
*
|
||||||
* @param Invoice $invoice
|
* @param Invoice $invoice
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
private function calculateProRataRefund($invoice) :float
|
private function calculateProRataRefund($invoice) :float
|
||||||
{
|
{
|
||||||
if(!$this->invoice->date)
|
if(!$this->invoice->date)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
$start_date = Carbon::parse($invoice->date);
|
$start_date = Carbon::parse($invoice->date);
|
||||||
|
|
||||||
$current_date = now();
|
$current_date = now();
|
||||||
@ -259,9 +259,9 @@ class SubscriptionService
|
|||||||
* Returns refundable set of line items
|
* Returns refundable set of line items
|
||||||
* transformed for direct injection into
|
* transformed for direct injection into
|
||||||
* the invoice
|
* the invoice
|
||||||
*
|
*
|
||||||
* @param Invoice $invoice
|
* @param Invoice $invoice
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function calculateProRataRefundItems($invoice, $is_credit = false) :array
|
private function calculateProRataRefundItems($invoice, $is_credit = false) :array
|
||||||
{
|
{
|
||||||
@ -285,14 +285,14 @@ class SubscriptionService
|
|||||||
|
|
||||||
if($item->product_key != ctrans('texts.refund'))
|
if($item->product_key != ctrans('texts.refund'))
|
||||||
{
|
{
|
||||||
|
|
||||||
$item->cost = ($item->cost*$ratio*$multiplier);
|
$item->cost = ($item->cost*$ratio*$multiplier);
|
||||||
$item->product_key = ctrans('texts.refund');
|
$item->product_key = ctrans('texts.refund');
|
||||||
$item->notes = ctrans('texts.refund') . ": ". $item->notes;
|
$item->notes = ctrans('texts.refund') . ": ". $item->notes;
|
||||||
|
|
||||||
|
|
||||||
$line_items[] = $item;
|
$line_items[] = $item;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,13 +302,13 @@ class SubscriptionService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* We only charge for the used days
|
* We only charge for the used days
|
||||||
*
|
*
|
||||||
* @param Invoice $invoice
|
* @param Invoice $invoice
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
private function calculateProRataCharge($invoice) :float
|
private function calculateProRataCharge($invoice) :float
|
||||||
{
|
{
|
||||||
|
|
||||||
$start_date = Carbon::parse($invoice->date);
|
$start_date = Carbon::parse($invoice->date);
|
||||||
|
|
||||||
$current_date = now();
|
$current_date = now();
|
||||||
@ -320,7 +320,7 @@ class SubscriptionService
|
|||||||
nlog("days to charge = {$days_to_charge} fays in frequency = {$days_in_frequency}");
|
nlog("days to charge = {$days_to_charge} fays in frequency = {$days_in_frequency}");
|
||||||
|
|
||||||
$pro_rata_charge = round(($days_to_charge/$days_in_frequency) * $invoice->amount ,2);
|
$pro_rata_charge = round(($days_to_charge/$days_in_frequency) * $invoice->amount ,2);
|
||||||
|
|
||||||
nlog("pro rata charge = {$pro_rata_charge}");
|
nlog("pro rata charge = {$pro_rata_charge}");
|
||||||
|
|
||||||
return $pro_rata_charge;
|
return $pro_rata_charge;
|
||||||
@ -329,15 +329,15 @@ class SubscriptionService
|
|||||||
/**
|
/**
|
||||||
* When downgrading, we may need to create
|
* When downgrading, we may need to create
|
||||||
* a credit
|
* a credit
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
*/
|
*/
|
||||||
public function createChangePlanCredit($data)
|
public function createChangePlanCredit($data)
|
||||||
{
|
{
|
||||||
$recurring_invoice = $data['recurring_invoice'];
|
$recurring_invoice = $data['recurring_invoice'];
|
||||||
$old_subscription = $data['subscription'];
|
$old_subscription = $data['subscription'];
|
||||||
$target_subscription = $data['target'];
|
$target_subscription = $data['target'];
|
||||||
|
|
||||||
$pro_rata_charge_amount = 0;
|
$pro_rata_charge_amount = 0;
|
||||||
$pro_rata_refund_amount = 0;
|
$pro_rata_refund_amount = 0;
|
||||||
|
|
||||||
@ -346,9 +346,9 @@ class SubscriptionService
|
|||||||
->where('is_deleted', 0)
|
->where('is_deleted', 0)
|
||||||
->withTrashed()
|
->withTrashed()
|
||||||
->orderBy('id', 'desc')
|
->orderBy('id', 'desc')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if($last_invoice->balance > 0)
|
if($last_invoice->balance > 0)
|
||||||
{
|
{
|
||||||
$pro_rata_charge_amount = $this->calculateProRataCharge($last_invoice, $old_subscription);
|
$pro_rata_charge_amount = $this->calculateProRataCharge($last_invoice, $old_subscription);
|
||||||
nlog("pro rata charge = {$pro_rata_charge_amount}");
|
nlog("pro rata charge = {$pro_rata_charge_amount}");
|
||||||
@ -364,7 +364,7 @@ class SubscriptionService
|
|||||||
nlog("total payable = {$total_payable}");
|
nlog("total payable = {$total_payable}");
|
||||||
|
|
||||||
$credit = $this->createCredit($last_invoice, $target_subscription);
|
$credit = $this->createCredit($last_invoice, $target_subscription);
|
||||||
|
|
||||||
$new_recurring_invoice = $this->createNewRecurringInvoice($recurring_invoice);
|
$new_recurring_invoice = $this->createNewRecurringInvoice($recurring_invoice);
|
||||||
|
|
||||||
$context = [
|
$context = [
|
||||||
@ -386,9 +386,9 @@ class SubscriptionService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* When changing plans, we need to generate a pro rata invoice
|
* When changing plans, we need to generate a pro rata invoice
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return Invoice
|
* @return Invoice
|
||||||
*/
|
*/
|
||||||
public function createChangePlanInvoice($data)
|
public function createChangePlanInvoice($data)
|
||||||
{
|
{
|
||||||
@ -404,9 +404,9 @@ class SubscriptionService
|
|||||||
->where('is_deleted', 0)
|
->where('is_deleted', 0)
|
||||||
->withTrashed()
|
->withTrashed()
|
||||||
->orderBy('id', 'desc')
|
->orderBy('id', 'desc')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if($last_invoice->balance > 0)
|
if($last_invoice->balance > 0)
|
||||||
{
|
{
|
||||||
$pro_rata_charge_amount = $this->calculateProRataCharge($last_invoice, $old_subscription);
|
$pro_rata_charge_amount = $this->calculateProRataCharge($last_invoice, $old_subscription);
|
||||||
nlog("pro rata charge = {$pro_rata_charge_amount}");
|
nlog("pro rata charge = {$pro_rata_charge_amount}");
|
||||||
@ -424,10 +424,10 @@ class SubscriptionService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response from payment service on
|
* Response from payment service on
|
||||||
* return from a plan change
|
* return from a plan change
|
||||||
*
|
*
|
||||||
* @param PaymentHash $payment_hash
|
* @param PaymentHash $payment_hash
|
||||||
*/
|
*/
|
||||||
private function handlePlanChange($payment_hash)
|
private function handlePlanChange($payment_hash)
|
||||||
{
|
{
|
||||||
@ -457,9 +457,9 @@ class SubscriptionService
|
|||||||
/**
|
/**
|
||||||
* Creates a new recurring invoice when changing
|
* Creates a new recurring invoice when changing
|
||||||
* plans
|
* plans
|
||||||
*
|
*
|
||||||
* @param RecurringInvoice $old_recurring_invoice
|
* @param RecurringInvoice $old_recurring_invoice
|
||||||
* @return RecurringInvoice
|
* @return RecurringInvoice
|
||||||
*/
|
*/
|
||||||
private function createNewRecurringInvoice($old_recurring_invoice) :RecurringInvoice
|
private function createNewRecurringInvoice($old_recurring_invoice) :RecurringInvoice
|
||||||
{
|
{
|
||||||
@ -512,10 +512,10 @@ class SubscriptionService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a credit note if the plan change requires
|
* Creates a credit note if the plan change requires
|
||||||
*
|
*
|
||||||
* @param Invoice $last_invoice
|
* @param Invoice $last_invoice
|
||||||
* @param Subscription $target
|
* @param Subscription $target
|
||||||
* @return Credit
|
* @return Credit
|
||||||
*/
|
*/
|
||||||
private function createCredit($last_invoice, $target)
|
private function createCredit($last_invoice, $target)
|
||||||
{
|
{
|
||||||
@ -544,10 +544,10 @@ class SubscriptionService
|
|||||||
/**
|
/**
|
||||||
* When changing plans we need to generate a pro rata
|
* When changing plans we need to generate a pro rata
|
||||||
* invoice which takes into account any credits.
|
* invoice which takes into account any credits.
|
||||||
*
|
*
|
||||||
* @param Invoice $last_invoice
|
* @param Invoice $last_invoice
|
||||||
* @param Subscription $target
|
* @param Subscription $target
|
||||||
* @return Invoice
|
* @return Invoice
|
||||||
*/
|
*/
|
||||||
private function proRataInvoice($last_invoice, $target)
|
private function proRataInvoice($last_invoice, $target)
|
||||||
{
|
{
|
||||||
@ -576,9 +576,9 @@ class SubscriptionService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the first invoice when a subscription is purchased
|
* Generates the first invoice when a subscription is purchased
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return Invoice
|
* @return Invoice
|
||||||
*/
|
*/
|
||||||
public function createInvoice($data): ?\App\Models\Invoice
|
public function createInvoice($data): ?\App\Models\Invoice
|
||||||
{
|
{
|
||||||
@ -603,9 +603,9 @@ class SubscriptionService
|
|||||||
/**
|
/**
|
||||||
* Generates a recurring invoice based on
|
* Generates a recurring invoice based on
|
||||||
* the specifications of the subscription
|
* the specifications of the subscription
|
||||||
*
|
*
|
||||||
* @param int $client_id The Client Id
|
* @param int $client_id The Client Id
|
||||||
* @return RecurringInvoice
|
* @return RecurringInvoice
|
||||||
*/
|
*/
|
||||||
public function convertInvoiceToRecurring($client_id) :RecurringInvoice
|
public function convertInvoiceToRecurring($client_id) :RecurringInvoice
|
||||||
{
|
{
|
||||||
@ -626,12 +626,11 @@ class SubscriptionService
|
|||||||
/**
|
/**
|
||||||
* Hit a 3rd party API if defined in the subscription
|
* Hit a 3rd party API if defined in the subscription
|
||||||
*
|
*
|
||||||
* @param array $context
|
* @param array $context
|
||||||
*/
|
*/
|
||||||
public function triggerWebhook($context)
|
public function triggerWebhook($context)
|
||||||
{
|
{
|
||||||
/* If no webhooks have been set, then just return gracefully */
|
if (empty($this->subscription->webhook_configuration['post_purchase_url']) || empty($this->subscription->webhook_configuration['post_purchase_rest_method'])) {
|
||||||
if(!array_key_exists('post_purchase_url', $this->subscription->webhook_configuration) || !array_key_exists('post_purchase_rest_method', $this->subscription->webhook_configuration)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,7 +666,7 @@ class SubscriptionService
|
|||||||
SystemLog::CATEGORY_WEBHOOK,
|
SystemLog::CATEGORY_WEBHOOK,
|
||||||
SystemLog::EVENT_WEBHOOK_RESPONSE,
|
SystemLog::EVENT_WEBHOOK_RESPONSE,
|
||||||
SystemLog::TYPE_WEBHOOK_RESPONSE,
|
SystemLog::TYPE_WEBHOOK_RESPONSE,
|
||||||
$client,
|
$client,
|
||||||
$client->company,
|
$client->company,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -718,9 +717,9 @@ class SubscriptionService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the cancellation of a subscription
|
* Handle the cancellation of a subscription
|
||||||
*
|
*
|
||||||
* @param RecurringInvoice $recurring_invoice
|
* @param RecurringInvoice $recurring_invoice
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function handleCancellation(RecurringInvoice $recurring_invoice)
|
public function handleCancellation(RecurringInvoice $recurring_invoice)
|
||||||
{
|
{
|
||||||
@ -730,7 +729,7 @@ class SubscriptionService
|
|||||||
->where('client_id', $recurring_invoice->client_id)
|
->where('client_id', $recurring_invoice->client_id)
|
||||||
->where('is_deleted', 0)
|
->where('is_deleted', 0)
|
||||||
->orderBy('id', 'desc')
|
->orderBy('id', 'desc')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
$invoice_start_date = Carbon::parse($outstanding_invoice->date);
|
$invoice_start_date = Carbon::parse($outstanding_invoice->date);
|
||||||
$refund_end_date = $invoice_start_date->addSeconds($this->subscription->refund_period);
|
$refund_end_date = $invoice_start_date->addSeconds($this->subscription->refund_period);
|
||||||
@ -807,15 +806,15 @@ class SubscriptionService
|
|||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 'email' => $this->email ?? $this->contact->email,
|
* 'email' => $this->email ?? $this->contact->email,
|
||||||
* 'quantity' => $this->quantity,
|
* 'quantity' => $this->quantity,
|
||||||
* 'contact_id' => $this->contact->id,
|
* 'contact_id' => $this->contact->id,
|
||||||
*/
|
*/
|
||||||
public function handleNoPaymentRequired(array $data)
|
public function handleNoPaymentRequired(array $data)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -827,7 +826,7 @@ class SubscriptionService
|
|||||||
|
|
||||||
// Hit the redirect
|
// Hit the redirect
|
||||||
return $this->handleRedirect($context['redirect_url']);
|
return $this->handleRedirect($context['redirect_url']);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -840,5 +839,5 @@ class SubscriptionService
|
|||||||
return redirect($this->subscription->webhook_configuration['return_url']);
|
return redirect($this->subscription->webhook_configuration['return_url']);
|
||||||
|
|
||||||
return redirect($default_redirect);
|
return redirect($default_redirect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
@section('meta_title', ctrans('texts.purchase'))
|
@section('meta_title', ctrans('texts.purchase'))
|
||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
@livewire('billing-portal-purchase', ['subscription' => $subscription, 'contact' => auth('contact')->user(), 'hash' => $hash, 'request_data' => $request_data])
|
@livewire('billing-portal-purchase', ['subscription' => $subscription, 'contact' => auth('contact')->user(), 'hash' => $hash, 'request_data' => $request_data, 'campaign' => request()->query('campaign') ?? null])
|
||||||
@stop
|
@stop
|
||||||
|
|
||||||
@push('footer')
|
@push('footer')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user