Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
1stevengrant committed Dec 3, 2022
0 parents commit 88ba153
Show file tree
Hide file tree
Showing 28 changed files with 4,426 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
root = true

[*]
charset = utf-8
indent_size = 4
indent_style = space
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml}]
indent_size = 2
15 changes: 15 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Path-based git attributes
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html

# Ignore all test and documentation with "export-ignore".
/.github export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/phpunit.xml.dist export-ignore
/psalm.xml.dist export-ignore
/tests export-ignore
/.editorconfig export-ignore
/.php-cs-fixer.dist.php export-ignore
/art export-ignore
/docs export-ignore
/UPGRADING.md export-ignore
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: ghijk
14 changes: 14 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
blank_issues_enabled: false
contact_links:
- name: Ask a question
url: https://github.com/ghijk/donation-checkout/discussions/new?category=q-a
about: Ask the community for help
- name: Request a feature
url: https://github.com/ghijk/donation-checkout/discussions/new?category=ideas
about: Share ideas for new features
- name: Report a security issue
url: https://github.com/ghijk/donation-checkout/security/policy
about: Learn how to notify us for sensitive bugs
- name: Report a bug
url: https://github.com/ghijk/donation-checkout/issues/new
about: Report a reproducable bug
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependencies"
32 changes: 32 additions & 0 deletions .github/workflows/dependabot-auto-merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: dependabot-auto-merge
on: pull_request_target

permissions:
pull-requests: write
contents: write

jobs:
dependabot:
runs-on: ubuntu-latest
if: ${{ github.actor == 'dependabot[bot]' }}
steps:

- name: Dependabot metadata
id: metadata
uses: dependabot/[email protected]
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"

- name: Auto-merge Dependabot PRs for semver-minor updates
if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor'}}
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

- name: Auto-merge Dependabot PRs for semver-patch updates
if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}}
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
24 changes: 24 additions & 0 deletions .github/workflows/fix-php-code-style-issues.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Fix PHP code style issues

on:
push:
paths:
- '**.php'

jobs:
php-code-styling:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3
with:
ref: ${{ github.head_ref }}

- name: Fix PHP code style issues
uses: aglipanci/[email protected]

- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Fix styling
37 changes: 37 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Tests

on: [push, pull_request]

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [ubuntu-latest, windows-latest]
php: [8.2, 8.1]
stability: [prefer-lowest, prefer-stable]

name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }}

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
coverage: none

- name: Setup problem matchers
run: |
echo "::add-matcher::${{ runner.tool_cache }}/php.json"
echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: Install dependencies
run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction

- name: Execute tests
run: vendor/bin/pest
28 changes: 28 additions & 0 deletions .github/workflows/update-changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: "Update Changelog"

on:
release:
types: [released]

jobs:
update:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3
with:
ref: main

- name: Update Changelog
uses: stefanzweifel/changelog-updater-action@v1
with:
latest-version: ${{ github.event.release.name }}
release-notes: ${{ github.event.release.body }}

- name: Commit updated CHANGELOG
uses: stefanzweifel/git-auto-commit-action@v4
with:
branch: main
commit_message: Update CHANGELOG
file_pattern: CHANGELOG.md
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
vendor
mix-manifest.json
1 change: 1 addition & 0 deletions .phpunit.result.cache
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":1,"defects":[],"times":{"\/Users\/stevengrant\/Sites\/statamic-donate\/addons\/ghijk\/donation-checkout\/tests\/DonationTest.php::it":0.004,"\/Users\/stevengrant\/statamic-addons\/ghijk\/donation-checkout\/tests\/DonationTest.php::it":0.003}}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Changelog

All notable changes to `donation-checkout` will be documented in this file.

181 changes: 181 additions & 0 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
## Documentation

### Stripe Configuration
Donation Checkout can handle both single and recurring donations. It uses Stripe Checkout to handle the payment process.

