Skip to content

Commit 7f4b49d

Browse files
committed
Initial commit
0 parents  commit 7f4b49d

28 files changed

+1340
-0
lines changed

.editorconfig

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
; This file is for unifying the coding style for different editors and IDEs.
2+
; More information at http://editorconfig.org
3+
4+
root = true
5+
6+
[*]
7+
charset = utf-8
8+
indent_size = 4
9+
indent_style = space
10+
end_of_line = lf
11+
insert_final_newline = true
12+
trim_trailing_whitespace = true
13+
14+
[*.md]
15+
trim_trailing_whitespace = false

.gitattributes

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Path-based git attributes
2+
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
3+
4+
# Ignore all test and documentation with "export-ignore".
5+
/.gitattributes export-ignore
6+
/.gitignore export-ignore
7+
/.travis.yml export-ignore
8+
/phpunit.xml.dist export-ignore
9+
/.scrutinizer.yml export-ignore
10+
/tests export-ignore
11+
/.editorconfig export-ignore

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
build
2+
composer.lock
3+
vendor
4+
coverage.clover
5+
.phpunit.result.cache

.scrutinizer.yml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
filter:
2+
excluded_paths: [tests/*]
3+
4+
checks:
5+
php:
6+
remove_extra_empty_lines: true
7+
remove_php_closing_tag: true
8+
remove_trailing_whitespace: true
9+
fix_use_statements:
10+
remove_unused: true
11+
preserve_multiple: false
12+
preserve_blanklines: true
13+
order_alphabetically: true
14+
fix_php_opening_tag: true
15+
fix_linefeed: true
16+
fix_line_ending: true
17+
fix_identation_4spaces: true
18+
fix_doc_comments: true

.styleci.yml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
preset: laravel
2+
3+
disabled:
4+
- single_class_element_per_statement

.travis.yml

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
language: php
2+
3+
cache:
4+
directories:
5+
- $HOME/.composer/cache
6+
7+
matrix:
8+
fast_finish: true
9+
include:
10+
- php: 7.2
11+
env: LARAVEL='5.8.*' TESTBENCH='3.8.*' COMPOSER_FLAGS='--prefer-lowest'
12+
- php: 7.2
13+
env: LARAVEL='5.8.*' TESTBENCH='3.8.*' COMPOSER_FLAGS='--prefer-stable'
14+
- php: 7.3
15+
env: LARAVEL='5.8.*' TESTBENCH='3.8.*' COMPOSER_FLAGS='--prefer-lowest'
16+
- php: 7.3
17+
env: LARAVEL='5.8.*' TESTBENCH='3.8.*' COMPOSER_FLAGS='--prefer-stable'
18+
- php: 7.2
19+
env: LARAVEL='6.*' TESTBENCH='4.*' COMPOSER_FLAGS='--prefer-lowest'
20+
- php: 7.2
21+
env: LARAVEL='6.*' TESTBENCH='4.*' COMPOSER_FLAGS='--prefer-stable'
22+
- php: 7.3
23+
env: LARAVEL='6.*' TESTBENCH='4.*' COMPOSER_FLAGS='--prefer-lowest'
24+
- php: 7.3
25+
env: LARAVEL='6.*' TESTBENCH='4.*' COMPOSER_FLAGS='--prefer-stable'
26+
27+
before_install:
28+
- travis_retry composer self-update
29+
- travis_retry composer require --no-update --no-interaction "illuminate/support:${LARAVEL}" "orchestra/testbench:${TESTBENCH}"
30+
31+
install:
32+
- travis_retry composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction --no-suggest
33+
34+
script:
35+
- vendor/bin/phpunit

CHANGELOG.md

Whitespace-only changes.

CONTRIBUTING.md

Whitespace-only changes.

LICENSE.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) App-vise V.O.F. <[email protected]>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Handle Appstore server-to-server notifications for auto-renewable subscriptions
2+
3+
[![Latest Version on Packagist](https://img.shields.io/packagist/v/app-vise/laravel-appstore-notifications.svg?style=flat-square)](https://packagist.org/packages/app-vise/laravel-appstore-notifications)
4+
[![Build Status](https://img.shields.io/travis/app-vise/laravel-appstore-notifications/master.svg?style=flat-square)](https://travis-ci.org/app-vise/laravel-appstore-notifications)
5+
[![StyleCI](https://styleci.io/repos/105920179/shield?branch=master)](https://styleci.io/repos/105920179)
6+
[![Quality Score](https://img.shields.io/scrutinizer/g/app-vise/laravel-appstore-notifications.svg?style=flat-square)](https://scrutinizer-ci.com/g/app-vise/laravel-appstore-notifications)
7+
[![Total Downloads](https://img.shields.io/packagist/dt/app-vise/laravel-appstore-notifications.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-appstore-notifications)
8+
9+
## Installation
10+
You can install this package via composer
11+
12+
```bash
13+
composer require app-vise/laravel-appstore-server-notifications
14+
```
15+
16+
The service provider will register itself.
17+
You have to publish the config file with:
18+
19+
```bash
20+
php artisan vendor:publish --provider="Appvise\AppStoreNotifications\NotificationsServiceProvider" --tag="config"
21+
```
22+
23+
## Usage
24+
25+
## Changelog
26+
27+
Please see CHANGELOG for more information about what has changed recently.
28+
29+
## Testing
30+
31+
```bash
32+
composer test
33+
```
34+
35+
## Security
36+
37+
If you discover any security related issues, please email [email protected] instead of using the issue tracker.
38+
39+
## Credits
40+
41+
- [Daan Geurts](https://github.com/DaanGeurts)
42+
- [All Contributors](../../contributors)
43+
44+
A big thanks to [Spatie's](https://spatie.be) laravel-stripe-webhooks which was a huge inspiration and starting point for this package
45+
## License
46+
47+
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

UPGRADING.md

Whitespace-only changes.

composer.json

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"name": "app-vise/laravel-appstore-server-notifications",
3+
"description": "Handling Appstore server to server notifications",
4+
"keywords": [
5+
"app-vise",
6+
"appvise",
7+
"laravel-appstore-server-to-server-notifications",
8+
"laravel-appstore-server-notifications",
9+
"laravel in app subscriptions",
10+
"laravel-appstore-server-notifications"
11+
],
12+
"license": "MIT",
13+
"authors": [
14+
{
15+
"name": "Daan Geurts",
16+
"email": "[email protected]",
17+
"homepage": "https://www.app-vise.nl",
18+
"role": "Developer"
19+
}
20+
],
21+
"require": {
22+
"php": "^7.2",
23+
"illuminate/support": "~5.7.0|^6.0",
24+
"bensampo/laravel-enum": "^1.0"
25+
},
26+
"require-dev": {
27+
"orchestra/testbench": "~3.8.0|^4.0",
28+
"phpunit/phpunit": "^8.2"
29+
},
30+
"autoload": {
31+
"psr-4": {
32+
"Appvise\\AppStoreNotifications\\": "src"
33+
}
34+
},
35+
"autoload-dev": {
36+
"psr-4": {
37+
"Appvise\\AppStoreNotifications\\Tests\\": "tests"
38+
}
39+
},
40+
"scripts": {
41+
"test": "vendor/bin/phpunit --verbose"
42+
},
43+
"config": {
44+
"sort-packages": true
45+
},
46+
"extra": {
47+
"laravel": {
48+
"providers": [
49+
"Appvise\\AppStoreNotifications\\NotificationsServiceProvider"
50+
]
51+
}
52+
}
53+
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
return [
3+
/*
4+
* Apple will send the shared secret with the request that should match
5+
* the one you use when validating receipts.
6+
* https://developer.apple.com/documentation/storekit/in-app_purchase/enabling_server-to-server_notifications?language=objc#overview
7+
*/
8+
'shared_secret' => env('APPLE_SHARED_SECRET'),
9+
/*
10+
* All the events that should be handeled by your application.
11+
* Typically you should uncomment all jobs
12+
*
13+
* You can find a list of all notification types here:
14+
* https://developer.apple.com/documentation/storekit/in-app_purchase/enabling_server-to-server_notifications?language=objc#3162176
15+
*/
16+
'jobs' => [
17+
// 'initial_buy' => \App\Jobs\AppstoreNotifications\HandleInitialBuy::class,
18+
// 'cancel' => \App\Jobs\AppstoreNotifications\HandleCancellation::class,
19+
// 'renewal' => \App\Jobs\AppstoreNotifications\HandleRenewal::class,
20+
// 'interactive_renewal' => \App\Jobs\AppstoreNotifications\HandleInteractiveRenewal::class,
21+
// 'did_change_renewal_pref' => \App\Jobs\AppstoreNotifications\HandleDidChangeRenewalPreferences::class,
22+
// 'did_change_renewal_status' => \App\Jobs\AppstoreNotifications\HandleDidChangeRenewalStatus::class,
23+
],
24+
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
use Illuminate\Database\Schema\Blueprint;
4+
use Illuminate\Database\Migrations\Migration;
5+
6+
class CreateAppleNotificationsTable extends Migration
7+
{
8+
public function up()
9+
{
10+
Schema::create('apple_notifications', function (Blueprint $table) {
11+
$table->bigIncrements('id');
12+
13+
$table->string('type');
14+
$table->text('payload')->nullable();
15+
$table->text('exception')->nullable();
16+
17+
$table->timestamps();
18+
});
19+
}
20+
21+
public function down()
22+
{
23+
Schema::dropIfExists('apple_notifications');
24+
}
25+
}

phpunit.xml.dist

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit bootstrap="vendor/autoload.php"
3+
backupGlobals="false"
4+
backupStaticAttributes="false"
5+
colors="true"
6+
verbose="true"
7+
convertErrorsToExceptions="true"
8+
convertNoticesToExceptions="true"
9+
convertWarningsToExceptions="true"
10+
processIsolation="true"
11+
stopOnFailure="false">
12+
<testsuites>
13+
<testsuite name="App-vise Test Suite">
14+
<directory>tests</directory>
15+
</testsuite>
16+
</testsuites>
17+
<filter>
18+
<whitelist>
19+
<directory suffix=".php">src/</directory>
20+
</whitelist>
21+
</filter>
22+
<logging>
23+
<log type="tap" target="build/report.tap"/>
24+
<log type="junit" target="build/report.junit.xml"/>
25+
<log type="coverage-html" target="build/coverage"/>
26+
<log type="coverage-text" target="build/coverage.txt"/>
27+
<log type="coverage-clover" target="build/logs/clover.xml"/>
28+
</logging>
29+
</phpunit>

src/NotificationsServiceProvider.php

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
namespace Appvise\AppStoreNotifications;
3+
4+
use Illuminate\Support\ServiceProvider;
5+
6+
class NotificationsServiceProvider extends ServiceProvider
7+
{
8+
public function boot()
9+
{
10+
if ($this->app->runningInConsole()) {
11+
$this->publishes([
12+
__DIR__.'/../config/appstore-server-notifications.php' => config_path('appstore-server-notifications.php'),
13+
], 'config');
14+
}
15+
16+
if (! class_exists('CreateAppleNotificationsTable')) {
17+
$timestamp = date('Y_m_d_His', time());
18+
$this->publishes([
19+
__DIR__.'/../database/migrations/create_apple_notifications_table.php.stub' => database_path("migrations/{$timestamp}_create_apple_notifications_table.php"),
20+
], 'migrations');
21+
}
22+
23+
$this->loadRoutesFrom(__DIR__.'/routes.php');
24+
}
25+
26+
public function register()
27+
{
28+
$this->mergeConfigFrom(__DIR__.'/../config/appstore-server-notifications.php', 'appstore-server-notifications');
29+
}
30+
}

src/WebhooksController.php

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Appvise\AppStoreNotifications;
4+
5+
use Appvise\AppStoreNotifications\Exceptions\WebhookFailed;
6+
use Appvise\AppStoreNotifications\Model\AppleNotification;
7+
use Appvise\AppStoreNotifications\Model\NotificationPayload;
8+
use Appvise\AppStoreNotifications\Model\NotificationType;
9+
use Illuminate\Http\Request;
10+
11+
class WebhooksController
12+
{
13+
public function __invoke(Request $request)
14+
{
15+
$jobConfigKey = NotificationType::{$request->input('notification_type')}();
16+
$payload = NotificationPayload::createFromRequest($request);
17+
18+
$this->determineValidRequest($payload);
19+
20+
AppleNotification::storeNotification($jobConfigKey, $payload);
21+
22+
$jobClass = config("appstore-server-notifications.jobs.{$jobConfigKey}", null);
23+
24+
if (is_null($jobClass)) {
25+
throw WebhookFailed::jobClassDoesNotExist($jobConfigKey);
26+
}
27+
28+
29+
$job = new $jobClass($payload);
30+
dispatch($job);
31+
32+
return response()->json();
33+
}
34+
35+
private function determineValidRequest(NotificationPayload $notificationPayload): bool
36+
{
37+
if ($notificationPayload->getPassword() !== config('appstore-server-notifications.shared_secret')) {
38+
throw WebhookFailed::nonValidRequest();
39+
}
40+
41+
return true;
42+
}
43+
}

src/exceptions/WebhookFailed.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Appvise\AppStoreNotifications\Exceptions;
4+
5+
use Exception;
6+
7+
class WebhookFailed extends Exception
8+
{
9+
public static function nonValidRequest()
10+
{
11+
return new static("Your shared secret does not match password in Apple's request", 400);
12+
}
13+
14+
public static function jobClassDoesNotExist(string $jobClass)
15+
{
16+
return new static("Could not process webhook because the configured job `$jobClass` does not exist.", 501);
17+
}
18+
19+
public function render($request)
20+
{
21+
return response(['error' => $this->getMessage()], 400);
22+
}
23+
}

0 commit comments

Comments
 (0)