Skip to content

Commit 51a19ca

Browse files
driesvintsStyleCIBotcrynobonetaylorotwell
authored
[2.x] Paddle Billing support (#198)
* Work on paddle billing * wip * Work on new Paddle Billing * wip * Work on paddle billing * wip * wip * Add successurl * Start subscriptions * Apply fixes from StyleCI * wip * wip * Work on paddle billing support * swap plans * wip * Quantity updates * wip * Billing anchor * Webhook controller subscription updates * Payment method url * Apply fixes from StyleCI * wip * Apply fixes from StyleCI * Cancel subscriptions * Add cancel urls * Switch up status checks * Implement trial time * wip * Remove protective guard * Transactions * Work on transactions * Preview price amounts * wip * Remove modifiers * Credit and refund * TransactionUpdated event handling * CustomerUpdated event * Unit tests * Apply fixes from StyleCI * Fix tests * Apply fixes from StyleCI * wip * [2.x] Use PHPUnit 10 (#202) * [2.x] Use PHPUnit 10 Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> * wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> * wip --------- Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> * Update composer.json Co-authored-by: Mior Muhammad Zaki <crynobone@gmail.com> * wip * wip * wip * wip * wip * Apply fixes from StyleCI * wip * wip * wip * wip * wip * Apply fixes from StyleCI * wip * wip * wip * Update UPGRADE.md * Update ManagesCustomer.php * wip * formatting * wip * Fix webhook signature verification --------- Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> Co-authored-by: StyleCI Bot <bot@styleci.io> Co-authored-by: Mior Muhammad Zaki <crynobone@gmail.com> Co-authored-by: Taylor Otwell <taylor@laravel.com>
1 parent 0d0e3ba commit 51a19ca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+2262
-2748
lines changed

.github/CONTRIBUTING.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ You will need to set some environment variables in a custom `phpunit.xml` file i
99
Copy the default file using `cp phpunit.xml.dist phpunit.xml` and add the following lines below the `DB_CONNECTION` environment variable in your new `phpunit.xml` file:
1010

1111
<env name="PADDLE_SANDBOX" value="true"/>
12-
<env name="PADDLE_VENDOR_ID" value="Your Paddle vendor ID"/>
13-
<env name="PADDLE_VENDOR_AUTH_CODE" value="Your Paddle auth code"/>
14-
<env name="PADDLE_TEST_PRODUCT" value="Identifier for a random one off product"/>
12+
<env name="PADDLE_SELLER_ID" value="Your Paddle seller ID"/>
13+
<env name="PADDLE_AUTH_CODE" value="Your Paddle auth code"/>
14+
<env name="PADDLE_TEST_PRICE" value="Identifier for a random one off price"/>
1515

1616
After setting these variables, you can run your tests by executing the `vendor/bin/phpunit` command.

.github/ISSUE_TEMPLATE/1_Bug_report.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ body:
88
attributes:
99
label: Cashier Paddle Version
1010
description: Provide the Cashier Paddle version that you are using.
11-
placeholder: 1.6.1
11+
placeholder: 2.1.0
1212
validations:
1313
required: true
1414
- type: input
@@ -44,4 +44,3 @@ body:
4444
description: Provide detailed steps to reproduce your issue. If necessary, please provide a GitHub repository to demonstrate your issue using `laravel new bug-report --github="--public"`.
4545
validations:
4646
required: true
47-

.github/workflows/tests.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ jobs:
4040
composer update --prefer-dist --no-interaction --no-progress
4141
4242
- name: Execute tests
43-
run: vendor/bin/phpunit --verbose
43+
run: vendor/bin/phpunit
4444
env:
45-
PADDLE_VENDOR_ID: ${{ secrets.PADDLE_VENDOR_ID }}
46-
PADDLE_VENDOR_AUTH_CODE: ${{ secrets.PADDLE_VENDOR_AUTH_CODE }}
47-
PADDLE_PUBLIC_KEY: ${{ secrets.PADDLE_PUBLIC_KEY }}
48-
PADDLE_TEST_PRODUCT: ${{ secrets.PADDLE_TEST_PRODUCT }}
45+
PADDLE_SELLER_ID: ${{ secrets.PADDLE_SELLER_ID }}
46+
PADDLE_AUTH_CODE: ${{ secrets.PADDLE_AUTH_CODE }}
47+
PADDLE_WEBHOOK_SECRET: ${{ secrets.PADDLE_WEBHOOK_SECRET }}
48+
PADDLE_TEST_PRICE: ${{ secrets.PADDLE_TEST_PRICE }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/vendor
22
composer.lock
33
/phpunit.xml
4+
/.phpunit.cache
45
.phpunit.result.cache

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
## Introduction
1919

20-
Laravel Cashier Paddle provides an expressive, fluent interface to [Paddle's](https://paddle.com) subscription billing services. It handles almost all of the boilerplate subscription billing code you are dreading writing. In addition to basic subscription management, Cashier can handle coupons, swapping subscription, subscription "quantities", cancellation grace periods and much more.
20+
Laravel Cashier Paddle provides an expressive, fluent interface to [Paddle's](https://paddle.com) subscription billing services. It handles almost all of the boilerplate subscription billing code you are dreading writing. In addition to basic subscription management, Cashier can handle swapping subscription, subscription "quantities", subscription pausing, cancellation grace periods and much more.
2121

2222
## Official Documentation
2323

UPGRADE.md

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,4 @@
22

33
## Upgrading To 2.0 From 1.x
44

5-
### Minimum Versions
6-
7-
The following required dependency versions have been updated:
8-
9-
- The minimum PHP version is now v8.0
10-
- The minimum Laravel version is now v9.0
5+
Unfortunately there is no official upgrade path from Paddle to migrate from Paddle Classic to Paddle Billing. Therefore, if you use Paddle Classic, you should continue to use Cashier Paddle 1.x. New projects on Paddle which use Paddle Billing should use Cashier Paddle 2.x.

composer.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@
2929
"illuminate/support": "^10.0",
3030
"illuminate/view": "^10.0",
3131
"moneyphp/money": "^3.2|^4.0",
32-
"nesbot/carbon": "^2.0",
32+
"nesbot/carbon": "^2.67",
3333
"spatie/url": "^1.3.5|^2.0",
34-
"symfony/http-kernel": "^6.0",
34+
"symfony/http-kernel": "^6.2",
3535
"symfony/polyfill-intl-icu": "^1.22.1"
3636
},
3737
"require-dev": {
38-
"mockery/mockery": "^1.0",
39-
"orchestra/testbench": "^8.0",
38+
"mockery/mockery": "^1.5.1",
39+
"orchestra/testbench": "^8.14",
4040
"phpstan/phpstan": "^1.10",
41-
"phpunit/phpunit": "^9.0"
41+
"phpunit/phpunit": "^10.1"
4242
},
4343
"suggest": {
4444
"ext-intl": "Allows for more locales besides the default \"en\" when formatting money values."

config/cashier.php

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@
77
| Paddle Keys
88
|--------------------------------------------------------------------------
99
|
10-
| The Paddle vendor ID and auth code will allow your application to call
10+
| The Paddle seller ID and auth code will allow your application to call
1111
| the Paddle API. The "public" key is typically used when interacting
1212
| with Paddle.js while the "secret" key accesses private endpoints.
1313
|
1414
*/
1515

16-
'vendor_id' => env('PADDLE_VENDOR_ID'),
16+
'seller_id' => env('PADDLE_SELLER_ID'),
1717

18-
'vendor_auth_code' => env('PADDLE_VENDOR_AUTH_CODE'),
18+
'auth_code' => env('PADDLE_AUTH_CODE'),
1919

20-
'public_key' => env('PADDLE_PUBLIC_KEY'),
20+
'retain_key' => env('PADDLE_RETAIN_KEY'),
21+
22+
'webhook_secret' => env('PADDLE_WEBHOOK_SECRET'),
2123

2224
/*
2325
|--------------------------------------------------------------------------
@@ -45,19 +47,6 @@
4547

4648
'webhook' => env('CASHIER_WEBHOOK'),
4749

48-
/*
49-
|--------------------------------------------------------------------------
50-
| Currency
51-
|--------------------------------------------------------------------------
52-
|
53-
| This is the default currency that will be used when generating charges
54-
| from your application. Of course, you are welcome to use any of the
55-
| various world currencies that are currently supported via Paddle.
56-
|
57-
*/
58-
59-
'currency' => env('CASHIER_CURRENCY', 'USD'),
60-
6150
/*
6251
|--------------------------------------------------------------------------
6352
| Currency Locale
@@ -77,8 +66,7 @@
7766
|--------------------------------------------------------------------------
7867
|
7968
| This option allows you to toggle between the Paddle live environment
80-
| and its sandboxed environment. This feature is only available for
81-
| a select group of vendors and not a publicly available feature.
69+
| and its sandboxed environment.
8270
|
8371
*/
8472

database/migrations/2019_05_03_000001_create_customers_table.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ public function up(): void
1515
$table->id();
1616
$table->foreignId('billable_id');
1717
$table->string('billable_type');
18+
$table->string('paddle_id')->unique();
19+
$table->string('name');
20+
$table->string('email');
1821
$table->timestamp('trial_ends_at')->nullable();
1922
$table->timestamps();
2023

database/migrations/2019_05_03_000002_create_subscriptions_table.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@ public function up(): void
1515
$table->id();
1616
$table->foreignId('billable_id');
1717
$table->string('billable_type');
18-
$table->string('name');
19-
$table->integer('paddle_id')->unique();
20-
$table->string('paddle_status');
21-
$table->integer('paddle_plan');
22-
$table->integer('quantity');
18+
$table->string('type');
19+
$table->string('paddle_id')->unique();
20+
$table->string('status');
2321
$table->timestamp('trial_ends_at')->nullable();
24-
$table->timestamp('paused_from')->nullable();
22+
$table->timestamp('paused_at')->nullable();
2523
$table->timestamp('ends_at')->nullable();
2624
$table->timestamps();
2725

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::create('subscription_items', function (Blueprint $table) {
15+
$table->id();
16+
$table->foreignId('subscription_id');
17+
$table->string('product_id');
18+
$table->string('price_id');
19+
$table->string('status');
20+
$table->integer('quantity');
21+
$table->timestamps();
22+
23+
$table->unique(['subscription_id', 'price_id']);
24+
});
25+
}
26+
27+
/**
28+
* Reverse the migrations.
29+
*/
30+
public function down(): void
31+
{
32+
Schema::dropIfExists('subscription_items');
33+
}
34+
};

database/migrations/2019_05_03_000003_create_receipts_table.php renamed to database/migrations/2019_05_03_000004_create_transactions_table.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,18 @@
1111
*/
1212
public function up(): void
1313
{
14-
Schema::create('receipts', function (Blueprint $table) {
14+
Schema::create('transactions', function (Blueprint $table) {
1515
$table->id();
1616
$table->foreignId('billable_id');
1717
$table->string('billable_type');
18-
$table->unsignedBigInteger('paddle_subscription_id')->nullable()->index();
19-
$table->string('checkout_id');
20-
$table->string('order_id')->unique();
21-
$table->string('amount');
18+
$table->string('paddle_id')->unique();
19+
$table->string('paddle_subscription_id')->nullable()->index();
20+
$table->string('invoice_number')->nullable();
21+
$table->string('status');
22+
$table->string('total');
2223
$table->string('tax');
2324
$table->string('currency', 3);
24-
$table->integer('quantity');
25-
$table->string('receipt_url')->unique();
26-
$table->timestamp('paid_at');
25+
$table->timestamp('billed_at');
2726
$table->timestamps();
2827

2928
$table->index(['billable_id', 'billable_type']);
@@ -35,6 +34,6 @@ public function up(): void
3534
*/
3635
public function down(): void
3736
{
38-
Schema::dropIfExists('receipts');
37+
Schema::dropIfExists('transactions');
3938
}
4039
};

phpunit.xml.dist

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<phpunit backupGlobals="false"
3-
backupStaticAttributes="false"
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
backupGlobals="false"
44
bootstrap="vendor/autoload.php"
55
colors="true"
6-
convertDeprecationsToExceptions="true"
7-
convertErrorsToExceptions="true"
8-
convertNoticesToExceptions="true"
9-
convertWarningsToExceptions="true"
106
processIsolation="false"
117
stopOnFailure="false"
12-
>
8+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.4/phpunit.xsd"
9+
cacheDirectory=".phpunit.cache"
10+
backupStaticProperties="false">
1311
<testsuites>
1412
<testsuite name="Unit">
1513
<directory suffix="Test.php">./tests/Unit</directory>
@@ -20,5 +18,7 @@
2018
</testsuites>
2119
<php>
2220
<env name="DB_CONNECTION" value="testing"/>
21+
<env name="PADDLE_AUTH_CODE" value="fake"/>
22+
<env name="PADDLE_SANDBOX" value="true"/>
2323
</php>
2424
</phpunit>
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1-
<a href="#!" data-override="{{ $url }}" {{ $attributes->merge(['class' => 'paddle_button']) }}>
1+
<?php
2+
$items = $checkout->getItems();
3+
$customer = $checkout->getCustomer();
4+
$custom = $checkout->getCustomData();
5+
?>
6+
7+
<a
8+
href='#!'
9+
data-items='{!! json_encode($items) !!}'
10+
@if ($customer) data-customer-id='{{ $customer->paddle_id }}' @endif
11+
@if ($custom) data-custom-data='{{ json_encode($custom) }}' @endif
12+
@if ($returnUrl = $checkout->getReturnUrl()) data-success-url='{{ $returnUrl }}' @endif
13+
{{ $attributes->merge(['class' => 'paddle_button']) }}
14+
>
215
{{ $slot }}
316
</a>

resources/views/js.blade.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1-
@php($vendor = ['vendor' => (int) config('cashier.vendor_id')])
1+
<?php
2+
$seller = array_filter([
3+
'seller' => (int) config('cashier.seller_id'),
4+
'pwAuth' => (int) config('cashier.retain_key'),
5+
]);
26
3-
<script src="https://cdn.paddle.com/paddle/paddle.js"></script>
7+
if (isset($seller['pwAuth']) && Auth::check() && $customer = Auth::user()->customer) {
8+
$seller['pwCustomer'] = ['id' => $customer->paddle_id];
9+
}
10+
?>
11+
12+
<script src="https://cdn.paddle.com/paddle/v2/paddle.js"></script>
413

514
@if (config('cashier.sandbox'))
615
<script type="text/javascript">
@@ -9,5 +18,5 @@
918
@endif
1019

1120
<script type="text/javascript">
12-
Paddle.Setup(@json($vendor));
21+
Paddle.Setup(@json($seller));
1322
</script>

src/Billable.php

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,14 @@
33
namespace Laravel\Paddle;
44

55
use Laravel\Paddle\Concerns\ManagesCustomer;
6-
use Laravel\Paddle\Concerns\ManagesReceipts;
76
use Laravel\Paddle\Concerns\ManagesSubscriptions;
7+
use Laravel\Paddle\Concerns\ManagesTransactions;
88
use Laravel\Paddle\Concerns\PerformsCharges;
99

1010
trait Billable
1111
{
1212
use ManagesCustomer;
1313
use ManagesSubscriptions;
14-
use ManagesReceipts;
14+
use ManagesTransactions;
1515
use PerformsCharges;
16-
17-
/**
18-
* Get the default Paddle API options for the current Billable model.
19-
*
20-
* @param array $options
21-
* @return array
22-
*/
23-
public function paddleOptions(array $options = [])
24-
{
25-
return Cashier::paddleOptions($options);
26-
}
2716
}

0 commit comments

Comments
 (0)