If you wish to create recurring donations, you will need to create a product in Stripe. You can do this by going to
the [Stripe dashboard and clicking on Products](https://dashboard.stripe.com/test/products).

You can give the product any name you like - I use `Donation` personally. The product name will be vieweable in the
Stripe Checkout though, so make sure it's sensible. The price should be 1.00, as this is the price that will be used
as the multiplier for the donation amount and the billing period should be set as `Monthly`.

After you've created the product, you will need to copy the price ID. You can find this by clicking on the product
and seeing the pricing section.

![](https://d.pr/i/fZ82pT+)

### Statamic Configuration

You will need to add the following to your `.env` file:

```dotenv
STRIPE_SECRET_KEY=
STRIPE_PUBLISHABLE_KEY=
```
Installing Donation Checkout will add a `donation-checkout.php` folder to your `config` folder. You will need to add
`stripe_price_plan_id` and decide on the success urls for single and recurring donations.

### Frontend Implementation

A donation requires a few parametersto be passed to Stripe:
- amount
- first name
- last name
- email address
- frequency (single or recurring)

### Expected outcomes

Passing the correct parameters to the `/donation-checkout/start` endpoint will check for a Statamic user with the
submitted email address. If one doesn't exist, it will create one. It will then check for Stripe Customer ID against that user. If one doesn't exist, it will create one.

From there it will create the appropriate Stripe Checkout session and return the session ID to the frontend.

Here's an example of a form that makes use of Alpine.js to handle the donation process:

```html
<!-- donation form start -->
<div x-data="donateForm">
<form class="bg-white shadow m-4 p-4 space-y-4 max-w-[600px]"
@submit.prevent="makeDonation()"
method="post">

<div>
<button class="px-4 py-2 border-2 border border-gray-300"
type="button"
:class="{'font-semibold bg-blue-500 text-white border-blue-500 hover:border-blue-500': data.frequency ===
'recurring' }"
@click="data.frequency = 'recurring'">
Monthly
</button>
<button class="px-4 py-2 border-2 border border-gray-300"
type="button"
:class="{ 'font-semibold bg-blue-500 text-white border-blue-500 hover:border-blue-500': data.frequency ===
'single' }"
@click="data.frequency = 'single'">
One-off
</button>
</div>

<p class="font-semibold">Choose a donation amount</p>

<div class="flex items-start mt-4">
<template x-for="a in data.amounts">
<button x-text="`£ ${a}`"
type="button"
:class="{ 'bg-blue-500 text-white border-blue-500 hover:border-blue-500': data.amount === a }"
@click="data.amount = a"
class="font-semibold mr-4 last:mr-0 w-[100px] h-[100px] p-4 border-2 border-gray-100 hover:border-gray-300"></button>
</template>
</div>
<label class="flex items-center space-x-4">
<span class="font-semibold">£</span>
<input type="number"
name="amount"
id="amount"
x-model="data.amount"
required
class="border p-2 w-full">
</label>
<div class="grid grid-cols-2 gap-4">
<div>
<label for="first_name" class="text-sm font-semibold block">
First Name
</label>
<input type="text"
name="first_name"
id="first_name"
required
class="border p-2 w-full"
x-model="data.first_name"
placeholder="John">
</div>
<div>
<label for="last_name" class="text-sm font-semibold block">
Last Name
</label>
<input type="text"
name="last_name"
id="last_name"
x-model="data.last_name"
required
class="border p-2 w-full"
placeholder="Doe">
</div>
</div>
<div>
<label for="email" class="text-sm font-semibold block">
Email
</label>
<input type="email"
name="email"
id="email"
class="border p-2 w-full"
x-model="data.email"
required
placeholder="[email protected]">
</div>
<div>
<button class="font-semibold bg-blue-500 hover:bg-blue-400 transition ease-in-out p-4 text-white">
Donate
</button>
</div>
</form>
</div>
<!-- /donation form -->
```

```js
document.addEventListener('alpine:init', () => {
Alpine.data('donateForm', () => ({
data: {
amount: 10,
amounts: [5, 10, 50],
frequency: 'recurring',
first_name: '',
last_name: '',
email: '',
},

makeDonation() {
fetch('/donation-checkout/start', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(this.data)
})
.then(r => r.json())
.then(data => window.location.href = data.url)
.catch(error => console.log(error))
}
}))
})

```
Breaking it down, the form has a few things going on: it has a button group to toggle `frequency` between single and
recurring. It has a button group to select the amount to donate, in addition to a number input that allows a manual override.

It has a text input to allow the user to enter their first name, last name and email address. These are all marked
as required fields and are validated in the `POST` request to `/donation-checkout/start`. If the request is
successful, it returns a Stripe Checkout session response which is converted to JSON and the `url` is used to redirect to Stripe Checkout.

If you want to use this implementation as is, be sure to have the script tags in the head of your layout template:

```html
<script src="{{ mix src='/js/site.js' }}" defer></script>
<script src="https://unpkg.com/[email protected]/dist/cdn.min.js" defer></script>
```

Of course, you could handle this in plain JavaScript, Vue, React or any other framework you prefer.
17 changes: 17 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Copyright ©️ 2022 GHIJK Ltd

Permission is hereby granted to any person obtaining a copy of this software (the “Software”) to use, copy, modify, merge, publish and/or distribute copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

- **Don't plagiarise.** The above copyright notice and this license shall be included in all copies or substantial portions of the Software.
- **Don't use the same license on more than one project.** Each licensed copy of the software shall be actively installed on no more than one production environment at any one time.
- **Don't alter the licensing features.** Software features related to licensing shall not be altered or circumvented in any way, including (but not limited to) license validation, payment prompts, feature restrictions, and update eligibility.
- **Pay up**. Payment shall be made immediately upon receipt of any notice, prompt, reminder, or other message indicating that a payment is owed.
- **Follow the law.** All use of the Software shall not violate any applicable law or regulation, nor infringe the rights of any other person or entity.

Failure to comply with the foregoing conditions will automatically and immediately result in termination of the permission granted hereby. This license does not include any right to receive updates to the Software or technical support. Licensees bear all risk related to the quality and performance of the Software and any modifications made or obtained to it, including liability for actual and consequential harm, such as loss or corruption of data, and any necessary service, repair, or correction.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, INCLUDING SPECIAL, INCIDENTAL AND CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

---

If you have any questions regarding the terms of this license, please email [[email protected]](mailto:[email protected]).
Loading

0 comments on commit 88ba153

Please sign in to comment.