Skip to content
This repository has been archived by the owner on Nov 30, 2022. It is now read-only.

Commit

Permalink
Completed building most of requirements for billing controller.. todo…
Browse files Browse the repository at this point in the history
…: restore on trial
  • Loading branch information
gnikyt committed Jun 12, 2018
1 parent 0e55c60 commit 9f756bd
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 39 deletions.
2 changes: 1 addition & 1 deletion src/ShopifyApp/Middleware/Billable.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function handle(Request $request, Closure $next)
$query->latestByType(Charge::CHARGE_ONETIME);
})->latest()->first();

if (!$shop->isGrandfathered() && (is_null($lastCharge) || $lastCharge->wasDeclined())) {
if (!$shop->isGrandfathered() && (is_null($lastCharge) || $lastCharge->isDeclined())) {
// They're not grandfathered in, and there is no charge or charge was declined... redirect to billing
return redirect()->route('billing');
}
Expand Down
18 changes: 14 additions & 4 deletions src/ShopifyApp/Models/Charge.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public function isTrial()
*/
public function isActiveTrial()
{
return $this->isTrial() && Carbon::now()->lte(Carbon::parse($this->trial_ends_on));
return $this->isTrial() && Carbon::today()->lte(Carbon::parse($this->trial_ends_on));
}

/**
Expand All @@ -110,7 +110,7 @@ public function remainingTrialDays()
return null;
}

return $this->isActiveTrial() ? Carbon::now()->diffInDays($this->trial_ends_on) : 0;
return $this->isActiveTrial() ? Carbon::today()->diffInDays($this->trial_ends_on) : 0;
}

/**
Expand All @@ -127,12 +127,22 @@ public function usedTrialDays()
return $this->trial_days - $this->remainingTrialDays();
}

/**
* Checks if the charge is active.
*
* @return bool
*/
public function isActive()
{
return $this->status === 'active';
}

/**
* Checks if the charge was accepted (for one-time and reccuring).
*
* @return bool
*/
public function wasAccepted()
public function isAccepted()
{
return $this->status === 'accepted';
}
Expand All @@ -142,7 +152,7 @@ public function wasAccepted()
*
* @return bool
*/
public function wasDeclined()
public function isDeclined()
{
return $this->status === 'declined';
}
Expand Down
47 changes: 36 additions & 11 deletions src/ShopifyApp/Traits/BillingControllerTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use OhMyBrew\ShopifyApp\Facades\ShopifyApp;
use OhMyBrew\ShopifyApp\Libraries\BillingPlan;
use OhMyBrew\ShopifyApp\Models\Charge;
use Carbon\Carbon;

trait BillingControllerTrait
{
Expand Down Expand Up @@ -38,23 +40,46 @@ public function process()
// Setup the plan and get the charge
$plan = new BillingPlan($shop, $this->chargeType());
$plan->setChargeId($chargeId);
$status = $plan->getCharge()->status;

// Check the customer's answer to the billing
$charge = $plan->getCharge();
if ($charge->status == 'accepted') {
// Customer accepted, activate the charge
$plan->activate();
// Grab the plan detailed used
$planDetails = $this->planDetails();
unset($planDetails['return_url']);

// Save the charge ID to the shop
$shop->charge_id = $chargeId;
$shop->save();
// Create a charge (regardless of the status)
$charge = new Charge();
$charge->type = $this->chargeType() === 'recurring' ? Charge::CHARGE_RECURRING : Charge::CHARGE_ONETIME;
$charge->charge_id = $chargeId;
$charge->status = $status;

// Go to homepage of app
return redirect()->route('home');
// Check the customer's answer to the billing
if ($status === 'accepted') {
// Activate and add details to our charge
$response = $plan->activate();
$charge->status = $response->status;
$charge->billing_on = $response->billing_on;
$charge->trial_ends_on = $response->trial_ends_on;
$charge->activated_on = $response->activated_on;
} else {
// Customer declined the charge, abort
// Customer declined the charge
$charge->cancelled_on = Carbon::today()->format('Y-m-d');
}

// Merge in the plan details since the fields match the database columns
foreach ($planDetails as $key => $value) {
$charge->{$key} = $value;
}

// Save and link to the shop
$shop->charges()->save($charge);

if ($status === 'declined') {
// Show the error... don't allow access
return abort(403, 'It seems you have declined the billing charge for this application');
}

// All good... go to homepage of app
return redirect()->route('home');
}

/**
Expand Down
10 changes: 5 additions & 5 deletions tests/Controllers/BillingControllerTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<?php

namespace OhMyBrew\ShopifyApp\Test\Controllers;

use OhMyBrew\ShopifyApp\Controllers\BillingController;
Expand Down Expand Up @@ -33,20 +32,21 @@ public function testSendsShopToBillingScreen()
public function testShopAcceptsBilling()
{
$shop = Shop::where('shopify_domain', 'example.myshopify.com')->first();
$this->assertEquals(678298290, $shop->charge_id); // Based on seedDatabase()

$response = $this->call('get', '/billing/process', ['charge_id' => 1029266947]);
$shop = $shop->fresh(); // Reload model

$response->assertStatus(302);
$this->assertEquals(1029266947, $shop->charge_id);
$this->assertEquals(1029266947, $shop->charges()->get()->last()->charge_id);
}

public function testShopDeclinesBilling()
{
$shop = Shop::where('shopify_domain', 'example.myshopify.com')->first();
$response = $this->call('get', '/billing/process', ['charge_id' => 10292]);
$lastCharge = $shop->charges()->get()->last();

$response->assertStatus(403);
$this->assertEquals(10292, $lastCharge->charge_id);
$this->assertEquals('declined', $lastCharge->status);
$this->assertEquals(
'It seems you have declined the billing charge for this application',
$response->exception->getMessage()
Expand Down
16 changes: 16 additions & 0 deletions tests/Middleware/BillableMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ public function testEnabledBillingWithUnpaidShop()
$this->assertEquals(true, strpos($result, 'Redirecting to http://localhost/billing') !== false);
}

public function testEnabledBillingWithShopWhoDeclinedCharges()
{
// Enable billing and set a shop
config(['shopify-app.billing_enabled' => true]);
session(['shopify_domain' => 'trashed-shop.myshopify.com']);

$called = false;
$result = (new Billable())->handle(request(), function ($request) use (&$called) {
// Should never be called
$called = true;
});

$this->assertFalse($called);
$this->assertEquals(true, strpos($result, 'Redirecting to http://localhost/billing') !== false);
}

public function testEnabledBillingWithPaidShop()
{
// Enable billing and set a shop
Expand Down
10 changes: 8 additions & 2 deletions tests/Models/ChargeModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,13 @@ public function testUsedTrialDays()

public function testAcceptedAndDeclined()
{
$this->assertTrue(Charge::find(1)->wasAccepted());
$this->assertTrue(!Charge::find(1)->wasDeclined());
$this->assertTrue(Charge::find(1)->isAccepted());
$this->assertFalse(Charge::find(1)->isDeclined());
}

public function testActive()
{
$this->assertFalse(Charge::find(1)->isActive());
$this->assertTrue(Charge::find(4)->isActive());
}
}
29 changes: 22 additions & 7 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ protected function createShops()
}

public function createCharges()
{;
{
// Test = true, status = accepted, trial = 7, active trial = no
$charge = new Charge();
$charge->charge_id = 98298298;
$charge->test = true;
Expand All @@ -109,43 +110,57 @@ public function createCharges()
$charge->type = 1;
$charge->price = 15.00;
$charge->trial_days = 7;
$charge->trial_ends_on = Carbon::createFromDate(2018, 6, 3, 'UTC')->addWeeks(1);
$charge->trial_ends_on = Carbon::createFromDate(2018, 6, 3, 'UTC')->addWeeks(1)->format('Y-m-d');
$charge->shop_id = Shop::where('shopify_domain', 'example.myshopify.com')->first()->id;
$charge->save();

// Test = false, status = active, trial = 7, active trial = yes
$charge = new Charge();
$charge->charge_id = 67298298;
$charge->test = false;
$charge->name = 'Base Plan';
$charge->status = 'accepted';
$charge->status = 'active';
$charge->type = 1;
$charge->price = 25.00;
$charge->trial_days = 7;
$charge->trial_ends_on = Carbon::now()->addDays(2);
$charge->trial_ends_on = Carbon::today()->addDays(2)->format('Y-m-d');
$charge->shop_id = Shop::where('shopify_domain', 'example.myshopify.com')->first()->id;
$charge->save();

// Test = false, status = active, trial = 7, active trial = no
$charge = new Charge();
$charge->charge_id = 78378873;
$charge->test = false;
$charge->name = 'Base Plan Old';
$charge->status = 'accepted';
$charge->status = 'active';
$charge->type = 1;
$charge->price = 25.00;
$charge->trial_days = 7;
$charge->trial_ends_on = Carbon::now()->subWeeks(4);
$charge->trial_ends_on = Carbon::today()->subWeeks(4)->format('Y-m-d');
$charge->shop_id = Shop::where('shopify_domain', 'example.myshopify.com')->first()->id;
$charge->save();

// Test = false, status = active, trial = 0
$charge = new Charge();
$charge->charge_id = 89389389;
$charge->test = false;
$charge->name = 'Base Plan Old Non-Trial';
$charge->status = 'accepted';
$charge->status = 'active';
$charge->type = 1;
$charge->price = 25.00;
$charge->trial_days = 0;
$charge->shop_id = Shop::where('shopify_domain', 'example.myshopify.com')->first()->id;
$charge->save();

// Test = false, status = declined, trial = 7, active trial = true
$charge = new Charge();
$charge->charge_id = 78378378378;
$charge->test = false;
$charge->name = 'Base Plan Declined';
$charge->status = 'declined';
$charge->type = 1;
$charge->price = 25.00;
$charge->shop_id = Shop::where('shopify_domain', 'no-token-shop.myshopify.com')->first()->id;
$charge->save();
}
}
18 changes: 9 additions & 9 deletions tests/fixtures/602d13096715a537f9bb6e2ea2ac0d493a24344c.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
{
"recurring_application_charge": {
"id": 1029266947,
"id": 455696195,
"name": "Super Mega Plan",
"api_client_id": 755357713,
"price": "15.00",
"status": "accepted",
"return_url": "http:\/\/yourapp.com",
"billing_on": "2017-08-17",
"created_at": "2017-08-17T15:16:08-04:00",
"updated_at": "2017-08-17T15:29:50-04:00",
"status": "active",
"return_url": "http://yourapp.com",
"billing_on": "2018-06-06",
"created_at": "2018-05-07T15:33:38-04:00",
"updated_at": "2018-05-07T15:47:13-04:00",
"test": null,
"activated_on": null,
"trial_ends_on": null,
"activated_on": "2018-05-07",
"trial_ends_on": "2018-05-07",
"cancelled_on": null,
"trial_days": 0,
"decorated_return_url": "http:\/\/yourapp.com?charge_id=1029266947"
"decorated_return_url": "http://yourapp.com?charge_id=455696195"
}
}

0 comments on commit 9f756bd

Please sign in to comment.