Skip to content

Commit

Permalink
Stripe Integration (#568)
Browse files Browse the repository at this point in the history
* create subscriptions menu for project dashboard (#555)

authored-by: David Igón <[email protected]>

* Add subscriptions

* Add subscriptions to project dashboard

* Update database code

* Update dashboard subscription form

* Start updating subscriptions dashboard to add new subscription

* Basic subscription form on dashboard

* CRUD for subscriptions on project dashboard

* Add support for subscriptions via stripe payments

* Fix Stripe integration details

* Make stripe subscriptions be enabled via rewards

* Remove legacy integration

* Remove javascript related to previous subscription model

* Fix stripe integration PR comments

* Use abstract payment in stripe payment method

* Fix Stripe webhook code

* Use yml webhook secret

* Add missing config

* Fix subscription gateway madness

* Add subscriptions to user dashboard

* Unify stripe subscription naming

* Allow users to list and cancel their stripe subscriptions

* Update subscription data vis

* Only let admins allow stripe and subscribables

* Redirect user to stripe checkout to purchase subscription

* Add 'creator' role

* Add commissions data and fix webhook status

* Redirect customer to next step in invest controller

* Display subscription based rewards different

* Highlight subscribable rewards on project side

* Add "subscriptions" submodule

* Improve metadata of stripe subscriptions

* Use stripe to validate success on payment response

* Allow basic listing of subscriptions to the admins

* Fix bug with invest reward function return type

* Feature Creator (#580)

* add calls for project and reward to get subscribable rewards for a given project

* add creator controller and first view

* add new copies for creator landing

* add posts for creator landing

* add strong to user name in creator landing

* add project section to creator layout

* fixes on creator css

* show all rewards in creator landing ordered by subscribable and amount

* change grid layout for creator subscriptions and change it to slider

* add links to share creator landing page

* move social share in creator to partial

* add channels to creator landing

* move creator partials to public

* add styles to slider arrows in creator subscriptions

* Add 'creator' role (#579)

* Only let admins allow stripe and subscribables

* Redirect user to stripe checkout to purchase subscription

* Add 'creator' role

* Cleaner code for createAdminSidebar function

* remove unnecessary partial

* fixes in redirects in creator controller

---------

Co-authored-by: Daniel Subiabre García <[email protected]>

---------

Co-authored-by: David <[email protected]>
  • Loading branch information
subiabre and davidbeig authored Dec 12, 2023
1 parent 199c07a commit 32472e5
Show file tree
Hide file tree
Showing 73 changed files with 2,132 additions and 98 deletions.
14 changes: 14 additions & 0 deletions Resources/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,20 @@ payments:
# Other variables may be added on other methods and
# customize the calculateFee() in the corresponding class

# Stripe
stripe:
active: false
publicKey: pk_test_
secretKey: sk_test_
webhookSecret: whsec_
commissions:
refunded:
fixed: 0
percent: 0
charged:
fixed: 0.25
percent: 2

# This is a built-in payment method using internal credit
pool:
active: true
Expand Down
6 changes: 6 additions & 0 deletions Resources/roles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ user: # This user is assigned automatically to all users regardless the user_rol
- remove-project # remove own project, this permission is implicit
level: 0 # Order of the role, roles with supperior level can do some actions over this

creator:
extends: user # inhertis permissions from role "user"
perms:
- highlight-project # can feature own projects in their creator profile
level: 10

vip:
extends: user # inherits permissions from role "user"
perms:
Expand Down
96 changes: 96 additions & 0 deletions Resources/templates/responsive/admin/subscriptions/list.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

$filters = $this->filters;
$the_filters = array(
'projects' => array(
'label' => 'Proyecto',
'first' => 'Todos los proyectos'
),
'statuses' => array(
'label' => 'Estado de la subscripción',
'first' => 'Todos los estados'
)
);

?>
<?php $this->layout('admin/layout') ?>

<?php $this->section('admin-content') ?>

<div class="widget board">
<h3 class="title">Filtros</h3>
<form id="filter-form" action="/admin/subscriptions" method="get">
<?php foreach ($the_filters as $filter => $data) : ?>
<div style="float:left;margin:5px;">
<label for="<?= $filter ?>-filter"><?= $data['label'] ?></label><br />
<select id="<?= $filter ?>-filter" name="<?= $filter ?>">
<option>
<?= $data['first'] ?>
</option>
<?php foreach ($this->raw($filter) as $itemId => $itemName) : ?>
<option value="<?= $itemId ?>" <?php if ($filters[$filter] === (string) $itemId) echo ' selected="selected"'; ?>>
<?= $itemName ?>
</option>
<?php endforeach ?>
</select>
</div>
<?php endforeach ?>

<br clear="both" />

<div style="float:left;margin:5px;">
<label for="name-filter">Usuario:</label><br />
<input type="text" id="name-filter" name="name" value="<?= $filters['name'] ?>" />
</div>

<br clear="both" />

<div style="float:left;margin:5px;">
<input type="submit" value="filtrar" />
</div>
</form>
<br clear="both" />
<a href="/admin/accounts?reset=filters">[<?= $this->text('admin-remove-filters') ?>]</a>
</div>

<div class="widget board">
<?php if ($this->list) : ?>
<table width="100%">
<thead>
<tr>
<th>Proyecto</th>
<th>Usuario</th>
<th>Recompensa</th>
<th>Importe</th>
<th>Estado</th>
<th>Stripe</th>
</tr>
</thead>

<tbody>
<?php foreach ($this->list as $subscription) : ?>
<?php $plan = $subscription['plan'] ?>
<?php $price = $subscription['items']['data'][0]['price']; ?>
<tr>
<td><?= $subscription['metadata']['project'] ?></td>
<td><?= $subscription['metadata']['user'] ?></td>
<td><?= $subscription['metadata']['reward'] ?></td>
<td><?= \amount_format($price['unit_amount'] / 100) . '/' . $plan['interval'] ?></td>
<td><span class="label label-info"><?= $subscription['status'] ?></span></td>
<td>
<a class="btn btn-default" title="<?= $this->text('regular-view') ?>" href="https://dashboard.stripe.com/subscriptions/<?= $subscription['id'] ?>"><i class="fa fa-info-circle"></i></a>
</td>
</tr>
<?php endforeach ?>
</tbody>

</table>

<?php else : ?>
<p>No hay subscripciones que cumplan con los filtros.</p>
<?php endif; ?>
</div>

<?= $this->insert('partials/utils/paginator', ['total' => $this->total, 'limit' => $this->limit]) ?>

<?php $this->replace() ?>
42 changes: 42 additions & 0 deletions Resources/templates/responsive/creator/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php $this->layout("layout", [
'bodyClass' => 'project creator',
]);

$permanentProject = $this->permanentProject;
$listOfProjects = $this->listOfProjects;
?>

<?php $this->section('head'); ?>
<?= $this->insert('creator/partials/styles') ?>
<?php $this->append(); ?>

<?php $this->section('content'); ?>

<main class="container-fluid main-info">
<div class="container-fluid">
<div class="row header text-center">
<h1 class="project-title"><?= $this->markdown($this->ee($permanentProject->name)) ?></h1>
<div class="project-by"><strong><?= $permanentProject->user->name ?></strong></div>
</div>

<div class="row">
<div class="col-md-12">
<?= $this->insert('project/partials/media', ['project' => $permanentProject ]) ?>
</div>
</div>

<?= $this->insert('creator/partials/share_social') ?>

<?= $this->insert('creator/partials/channel', ['project' => $permanentProject]) ?>

<?= $this->insert('creator/partials/subscriptions', ['project' => $permanentProject, 'subscriptions' => $permanentProject->getRewardsOrderBySubscribable()]) ?>

<?= $this->insert('creator/partials/posts', ['project' => $permanentProject, 'subscriptions' => $permanentProject->getSubscribableRewards()]) ?>
</div>
</main>

<?php $this->append(); ?>

<?php $this->section('footer'); ?>
<?= $this->insert('creator/partials/javascript') ?>
<?php $this->append(); ?>
18 changes: 18 additions & 0 deletions Resources/templates/responsive/creator/partials/channel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
$channels = $this->channels;
if (!$channels)
return;
?>

<section class="channel">
<h2><?= $this->t('regular-channels') ?></h2>
<div class="slider slider-channel">
<?php foreach($this->channels as $channel): ?>
<article class="channel">
<a href="/channel/<?= $channel->id ?>">
<img width="100" height="100" src="<?= $channel->getLogo()->getLink(100, 0, false) ?>" alt="<?= $channel->name ?>" title="<?= $channel->name ?>">
</a>
</article>
<?php endforeach; ?>
</div>
</section>
25 changes: 25 additions & 0 deletions Resources/templates/responsive/creator/partials/post_item.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
$post = $this->post;
$user = $this->user;
?>

<article class="post">
<?php if ($post->image): ?>
<div class="post-image">
<img class="post-image" src="<?= $post->image->getLink(80,80,false) ?>" alt="<?= $post->title ?>">
</div>
<?php endif; ?>

<div class="card-body">
<div class="card-info">
<h2><a href="<?= "/blog/$post->slug" ?>" target="_blank" ><?= $post->title ?></a></h2>
<p><?= $post->subtitle ?></p>
</div>
<div class="card-author-info">
<div class="author-image">
<img src="<?= $user->avatar->getLink(30,30,false) ?>" alt="<?= $user->name ?>"> <?= $user->name ?>
</div>
<span><?= date_formater($this->post->date) ?></span>
</div>
</div>
</article>
15 changes: 15 additions & 0 deletions Resources/templates/responsive/creator/partials/posts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
$posts = $this->posts;
if (empty($posts))
return;
?>

<section class="posts">
<h2><?= $this->t('regular-posts') ?></h2>

<div class="post-grid">
<?php foreach($posts as $post): ?>
<?= $this->insert('creator/partials/post_item', ['post' => $post]); ?>
<?php endforeach; ?>
</div>
</section>
15 changes: 15 additions & 0 deletions Resources/templates/responsive/creator/partials/projects.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
$projects = $this->projects;
if (empty($projects))
return;
?>

<section class="projects" >
<h2><?= $this->t('regular-projects') ?></h2>

<div class="project-grid">
<?php foreach ($this->listOfProjects as $project) : ?>
<?= $this->insert('project/widgets/normal', ['project' => $project]) ?>
<?php endforeach ?>
</div>
</section>
25 changes: 25 additions & 0 deletions Resources/templates/responsive/creator/partials/share_social.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
$share_url = $this->get_url() . '/creator/' . $this->user->id;

$user_twitter = str_replace(
[
'https://',
'http://',
'www.',
'twitter.com/',
'#!/',
'@'
], '', $this->user->twitter);
$author_share = !empty($user_twitter) ? ' '.$this->text('regular-by').' @'.$user_twitter.' ' : '';
$share_title = $author_share;

$facebook_url = 'http://facebook.com/sharer.php?u=' . urlencode($share_url) . '&t=' . urlencode($share_title);
$twitter_url = 'http://twitter.com/intent/tweet?text=' . urlencode($share_title . ': ' . $share_url . ' #Goteo');
?>
<section class="share-social">
<ul class="info-extra list-inline">
<li><a class="fa fa-2x fa-twitter" title="" target="_blank" href="<?= $twitter_url ?>"></a></li>
<li><a class="fa fa-2x fa-facebook" title="" target="_blank" href="<?= $facebook_url ?>"></a></li>
<li><a class="fa fa-2x fa-telegram" title="" target="_blank" href="https://telegram.me/share/url?url=<?= $share_url ?>&text=<?= urlencode($share_title) ?>"></a></li>
</ul>
</section>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
$project = $this->project;
$subscription = $this->subscription;
?>

<article class="subscription">
<div class="card-header">
<h2 title="<?= $subscription->reward ?>"><?= $subscription->reward ?></h2>
</div>
<div class="card-body">
<div class="amount-box text-center text-uppercase">
<span class="amount"><?= amount_format($subscription->amount) ?></span>
</div>

<p>
<?= $this->markdown($subscription->description) ?>
</p>
</div>
<div class="card-footer">
<div class="reward-donate text-center">
<a class="btn btn-lg btn-cyan text-uppercase" href="/invest/<?= $project->id ?>/<?= $subscription->id ?>">
<?= $this->text('project-regular-support') ?>
</a>
</div>
</div>
</article>
15 changes: 15 additions & 0 deletions Resources/templates/responsive/creator/partials/subscriptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
$subscriptions = $this->subscriptions;
if (empty($subscriptions))
return;
?>

<section class="subscriptions">
<h2><?= $this->t('regular-subscriptions') ?></h2>

<div class="slider slider-subscriptions">
<?php foreach($subscriptions as $subscription): ?>
<?= $this->insert('creator/partials/subscription_item', ['subscription' => $subscription]); ?>
<?php endforeach; ?>
</div>
</section>
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
<?php
$id = $this->reward->id;
$form = $this->raw('form');
$unlimited = (int)$form["units_$id"]->vars['value'] == 0;
$id = $this->reward->id;
$form = $this->raw('form');
$unlimited = (int)$form["units_$id"]->vars['value'] == 0;
?>
<div class="panel section-content" data-id="<?= $id ?>">
<div class="panel-body reward-item">
<div class="row">
<div class="amount"><?= $this->form_row($form["amount_$id"]) ?></div>
<div class="units fade <?= $unlimited ? 'out' : 'in' ?>"><?= $this->form_row($form["units_$id"]) ?></div>
<div class="unlimited form-group">
<label for="unlimited_<?= $id ?>"><?= $this->text('project-reward-unlimited') ?></label>
<div class="input-wrap">
<?= $this->form_row($form["unlimited_$id"]) ?>
</div>
<div class="panel-body reward-item">
<div class="row">
<div class="amount"><?= $this->form_row($form["amount_$id"]) ?></div>
<div class="units fade <?= $unlimited ? 'out' : 'in' ?>"><?= $this->form_row($form["units_$id"]) ?></div>
<div class="unlimited form-group">
<label for="unlimited_<?= $id ?>"><?= $this->text('project-reward-unlimited') ?></label>
<div class="input-wrap">
<?= $this->form_row($form["unlimited_$id"]) ?>
</div>
</div>
</div>
</div>
<?= $this->form_row($form["reward_$id"]) ?>
<?= $this->form_row($form["description_$id"]) ?>
<div class="remove"><?= $this->form_row($form["remove_$id"], [], true) ?></div>
<?php if($this->show_taken): ?>
<p class="text-muted"><i class="fa fa-hand-o-right"></i> <?= $this->text('project-donors-with-reward', $this->reward->getTaken()) ?></p>
<?php endif ?>
</div>
</div>
<div class="row">
<div class="subscribable form-group">
<label for="subscribable_<?= $id ?>"><?= $this->text('project-reward-subscribable') ?></label>
<?= $this->text('project-reward-stripe-based-subscriptions') ?>
<div class="input-wrap">
<?= $this->form_row($form["subscribable_$id"]) ?>
</div>
</div>
</div>
<?= $this->form_row($form["reward_$id"]) ?>
<?= $this->form_row($form["description_$id"]) ?>
<div class="remove"><?= $this->form_row($form["remove_$id"], [], true) ?></div>
<?php if ($this->show_taken) : ?>
<p class="text-muted"><i class="fa fa-hand-o-right"></i> <?= $this->text('project-donors-with-reward', $this->reward->getTaken()) ?></p>
<?php endif ?>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
$id = $this->subscription->id;
$form = $this->raw('form');
?>
<div class="panel section-content" data-id="<?= $id ?>">
<div class="panel-body subscription-item">
<div class="row">
<div class="amount"><?= $this->form_row($form["amount_$id"]) ?></div>
</div>
<?= $this->form_row($form["name_$id"]) ?>
<?= $this->form_row($form["description_$id"]) ?>
<div class="remove"><?= $this->form_row($form["remove_$id"], [], true) ?></div>
</div>
</div>
Loading

0 comments on commit 32472e5

Please sign in to comment.