Laravel Cashier Paddle provides an expressive, fluent interface to Paddle's subscription billing services.

Overview

Logo Laravel Cashier Paddle

Build Status Total Downloads Latest Stable Version License

Introduction

Laravel Cashier Paddle provides an expressive, fluent interface to Paddle's 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.

Official Documentation

Documentation for Cashier Paddle can be found on the Laravel website.

Contributing

Thank you for considering contributing to Cashier Paddle! You can read the contribution guide here.

Code of Conduct

In order to ensure that the Laravel community is welcoming to all, please review and abide by the Code of Conduct.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

License

Laravel Cashier Paddle is open-sourced software licensed under the MIT license.

Comments
  • Simple Charge The checkout id must be a valid checkout id.

    Simple Charge The checkout id must be a valid checkout id.

    • Cashier Paddle Version: 1.0@beta
    • Laravel Version: 7.0
    • PHP Version: 7.2.5

    Hi, I am using cashier-paddle for one of my laravel 7 projects. I am trying to integrate a paddle simple charge. I followed the official documentation and generated the payLink. But after putting the Cashier's provided paddle-button Blade component it doesn't work. It shows Page Not Found and in the developer network tab, I am getting this error The checkout id must be a valid checkout id. I will be thankful if anyone can help me to solve the issue. Thanks in advance.

    needs more info 
    opened by esanalok 17
  • Coupon Code is not applied when using

    Coupon Code is not applied when using "withCoupon()"?

    • Cashier Paddle Version: 1.0.0-beta
    • Laravel Version: 7.13.0
    • PHP Version: 7.4.5
    • Database Driver & Version: MySQL 5.7

    Description:

    I'm trying to apply a coupon to a pay link by using the SubscriptionBuilder and the withCoupon()-method.

    In my app, the checkout process looks like this:

    1. User selects a planfrom a list of plans and adds an optional coupon code and submits the form
    2. Controller builds PayLink and redirects user to Paddle (I'm not using the inline Checkout right now)
    3. User completes checkout on Paddle and is redirected back to the app

    However, the coupon code doesn't seem to be applied. The price is not reduced and the user still has the option to add the coupon again by clicking "Add Coupon". (The coupon is valid as it's being applied when doing on paddle.com)

    While debugging I've seen, that the coupon is available during the buildPayload-method call. The value is also still present before calling Cashier::post() here

    I have the problem both with "Checkout" and "Product" Coupons.

    Steps To Reproduce:

    Build a paylink by using withCoupon().

    $payLink = $user->newSubscription('default', $paddlePlanId)
        ->returnTo(route('home'))
        ->withCoupon('NAME-OF-COUPON')
        ->create();
    
    return redirect($payLink);
    
    bug 
    opened by stefanzweifel 17
  • Page Not Found Sorry, the page you were looking for could not be found.

    Page Not Found Sorry, the page you were looking for could not be found.

      Hello,
    

    I am trying to create a fake purchase and have a few questions please.

    1)When the amount if below 0.75 Euro, I get the error (The price is too low), is this normal?

    2)When I use the belowcode:

      $user = User::find(Auth::id());
            $payLink = $user->charge(0.75, 'test onecharge');
    
            return view('home', ['payLink' => $payLink]);
    

    I see a green button on my front end, click on it but get this message: image1

    I thought this code could be used to create 1 time charge from the back end(without firs inputting the product name in the paddle admin panel.

    Any idea why this is happening please?

    Thank you.

    opened by Benoit1980 16
  • Add a `fake` method to Cashier

    Add a `fake` method to Cashier

    Overview

    This PR adds a way for users to easily fake events and API calls with a single command and a couple options for customizing the responses and asserting that certain events are dispatched.

    How it works

    Under the hood, Cashier::fake() creates a new instance of CashierFake which, upon creation, fakes API calls with Http::fake() and Cashier-provided events as well with Event::fake(). A user may customize this experience if they wish to override the defaults by providing an array with an endpoint as the key and a response as its value as such:

    Cashier::fake([
      'subscription/create' => ['fake-response' => 'and its data']
    ]);
    

    Internally, CashierFake will format this path into a paddle API call within the retrieveEndpoint($path) call which uses Cashier's vendorsUrl method and some constants to return an endpoint such as: vendors.paddle.com/api/2.0/subscription/create. From here it will take the faked response and either return it as part of a Http::response if it's an array or allow the user to customize that behaviour by passing a function.

    There are two additional methods that can be used: paypal() and card(). These functions change the information returned by the subscription/users endpoint with paypal() sending a response that the user is paying via PayPal and card() that it is paying through a Visa with the following parameters:

    {
      card_type: 'visa',
      last_four_digits: '1234',
      expiry_date: '04/2022',
    }
    

    If these values need to be overwritten, you may pass your own information to the card() method and it will merge this into the response as such:

    Cashier::fake()->card(['card_type' => 'mastercard']);
    

    Finally the CashierFake method also fakes Events provided by the library. These events are:

    • Laravel\Paddle\Events\PaymentSucceeded
    • Laravel\Paddle\Events\SubscriptionCancelled
    • Laravel\Paddle\Events\SubscriptionCreated
    • Laravel\Paddle\Events\SubscriptionPaymentFailed
    • Laravel\Paddle\Events\SubscriptionPaymentSucceeded
    • Laravel\Paddle\Events\SubscriptionUpdated

    A user may append additional events to this process if they wish by adding passing them to the fake such as:

    Cashier::fake(events: CustomEvent::class);
    
    // or
    Cashier::fake(events: [CustomEvent::class, AndAnotherOne::class]);
    

    This also provides a number of assertions, present both on the CashierFake and Cashier class. The assertion methods on the Cashier act as a proxy for the CashierFake and forward the requests into that class. I went with this approach instead of putting the assertions only on the Cashier as I felt importing all the events it needed to cover, plus the Event Facade felt messy and distracts a dev who is trying to understand the concerns of the Cashier class. Open to feedback on this one or if someone wants to recommend a better way of doing this.

    Example of assertion syntax:

    // Switching between Cashier/CashierFake sucks
    Cashier::fake()
    
    CashierFake::assertSubscriptionCreated();
    
    // This looks better:
    Cashier::fake();
    
    Cashier::assertSubscriptionCreated();
    
    // However this looks like garbage...so again...placed the assertions in CashierFake and 
    // did a bit of code duplication in favour of import hell.
    use Illuminate\Support\Facades\Http;
    use Laravel\Paddle\Exceptions\PaddleException;
    use Money\Currencies\ISOCurrencies;
    use Money\Currency;
    use Money\Formatter\IntlMoneyFormatter;
    use Money\Money;
    use NumberFormatter;
    use Illuminate\Support\Facades\Event;
    use Laravel\Paddle\Events\PaymentSucceeded;
    use Laravel\Paddle\Events\SubscriptionCancelled;
    use Laravel\Paddle\Events\SubscriptionCreated;
    use Laravel\Paddle\Events\SubscriptionPaymentFailed;
    use Laravel\Paddle\Events\SubscriptionPaymentSucceeded;
    use Laravel\Paddle\Events\SubscriptionUpdated;
    
    class Cashier
    {
      // ...
    }
    

    One final thing...

    Let me know if you want me to remove this but I found that setting <server /> variables in my PHPUnit did nothing...<env /> did...so I've updated the CONTRIBUTING.md file with that. I've also added an env there for PADDLE_SANDBOX because it's likely that you're going to be testing in sandbox mode...not sure if this should also be a part of the phpunit.xml.dist too...lemme know.

    opened by kylemilloy 14
  • Paddle Subscription Modifiers

    Paddle Subscription Modifiers

    Hey,

    Wondering if Paddles subscription modifiers exist within the package? Took a look at the docs, but only thing it mentions is Subscription single charges - is this referencing modifiers reference here?

    I am aiming to make use of this feature to be able to modify a users recurring subscription price and metered billing.

    Cheers!

    enhancement 
    opened by enkota 14
  • Unknown column 'subscriptions.billable_id' after upgrading the laravel framework and paddle.

    Unknown column 'subscriptions.billable_id' after upgrading the laravel framework and paddle.

    • Cashier Paddle Version: ^1.0@beta (v1.0.0-beta2)
    • Laravel Version: 7.25.0
    • PHP Version: ^7.2.5
    • Database Driver & Version: mysql

    Description:

    After a composer update, and running the migrations, the column went missing.

    In my code I'm trying to do the following:

    @if(Auth::user()->subscribedToPlan($monthly = 123123, 'Service Pro'))

    opened by dlogvin 13
  • How to check if the user is one trial or subscribed to any plan

    How to check if the user is one trial or subscribed to any plan

    I have 3 different subscriptions : Basic,pro,unlimited.

    I am planning to use policies to check if a user is subscribed to a determined plan or to some plan at all or if he/she is on trial, is there a function or a way to check if a user is on trial of any plan or subscribed to any plan?

    Thanks for this wonderful packages @driesvints , I am almost done with the implementation in my SaaS.

    enhancement 
    opened by techguydev 13
  • isInitialPayment shows false even though it should be true

    isInitialPayment shows false even though it should be true

    • Cashier Paddle Version: v1.5.2
    • Laravel Version: v9.5.1
    • PHP Version: 8.0.14
    • Database Driver & Version:

    Description:

    I'm trying to work with the event SubscriptionPaymentSucceeded but while using the public method isInitialPayment(), I noticed that it's not working correctly.

    To fix the "bug" it should be

    public function isInitialPayment()
    {
      (int) return $this->payload['initial_payment'] === 1;
    }
    
    opened by pmochine 10
  • Adds subscription modifiers

    Adds subscription modifiers

    This PR is a draft until there's consensus on what it should look like.

    Implements #71

    Paddle subscription prices are fixed and require a modifier to change. Modifiers allow you to implement metered billing or add-on subscriptions.

    Examples

    Subscription add-ons User is subscribed to a webshop builder for $100/month. The shipping plugin costs $20/month. Total cost is $120/month.

    Metered billing with base plan User is subscribed to a plan which allows for 100.000 API calls for $100/month and subsequent calls are $2 / 1000 calls. When a user uses 120.000 API calls the total cost is $100 + (20.000/1.000) * $2 = $140.

    Metered billing without a base plan ~~Contacted Paddle how to approach this. Will update later.~~ Paddle says it's not possible to do this without a base plan. They suggest a $0 subscription and using quantity to set the right amount. This doesn't involve modifiers / this PR.

    Implementation

    Subscription would have a hasMany() relationship to modifiers so a new database table would be created.

    Create a modifier and attach to a subscription

    $user->subscription()->newModifier()
        ->amount(15.00)
        ->description('Webshop add-on')
        ->recurring(true)
        ->create();
    

    Get all modifiers

    $user->subscription()->modifiers;
    

    Get specific modifier

    $user->subscription()->modifier('modifier_id');
    

    Remove modifier

    $user->subscription()->modifier('modifier_id')->delete();
    

    To-do

    • [x] Modifiers can be created
    • [x] Modifiers can be accessed
    • [x] Modifiers can be deleted
    • [ ] Modifiers can be synced from Paddle with a command.
    opened by yoeriboven 10
  • [1.x] Subscription Modifiers

    [1.x] Subscription Modifiers

    Picks up the work from https://github.com/laravel/cashier-paddle/pull/90 by @yoeriboven. I've sent this in as a PR with a branch on this repo so we can verify that the tests pass.

    Closes https://github.com/laravel/cashier-paddle/issues/71

    opened by driesvints 9
  • Problem with WebHook Custom handlers

    Problem with WebHook Custom handlers

    Hello,

            "php": "^7.4",
            "laravel/cashier-paddle": "^1.0.0-beta.2",
            "laravel/framework": "^7.24.0",
    

    Based on the documentation: https://laravel.com/docs/7.x/cashier-paddle#defining-webhook-event-handlers

    I have created a controller at \App\Http\Controllers\WebhookController and added this code in it:

    <?php
    
    namespace App\Http\Controllers;
    
    use Laravel\Paddle\Http\Controllers\WebhookController as CashierController;
    
    class WebhookController extends CashierController
    {
        /**
         * Handle payment succeeded.
         *
         * @param  array  $payload
         * @return void
         */
        public function handlePaymentSucceeded(array $payload)
        {
            if (Receipt::where('order_id', $payload['order_id'])->count()) {
                return;
            }
    
            $this->findOrCreateCustomer($payload['passthrough'])->receipts()->create([
                'checkout_id' => $payload['checkout_id'],
                'order_id' => $payload['order_id'],
                'amount' => $payload['sale_gross'],
                'tax' => $payload['payment_tax'],
                'currency' => $payload['currency'],
                'quantity' => (int) $payload['quantity'],
                'receipt_url' => $payload['receipt_url'],
                'paid_at' => Carbon::createFromFormat('Y-m-d H:i:s', $payload['event_time'], 'UTC'),
            ]);
        }
    }
    

    I was hoping to be able to use the handlePaymentSucceeded to see if I could recreate a receipt(like the original method from CashierController as I need later on to add a bit more code to it).

    I have also added this route in the web.php:

    Route::post('paddle/webhook', '\App\Http\Controllers\WebhookController@handleWebhook');
    

    When passing a purchase via:

               $payLink = $user->chargeProduct($product->product_id, [
                   'quantity_variable' => 0,
               ]);
    

    Which works perfectly as I receive both a Paypal receipt and Paddle receipt, I receive this error in telescope:

    BadMethodCallException
    Method App\Http\Controllers\WebhookController::handleWebhook does not exist.
    

    If I remove this controller App\Http\Controllers\WebhookController, the receipt is created correctly in the database(demonstrating that everything works), but the issue only happens when I use the "extends CashierController".

    Any idea if there is something missing in your doc there please? Perhaps the constructor needs to be copied aswell?

    Thank you,

    opened by Benoit1980 8
Releases(v1.7.0)
Thunder is an advanced Laravel tool to track user consumption using Cashier's Metered Billing for Stripe. ⚡

⚡ Thunder Thunder is an advanced Laravel tool to track user consumption using Cashier's Metered Billing for Stripe. ⚡ ?? Supporting If you are using o

Renoki Co. 10 Nov 21, 2022
List of 77 languages for Laravel Framework 4, 5, 6, 7 and 8, Laravel Jetstream , Laravel Fortify, Laravel Breeze, Laravel Cashier, Laravel Nova and Laravel Spark.

Laravel Lang In this repository, you can find the lang files for the Laravel Framework 4/5/6/7/8, Laravel Jetstream , Laravel Fortify, Laravel Cashier

Laravel Lang 6.9k Jan 2, 2023
Laravel newsletter subscription system

Laravel newsletter subscription system a powerfull newsletter subscription system for laravel Installation Run the command below to install this packa

Laravel Iran Community 4 Jan 18, 2022
Official Mollie integration for Laravel Cashier

Subscription billing with Laravel Cashier for Mollie Laravel Cashier provides an expressive, fluent interface to subscriptions using Mollie's billing

Mollie 80 Dec 31, 2022
Vandar Cashier is a Laravel package that allows you to seamlessly implement IPG and Direct Debit on your application

Vandar Cashier is a Laravel package that provides you with a seamless integration with Vandar services. Take a look at Vandar Documentation for more i

Vandar 11 Dec 14, 2022
Ubilling is opensource ISP billing system based on stargazer

Ubilling Ubilling is opensource ISP billing system based on stargazer. Please visit our official resources: Project homepage Documentation Community f

Rostyslav 105 Dec 5, 2022
Driver for managing cash payments in the Cashier Provider ecosystem

Cash Driver Provider Installation To get the latest version of Cash Driver Provider, simply require the project using Composer: $ composer require cas

Cashier Provider 4 Aug 30, 2022
This is a free Billing System for Resellme clients.

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Resellme 4 Oct 31, 2022
Unleash the expressive power of the natural language in your Laravel application.

jrmajor/laravel-fluent Unleash the expressive power of the natural language in your Laravel application. Read the Fluent Syntax Guide in order to lear

Jeremiasz Major 17 Dec 17, 2022
A Laravel (php) package to interface with the geo-location services at geonames.org.

geonames v7.x A Laravel (php) package to interface with the geo-location services at geonames.org. Major Version Jump I jumped several major versions

Michael Drennen 82 Nov 24, 2022
The fluent laravel marketplace

the marketplace CheatSheet will be availble soon marketplace provides you the following : 1. Product & Product Variation System Create simple products

Security Theater 189 Nov 24, 2022
A fluent Laravel package for Plaid

A fluent Laravel package for Plaid

Abivia 12 Sep 25, 2022
Object-oriented, composable, fluent API for writing validations in Laravel

Laravel Hyrule Hyrule provides an object-oriented, fluent API for building validation rules for use w/ Laravel's Validation component. This unlocks pa

Square 330 Dec 8, 2022
27Laracurl Laravel wrapper package for PHP cURL class that provides OOP interface to cURL. [10/27/2015] View Details

Laracurl Laravel cURL Wrapper for Andreas Lutro's OOP cURL Class Installation To install the package, simply add the following to your Laravel install

zjango 8 Sep 9, 2018
Laravel Soulbscription - This package provides a straightforward interface to handle subscriptions and features consumption.

About This package provides a straightforward interface to handle subscriptions and features consumption. Installation You can

Lucas Vinicius 269 Jan 1, 2023
Laravel-veneer - A suite of mocked services to use in your Laravel tests.

Laravel Veneer A suite of fixture data and methods to help make mocking 3rd party services easier. Overview Laravel Veneer aims to solve two problems

Oh See Software 4 Jun 23, 2022
Zarinpal is a laravel package to easily use zarinpal.com payment services in your applications

پکیج اتصال به درگاه پرداخت زرین پال zarinpal.com برای اتصال به درگاه پرداخت اینترنتی زرین پال و استفاده از api های آن می توانید از این پکیج استفاده کن

Rahmat Waisi 4 Jan 26, 2022
Generate services in Laravel with the artisan command

Laravel Service Generator Quickly generate services for your projects! Table of Contents Features Installation Usage Generate services Generate servic

Tim Wassenburg 15 Dec 2, 2022
Collection of Google Maps API Web Services for Laravel

Collection of Google Maps API Web Services for Laravel Provides convenient way of setting up and making requests to Maps API from Laravel application.

Alexander Pechkarev 467 Jan 5, 2023