258 lines
6.5 KiB
Bash
Executable File
258 lines
6.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
PADDLE_API_URL="https://api.paddle.com"
|
|
|
|
: "${PADDLE_API_KEY:?PADDLE_API_KEY is not set}"
|
|
: "${PADDLE_PRODUCT_ID:?PADDLE_PRODUCT_ID is not set}"
|
|
|
|
command -v curl >/dev/null || {
|
|
echo "ERROR: curl is required."
|
|
exit 1
|
|
}
|
|
|
|
command -v jq >/dev/null || {
|
|
echo "ERROR: jq is required."
|
|
exit 1
|
|
}
|
|
|
|
if [[ "$PADDLE_API_KEY" != pdl_live_apikey_* ]]; then
|
|
echo "ERROR: This script requires a Paddle LIVE API key."
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$PADDLE_PRODUCT_ID" != pro_* ]]; then
|
|
echo "ERROR: Invalid Paddle product ID."
|
|
exit 1
|
|
fi
|
|
|
|
echo "============================================"
|
|
echo " SonarDesk Paddle Production Price Setup"
|
|
echo "============================================"
|
|
echo
|
|
echo "Product: $PADDLE_PRODUCT_ID"
|
|
echo
|
|
|
|
# ------------------------------------------------------------
|
|
# Verify product
|
|
# ------------------------------------------------------------
|
|
|
|
PRODUCT_RESPONSE="$(
|
|
curl -fsS \
|
|
-H "Authorization: Bearer $PADDLE_API_KEY" \
|
|
-H "Accept: application/json" \
|
|
"$PADDLE_API_URL/products/$PADDLE_PRODUCT_ID"
|
|
)"
|
|
|
|
PRODUCT_NAME="$(echo "$PRODUCT_RESPONSE" | jq -r '.data.name // empty')"
|
|
|
|
if [[ -z "$PRODUCT_NAME" ]]; then
|
|
echo "ERROR: Could not retrieve Paddle product."
|
|
exit 1
|
|
fi
|
|
|
|
echo "Found product: $PRODUCT_NAME"
|
|
echo
|
|
|
|
# ------------------------------------------------------------
|
|
# Existing prices
|
|
# ------------------------------------------------------------
|
|
|
|
get_prices() {
|
|
curl -fsS \
|
|
-H "Authorization: Bearer $PADDLE_API_KEY" \
|
|
-H "Accept: application/json" \
|
|
"$PADDLE_API_URL/prices?product_id=$PADDLE_PRODUCT_ID&status=active&per_page=100"
|
|
}
|
|
|
|
find_price_by_description() {
|
|
local description="$1"
|
|
|
|
get_prices |
|
|
jq -r \
|
|
--arg description "$description" \
|
|
'.data[]
|
|
| select(.description == $description)
|
|
| .id' |
|
|
head -n 1
|
|
}
|
|
|
|
create_price() {
|
|
local description="$1"
|
|
local amount="$2"
|
|
local interval="$3"
|
|
|
|
echo "Creating: $description"
|
|
|
|
curl -fsS \
|
|
-X POST \
|
|
"$PADDLE_API_URL/prices" \
|
|
-H "Authorization: Bearer $PADDLE_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-H "Accept: application/json" \
|
|
--data "$(
|
|
jq -n \
|
|
--arg product "$PADDLE_PRODUCT_ID" \
|
|
--arg description "$description" \
|
|
--arg amount "$amount" \
|
|
--arg interval "$interval" \
|
|
'{
|
|
product_id: $product,
|
|
description: $description,
|
|
unit_price: {
|
|
amount: $amount,
|
|
currency_code: "GBP"
|
|
},
|
|
billing_cycle: {
|
|
interval: $interval,
|
|
frequency: 1
|
|
},
|
|
quantity: {
|
|
minimum: 1,
|
|
maximum: 1
|
|
},
|
|
tax_mode: "account_setting"
|
|
}'
|
|
)" |
|
|
jq -r '.data.id'
|
|
}
|
|
|
|
update_price_amount() {
|
|
local price_id="$1"
|
|
local description="$2"
|
|
local amount="$3"
|
|
|
|
echo "Updating: $description ($price_id)"
|
|
|
|
curl -fsS \
|
|
-X PATCH \
|
|
"$PADDLE_API_URL/prices/$price_id" \
|
|
-H "Authorization: Bearer $PADDLE_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-H "Accept: application/json" \
|
|
--data "$(
|
|
jq -n \
|
|
--arg description "$description" \
|
|
--arg amount "$amount" \
|
|
'{
|
|
description: $description,
|
|
unit_price: {
|
|
amount: $amount,
|
|
currency_code: "GBP"
|
|
}
|
|
}'
|
|
)" >/dev/null
|
|
}
|
|
|
|
ensure_price() {
|
|
local description="$1"
|
|
local amount="$2"
|
|
local interval="$3"
|
|
|
|
local existing
|
|
existing="$(find_price_by_description "$description")"
|
|
|
|
if [[ -n "$existing" ]]; then
|
|
local current_amount
|
|
current_amount="$(
|
|
get_prices |
|
|
jq -r \
|
|
--arg id "$existing" \
|
|
'.data[]
|
|
| select(.id == $id)
|
|
| .unit_price.amount'
|
|
)"
|
|
|
|
if [[ "$current_amount" != "$amount" ]]; then
|
|
echo "Existing price $existing has amount $current_amount."
|
|
echo "Required amount is $amount."
|
|
update_price_amount \
|
|
"$existing" \
|
|
"$description" \
|
|
"$amount"
|
|
else
|
|
echo "Exists: $description ($existing)"
|
|
fi
|
|
|
|
echo "$existing"
|
|
return
|
|
fi
|
|
|
|
create_price \
|
|
"$description" \
|
|
"$amount" \
|
|
"$interval"
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# SonarDesk production prices
|
|
#
|
|
# Paddle amounts are in pennies:
|
|
#
|
|
# £2.99 = 299
|
|
# £24.99 = 2499
|
|
# £4.99 = 499
|
|
# £44.99 = 4499
|
|
# ------------------------------------------------------------
|
|
|
|
echo "Configuring prices..."
|
|
echo
|
|
|
|
PERSONAL_MONTHLY="$(
|
|
ensure_price \
|
|
"SonarDesk Personal Monthly" \
|
|
"299" \
|
|
"month" |
|
|
tail -n 1
|
|
)"
|
|
|
|
PERSONAL_ANNUAL="$(
|
|
ensure_price \
|
|
"SonarDesk Personal Annual" \
|
|
"2499" \
|
|
"year" |
|
|
tail -n 1
|
|
)"
|
|
|
|
PROFESSIONAL_MONTHLY="$(
|
|
ensure_price \
|
|
"SonarDesk Professional Monthly" \
|
|
"499" \
|
|
"month" |
|
|
tail -n 1
|
|
)"
|
|
|
|
PROFESSIONAL_ANNUAL="$(
|
|
ensure_price \
|
|
"SonarDesk Professional Annual" \
|
|
"4499" \
|
|
"year" |
|
|
tail -n 1
|
|
)"
|
|
|
|
echo
|
|
echo "============================================"
|
|
echo " Paddle Production Prices"
|
|
echo "============================================"
|
|
echo
|
|
echo "Personal Monthly: $PERSONAL_MONTHLY"
|
|
echo "Personal Annual: $PERSONAL_ANNUAL"
|
|
echo "Professional Monthly: $PROFESSIONAL_MONTHLY"
|
|
echo "Professional Annual: $PROFESSIONAL_ANNUAL"
|
|
echo
|
|
echo "Add these to the production .env:"
|
|
echo
|
|
echo "PADDLE_ENVIRONMENT=production"
|
|
echo "PADDLE_API_URL=https://api.paddle.com"
|
|
echo "PADDLE_PRODUCT_ID=$PADDLE_PRODUCT_ID"
|
|
echo "PADDLE_PERSONAL_MONTHLY_PRICE_ID=$PERSONAL_MONTHLY"
|
|
echo "PADDLE_PERSONAL_ANNUAL_PRICE_ID=$PERSONAL_ANNUAL"
|
|
echo "PADDLE_PROFESSIONAL_MONTHLY_PRICE_ID=$PROFESSIONAL_MONTHLY"
|
|
echo "PADDLE_PROFESSIONAL_ANNUAL_PRICE_ID=$PROFESSIONAL_ANNUAL"
|
|
echo
|
|
echo "IMPORTANT:"
|
|
echo "PADDLE_API_KEY and PADDLE_CLIENT_SIDE_TOKEN must also be LIVE values."
|
|
echo "PADDLE_WEBHOOK_SECRET must come from the LIVE webhook destination."
|
|
echo
|