Skip to content

Commit

Permalink
Enforce types to prevent Paddle API errors in edge cases
Browse files Browse the repository at this point in the history
  • Loading branch information
robwoodgate committed Oct 9, 2024
1 parent d55c6f8 commit f867f07
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 16 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ Paddle Billing is the evolution of Paddle Classic, and is the default billing AP

If you signed up for Paddle before this date, [you need to opt-in](https://developer.paddle.com/changelog/2023/enable-paddle-billing) to Paddle Billing. After you opt in, you can toggle between Paddle Billing and Paddle Classic, and run the two side by side for as long as you need.


### REQUIREMENTS

This plugin requires [aMember](https://www.cogmentis.com/go/amember) v6.x and PHP 7.2 or higher
Expand All @@ -15,6 +14,12 @@ This plugin requires [aMember](https://www.cogmentis.com/go/amember) v6.x and PH

2. Enable and configure the plugin in *aMember CP -> Setup/Configuration -> Plugins*

### TROUBLESHOOTING

This plugin writes Paddle responses to the aMember Invoice log (aMember admin > Utilities > Logs > Invoice).

In case of an error, please check there as well as in the aMember Error Log (aMember admin > Utilities > Logs > Errors).

### LICENCE / CREDITS

This plugin is provided under the MIT License.
Expand Down
37 changes: 22 additions & 15 deletions paddle-billing.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class Am_Paysystem_PaddleBilling extends Am_Paysystem_Abstract
{
public const PLUGIN_STATUS = self::STATUS_BETA;
public const PLUGIN_REVISION = '2.5';
public const PLUGIN_REVISION = '2.6';
public const CUSTOM_DATA_INV = 'am_invoice';
public const PRICE_ID = 'paddle-billing_pri_id';
public const SUBSCRIPTION_ID = 'paddle-billing_sub_id';
Expand Down Expand Up @@ -335,7 +335,7 @@ public function _process($invoice, $request, $result): void

// Build the core transaction item payload
$txnitm = [
'quantity' => $item->qty,
'quantity' => (int) $item->qty,
'price' => [
'description' => $product->getBillingPlan()->getTerms(),
'name' => ___('Subscription').$sptext,
Expand All @@ -356,8 +356,8 @@ public function _process($invoice, $request, $result): void
'currency_code' => $item->currency,
],
'quantity' => [
'minimum' => $item->qty,
'maximum' => $item->qty,
'minimum' => (int) $item->qty,
'maximum' => (int) $item->qty,
],
'custom_data' => [
'invoice_item' => $item->item_id,
Expand Down Expand Up @@ -763,6 +763,8 @@ public function getReadme()
$whk_url = $this->getPluginUrl('ipn');
$pay_url = $this->getPluginUrl('pay');
$paddleJs = $this->paddleJsSetupCode(true);
$ilog_url = Am_Di::getInstance()->url('default/admin-logs/p/invoice');
$elog_url = Am_Di::getInstance()->url('default/admin-logs/');

return <<<README
<strong>Paddle Billing Plugin v{$version}</strong>
Expand Down Expand Up @@ -801,6 +803,11 @@ public function getReadme()
<textarea onclick="this.select();" style="width:100%;" rows="8">{$paddleJs}</textarea>
<strong>TROUBLESHOOTING</strong>
This plugin writes Paddle responses to the aMember <a href="{$ilog_url}">Invoice log</a>.
In case of an error, please check there as well as in the aMember <a href="{$elog_url}">Error log</a>.
-------------------------------------------------------------------------------
Copyright 2024 (c) Rob Woodgate, Cogmentis Ltd.
Expand Down Expand Up @@ -990,7 +997,7 @@ protected function getAmount($amount, $currency = 'USD'): string
return (string) ($amount * pow(10, Am_Currency::$currencyList[$currency]['precision']));
}

protected function getText($period)
protected function getText($period): string
{
// Convert string if needed
if (!$period instanceof Am_Period) {
Expand All @@ -1000,7 +1007,7 @@ protected function getText($period)
return ucwords($period->getText());
}

protected function getRebillText($rebill_times)
protected function getRebillText($rebill_times): string
{
switch ($rebill_times) {
case '0':
Expand All @@ -1019,7 +1026,7 @@ protected function getRebillText($rebill_times)
return ucwords($period->getText());
}

protected function getFrequency($period)
protected function getFrequency($period): int
{
// Convert string if needed
if (!$period instanceof Am_Period) {
Expand All @@ -1032,10 +1039,10 @@ protected function getFrequency($period)
return 1;
}

return $period->getCount();
return (int) $period->getCount();
}

protected function getInterval($period)
protected function getInterval($period): string
{
// Convert string if needed
if (!$period instanceof Am_Period) {
Expand All @@ -1051,7 +1058,7 @@ protected function getInterval($period)
return $map[$period->getUnit()] ?? 'year';
}

protected function getDays($period)
protected function getDays($period): int
{
// Convert string if needed
if (!$period instanceof Am_Period) {
Expand All @@ -1060,26 +1067,26 @@ protected function getDays($period)

switch ($period->getUnit()) {
case Am_Period::DAY:
return $period->getCount();
return (int) $period->getCount();

case Am_Period::MONTH:
return $period->getCount() * 30;
return (int) ($period->getCount() * 30);

case Am_Period::YEAR:
return $period->getCount() * 365;
return (int) ($period->getCount() * 365);

case Am_Period::FIXED:
case Am_Period::MAX_SQL_DATE:
$date = new DateTime($period->getCount());

return $date->diff(new DateTime('now'))->days + 1;
return (int) ($date->diff(new DateTime('now'))->days + 1);

default:
return 10; // actual value in this case does not matter
}
}

protected function paddleJsSetupCode($snippet = false)
protected function paddleJsSetupCode($snippet = false): string
{
$environment = $this->isSandbox() ? 'Paddle.Environment.set("sandbox");' : '';
$client_token = $this->getConfig('client_token');
Expand Down

0 comments on commit f867f07

Please sign in to comment.