update to provisioner code nwew paddle code
This commit is contained in:
+209
-174
@@ -1,222 +1,257 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# pdl_live_apikey_01m3sj642qagm8h0r9z6yqrgzs_3jR1damnQ1XTyA23MpmkTM_Aka
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# SonarDesk - Paddle Production Price Setup
|
||||
#
|
||||
# Creates:
|
||||
# Personal Monthly
|
||||
# Personal Annual
|
||||
# Professional Monthly
|
||||
# Professional Annual
|
||||
#
|
||||
# against an EXISTING Paddle production product.
|
||||
#
|
||||
# Usage:
|
||||
# PADDLE_API_KEY="pdl_live_apikey_..." \
|
||||
# PADDLE_PRODUCT_ID="pro_..." \
|
||||
# ./scripts/paddle-production-prices.sh
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
PADDLE_API_URL="https://api.paddle.com"
|
||||
|
||||
: "${PADDLE_API_KEY:?PADDLE_API_KEY is required}"
|
||||
: "${PADDLE_PRODUCT_ID:?PADDLE_PRODUCT_ID is required}"
|
||||
: "${PADDLE_API_KEY:?PADDLE_API_KEY is not set}"
|
||||
: "${PADDLE_PRODUCT_ID:?PADDLE_PRODUCT_ID is not set}"
|
||||
|
||||
if [[ "${PADDLE_API_KEY}" != pdl_live_apikey_* ]]; then
|
||||
echo "ERROR: This does not look like a Paddle LIVE API key."
|
||||
echo "Refusing to continue."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${PADDLE_PRODUCT_ID}" != pro_* ]]; then
|
||||
echo "ERROR: PADDLE_PRODUCT_ID must start with pro_"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
command -v curl >/dev/null 2>&1 || {
|
||||
command -v curl >/dev/null || {
|
||||
echo "ERROR: curl is required."
|
||||
exit 1
|
||||
}
|
||||
|
||||
command -v jq >/dev/null 2>&1 || {
|
||||
command -v jq >/dev/null || {
|
||||
echo "ERROR: jq is required."
|
||||
echo "Install it on macOS with: brew install jq"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo
|
||||
echo "============================================================"
|
||||
echo " SonarDesk Paddle PRODUCTION Price Setup"
|
||||
echo "============================================================"
|
||||
echo
|
||||
echo "API: ${PADDLE_API_URL}"
|
||||
echo "Product: ${PADDLE_PRODUCT_ID}"
|
||||
echo
|
||||
echo "WARNING: This will create REAL Paddle production prices."
|
||||
echo
|
||||
|
||||
read -r -p "Continue? Type PRODUCTION to continue: " confirmation
|
||||
|
||||
if [[ "${confirmation}" != "PRODUCTION" ]]; then
|
||||
echo "Cancelled."
|
||||
exit 0
|
||||
if [[ "$PADDLE_API_KEY" != pdl_live_apikey_* ]]; then
|
||||
echo "ERROR: This script requires a Paddle LIVE API key."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Pricing
|
||||
#
|
||||
# Paddle unit_price amounts use the smallest currency unit:
|
||||
# £9.99 = 999
|
||||
# £99.00 = 9900
|
||||
#
|
||||
# Change these four values BEFORE running if required.
|
||||
# ---------------------------------------------------------------------------
|
||||
if [[ "$PADDLE_PRODUCT_ID" != pro_* ]]; then
|
||||
echo "ERROR: Invalid Paddle product ID."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CURRENCY="GBP"
|
||||
echo "============================================"
|
||||
echo " SonarDesk Paddle Production Price Setup"
|
||||
echo "============================================"
|
||||
echo
|
||||
echo "Product: $PADDLE_PRODUCT_ID"
|
||||
echo
|
||||
|
||||
PERSONAL_MONTHLY_AMOUNT="999"
|
||||
PERSONAL_ANNUAL_AMOUNT="9990"
|
||||
# ------------------------------------------------------------
|
||||
# Verify product
|
||||
# ------------------------------------------------------------
|
||||
|
||||
PROFESSIONAL_MONTHLY_AMOUNT="1999"
|
||||
PROFESSIONAL_ANNUAL_AMOUNT="19990"
|
||||
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
|
||||
echo "Creating: ${description}"
|
||||
echo "Creating: $description"
|
||||
|
||||
local payload
|
||||
|
||||
payload=$(jq -n \
|
||||
--arg product_id "${PADDLE_PRODUCT_ID}" \
|
||||
--arg description "${description}" \
|
||||
--arg amount "${amount}" \
|
||||
--arg currency "${CURRENCY}" \
|
||||
--arg interval "${interval}" \
|
||||
'{
|
||||
product_id: $product_id,
|
||||
description: $description,
|
||||
unit_price: {
|
||||
amount: $amount,
|
||||
currency_code: $currency
|
||||
},
|
||||
billing_cycle: {
|
||||
interval: $interval,
|
||||
frequency: 1
|
||||
},
|
||||
quantity: {
|
||||
minimum: 1,
|
||||
maximum: 1
|
||||
},
|
||||
tax_mode: "account_setting"
|
||||
}'
|
||||
)
|
||||
|
||||
local response
|
||||
local http_code
|
||||
local response_file
|
||||
|
||||
response_file=$(mktemp)
|
||||
|
||||
http_code=$(curl \
|
||||
--silent \
|
||||
--show-error \
|
||||
--output "${response_file}" \
|
||||
--write-out "%{http_code}" \
|
||||
--request POST \
|
||||
--url "${PADDLE_API_URL}/prices" \
|
||||
--header "Authorization: Bearer ${PADDLE_API_KEY}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--header "Accept: application/json" \
|
||||
--data "${payload}")
|
||||
|
||||
response=$(cat "${response_file}")
|
||||
rm -f "${response_file}"
|
||||
|
||||
if [[ "${http_code}" -lt 200 || "${http_code}" -ge 300 ]]; then
|
||||
echo
|
||||
echo "ERROR creating ${description}"
|
||||
echo "HTTP ${http_code}"
|
||||
echo
|
||||
|
||||
echo "${response}" | jq . 2>/dev/null || echo "${response}"
|
||||
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local price_id
|
||||
|
||||
price_id=$(echo "${response}" | jq -r '.data.id // empty')
|
||||
|
||||
if [[ -z "${price_id}" ]]; then
|
||||
echo "ERROR: Paddle created the price but no price ID was returned."
|
||||
echo "${response}" | jq .
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Created ${description}: ${price_id}"
|
||||
|
||||
printf '%s' "${price_id}"
|
||||
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'
|
||||
}
|
||||
|
||||
echo
|
||||
echo "Creating SonarDesk production prices..."
|
||||
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_ID=$(
|
||||
create_price \
|
||||
PERSONAL_MONTHLY="$(
|
||||
ensure_price \
|
||||
"SonarDesk Personal Monthly" \
|
||||
"${PERSONAL_MONTHLY_AMOUNT}" \
|
||||
"month" | tail -1
|
||||
)
|
||||
"299" \
|
||||
"month" |
|
||||
tail -n 1
|
||||
)"
|
||||
|
||||
PERSONAL_ANNUAL_ID=$(
|
||||
create_price \
|
||||
PERSONAL_ANNUAL="$(
|
||||
ensure_price \
|
||||
"SonarDesk Personal Annual" \
|
||||
"${PERSONAL_ANNUAL_AMOUNT}" \
|
||||
"year" | tail -1
|
||||
)
|
||||
"2499" \
|
||||
"year" |
|
||||
tail -n 1
|
||||
)"
|
||||
|
||||
PROFESSIONAL_MONTHLY_ID=$(
|
||||
create_price \
|
||||
PROFESSIONAL_MONTHLY="$(
|
||||
ensure_price \
|
||||
"SonarDesk Professional Monthly" \
|
||||
"${PROFESSIONAL_MONTHLY_AMOUNT}" \
|
||||
"month" | tail -1
|
||||
)
|
||||
"499" \
|
||||
"month" |
|
||||
tail -n 1
|
||||
)"
|
||||
|
||||
PROFESSIONAL_ANNUAL_ID=$(
|
||||
create_price \
|
||||
PROFESSIONAL_ANNUAL="$(
|
||||
ensure_price \
|
||||
"SonarDesk Professional Annual" \
|
||||
"${PROFESSIONAL_ANNUAL_AMOUNT}" \
|
||||
"year" | tail -1
|
||||
)
|
||||
"4499" \
|
||||
"year" |
|
||||
tail -n 1
|
||||
)"
|
||||
|
||||
echo
|
||||
echo "============================================"
|
||||
echo " Paddle Production Prices"
|
||||
echo "============================================"
|
||||
echo
|
||||
echo "============================================================"
|
||||
echo " Paddle Production Prices Created"
|
||||
echo "============================================================"
|
||||
echo "Personal Monthly: $PERSONAL_MONTHLY"
|
||||
echo "Personal Annual: $PERSONAL_ANNUAL"
|
||||
echo "Professional Monthly: $PROFESSIONAL_MONTHLY"
|
||||
echo "Professional Annual: $PROFESSIONAL_ANNUAL"
|
||||
echo
|
||||
echo "Add the following to your PRODUCTION .env:"
|
||||
echo "Add these to the production .env:"
|
||||
echo
|
||||
echo "PADDLE_ENVIRONMENT=production"
|
||||
echo "PADDLE_API_URL=https://api.paddle.com"
|
||||
echo
|
||||
echo "PADDLE_PRODUCT_ID=${PADDLE_PRODUCT_ID}"
|
||||
echo
|
||||
echo "PADDLE_PERSONAL_MONTHLY_PRICE_ID=${PERSONAL_MONTHLY_ID}"
|
||||
echo "PADDLE_PERSONAL_ANNUAL_PRICE_ID=${PERSONAL_ANNUAL_ID}"
|
||||
echo "PADDLE_PROFESSIONAL_MONTHLY_PRICE_ID=${PROFESSIONAL_MONTHLY_ID}"
|
||||
echo "PADDLE_PROFESSIONAL_ANNUAL_PRICE_ID=${PROFESSIONAL_ANNUAL_ID}"
|
||||
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 "Do not run this script again unless you intentionally want another"
|
||||
echo "set of Paddle production prices."
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user