Skip to content

Instantly share code, notes, and snippets.

@adamyanalunas
Created November 16, 2019 01:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamyanalunas/e9b250711bb826682b85a8366850f63f to your computer and use it in GitHub Desktop.
Save adamyanalunas/e9b250711bb826682b85a8366850f63f to your computer and use it in GitHub Desktop.

Setting App Store Custom License Agreement

Want to programmatically set a custom license agreement in the App Store? Connect API doesn’t have an endpoint for that. Fastlane doesn’t have anything, either.

Don’t worry. Let’s just blindly POST some JSON to an App Store Connect endpoint to get where we need to go.

What could go wrong!

Examples

app_store_license(bundle_id: 'com.compay.app-bundle-name', license: 'Lots of corproate mumbo jumob')
app_store_license(bundle_id: 'com.compay.app-bundle-name', license: 'Tu nichts Unartiges!', countries: ['Australia'])

Warnings

Some values, like ratings, are hardcoded in this example. I leave it as an exercise to the reader to assure the proper values are set or derived from elsewhere.

Obviously this is not ideal code or an ideal solution. However, it’s better than nothing. Better to ship than not.

def app_store_license(bundle_id: nil, license: "", countries: nil)
# Make sure your Spacehip::Tunes.client is already logged in
app = Spaceship::Tunes::Application.find(bundle_id)
raise "Could not find an app with the bundle ID `#{bundle_id}`" unless app
app_id = app.apple_id
details = app.details
url = "https://appstoreconnect.apple.com/WebObjects/iTunesConnect.woa/ra/apps/#{app_id}/details"
localized_metadata = details.languages
# This is just for demo purposes. You should probably extract this somewhere.
countries ||= ["Albania", "Algeria", "Angola", "Anguilla", "Antigua and Barbuda", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Botswana", "Brazil", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Cambodia", "Canada", "Cape Verde", "Cayman Islands", "Chad", "Chile", "China", "Colombia", "Congo, Republic of", "Costa Rica", "Croatia", "Cyprus", "Czech Republic", "Denmark", "Dominica", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Estonia", "Fiji", "Finland", "France", "Gambia", "Germany", "Ghana", "Greece", "Grenada", "Guatemala", "Guinea-Bissau", "Guyana", "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Ireland", "Israel", "Italy", "Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Korea, Republic Of", "Kuwait", "Kyrgyzstan", "Lao People's Democratic Republic", "Latvia", "Lebanon", "Liberia", "Lithuania", "Luxembourg", "Macau", "Madagascar", "Malawi", "Malaysia", "Mali", "Malta", "Mauritania", "Mauritius", "Mexico", "Micronesia, Federated States of", "Moldova, Republic Of", "Mongolia", "Montserrat", "Mozambique", "Namibia", "Nepal", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "North Macedonia", "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Qatar", "Romania", "Russia", "Saint Lucia", "Saudi Arabia", "Senegal", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", "South Africa", "Spain", "Sri Lanka", "St. Kitts and Nevis", "St. Vincent and The Grenadines", "Suriname", "Swaziland", "Sweden", "Switzerland", "São Tomé and Príncipe", "Taiwan", "Tajikistan", "Tanzania, United Republic Of", "Thailand", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Turks and Caicos", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan", "Venezuela", "Vietnam", "Virgin Islands, British", "Yemen", "Zimbabwe"]
# Believe it or not, this is as little as I could send. Any less and I got 400’s and 500’s
data = {
adamId: app_id,
localizedMetadata: {
value: localized_metadata,
isEditable: true,
isRequired: true,
errorKeys: nil
},
availablePrimaryLocaleCodes: details.available_primary_locale_codes,
primaryLocaleCode: {
value: details.primary_locale_code,
isEditable: true,
isRequired: true,
errorKeys: nil
},
primaryCategory: {
value: details.primary_category,
isEditable: true,
isRequired: false,
errorKeys: nil
},
primaryFirstSubCategory: {
value: details.primary_first_sub_category,
isEditable: true,
isRequired: false,
errorKeys: nil
},
primarySecondSubCategory: {
value: details.primary_second_sub_category,
isEditable: true,
isRequired: false,
errorKeys: nil
},
secondaryCategory: {
value: details.secondary_category,
isEditable: true,
isRequired: false,
errorKeys: nil
},
secondaryFirstSubCategory: {
value: details.secondary_first_sub_category,
isEditable: true,
isRequired: false,
errorKeys: nil
},
secondarySecondSubCategory: {
value: details.secondary_second_sub_category,
isEditable: true,
isRequired: false,
errorKeys: nil
},
availableBundleIds: nil,
bundleId: {
value: bundle_id,
isEditable: false,
isRequired: true,
errorKeys: nil
},
bundleIdSuffix: {
value: nil,
isEditable: false,
isRequired: true,
errorKeys: nil
},
license: {
countries: countries,
isEditable: true,
isRequired: false,
errorKeys: nil,
isEmptyValue: false,
EULAText: license
},
vendorId: app.vendor_id,
# NOTE: This might override the existing value. You’ve been warnned!
rating: "4+",
ageBandMinAge: nil,
ageBandMaxAge: nil,
countryRatings: {
BR: "L"
},
subscriptionStatusUrl: {
value: nil,
isEditable: true,
isRequired: false,
errorKeys: nil,
maxLength: 255,
minLength: 0
},
gracRatingClassificationNumber: {
value: nil,
isEditable: true,
isRequired: false,
errorKeys: nil
}
}.to_json
response = Spaceship::Tunes.client.request(:post) { |req|
req.url(url)
req.headers['Content-Type'] = 'application/json'
req.body = data
}
response
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment