Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cuopon option for stripe checkout session, customer portal, webhook callback handler for billable #19

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions Billable.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ public function createCheckoutSessionForSubscription($planID, array $optionsPara
'cancel_url' => $url_base . $controller_url_name . 'cancel',
];

if(array_key_exists('couponID', $optionsParam)){
$options['subscription_data']['coupon'] = $optionsParam['couponID'] ;
}

if(array_key_exists('success_url', $optionsParam)){
$options['success_url'] = $optionsParam['success_url'];
}
Expand All @@ -120,6 +124,40 @@ public function createCheckoutSessionForSubscription($planID, array $optionsPara
return $session;
}

/**
* Logic code for Yii app. To be overwritten
*/
public function handlerAfterSubscriptionsUpdated(): void
{

}

/**
* Creates a Stripe's customer portal session and get and url to redirect
*
* @param array $options['return_url'] url to return after customer portal
*
* @return \Stripe\Checkout\Session
*
* @throws Card
*/
public function createCustomerPortalSession( array $optionsParam = []): \Stripe\BillingPortal\Session
{
$customer = $this->getStripeCustomer();
if (!$this->stripe_id) {
throw new InvalidArgumentException('No stripe customer provided.');
}

$options = [ 'customer' => $this->stripe_id ];
if(array_key_exists('return_url', $optionsParam)){
$options['return_url'] = $optionsParam['return_url'];
}

\Stripe\Stripe::setApiKey(Yii::$app->params['stripe']['apiKey']);
$session = \Stripe\BillingPortal\Session::create($options);
return $session;
}

/**
* Make a "one off" charge on the customer for the given amount.
*
Expand Down
126 changes: 126 additions & 0 deletions behaviors/CarbonBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php

namespace yii2mod\cashier\behaviors;

use Carbon\Carbon;
use yii\base\Behavior;
use yii\db\ActiveRecord;

/**
* CarbonBehavior automatically creates a Carbon Instance for one or multiple attributes of an ActiveRecord
* object when `afterFind` event happen.
*
* To use CarbonBehavior, configure the [[attributes]] property which should specify the list of attributes
* that need to be converted.
*
* ```php
*
* public function behaviors()
* {
* return [
* [
* 'class' => CarbonBehavior::className(),
* 'attributes' => [
* 'createdAt'
* ],
* ],
* ];
* }
*
* $user = UserModel::findOne(1);
*
* var_dump($user->createdAt->year);
* var_dump($user->createdAt->month);
* var_dump($user->createdAt->day);
*
* // change date
*
* $user->createdAt->addYear();
* $user->save();
*
* ```
*
* @see http://carbon.nesbot.com/docs/#api-introduction
*
* @package yii2mod\behaviors
*/
class CarbonBehavior extends Behavior
{
/**
* @var ActiveRecord the owner of this behavior
*/
public $owner;

/**
* @var array list of attributes that will be converted to carbon instance
*/
public $attributes = [];

/**
* @var string date format for carbon
*/
public $dateFormat = 'Y-m-d H:i:s';

/**
* @return array
*/
public function events()
{
return [
ActiveRecord::EVENT_AFTER_FIND => 'attributesToCarbon',
ActiveRecord::EVENT_BEFORE_UPDATE => 'attributesToDefaultFormat',
ActiveRecord::EVENT_AFTER_UPDATE => 'attributesToCarbon',
];
}

/**
* Convert the model's attributes to an Carbon instance.
*
* @param $event
*
* @return static
*/
public function attributesToCarbon($event)
{
foreach ($this->attributes as $attribute) {
$value = $this->owner->$attribute;
if (!empty($value)) {
// If this value is an integer, we will assume it is a UNIX timestamp's value
// and format a Carbon object from this timestamp.
if (is_numeric($value)) {
$this->owner->$attribute = Carbon::createFromTimestamp($value);
}

// If the value is in simply year, month, day format, we will instantiate the
// Carbon instances from that format.
elseif (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $value)) {
$this->owner->$attribute = Carbon::createFromFormat('Y-m-d', $value)->startOfDay();
} else {
$this->owner->$attribute = Carbon::createFromFormat($this->dateFormat, $this->owner->$attribute);
}
}
}
}

/**
* Handles owner 'beforeUpdate' event for converting attributes values to the default format
*
* @param $event
*
* @return bool
*/
public function attributesToDefaultFormat($event)
{
$oldAttributes = $this->owner->oldAttributes;
foreach ($this->attributes as $attribute) {
$oldAttributeValue = $oldAttributes[$attribute];

if ($this->owner->$attribute instanceof Carbon) {
//If old attribute value is an integer, then we convert the current attribute value to the timestamp for prevent db errors
if (is_numeric($oldAttributeValue)) {
$this->owner->$attribute = $this->owner->$attribute->timestamp;
}
}
}
}
}
1 change: 0 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"require": {
"php": ">=7.1",
"yiisoft/yii2": "~2.0.14",
"yii2mod/yii2-behaviors": "~2.0",
"stripe/stripe-php": "~7.0",
"nesbot/carbon": "~2.29.1",
"dompdf/dompdf": "^0.8.0"
Expand Down
6 changes: 6 additions & 0 deletions controllers/WebhookController.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,18 @@ protected function handleCustomerSubscriptionDeleted(array $payload)
{
$user = $this->getUserByStripeId($payload['data']['object']['customer']);
if ($user) {
$hasUpdated = false;
$subscriptions = $user->getSubscriptions()->all();
/* @var $subscription SubscriptionModel */
foreach ($subscriptions as $subscription) {
if ($subscription->stripe_id === $payload['data']['object']['id']) {
$subscription->markAsCancelled();
$hasUpdated = true;
}
}
if($hasUpdated){
$user->handlerAfterSubscriptionsUpdated();
}
}

return new Response([
Expand All @@ -112,6 +117,7 @@ protected function handleCheckoutSessionCompleted(array $payload)
$subscriptionModel = $user->subscriptionByStripeID($dataObj['subscription']);
if (!$subscriptionModel) {
$subscriptionModel = $user->loadSubscriptionModel($dataObj['subscription'], $dataObj['client_reference_id']);
$user->handlerAfterSubscriptionsUpdated();
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion models/SubscriptionModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
use LogicException;
use Yii;
use yii\db\ActiveRecord;
use yii2mod\behaviors\CarbonBehavior;

// OLD lib
// from composer.json => "yii2mod/yii2-behaviors": "~2.0",
// use yii2mod\behaviors\CarbonBehavior;

use yii2mod\cashier\behaviors\CarbonBehavior;

/**
* This is the model class for table "subscriptions".
Expand Down
2 changes: 1 addition & 1 deletion tests/CashierTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ protected function getTestToken()
'card' => [
'number' => '4242424242424242',
'exp_month' => 5,
'exp_year' => 2020,
'exp_year' => 2032,
'cvc' => '123',
],
], ['api_key' => Yii::$app->params['stripe']['apiKey']])->id;
Expand Down