Closed hhoweson closed 5 years ago
It seems like you have not included the output of fastlane env
To make it easier for us help you resolve this issue, please update the issue to include the output of fastlane env
:+1:
It can not change title and description when it is in ReadyForSale status
Would it be possible to add this since it is possible through the itc interface? Thanks
@hhoweson could you try
https://github.com/fastlane/fastlane/blob/master/spaceship/lib/spaceship/tunes/iap_detail.rb#L72? What’s th full code you currently run so we can replicate it in IRB? The data you posted seems to be fine. This is similar to all_apps = Spaceship::Tunes::Application.all
where you also only get the standard / basic information (read only). If you want to edit anything you need to go „one level deeper“:
details.name['en-US'] = "App Name"
details.privacy_url['en-US'] = "https://fastlane.tools"
details.save!
Aaaah, I see now, thank you! I had not realised that more information was available by using .edit, I can now view the titles and descriptions 👍, however I do have an issue editing them. Even if I change nothing I get the following error when I try to save:
/Library/Ruby/Gems/2.3.0/gems/fastlane-2.117.1/spaceship/lib/spaceship/tunes/tunes_client.rb:230:in `handle_itc_response': ITC.response.error.OPERATION_FAILED (Spaceship::Tunes::Error)
from /Library/Ruby/Gems/2.3.0/gems/fastlane-2.117.1/spaceship/lib/spaceship/tunes/tunes_client.rb:1241:in `block in update_iap!'
from /Library/Ruby/Gems/2.3.0/gems/fastlane-2.117.1/spaceship/lib/spaceship/tunes/tunes_client.rb:1461:in `with_tunes_retry'
from /Library/Ruby/Gems/2.3.0/gems/fastlane-2.117.1/spaceship/lib/spaceship/tunes/tunes_client.rb:1235:in `update_iap!'
from /Library/Ruby/Gems/2.3.0/gems/fastlane-2.117.1/spaceship/lib/spaceship/tunes/iap_detail.rb:182:in `save!'
from getIaps.rb:198:in `block (2 levels) in <main>'
from getIaps.rb:87:in `each'
from getIaps.rb:87:in `block in <main>'
from getIaps.rb:71:in `each'
from getIaps.rb:71:in `<main>'
My code is similar to this:
app = Spaceship::Tunes::Application.find(app_id)
iaps = app.in_app_purchases.all
iapReadonly = iaps[0]
iap = iapReadonly.edit
iap.save!
The save command is on line 71 of my code and appear to be the command causing the error
@hhoweson Could you check ~/tmp for the spaceship
log? The trace does not tell much, except spaceship
was not able to save your changes.
# Logfile created on 2019-03-25 09:12:49 +0000 by logger.rb/56438
INFO [09:12:49]: >> GET https://olympus.itunes.apple.com/v1/session: [undefined body]
DEBUG [09:12:50]: << GET https://olympus.itunes.apple.com/v1/session: 200 {"user"=>{"fullName"=>"aditya mehta", "firstName"=>"aditya", "lastName"=>"mehta", "emailAddress"=>"mixpanel@utalk.com", "prsId"=>"16053026469"}, "provider"=>{"providerId"=>108936, "name"=>"EuroTalk Ltd", "contentTypes"=>["SOFTWARE"], "subType"=>"COMPANY"}, "availableProviders"=>[{"providerId"=>108936, "name"=>"EuroTalk Ltd", "contentTypes"=>["SOFTWARE"], "subType"=>"COMPANY"}], "backingType"=>"ITC", "backingTypes"=>["ITC"], "roles"=>["SALES", "MARKETING", "REPORTS", "CUSTOMER_SUPPORT"], "unverifiedRoles"=>[], "featureFlags"=>["showWwdrUserRoles", "adpRad", "apiKeys"], "agreeToTerms"=>true, "termsSignatures"=>["ASC", "RAD"], "modules"=>[{"key"=>"Apps", "name"=>"ITC.HomePage.Apps.IconText", "localizedName"=>"My Apps", "url"=>"https://appstoreconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app", "iconUrl"=>"https://appstoreconnect.apple.com/static/img/ico_homepage/themed/apps/Apps@2x.d3ce493e56172e92aed6.png", "down"=>false, "visible"=>true, "hasNotifications"=>false}, {"key"=>"AppAnalytics", "name"=>"ITC.HomePage.AppAnalytics.IconText", "localizedName"=>"App Analytics", "url"=>"https://analytics.itunes.apple.com/", "iconUrl"=>"https://appstoreconnect.apple.com/static/img/ico_homepage/themed/apps/AppAnalytics@2x.e19f711d943cb42d65b2.png", "down"=>false, "visible"=>true, "hasNotifications"=>false}, {"key"=>"SalesTrends", "name"=>"ITC.HomePage.SalesTrends.IconText", "localizedName"=>"Sales and Trends", "url"=>"https://reportingitc2.apple.com/?", "iconUrl"=>"https://appstoreconnect.apple.com/static/img/ico_homepage/themed/apps/SalesTrends@2x.b1f802112426525d990a.png", "down"=>false, "visible"=>true, "hasNotifications"=>false}, {"key"=>"Account", "name"=>"ITC.HomePage.Account.IconText", "localizedName"=>"Users and Access", "url"=>"https://appstoreconnect.apple.com/access/users", "iconUrl"=>"https://appstoreconnect.apple.com/static/img/ico_homepage/themed/apps/ManageUsers@2x.81511f3933fb2fb4b20d.png", "down"=>false, "visible"=>true, "hasNotifications"=>false}, {"key"=>"Resources", "name"=>"ITC.HomePage.Resources.IconText", "localizedName"=>"Resources and Help", "url"=>"https://developer.apple.com/app-store-connect/", "iconUrl"=>"https://appstoreconnect.apple.com/static/img/ico_homepage/themed/apps/Resources@2x.3c8d0d8c08e876cf9470.png", "down"=>false, "visible"=>true, "hasNotifications"=>false}], "helpLinks"=>[{"key"=>"AllAsc", "url"=>"https://help.apple.com/app-store-connect/", "localizedText"=>"App Store Connect Resources"}, {"key"=>"Xcode", "url"=>"https://help.apple.com/xcode/mac/current/", "localizedText"=>"Xcode Help"}, {"key"=>"DeveloperAccount", "url"=>"https://help.apple.com/developer-account/", "localizedText"=>"Developer Account Help"}, {"key"=>"SupportContact", "url"=>"https://developer.apple.com/support/", "localizedText"=>"Support and Contact"}], "userProfile"=>[{"key"=>"signIn", "url"=>"https://appstoreconnect.apple.com/login", "localizedText"=>"Sign In"}, {"key"=>"personalDetails", "url"=>"https://appstoreconnect.apple.com/access/users/918a9466-8331-4c46-b71b-d3503cf59d37/settings", "localizedText"=>"Edit Profile"}, {"key"=>"signOut", "url"=>"https://appstoreconnect.apple.com/logout", "localizedText"=>"Sign Out"}], "pccDto"=>nil, "publicUserId"=>"918a9466-8331-4c46-b71b-d3503cf59d37"}
INFO [09:12:50]: >> GET ra/apps/manageyourapps/summary/v2: [undefined body]
DEBUG [09:12:53]: << GET ra/apps/manageyourapps/summary/v2: 200 {"data"=>{*****}, "messages"=>{"warn"=>nil, "info"=>nil, "error"=>nil}, "statusCode"=>"SUCCESS"}
INFO [09:12:53]: >> GET ra/apps/1085013031/iaps: [undefined body]
DEBUG [09:12:54]: << GET ra/apps/1085013031/iaps: 200 {"data"=>[*****], "messages"=>{"warn"=>nil, "info"=>nil, "error"=>nil}, "statusCode"=>"SUCCESS"}
INFO [09:12:54]: >> GET ra/apps/1085013031/iaps/1407845488: [undefined body]
DEBUG [09:12:59]: << GET ra/apps/1085013031/iaps/1407845488: 200 {"data"=>{*****}, "messages"=>{"warn"=>nil, "error"=>nil, "info"=>nil}, "statusCode"=>"SUCCESS"}
INFO [09:12:59]: >> PUT ra/apps/1085013031/iaps/1407845488: {"sectionErrorKeys":[],"sectionInfoKeys":[],"sectionWarningKeys":[],"value":null,"id":"3335729086","adamId":"1407845488","appAdamIds":["1085013031"],"familyId":null,"addOnType":"nonConsumable","isNewsSubscription":false,"isReplaced":false,"replacementAdamId":null,"referenceName":{"value":"001 Learn English (American) (VA PA)","isEditable":true,"isRequired":true,"errorKeys":null,"maxLength":64,"minLength":2},"productId":{"value":"ios_utalkone_wholelanguage_va_pa_001","isEditable":false,"isRequired":true,"errorKeys":null,"maxLength":100,"minLength":2},"clearedForSale":{"value":true,"isEditable":true,"isRequired":false,"errorKeys":null},"pricingDurationType":null,"pricingIntervals":[{"value":{"tierStem":41,"priceTierEffectiveDate":null,"priceTierEndDate":null,"country":"WW","grandfathered":null}}],"ungrandfatheredIntervals":null,"freeTrialDurationType":null,"bonusPeriodDurationType":null,"versions":[{"reviewNotes":{"value":null},"contentHosting":{"value":false,"isEditable":true,"isRequired":false,"errorKeys":null},"details":{"value":[{"value":{"description":{"value":"In app purchase: Американский английский"},"name":{"value":"Американский английский"},"localeCode":"ru"}},{"value":{"description":{"value":"In app purchase: Imparare Inglese americano"},"name":{"value":"Imparare Inglese americano"},"localeCode":"it"}},{"value":{"description":{"value":"In app purchase: Learn English (American)"},"name":{"value":"Learn English (American)"},"localeCode":"en-GB"}},{"value":{"description":{"value":"All categories & topics with lifetime access."},"name":{"value":"Learn English (American)"},"localeCode":"en-US"}},{"value":{"description":{"value":"In app purchase: Amerikanisches Englisch"},"name":{"value":"Amerikanisches Englisch"},"localeCode":"de-DE"}},{"value":{"description":{"value":"In app purchase: Aprender Inglês americano"},"name":{"value":"Aprender Inglês americano"},"localeCode":"pt-BR"}},{"value":{"description":{"value":"In app purchase: Aprenda Inglés estadounidens"},"name":{"value":"Aprenda Inglés estadounidense"},"localeCode":"es-ES"}},{"value":{"description":{"value":"In app purchase: 영어(미국) 공부"},"name":{"value":"영어(미국) 공부"},"localeCode":"ko"}},{"value":{"description":{"value":"In app purchase: Μάθετε Αγγλικά Αμερικής"},"name":{"value":"Μάθετε Αγγλικά Αμερικής"},"localeCode":"el"}},{"value":{"description":{"value":"In app purchase: Apprendre Anglais américain"},"name":{"value":"Apprendre Anglais américain"},"localeCode":"fr-CA"}},{"value":{"description":{"value":"In app purchase: Opi Amerikanenglanti"},"name":{"value":"Opi Amerikanenglanti"},"localeCode":"fi"}},{"value":{"description":{"value":"In app purchase: Learn English (American)"},"name":{"value":"Learn English (American)"},"localeCode":"en-AU"}},{"value":{"description":{"value":"In app purchase: はじめてのアメリカ英語"},"name":{"value":"はじめてのアメリカ英語"},"localeCode":"ja"}},{"value":{"description":{"value":"In app purchase: Lær Amerikansk engelsk"},"name":{"value":"Lær Amerikansk engelsk"},"localeCode":"no"}},{"value":{"description":{"value":"In app purchase: Aprenda Inglês americano"},"name":{"value":"Aprenda Inglês americano"},"localeCode":"pt-PT"}},{"value":{"description":{"value":"In app purchase: Amerikan İngilizcesi öğrenme"},"name":{"value":"Amerikan İngilizcesi öğrenmek"},"localeCode":"tr"}},{"value":{"description":{"value":"In app purchase: อังกฤษ - อเมริกัน"},"name":{"value":"อังกฤษ - อเมริกัน"},"localeCode":"th"}},{"value":{"description":{"value":"In app purchase: Learn English (American)"},"name":{"value":"Learn English (American)"},"localeCode":"en-CA"}},{"value":{"description":{"value":"In app purchase: Apprendre Anglais américain"},"name":{"value":"Apprendre Anglais américain"},"localeCode":"fr-FR"}},{"value":{"description":{"value":"In app purchase: Tiếng Anh (Mỹ)"},"name":{"value":"Tiếng Anh (Mỹ)"},"localeCode":"vi"}},{"value":{"description":{"value":"In app purchase: Belajar Inggeris AS"},"name":{"value":"Belajar Inggeris AS"},"localeCode":"ms"}},{"value":{"description":{"value":"In app purchase: Inglés estadounidense"},"name":{"value":"Inglés estadounidense"},"localeCode":"es-MX"}},{"value":{"description":{"value":"In app purchase: Lär dig Amerikansk engelska"},"name":{"value":"Lär dig Amerikansk engelska"},"localeCode":"sv"}},{"value":{"description":{"value":"In app purchase: Belajar Inggris (A.S.)"},"name":{"value":"Belajar Inggris (A.S.)"},"localeCode":"id"}},{"value":{"description":{"value":"In app purchase: Lær Amerikansk engelsk"},"name":{"value":"Lær Amerikansk engelsk"},"localeCode":"da"}}]},"id":"99487019","reviewScreenshot":{"value":{"assetToken":"Purple115/v4/31/d0/98/31d098ea-0495-8c47-0aaa-9d74ae6c33fb/pr_source.png","sortOrder":0,"type":"SortedN41ScreenShot","size":242851,"width":640,"height":1136,"checksum":"70c81d73d2005020654a0921fbfc5f5d","url":"https://is5-ssl.mzstatic.com/image/thumb/Purple115/v4/31/d0/98/31d098ea-0495-8c47-0aaa-9d74ae6c33fb/pr_source.png/640x1136ss-80.png","thumbNailUrl":"https://is5-ssl.mzstatic.com/image/thumb/Purple115/v4/31/d0/98/31d098ea-0495-8c47-0aaa-9d74ae6c33fb/pr_source.png/340x340bb-80.png","originalFileName":"ftl_8325cb9b79e79ac37d78ab233cea767b_4a7404053782ec2d5661d82d0021d934.png"}}}],"missingRequiredPrivacyPolicyData":false,"missingRequiredFamilyDetail":false}
DEBUG [09:13:04]: << PUT ra/apps/1085013031/iaps/1407845488: 500 {"data"=>nil, "messages"=>{"warn"=>nil, "info"=>nil, "error"=>["ITC.response.error.OPERATION_FAILED"]}, "statusCode"=>"ERROR"}
DEBUG [09:13:04]: Request was successful
I replaced the data with "*****" because there was too much of it to upload as a comment
Very strange. And you can confirm that the exact same operation is doable in the interface over at App Store Connect? (i.e. the in app purchase is editable?) I currently don't have any to test, so it's hard to check.
I can confirm that, yes. The save command fails even if nothing is changed though. In addition to that the code appears to offer the functionality to edit the localisations.
It appears this is not the first time someone has run into this issue: https://github.com/fastlane/fastlane/issues/13501 https://github.com/fastlane/fastlane/issues/10743 https://github.com/fastlane/fastlane/issues/10216
Here is a comparison of what apple sends vs what spaceship sends: https://www.diffchecker.com/NFAqamM3
There appears to be a lot of differences however I shouldn't imagine it would take too long to fix..?
More than happy to review your pull request. I believe the in-app purchase part was added quite some time ago and therefore might lack updates or maintenance over time.
I think I might give it a pass and attempt to develop an alternate solution in php, I'm not particularly proficient in ruby and don't have a lot of time to spend on this, hopefully what I have discovered here might be useful for someone else who wishes to give it a go (or maybe me at some point in the future). Thanks for your help!
Here is my version that I created in php:
<?php
$authCookie = getAuthCookie('johnDoe@icloud.com', 'password');
$appId = '123456789';
$iaps = getIaps($appId, $authCookie);
foreach($iaps as $iap){
print $iap['referenceName']."\n";
$iapId = $iap['adamId'];
$data = getIapData($appId, $iapId, $authCookie);
// Do what you want with the data here
updateIapData($data, $appId, $iapId, $authCookie);
}
function getIaps($appId, $authCookie){
$url = "https://appstoreconnect.apple.com/WebObjects/iTunesConnect.woa/ra/apps/$appId/iaps";
$response = json_decode(request($url, [], [$authCookie]), true);
$statusCode = $response['statusCode'];
if($statusCode === 'SUCCESS'){
return $response['data'];
} else {
return null;
}
}
function getIapData($appId, $iapId, $authCookie){
$url = "https://appstoreconnect.apple.com/WebObjects/iTunesConnect.woa/ra/apps/$appId/iaps/$iapId";
$response = json_decode(request($url, [], [$authCookie]), true);
$statusCode = $response['statusCode'];
return ($statusCode === 'SUCCESS')? $response['data'] : null;
}
function updateIapData($data, $appId, $iapId, $authCookie){
$url = "https://appstoreconnect.apple.com/WebObjects/iTunesConnect.woa/ra/apps/$appId/iaps/$iapId";
$response = json_decode(request($url, $data, [$authCookie], "PUT"), true);
$statusCode = $response['statusCode'];
return ($statusCode === SUCCESS);
}
function getAuthCookie($accountName, $password){ // Get authentication cookie from itunes connect
$authServiceKey = json_decode(request('https://olympus.itunes.apple.com/v1/app/config?hostname=itunesconnect.apple.com'), true)['authServiceKey'];
$url = "https://idmsa.apple.com/appleauth/auth/signin";
$payload = [
"accountName" => $accountName,
"password" => $password,
"rememberMe" => true
];
$headers = [
"X-Apple-Widget-Key: $authServiceKey"
];
$result = request($url, $payload, $headers, "POST", true);
preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $result, $matches);
$cookies = array();
foreach($matches[1] as $item) {
parse_str($item, $cookie);
$cookies = array_merge($cookies, $cookie);
}
if(!isset($cookies['myacinfo'])){
die('Authentication failed');
}
$authCookie = "Cookie: myacinfo=".$cookies['myacinfo'];
return $authCookie;
}
function request($url, $payload = array(), $headers = array(), $requestType = "GET", $returnHeaders = false){ // Generic curl request function
$headers[] = "Content-Type: application/json;charset=UTF-8";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload, JSON_UNESCAPED_SLASHES));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $requestType);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_ENCODING, 'UTF-8');
if($returnHeaders){
curl_setopt($ch, CURLOPT_HEADER, 1);
}
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
return $result;
}
?>
There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates.
Please make sure to update to the latest fastlane
version and check if that solves the issue. Let us know if that works for you by adding a comment :+1:
This issue will be auto-closed because there hasn't been any activity for a few months. Feel free to open a new one if you still experience this problem :+1:
app.in_app_purchases.all returns
From what I can tell .versions should return all the titles and descriptions for the IAP in different localisations (and let you change them) however it doesn't? Am I misunderstanding how this works or is it broken?
Thanks, Henry