-
-
Notifications
You must be signed in to change notification settings - Fork 373
Creating a Billable App
First of all, its best to read up on Shopify's documentation to get to know how it works internally.
To enable billing on your app, there is configuration already in config/shopify-app.php
which is based on environment variables. Using these variables, here is what you need to setup.
Here is an example setup to get a basic app into billable mode:
SHOPIFY_BILLING_ENABLED=1
SHOPIFY_BILLING_TYPE=recurring
SHOPIFY_BILLING_PLAN="Demo Plan"
SHOPIFY_BILLING_TEST=1
SHOPIFY_BILLING_PRICE=15.00
SHOPIFY_BILLING_TRIAL_DAYS=14
Here is an explanation of the configuration, many are already set with sane-defaults:
SHOPIFY_BILLING_ENABLED=0
to disable billing state for application (default)
SHOPIFY_BILLING_ENABLED=1
to enable billing state for application
SHOPIFY_BILLING_TYPE=recurring
for recurring monthly billing (default)
SHOPIFY_BILLING_TYPE=single
for a one-time charge
SHOPIFY_BILLING_PLAN="Your plan name"
for a plan name to display to the customer
SHOPIFY_BILLING_PRICE=0.00
for a price of the plan
SHOPIFY_BILLING_TRIAL_DAYS=0
for number of days for trial (default: 7)
SHOPIFY_BILLING_TEST=0
to disable testing mode (default)
SHOPIFY_BILLING_TEST=1
to enable testing mode
SHOPIFY_BILLING_REDIRECT="/url/path"
for setting the path to handle the accepting or declining of the application charge (default: /billing/proccess)
Note: Its not recommended to change this unless you're using custom logic or overriding the billing controller.
SHOPIFY_BILLING_CAPPED_AMOUNT=100.00
Note: billing_terms
must be set when using billing_capped_amount
.
SHOPIFY_BILLING_TERMS="$1 for 50 emails."
Once you've set the required environment variables, you're ready to go.
Here's how the flow works:
- Shop installs the app
- Shop accepts the app's permissions
- Shop is presented with the billing screen to accept or decline
- 3a. If they accept, charge is activated, charge ID is saved to database, shop is sent to your app's homepage
- 3b. If they decline, charge is marked declined, shop is sent to error screen saying they did not pay.
Note: If billing is being applied on top of an existing app, when the shop accesses your app, they will sent to the billing screen.
Grandfather mode is useful when you wish to give a shop free access to your app. A simple boolean flag in the database (grandfathered
) tells the billable middleware to let them through.
UPDATE shops SET grandfathered = 1 WHERE shopify_domain = "domain.myshopify.com"
// Lookup
$shop = Shop::where('shopify_domain', 'domain.myshopify.com')->first();
// Or, for a current shop logged in
$shop = ShopifyApp::shop();
$shop->grandfathered = 1;
$shop->save();
The package is setup to track (initial) charges. If you setup billing as one-time or recurring for your app, the package will create a charge in the charges table tied to the app. This way, if the shop uninstalled during a trial period and you have the app/uninstalled webhook enabled, it will cancel the charge for the shop. If the shop trys to reinstall shortly after, the package will know, and adjust the trail days for you. This way, a shop can not bypass the trial period.
If you need to create a charge (maybe for usage charges, etc) you can do so via:
use Carbon\Carbon;
use OhMyBrew\ShopifyApp\Models\Charge;
// ...
$charge = new Charge;
$charge->charge_id = (response from charging using API);
$charge->test = (false|true); // only applicable to one-time or reccuring
$charge->status = '...';
$charge->type = (1|2|3|4); // Charge::CHARGE_RECURRING = 1, Charge::CHARGE_ONETIME = 2, Charge::CHARGE_USAGE = 3, Charge::CHARGE_CREDIT = 4
$charge->price = (float);
$charge->trial_days = (int);
$charge->trial_ends_on = (response from API);
$charge->shop_id = (shop's ID);
$charge->save();
The charge model uses the same fields as Shopify's API, so feel free to make a request to the API and fill in the values applicable to the type of charge you're issuing.
Shopify internally handles cancelling the previous plan. You simply need to direct the shop to the billing screen to accept the new charge.
Programmatically, you can do this with the package's BillingPlan
class.
// ...
use OhMyBrew\ShopifyApp\Libraries\BillingPlan;
// ...
$plan = new BillingPlan(ShopifyApp::shop(), 'recurring');
$plan->setDetails(
[
'name' => "Plan Name", // Example: "Super Plan!"
'price' => 0.00, // Example: 15.00
'return_url' => url(config('shopify-app.billing_redirect')),
]
);
// Plan is ready, you must now redirect the user to the billing screen, an example of doing this via the build-in view
return view('shopify-app::billing.fullpage_redirect', [
'url' => $plan->getConfirmationUrl(),
]);
It will check first if billing is enabled. If it is enabled... it will check if the shop has a charge_id
or if the shop is grandfathered in to let them through to the route. If the shop have no charge_id
and are not a grandfather, the shop is sent to the billing controller to pay.
If billing is not enabled, it simply skips all checks and lets the shop through.
Currently its used only on the app's home route. In most cases, this is all you will need because every time a shop clicks your app from their Shopify admin, it will go through to the home route by default which includes the shop authorization middleware, and the billable middleware.
If you'd like to use it on more routes, here's an example usage:
Route::get(
'/settings',
'App\Controllers\SettingsController@index'
)
->middleware(['auth.shop', 'billable']) // <---
->name('settings');
road map
Welcome to the wiki!
Please see the homepage for a list of relevant pages.