pindo 4.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. checksums.yaml +7 -0
  2. data/bin/pindo +35 -0
  3. data/lib/pindo/base/aeshelper.rb +31 -0
  4. data/lib/pindo/base/deviceinfo.rb +90 -0
  5. data/lib/pindo/base/executable.rb +224 -0
  6. data/lib/pindo/base/githelper.rb +489 -0
  7. data/lib/pindo/base/hashhelper.rb +134 -0
  8. data/lib/pindo/base/plaininformative.rb +15 -0
  9. data/lib/pindo/base/plistbuddyexecutable.rb +121 -0
  10. data/lib/pindo/base/standarderror.rb +14 -0
  11. data/lib/pindo/client/applovinclient.rb +156 -0
  12. data/lib/pindo/client/aws3sclient.rb +183 -0
  13. data/lib/pindo/client/bossclient.rb +229 -0
  14. data/lib/pindo/client/bossconfigclient.rb +175 -0
  15. data/lib/pindo/client/giteeclient.rb +65 -0
  16. data/lib/pindo/client/httpclient.rb +40 -0
  17. data/lib/pindo/client/pgyerclient.rb +439 -0
  18. data/lib/pindo/client/tgateclient.rb +103 -0
  19. data/lib/pindo/command.rb +101 -0
  20. data/lib/pindo/config/pindoconfig.rb +439 -0
  21. data/lib/pindo/config/pindouserlocalconfig.rb +81 -0
  22. data/lib/pindo/deploy/Fastfile +233 -0
  23. data/lib/pindo/deploy/build.rb +167 -0
  24. data/lib/pindo/deploy/bundleid.rb +245 -0
  25. data/lib/pindo/deploy/cert.rb +508 -0
  26. data/lib/pindo/deploy/check.rb +79 -0
  27. data/lib/pindo/deploy/configproj.rb +89 -0
  28. data/lib/pindo/deploy/confusecode.rb +248 -0
  29. data/lib/pindo/deploy/confuseproj.rb +112 -0
  30. data/lib/pindo/deploy/fabric.rb +58 -0
  31. data/lib/pindo/deploy/getitcinfo.rb +248 -0
  32. data/lib/pindo/deploy/iap.rb +796 -0
  33. data/lib/pindo/deploy/initconfig.rb +128 -0
  34. data/lib/pindo/deploy/itcapp.rb +147 -0
  35. data/lib/pindo/deploy/itcinfo.rb +369 -0
  36. data/lib/pindo/deploy/pem.rb +55 -0
  37. data/lib/pindo/deploy/pullconfig.rb +46 -0
  38. data/lib/pindo/deploy/pushconfig.rb +83 -0
  39. data/lib/pindo/deploy/quswark.rb +146 -0
  40. data/lib/pindo/deploy/quswauth.rb +67 -0
  41. data/lib/pindo/deploy/reportbug.rb +135 -0
  42. data/lib/pindo/deploy/resign.rb +338 -0
  43. data/lib/pindo/deploy/tag.rb +108 -0
  44. data/lib/pindo/deploy/updateconfig.rb +129 -0
  45. data/lib/pindo/deploy/uploadipa.rb +63 -0
  46. data/lib/pindo/deploy.rb +44 -0
  47. data/lib/pindo/dev/autobuild.rb +204 -0
  48. data/lib/pindo/dev/autoresign.rb +186 -0
  49. data/lib/pindo/dev/confusecode.rb +127 -0
  50. data/lib/pindo/dev/confuseproj.rb +111 -0
  51. data/lib/pindo/dev/createbuild.rb +159 -0
  52. data/lib/pindo/dev/debug.rb +141 -0
  53. data/lib/pindo/dev/pub.rb +171 -0
  54. data/lib/pindo/dev/renewcert.rb +142 -0
  55. data/lib/pindo/dev.rb +23 -0
  56. data/lib/pindo/env/dreamstudio.rb +53 -0
  57. data/lib/pindo/env/flutter.rb +59 -0
  58. data/lib/pindo/env/flutter.sh +116 -0
  59. data/lib/pindo/env/quarkenv.rb +58 -0
  60. data/lib/pindo/env/swarkenv.rb +62 -0
  61. data/lib/pindo/env/workhard.rb +56 -0
  62. data/lib/pindo/env.rb +17 -0
  63. data/lib/pindo/ipa/autoresign.rb +188 -0
  64. data/lib/pindo/ipa/import.rb +261 -0
  65. data/lib/pindo/ipa/output.rb +396 -0
  66. data/lib/pindo/ipa.rb +22 -0
  67. data/lib/pindo/lib/forcepush.rb +159 -0
  68. data/lib/pindo/lib/lint.rb +115 -0
  69. data/lib/pindo/lib/push.rb +143 -0
  70. data/lib/pindo/lib/update.rb +75 -0
  71. data/lib/pindo/lib.rb +18 -0
  72. data/lib/pindo/module/appselect.rb +200 -0
  73. data/lib/pindo/module/appstore_in_app_purchase.rb +1803 -0
  74. data/lib/pindo/module/appstore_metadata_connect_api_helper.rb +12 -0
  75. data/lib/pindo/module/appstore_metadata_fastlane_helper.rb +922 -0
  76. data/lib/pindo/module/buildconfighelper.rb +13 -0
  77. data/lib/pindo/module/buildhelper.rb +76 -0
  78. data/lib/pindo/module/commonconfuseproj.rb +271 -0
  79. data/lib/pindo/module/config_project.sh +143 -0
  80. data/lib/pindo/module/configprojhelper.rb +631 -0
  81. data/lib/pindo/module/iap_tier.json +813 -0
  82. data/lib/pindo/module/icon_contents.json +116 -0
  83. data/lib/pindo/module/imessage_icon.json +91 -0
  84. data/lib/pindo/module/imgset_contents.json +21 -0
  85. data/lib/pindo/module/launchimg_contents.json +21 -0
  86. data/lib/pindo/module/pemcreate.rb +63 -0
  87. data/lib/pindo/module/pgyerhelper.rb +339 -0
  88. data/lib/pindo/module/xcodebuildpre.rb +258 -0
  89. data/lib/pindo/module/xcodehelper.rb +521 -0
  90. data/lib/pindo/options/appconfigoptions.rb +23 -0
  91. data/lib/pindo/options/deployoptions.rb +363 -0
  92. data/lib/pindo/pgyer/apptest.rb +104 -0
  93. data/lib/pindo/pgyer/comment.rb +95 -0
  94. data/lib/pindo/pgyer/download.rb +105 -0
  95. data/lib/pindo/pgyer/login.rb +61 -0
  96. data/lib/pindo/pgyer/upload.rb +234 -0
  97. data/lib/pindo/pgyer.rb +17 -0
  98. data/lib/pindo/repo/clone.rb +78 -0
  99. data/lib/pindo/repo/create.rb +55 -0
  100. data/lib/pindo/repo/login.rb +64 -0
  101. data/lib/pindo/repo/search.rb +60 -0
  102. data/lib/pindo/repo.rb +16 -0
  103. data/lib/pindo/setup.rb +60 -0
  104. data/lib/pindo/upgrade.rb +56 -0
  105. data/lib/pindo/utils/applovin.rb +213 -0
  106. data/lib/pindo/utils/boss.rb +209 -0
  107. data/lib/pindo/utils/clearcert.rb +60 -0
  108. data/lib/pindo/utils/device.rb +279 -0
  109. data/lib/pindo/utils/icon.rb +91 -0
  110. data/lib/pindo/utils/icon.sh +133 -0
  111. data/lib/pindo/utils/podindex.rb +56 -0
  112. data/lib/pindo/utils/podindex.sh +30 -0
  113. data/lib/pindo/utils/renewproj.rb +146 -0
  114. data/lib/pindo/utils/tgate.rb +159 -0
  115. data/lib/pindo/utils/xcassets.rb +46 -0
  116. data/lib/pindo/utils/xcassets.sh +88 -0
  117. data/lib/pindo/utils.rb +29 -0
  118. data/lib/pindo/version.rb +110 -0
  119. data/lib/pindo.rb +34 -0
  120. metadata +364 -0
@@ -0,0 +1,1803 @@
1
+
2
+ require 'fileutils'
3
+ require 'faraday'
4
+ require 'spaceship'
5
+
6
+ module Pindo
7
+
8
+ module AppStoreInAppPurchase
9
+
10
+ def get_price_tier_dict
11
+
12
+ iap_tier_file = File.join(File.expand_path('./', __dir__), 'iap_tier.json')
13
+ iap_tier_json = JSON.parse(File.read(iap_tier_file))
14
+
15
+ return iap_tier_json
16
+
17
+ end
18
+
19
+ def get_consumable_iap_items(appstore_client:nil, app_id:nil, in_app_purchase_type:nil)
20
+
21
+ in_app_purchases_response = appstore_client.list_all_in_app_purchases_for_app(id: app_id, include:"appStoreReviewScreenshot,inAppPurchaseLocalizations,content", filter:{
22
+ inAppPurchaseType:in_app_purchase_type
23
+ }, limit:50)
24
+ # puts JSON.pretty_generate(in_app_purchases_response)
25
+
26
+ in_app_purchase_items = []
27
+
28
+ if !in_app_purchases_response.nil? && !in_app_purchases_response[:data].nil?
29
+ in_app_purchases_response[:data].each do |purchase_item|
30
+ iap_item = {}
31
+
32
+ puts "product_id: #{purchase_item[:attributes][:product_id]}"
33
+
34
+ iap_item["reference_name"] = purchase_item[:attributes][:name]
35
+ iap_item["product_id"] = purchase_item[:attributes][:product_id]
36
+ # iap_item["state"] = purchase_item[:attributes][:state]
37
+ iap_item["review_note"] = purchase_item[:attributes][:review_note]
38
+ iap_item["in_app_purchase_type"] = purchase_item[:attributes][:in_app_purchase_type]
39
+ if !purchase_item[:relationships].nil? && !purchase_item[:relationships][:in_app_purchase_localizations].nil? && !purchase_item[:relationships][:in_app_purchase_localizations][:data].nil? && purchase_item[:relationships][:in_app_purchase_localizations][:data].size > 0
40
+ temp_item = purchase_item[:relationships][:in_app_purchase_localizations][:data].first
41
+ iap_item["localizations_id"] = temp_item[:id]
42
+ end
43
+ if !purchase_item[:relationships][:app_store_review_screenshot].nil? && !purchase_item[:relationships][:app_store_review_screenshot][:data].nil? && !purchase_item[:relationships][:app_store_review_screenshot][:data][:id].nil?
44
+ iap_item["review_screenshot_id"] = purchase_item[:relationships][:app_store_review_screenshot][:data][:id]
45
+ end
46
+
47
+ if !iap_item["localizations_id"].nil? && !in_app_purchases_response.nil? && !in_app_purchases_response[:included].nil?
48
+ localizations_item = in_app_purchases_response[:included].find { |item| item[:type].eql?("inAppPurchaseLocalizations") && item[:id].eql?(iap_item["localizations_id"])}
49
+
50
+ iap_item["display_name"] = localizations_item[:attributes][:name]
51
+ iap_item["description"] = localizations_item[:attributes][:description]
52
+ end
53
+
54
+ iap_item["review_screenshot"] = nil
55
+
56
+ iap_item["price"] = nil
57
+ # if !iap_item["review_screenshot_id"].nil? && !in_app_purchases_response.nil? && !in_app_purchases_response[:included].nil?
58
+ # iap_item = in_app_purchases_response[:included].find { |item| item[:type].eql?("inAppPurchaseAppStoreReviewScreenshots") && item[:id].eql?(iap_item["review_screenshot_id"])}
59
+ # end
60
+
61
+ iap_item["price"] = get_purchase_item_price(appstore_client:appstore_client, in_app_purchase_id:purchase_item[:id])
62
+
63
+ iap_item.delete("localizations_id")
64
+ iap_item.delete("review_screenshot_id")
65
+ in_app_purchase_items << iap_item
66
+ end
67
+ end
68
+
69
+ in_app_purchase_items.sort! { | itema, itemb | itema["product_id"] <=> itemb["product_id"]}
70
+
71
+ return in_app_purchase_items
72
+ end
73
+
74
+ def get_app_share_secrets(app_id:nil, need_create:true)
75
+
76
+ puts "获取App Shared Secret ..."
77
+ scecrets_id = nil
78
+ begin
79
+ client = Spaceship::ConnectAPI
80
+ app_sharedsecrets_item = nil
81
+ response = client.tunes_request_client.get("apps/#{app_id}/appSharedSecrets")
82
+ # puts JSON.pretty_generate(response.body)
83
+ result_data = response.body
84
+
85
+ if !result_data.nil? && !result_data["data"].nil? && result_data["data"].size > 0
86
+ app_sharedsecrets_item = result_data["data"].first
87
+ # puts JSON.pretty_generate(app_sharedsecrets_item)
88
+ else
89
+ puts "从app store 未获取到App Shared Secret."
90
+ end
91
+
92
+ if app_sharedsecrets_item.nil? && need_create
93
+ answer = agree("请确认是否要创建App Shared Secret? (Y/n):")
94
+ # answer = false
95
+ if answer
96
+ body = {
97
+ data: {
98
+ type: "appSharedSecrets",
99
+ relationships: {
100
+ app:{
101
+ data:{
102
+ type:"apps",
103
+ id:app_id
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+ response = client.tunes_request_client.post("appSharedSecrets", body)
110
+ post_result_data = response.body
111
+ if !post_result_data.nil? && !post_result_data["data"].nil? && !post_result_data["data"]["attributes"].nil?
112
+ app_sharedsecrets_item = post_result_data["data"]
113
+ # puts JSON.pretty_generate(app_sharedsecrets_item)
114
+ end
115
+ end
116
+ end
117
+
118
+ if !app_sharedsecrets_item.nil?
119
+ # puts JSON.pretty_generate(app_sharedsecrets_item)
120
+ scecrets_id = app_sharedsecrets_item["attributes"]["secret"]
121
+ end
122
+
123
+ rescue => err
124
+ puts err
125
+ puts "获取App Shared Secret失败!"
126
+ end
127
+ return scecrets_id
128
+ end
129
+
130
+ def create_consumable_iap_items(appstore_client:nil, app_id:nil, in_app_purchase_items:nil)
131
+
132
+ in_app_purchase_items = in_app_purchase_items || []
133
+ in_app_purchase_items.sort! { | itema, itemb | itema["product_id"] <=> itemb["product_id"]}
134
+
135
+ in_app_purchases_response = appstore_client.list_all_in_app_purchases_for_app(id: app_id, limit:50)
136
+ # puts JSON.pretty_generate(in_app_purchases_response)
137
+
138
+ if !in_app_purchases_response.nil? && !in_app_purchases_response[:data].nil?
139
+ in_app_purchase_items.each do |purchase_item|
140
+
141
+ in_app_purchases_response[:data].each do |iap_item|
142
+
143
+ if iap_item[:attributes][:product_id].to_s.eql?(purchase_item["product_id"])
144
+ purchase_item["purchase_id"] = iap_item[:id]
145
+ purchase_item["state"] = iap_item[:attributes][:state]
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+
152
+ in_app_purchase_items.each do |purchase_item|
153
+
154
+ puts "购买项:" + purchase_item["product_id"]
155
+ if purchase_item["purchase_id"].nil?
156
+ create_purchase_item(appstore_client:appstore_client, app_id:app_id, purchase_item:purchase_item)
157
+ end
158
+
159
+ if !purchase_item["purchase_id"].nil?
160
+ in_app_purchase_id = purchase_item["purchase_id"]
161
+
162
+ if !purchase_item["state"].nil? && purchase_item["state"].to_s.eql?("APPROVED")
163
+ puts " 购买项已经上线, 只能修改价格"
164
+ create_purchase_item_price(appstore_client:appstore_client, in_app_purchase_id:in_app_purchase_id, purchase_item:purchase_item)
165
+ else
166
+ sleep(1)
167
+ update_purchase_item_name(appstore_client:appstore_client, in_app_purchase_id:in_app_purchase_id, purchase_item:purchase_item)
168
+ create_purchase_item_price(appstore_client:appstore_client, in_app_purchase_id:in_app_purchase_id, purchase_item:purchase_item)
169
+ upload_purchase_item_screenshots(appstore_client:appstore_client, in_app_purchase_id:in_app_purchase_id, purchase_item:purchase_item)
170
+ create_purchase_item_localization(appstore_client:appstore_client, in_app_purchase_id:in_app_purchase_id, purchase_item:purchase_item)
171
+ update_purchase_item_name(appstore_client:appstore_client, in_app_purchase_id:in_app_purchase_id, purchase_item:purchase_item)
172
+
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+ def create_purchase_item(appstore_client:nil, app_id:nil, purchase_item:nil)
179
+ #创建购买项
180
+ puts " 创建iap: " + purchase_item["product_id"]
181
+
182
+ appstore_app_id = app_id.to_s
183
+ purchase_id = nil
184
+
185
+ begin
186
+ response = appstore_client.create_in_app_purchase(
187
+ name:purchase_item["reference_name"],
188
+ product_id:purchase_item["product_id"],
189
+ in_app_purchase_type:purchase_item["in_app_purchase_type"],
190
+ available_in_all_territories:true,
191
+ review_note:purchase_item["review_note"],
192
+ relationships: {
193
+ app:{
194
+ data:{
195
+ id: appstore_app_id,
196
+ type: 'apps'
197
+ }
198
+ }
199
+ }
200
+ )
201
+
202
+ if !response.nil? && !response[:data].nil? && !response[:data][:id].nil?
203
+
204
+ purchase_id = !response[:data][:id]
205
+ purchase_item["purchase_id"] = response[:data][:id]
206
+ return purchase_id
207
+ else !response.nil? && !response[:errors].nil?
208
+ # puts JSON.pretty_generate(response)
209
+ response[:errors].each do |error_item|
210
+ if error_item[:status].to_s.eql?("409") && error_item[:code].to_s.eql?("ENTITY_ERROR.ATTRIBUTE.INVALID.DUPLICATE") && error_item[:source][:pointer].to_s.eql?("/data/attributes/name")
211
+ err_msg = " !!!!!" + purchase_item["product_id"] + " 购买项创建失败!!!, Reference Name重复!!!"
212
+ raise Informative, err_msg
213
+ end
214
+ end
215
+ err_msg = purchase_item["product_id"] + " 购买项创建失败!!!"
216
+ # puts JSON.pretty_generate(response)
217
+ end
218
+ rescue => err
219
+ puts err
220
+ err_msg = purchase_item["product_id"] + " 购买项创建失败!!!"
221
+ raise Informative, err_msg
222
+ end
223
+ end
224
+
225
+ def update_purchase_item_name(appstore_client:nil, in_app_purchase_id:nil, purchase_item:nil)
226
+
227
+ puts " 更新Reference Name"
228
+ begin
229
+ response = appstore_client.update_in_app_purchase(
230
+ name:purchase_item["reference_name"],
231
+ available_in_all_territories:true,
232
+ review_note:purchase_item["review_note"],
233
+ id:in_app_purchase_id
234
+ )
235
+ rescue => err
236
+ puts err
237
+ puts " 更新Reference Name失败!!!"
238
+ end
239
+ end
240
+
241
+
242
+ def create_purchase_item_localization(appstore_client:nil, in_app_purchase_id:nil, purchase_item:nil)
243
+
244
+ puts " 更新Display Name"
245
+ begin
246
+
247
+ response = appstore_client.list_in_app_purchase_all_localizations(
248
+ id:in_app_purchase_id,
249
+ limit:200
250
+ )
251
+ # puts JSON.pretty_generate(response)
252
+ if !response[:data].nil?
253
+
254
+ response[:data].each do |localization_item|
255
+ locale = localization_item[:attributes][:locale]
256
+ locale_id = localization_item[:id]
257
+ display_name = localization_item[:name]
258
+ description = localization_item[:description]
259
+ purchase_item["localization"][locale] = purchase_item["localization"][locale] || {}
260
+ purchase_item["localization"][locale]["locale"] = locale
261
+ purchase_item["localization"][locale]["locale_id"] = locale_id
262
+ purchase_item["localization"][locale]["display_name"] = purchase_item["localization"][locale]["display_name"] || display_name
263
+ purchase_item["localization"][locale]["description"] = purchase_item["localization"][locale]["description"] || description
264
+ end
265
+
266
+ end
267
+
268
+
269
+
270
+ purchase_item["localization"].each do |locale, locale_item|
271
+
272
+ if !locale_item.nil? && !locale_item["locale_id"].nil?
273
+
274
+ response = appstore_client.update_in_app_purchase_localization(
275
+ id:locale_item["locale_id"],
276
+ name:locale_item["display_name"],
277
+ description:locale_item["description"]
278
+ )
279
+ # puts JSON.pretty_generate(response)
280
+
281
+ else
282
+
283
+ response = appstore_client.create_in_app_purchase_localization(
284
+ name:locale_item["display_name"],
285
+ description:locale_item["description"],
286
+ locale:locale,
287
+ relationships: {
288
+ inAppPurchaseV2:{
289
+ data:{
290
+ id: in_app_purchase_id,
291
+ type: 'inAppPurchases'
292
+ }
293
+ }
294
+ }
295
+ )
296
+
297
+ # puts JSON.pretty_generate(response)
298
+
299
+ end
300
+
301
+ end
302
+
303
+
304
+ rescue => err
305
+ puts err
306
+ puts " 更新Display Name失败!!!"
307
+ end
308
+ end
309
+
310
+ def get_purchase_item_price(appstore_client:nil, in_app_purchase_id:nil)
311
+
312
+ price = 0
313
+ respose_price = appstore_client.read_in_app_purchase_price_info(
314
+ id:in_app_purchase_id,
315
+ include:'inAppPurchasePricePoint',
316
+ filter:{
317
+ territory:'USA'
318
+ }
319
+
320
+ )
321
+ # puts JSON.pretty_generate(respose_price)
322
+
323
+ price_id = nil
324
+ if !respose_price[:data].nil? && respose_price[:data].size > 0
325
+ price_item = respose_price[:data].first
326
+ price_id = price_item[:relationships][:in_app_purchase_price_point][:data][:id]
327
+ end
328
+ if !price_id.nil?
329
+ item = respose_price[:included].find { |e| e[:id].eql?(price_id) }
330
+ if !item.nil?
331
+ price = item[:attributes][:customer_price]
332
+ end
333
+ end
334
+
335
+ return price
336
+ end
337
+
338
+ def create_purchase_item_price(appstore_client:nil, in_app_purchase_id:nil, purchase_item:nil)
339
+ puts " 更新价格"
340
+ begin
341
+ respose_price = appstore_client.list_in_app_purchase_all_price_points(
342
+ id:in_app_purchase_id,
343
+ include: 'territory',
344
+ filter: {
345
+ territory: 'USA',
346
+ price_tier: purchase_item["price_tier"]
347
+ },
348
+ limit:100
349
+ )
350
+ # puts JSON.pretty_generate(respose_price)
351
+
352
+
353
+ price_id = nil
354
+
355
+
356
+ respose_price[:data].each do |price_item|
357
+ if price_item[:attributes][:customer_price].to_s.eql?(purchase_item["price"].to_s)
358
+ price_id = price_item[:id]
359
+ purchase_item["price_id"] = price_item[:id]
360
+ puts " 更新价格 :" + purchase_item["price"] +"$"
361
+ end
362
+ end
363
+ if !price_id.nil?
364
+ in_app_purchase = appstore_client.create_in_app_purchase_price_schedule(
365
+ relationships: {
366
+ manual_prices: {
367
+ data: [
368
+ {
369
+ type: 'inAppPurchasePrices',
370
+ id: '${price1}'
371
+ }
372
+ ]
373
+ },
374
+ in_app_purchase: {
375
+ data: {
376
+ type: 'inAppPurchases',
377
+ id: in_app_purchase_id
378
+ }
379
+ }
380
+ },
381
+ included: [
382
+ {
383
+ type: 'inAppPurchasePrices',
384
+ id: '${price1}',
385
+ attributes: {
386
+ startDate: nil
387
+ },
388
+ relationships: {
389
+ inAppPurchaseV2: {
390
+ data: {
391
+ type: 'inAppPurchases',
392
+ id: in_app_purchase_id
393
+ }
394
+ },
395
+ inAppPurchasePricePoint: {
396
+ data: {
397
+ type: 'inAppPurchasePricePoints',
398
+ id: price_id
399
+ }
400
+ }
401
+ }
402
+ }
403
+ ]
404
+ )
405
+ end
406
+
407
+ rescue => err
408
+ puts "创建价格失败: " + purchase_item["product_id"]
409
+ puts err
410
+ end
411
+ end
412
+
413
+ def upload_purchase_item_screenshots(appstore_client:nil, in_app_purchase_id:nil, purchase_item:nil)
414
+ puts " 更新截屏"
415
+ begin
416
+ # upload screenshots
417
+ response_iap_screenshot = appstore_client.read_review_screenshot_for_in_app_purchase(id:in_app_purchase_id)
418
+
419
+ path = purchase_item["review_screenshot_fullpath"]
420
+ filename = File.basename(path)
421
+ filesize = File.size(path)
422
+ bytes = File.binread(path)
423
+
424
+ checksum = Digest::MD5.hexdigest(bytes)
425
+
426
+
427
+ need_upload_screenshot = true
428
+
429
+ if !response_iap_screenshot[:data].nil? && !response_iap_screenshot[:data][:attributes].nil? && !response_iap_screenshot[:data][:attributes][:asset_delivery_state].nil? && !response_iap_screenshot[:data][:attributes][:asset_delivery_state][:state].nil?
430
+
431
+ if response_iap_screenshot[:data][:attributes][:asset_delivery_state][:state].to_s.eql?("COMPLETE")
432
+
433
+ if !response_iap_screenshot[:data].nil? && !response_iap_screenshot[:data][:attributes].nil? && !response_iap_screenshot[:data][:attributes][:source_file_checksum].nil?
434
+
435
+ if checksum.to_s.eql?(response_iap_screenshot[:data][:attributes][:source_file_checksum].to_s)
436
+
437
+ puts " 有截屏,截屏未修改,无需重新上传"
438
+ need_upload_screenshot = false
439
+
440
+ end
441
+ end
442
+ end
443
+ end
444
+
445
+
446
+ # puts JSON.pretty_generate(response_iap_screenshot)
447
+ if need_upload_screenshot && !response_iap_screenshot[:data].nil? && !response_iap_screenshot[:data][:attributes].nil? && !response_iap_screenshot[:data][:attributes][:file_name].nil?
448
+ puts " 有截屏,先删除再更新"
449
+ # puts JSON.pretty_generate(response_iap_screenshot)
450
+ appstore_client.delete_in_app_purchase_review_screenshot(id:response_iap_screenshot[:data][:id])
451
+ end
452
+
453
+
454
+ if need_upload_screenshot
455
+
456
+ puts " 正在上传...."
457
+ response_iap_screenshot = appstore_client.create_in_app_purchase_review_screenshot(
458
+ file_name:filename,
459
+ file_size: filesize,
460
+ relationships: {
461
+ inAppPurchaseV2:{
462
+ data:{
463
+ id: in_app_purchase_id,
464
+ type: 'inAppPurchases'
465
+ }
466
+ }
467
+ }
468
+ )
469
+
470
+ # puts JSON.pretty_generate(response_iap_screenshot)
471
+ upload_id = response_iap_screenshot[:data][:id]
472
+ upload_operations = response_iap_screenshot[:data][:attributes][:upload_operations]
473
+ upload_operations.each_with_index do |upload_operation, index|
474
+ headers = {}
475
+ upload_operation[:request_headers].each do |item|
476
+ headers[item[:name]] = item[:value]
477
+ end
478
+ offset = upload_operation[:offset]
479
+ length = upload_operation[:length]
480
+ conn = Faraday.new
481
+ res = conn.put(upload_operation[:url], bytes[offset, length], headers)
482
+ end
483
+
484
+
485
+
486
+ in_app_purchase = appstore_client.update_in_app_purchase_app_store_review_screenshot(
487
+ id:upload_id,
488
+ uploaded: true,
489
+ source_file_checksum:checksum
490
+ )
491
+ puts " 上传完成!!"
492
+
493
+
494
+ else
495
+ puts " 存在图片,无需上传...."
496
+ end
497
+
498
+
499
+
500
+ rescue => err
501
+ puts err
502
+ puts " 更新截屏失败!!!"
503
+ end
504
+ end
505
+
506
+ def get_subscriptions_groups(appstore_client:nil, app_id:nil)
507
+
508
+ subscription_group_items = []
509
+
510
+ #查询是否存在group
511
+ subscription_groups_response = appstore_client.list_all_subscription_groups_for_app(id: app_id, include:'subscriptionGroupLocalizations', limit:50)
512
+ # puts JSON.pretty_generate(subscription_groups_response)
513
+ #如果存在group,则更新,不存在则创建
514
+ if !subscription_groups_response.nil? && !subscription_groups_response[:data].nil?
515
+
516
+
517
+ subscription_groups_response[:data].each do |old_subscription_group_item|
518
+ subscription_group_item = { }
519
+
520
+ subscription_group_item["group_reference_name"] = old_subscription_group_item[:attributes][:reference_name]
521
+ if !old_subscription_group_item[:relationships][:subscription_group_localizations][:data].nil? && old_subscription_group_item[:relationships][:subscription_group_localizations][:data].size > 0
522
+ group_localization_item = old_subscription_group_item[:relationships][:subscription_group_localizations][:data].first
523
+ subscription_group_item["group_localizations_id"] = group_localization_item[:id]
524
+ end
525
+
526
+ if !subscription_group_item["group_localizations_id"].nil? && !subscription_groups_response[:included].nil?
527
+ group_localization_item = subscription_groups_response[:included].find { |item| item[:type].eql?("subscriptionGroupLocalizations") && item[:id].eql?(subscription_group_item["group_localizations_id"])}
528
+ if !group_localization_item.nil?
529
+ subscription_group_item["group_display_name"] = group_localization_item[:attributes][:name]
530
+ subscription_group_item["custom_app_name"] = group_localization_item[:attributes][:custom_app_name]
531
+ end
532
+ end
533
+
534
+ subscription_group_item["subscription_items"] = get_subscription_items(appstore_client:appstore_client, subscription_group_id:old_subscription_group_item[:id])
535
+ subscription_group_item.delete("group_localizations_id")
536
+ subscription_group_items << subscription_group_item
537
+ end
538
+ end
539
+
540
+
541
+ return subscription_group_items
542
+
543
+ end
544
+
545
+
546
+
547
+ def create_subscriptions_groups(appstore_client:nil, app_id:nil, subscription_group_items:nil)
548
+
549
+ subscription_group_items = subscription_group_items || []
550
+
551
+ #查询是否存在group
552
+ subscription_groups_response = appstore_client.list_all_subscription_groups_for_app(id: app_id, limit:50)
553
+ # puts JSON.pretty_generate(subscription_groups_response)
554
+ #如果存在group,则更新,不存在则创建
555
+ if !subscription_groups_response.nil? && !subscription_groups_response[:data].nil?
556
+
557
+ puts
558
+ puts "**已存在订阅组的数目** : #{subscription_groups_response[:data].size}"
559
+ puts
560
+
561
+ subscription_groups_response[:data].each do |old_subscription_group_item|
562
+ subscription_group_items.each do |new_subscription_group_item|
563
+ if !old_subscription_group_item[:attributes].nil? && old_subscription_group_item[:attributes][:reference_name].to_s.eql?(new_subscription_group_item["group_reference_name"])
564
+ new_subscription_group_item["group_id"] = old_subscription_group_item[:id]
565
+ end
566
+ end
567
+ end
568
+ end
569
+
570
+ subscription_group_items.each do |new_subscription_group_item|
571
+
572
+ if new_subscription_group_item["group_id"].nil?
573
+ if subscription_groups_response[:data].size > 0
574
+ puts
575
+ answer = agree("请确认要创建新的Subscription Group(Y/n):")
576
+ unless answer
577
+ raise Informative, "修改iap.json文件 !!! group_reference_name不一致会创建新的Subscription Group !!!"
578
+ end
579
+ end
580
+ create_subscription_group_item(appstore_client:appstore_client, app_id:app_id, subscription_group_item:new_subscription_group_item)
581
+ end
582
+
583
+ if !new_subscription_group_item["group_id"].nil?
584
+
585
+ subscription_group_id = new_subscription_group_item["group_id"]
586
+
587
+ create_subscription_group_localization(appstore_client:appstore_client, subscription_group_id:new_subscription_group_item["group_id"], subscription_group_item:new_subscription_group_item)
588
+ sleep(1)
589
+ subscription_items = new_subscription_group_item["subscription_items"]
590
+ create_subscription_items(appstore_client:appstore_client, subscription_group_id:subscription_group_id, subscription_items:subscription_items)
591
+
592
+ end
593
+ end
594
+
595
+
596
+ end
597
+
598
+ def create_subscription_group_item(appstore_client:nil, app_id:nil, subscription_group_item:nil)
599
+
600
+ begin
601
+ group_response = appstore_client.create_subscription_group(
602
+ reference_name:subscription_group_item["group_reference_name"],
603
+ relationships: {
604
+ app:{
605
+ data:{
606
+ id: app_id,
607
+ type: 'apps'
608
+ }
609
+ }
610
+ })
611
+ # puts JSON.pretty_generate(group_response)
612
+ rescue => err
613
+ puts err
614
+ end
615
+
616
+ end
617
+
618
+ def create_subscription_group_localization(appstore_client:nil, subscription_group_id:nil, subscription_group_item:nil)
619
+ begin
620
+
621
+
622
+ response = appstore_client.list_all_subscription_group_localizations(
623
+ id:subscription_group_id,
624
+ limit:200
625
+ )
626
+ # puts JSON.pretty_generate(response)
627
+
628
+ if !response[:data].nil?
629
+
630
+ response[:data].each do |localization_item|
631
+ locale = localization_item[:attributes][:locale]
632
+ locale_id = localization_item[:id]
633
+ group_display_name = localization_item[:name]
634
+ custom_app_name = localization_item[:custom_app_name]
635
+ subscription_group_item["localization"][locale] = subscription_group_item["localization"][locale] || {}
636
+ subscription_group_item["localization"][locale]["locale"] = locale
637
+ subscription_group_item["localization"][locale]["locale_id"] = locale_id
638
+ subscription_group_item["localization"][locale]["group_display_name"] = subscription_group_item["localization"][locale]["group_display_name"] || group_display_name
639
+ subscription_group_item["localization"][locale]["custom_app_name"] = subscription_group_item["localization"][locale]["custom_app_name"] || custom_app_name
640
+ end
641
+
642
+ end
643
+
644
+
645
+
646
+ subscription_group_item["localization"].each do |locale, locale_item|
647
+
648
+
649
+ if !locale_item.nil? && !locale_item["locale_id"].nil?
650
+
651
+ response = appstore_client.update_subscription_group_localization(
652
+ id:locale_item["locale_id"],
653
+ name:locale_item["group_display_name"],
654
+ custom_app_name:locale_item["custom_app_name"]
655
+ )
656
+ # puts JSON.pretty_generate(response)
657
+
658
+ else
659
+
660
+ response = appstore_client.create_subscription_group_localization(
661
+ name:locale_item["group_display_name"],
662
+ locale:locale,
663
+ custom_app_name:locale_item["custom_app_name"],
664
+ relationships: {
665
+ subscriptionGroup:{
666
+ data:{
667
+ id: subscription_group_id,
668
+ type: 'subscriptionGroups'
669
+ }
670
+ }
671
+ }
672
+ )
673
+ # puts JSON.pretty_generate(response)
674
+
675
+ end
676
+
677
+
678
+
679
+ end
680
+
681
+
682
+
683
+ rescue => err
684
+ puts err
685
+ puts " 更新Group Display Name 失败!!"
686
+ end
687
+
688
+ end
689
+
690
+
691
+ def get_subscription_items(appstore_client:nil, subscription_group_id:nil)
692
+ subscription_items = []
693
+
694
+ tier_json = get_price_tier_dict
695
+ items_dict = tier_json["subscription_duration"]
696
+ subscription_period_dict = items_dict.invert
697
+
698
+ subscription_response = appstore_client.list_all_subscription_for_subscription_group(id: subscription_group_id, include:'subscriptionLocalizations,introductoryOffers', limit:50)
699
+ # puts JSON.pretty_generate(subscription_response)
700
+ if !subscription_response.nil? && !subscription_response[:data].nil?
701
+ subscription_response[:data].each do |old_subscription_item|
702
+
703
+ puts "product_id: #{old_subscription_item[:attributes][:product_id]}"
704
+
705
+ new_subscription_item = {}
706
+
707
+ new_subscription_item["reference_name"] = old_subscription_item[:attributes][:name]
708
+ new_subscription_item["product_id"] = old_subscription_item[:attributes][:product_id]
709
+ new_subscription_item["subscription_duration"] = subscription_period_dict[old_subscription_item[:attributes][:subscription_period]]
710
+ # new_subscription_item["state"] = old_subscription_item[:attributes][:state]
711
+ new_subscription_item["reference_name"] = old_subscription_item[:attributes][:name]
712
+ new_subscription_item["review_note"] = old_subscription_item[:attributes][:review_note]
713
+
714
+ new_subscription_item["display_name"] = nil
715
+ new_subscription_item["description"] = nil
716
+ new_subscription_item["price"] = nil
717
+ new_subscription_item["review_screenshot"] = nil
718
+ new_subscription_item["subscription_free_trial"] = nil
719
+
720
+
721
+
722
+ if !old_subscription_item[:relationships].nil? && !old_subscription_item[:relationships][:subscription_localizations].nil? && !old_subscription_item[:relationships][:subscription_localizations][:data].nil? && old_subscription_item[:relationships][:subscription_localizations][:data].size > 0
723
+ subscription_localization_item = old_subscription_item[:relationships][:subscription_localizations][:data].first
724
+ new_subscription_item["localizations_id"] = subscription_localization_item[:id]
725
+ end
726
+
727
+ if !new_subscription_item["localizations_id"].nil? && !subscription_response[:included].nil?
728
+ localizations_item = subscription_response[:included].find { |item| item[:type].eql?("subscriptionLocalizations") && item[:id].eql?(new_subscription_item["localizations_id"])}
729
+
730
+ new_subscription_item["display_name"] = localizations_item[:attributes][:name]
731
+ new_subscription_item["description"] = localizations_item[:attributes][:description]
732
+ end
733
+
734
+
735
+ if !old_subscription_item[:relationships].nil? && !old_subscription_item[:relationships][:introductory_offers].nil? && !old_subscription_item[:relationships][:introductory_offers][:data].nil? && old_subscription_item[:relationships][:introductory_offers][:data].size > 0
736
+ new_subscription_item["subscription_free_trial"] = "3d"
737
+ else
738
+ new_subscription_item.delete("subscription_free_trial")
739
+ end
740
+
741
+ new_subscription_item["price"] = get_subscription_item_price(appstore_client:appstore_client, subscription_id:old_subscription_item[:id])
742
+ new_subscription_item.delete("localizations_id")
743
+
744
+
745
+ subscription_items << new_subscription_item
746
+
747
+ end
748
+ end
749
+
750
+ subscription_items.sort! { | itema, itemb | itema["product_id"] <=> itemb["product_id"]}
751
+ return subscription_items
752
+
753
+ end
754
+
755
+ def create_subscription_items(appstore_client:nil, subscription_group_id:nil, subscription_items:nil)
756
+
757
+
758
+ subscription_items = subscription_items || []
759
+ subscription_items.sort! { | itema, itemb | itema["product_id"] <=> itemb["product_id"]}
760
+
761
+ #查询是否存在group
762
+ subscription_response = appstore_client.list_all_subscription_for_subscription_group(id: subscription_group_id, limit:50)
763
+ # puts JSON.pretty_generate(subscription_response)
764
+ #subscription,则更新,不存在则创建
765
+ if !subscription_response.nil? && !subscription_response[:data].nil?
766
+ subscription_response[:data].each do |old_subscription_item|
767
+ subscription_items.each do |new_subscription_item|
768
+ if !old_subscription_item[:attributes].nil? && old_subscription_item[:attributes][:product_id].to_s.eql?(new_subscription_item["product_id"])
769
+ new_subscription_item["subscription_id"] = old_subscription_item[:id]
770
+ new_subscription_item["state"] = old_subscription_item[:attributes][:state]
771
+ end
772
+ end
773
+ end
774
+ end
775
+
776
+ subscription_items.each do |new_subscription_item|
777
+ puts " 订阅项:" + new_subscription_item["product_id"]
778
+ if new_subscription_item["subscription_id"].nil?
779
+ create_subscription_item(appstore_client:appstore_client, subscription_group_id:subscription_group_id, subscription_item:new_subscription_item)
780
+ end
781
+
782
+ if !new_subscription_item["subscription_id"].nil?
783
+ subscription_id = new_subscription_item["subscription_id"]
784
+ puts " 订阅项id: #{subscription_id}"
785
+
786
+ sleep(1)
787
+ if !new_subscription_item["state"].nil? && new_subscription_item["state"].to_s.eql?("APPROVED")
788
+ puts " 订阅项已经上线, 只能修改价格"
789
+ create_subscription_item_price(appstore_client:appstore_client, subscription_id:subscription_id, subscription_item:new_subscription_item)
790
+ update_subscription_item_introductory_offer(appstore_client:appstore_client, subscription_id:subscription_id, subscription_item:new_subscription_item)
791
+ else
792
+
793
+ update_subscription_item_attributes(appstore_client:appstore_client, subscription_id:subscription_id, subscription_item:new_subscription_item)
794
+ create_subscription_item_localization(appstore_client:appstore_client, subscription_id:subscription_id, subscription_item:new_subscription_item)
795
+ update_subscription_item_screenshots(appstore_client:appstore_client, subscription_id:subscription_id, subscription_item:new_subscription_item)
796
+
797
+ create_subscription_item_price(appstore_client:appstore_client, subscription_id:subscription_id, subscription_item:new_subscription_item)
798
+ delete_subscription_item_introductory_offer(appstore_client:appstore_client, subscription_id:subscription_id, subscription_item:new_subscription_item)
799
+ update_subscription_item_period(appstore_client:appstore_client, subscription_id:subscription_id, subscription_item:new_subscription_item)
800
+ update_subscription_item_introductory_offer(appstore_client:appstore_client, subscription_id:subscription_id, subscription_item:new_subscription_item)
801
+ end
802
+
803
+
804
+
805
+ end
806
+ end
807
+
808
+
809
+ # subscription_items.each do |new_subscription_item|
810
+ # puts " 订阅项:" + new_subscription_item["product_id"]
811
+
812
+ # if !new_subscription_item["subscription_id"].nil?
813
+ # subscription_id = new_subscription_item["subscription_id"]
814
+
815
+ # create_subscription_item_price_with_singlefunc(appstore_client:appstore_client, subscription_id:subscription_id, subscription_item:new_subscription_item)
816
+ # if new_subscription_item["subscription_free_trial"].nil?
817
+ # delete_subscription_item_introductory_offer_with_singlefunc(appstore_client:appstore_client, subscription_id:subscription_id)
818
+ # end
819
+
820
+ # end
821
+ # end
822
+
823
+ #再更新一次Display Name , 状态变成yRead to Submit
824
+ subscription_items.each do |new_subscription_item|
825
+
826
+ if !new_subscription_item["subscription_id"].nil?
827
+
828
+ if !new_subscription_item["state"].nil? && new_subscription_item["state"].to_s.eql?("APPROVED")
829
+
830
+ else
831
+ subscription_id = new_subscription_item["subscription_id"]
832
+ create_subscription_item_localization(appstore_client:appstore_client, subscription_id:subscription_id, subscription_item:new_subscription_item)
833
+ end
834
+
835
+ end
836
+ end
837
+
838
+
839
+
840
+
841
+ end
842
+
843
+
844
+
845
+ def create_subscription_item(appstore_client:nil, subscription_group_id:nil, subscription_item:nil)
846
+ #创建购买项
847
+ begin
848
+ response = appstore_client.create_subscription(
849
+ name:subscription_item["reference_name"],
850
+ product_id:subscription_item["product_id"],
851
+ available_in_all_territories:true,
852
+ family_sharable:false,
853
+ review_note:subscription_item["review_note"],
854
+ subscription_period:subscription_item["subscription_duration"],
855
+ group_level:1,
856
+ relationships: {
857
+ group:{
858
+ data:{
859
+ id: subscription_group_id,
860
+ type: 'subscriptionGroups'
861
+ }
862
+ }
863
+ }
864
+ )
865
+
866
+ # puts JSON.pretty_generate(response)
867
+
868
+ if !response.nil? && !response[:data].nil? && !response[:data][:id].nil?
869
+
870
+ purchase_id = !response[:data][:id]
871
+ subscription_item["subscription_id"] = response[:data][:id]
872
+ return purchase_id
873
+ else !response.nil? && !response[:errors].nil?
874
+ # puts JSON.pretty_generate(response)
875
+ response[:errors].each do |error_item|
876
+ if error_item[:status].to_s.eql?("409") && error_item[:code].to_s.eql?("ENTITY_ERROR.ATTRIBUTE.INVALID.DUPLICATE") && error_item[:source][:pointer].to_s.eql?("/data/attributes/name")
877
+ err_msg = " !!!!!" + subscription_item["product_id"] + " 购买项创建失败!!! Reference Name重复!!!"
878
+ raise Informative, err_msg
879
+ end
880
+ end
881
+ err_msg = subscription_item["product_id"] + " 购买项创建失败!!!"
882
+ # puts JSON.pretty_generate(response)
883
+ end
884
+ rescue => err
885
+ puts err
886
+ err_msg = subscription_item["product_id"] + " 购买项创建失败!!!"
887
+ raise Informative, err_msg
888
+ end
889
+ end
890
+
891
+ def update_subscription_item_attributes(appstore_client:nil, subscription_id:nil, subscription_item:nil)
892
+ puts " 更新Reference Name"
893
+
894
+ begin
895
+ response = appstore_client.update_subscription(
896
+ id:subscription_id,
897
+ name:subscription_item["reference_name"],
898
+ available_in_all_territories:true,
899
+ family_sharable:false,
900
+ review_note:subscription_item["review_note"],
901
+ group_level:1
902
+ )
903
+ # puts JSON.pretty_generate(response)
904
+
905
+ if !response.nil? && !response[:data].nil? && !response[:data][:id].nil?
906
+
907
+ purchase_id = !response[:data][:id]
908
+ subscription_item["subscription_id"] = response[:data][:id]
909
+ return purchase_id
910
+ else !response.nil? && !response[:errors].nil?
911
+ # puts JSON.pretty_generate(response)
912
+ response[:errors].each do |error_item|
913
+ if error_item[:status].to_s.eql?("409") && error_item[:code].to_s.eql?("ENTITY_ERROR.ATTRIBUTE.INVALID.DUPLICATE") && error_item[:source][:pointer].to_s.eql?("/data/attributes/name")
914
+ err_msg = " !!!!!" + subscription_item["product_id"] + " 购买项更新失败!!! Reference Name重复!!!"
915
+ raise Informative, err_msg
916
+ end
917
+ end
918
+ err_msg = subscription_item["product_id"] + " 购买项更新失败!!!"
919
+ # puts JSON.pretty_generate(response)
920
+ end
921
+
922
+ rescue => err
923
+ puts err
924
+ end
925
+ end
926
+
927
+ def update_subscription_item_period(appstore_client:nil, subscription_id:nil, subscription_item:nil)
928
+
929
+ begin
930
+ puts " 设置订阅的周期: #{subscription_item["subscription_duration"]}"
931
+ response = appstore_client.update_subscription(
932
+ id:subscription_id,
933
+ subscription_period:subscription_item["subscription_duration"]
934
+ )
935
+ # puts JSON.pretty_generate(response)
936
+
937
+ if !response.nil? && !response[:data].nil? && !response[:data][:id].nil?
938
+
939
+ purchase_id = !response[:data][:id]
940
+ subscription_item["subscription_id"] = response[:data][:id]
941
+ return purchase_id
942
+ else !response.nil? && !response[:errors].nil?
943
+ puts " !!!! 设置订阅的周期失败 !!!!"
944
+ end
945
+
946
+ rescue => err
947
+ puts err
948
+ puts " !!!! 设置订阅的周期失败 !!!!"
949
+ end
950
+ end
951
+
952
+ def create_subscription_item_localization(appstore_client:nil, subscription_id:nil, subscription_item:nil)
953
+ puts " 更新Display Name"
954
+ begin
955
+ # 更新购买项描述多语言
956
+ response = appstore_client.list_subscription_all_localizations(
957
+ id:subscription_id,
958
+ limit:200
959
+ )
960
+ if !response[:data].nil?
961
+
962
+ response[:data].each do |localization_item|
963
+ locale = localization_item[:attributes][:locale]
964
+ locale_id = localization_item[:id]
965
+ display_name = localization_item[:name]
966
+ description = localization_item[:description]
967
+ subscription_item["localization"][locale] = subscription_item["localization"][locale] || {}
968
+ subscription_item["localization"][locale]["locale"] = locale
969
+ subscription_item["localization"][locale]["locale_id"] = locale_id
970
+ subscription_item["localization"][locale]["display_name"] = subscription_item["localization"][locale]["display_name"] || display_name
971
+ subscription_item["localization"][locale]["description"] = subscription_item["localization"][locale]["description"] || description
972
+ end
973
+
974
+ end
975
+
976
+ # puts JSON.pretty_generate(response)
977
+
978
+ subscription_item["localization"].each do |locale, locale_item|
979
+
980
+
981
+ if !locale_item.nil? && !locale_item["locale_id"].nil?
982
+
983
+ response = appstore_client.update_subscription_localizations(
984
+ id:locale_item["locale_id"],
985
+ name:locale_item["display_name"],
986
+ description:locale_item["description"]
987
+ )
988
+ # puts JSON.pretty_generate(response)
989
+
990
+ else
991
+
992
+ response = appstore_client.create_subscription_localizations(
993
+ name:locale_item["display_name"],
994
+ description:locale_item["description"],
995
+ locale:locale,
996
+ relationships: {
997
+ subscription:{
998
+ data:{
999
+ id: subscription_id,
1000
+ type: 'subscriptions'
1001
+ }
1002
+ }
1003
+ }
1004
+ )
1005
+
1006
+ # puts JSON.pretty_generate(response)
1007
+
1008
+ end
1009
+
1010
+
1011
+
1012
+ end
1013
+
1014
+
1015
+
1016
+ rescue => err
1017
+ puts err
1018
+ end
1019
+ end
1020
+
1021
+
1022
+ def get_subscription_item_price(appstore_client:nil, subscription_id:nil)
1023
+
1024
+ itc_usa_latest_price = 0
1025
+
1026
+ respose_price = appstore_client.list_subscription_all_price(
1027
+ id:subscription_id,
1028
+ include:"subscriptionPricePoint",
1029
+ filter: {
1030
+ territory: 'USA'
1031
+ },
1032
+ limit:200
1033
+ )
1034
+ # puts JSON.pretty_generate(respose_price)
1035
+
1036
+ if !respose_price[:included].nil?
1037
+ # respose_price[:included].each do |include_item|
1038
+ # if include_item[:type].to_s.eql?("subscriptionPricePoints")
1039
+ # itc_usa_latest_price = include_item[:attributes][:customer_price]
1040
+ # end
1041
+ # end
1042
+
1043
+ #get the latest price
1044
+ include_item = respose_price[:included].last
1045
+ if !include_item.nil? && !include_item[:type].nil? && include_item[:type].to_s.eql?("subscriptionPricePoints")
1046
+ itc_usa_latest_price = include_item[:attributes][:customer_price]
1047
+ end
1048
+ end
1049
+ return itc_usa_latest_price
1050
+
1051
+ end
1052
+
1053
+ def create_subscription_item_price(appstore_client:nil, subscription_id:nil, subscription_item:nil)
1054
+
1055
+ puts " 更新价格 "
1056
+ begin
1057
+
1058
+
1059
+ #在线订阅修改价格
1060
+
1061
+ itc_usa_latest_price = nil
1062
+ itc_usa_latest_start_date = nil
1063
+ need_modify_price = true
1064
+
1065
+ if subscription_item["state"].to_s.eql?("APPROVED")
1066
+
1067
+ respose_price = appstore_client.list_subscription_all_price(
1068
+ id:subscription_id,
1069
+ include:"subscriptionPricePoint",
1070
+ filter: {
1071
+ territory: 'USA'
1072
+ },
1073
+ limit:200
1074
+ )
1075
+ # puts JSON.pretty_generate(respose_price)
1076
+
1077
+
1078
+ if !respose_price[:data].nil?
1079
+ respose_price[:data].each_with_index do |data_item, data_index|
1080
+ if data_item[:type].to_s.eql?("subscriptionPrices")
1081
+ temp_id = data_item[:id]
1082
+ temp_price_point_id = data_item[:relationships][:subscription_price_point][:data][:id]
1083
+ price_point_item = respose_price[:included].find { |e| e[:id].eql?(temp_price_point_id) }
1084
+
1085
+ itc_usa_price = price_point_item[:attributes][:customer_price]
1086
+ data_string = data_item[:attributes][:start_date].nil? ? "无" : data_item[:attributes][:start_date]
1087
+ puts " 线上价格#{data_index} :" + itc_usa_price +"$" + " 生效日期 : " + data_string
1088
+ end
1089
+ end
1090
+
1091
+ #get the latest price
1092
+ data_item = respose_price[:data].last
1093
+ if data_item[:type].to_s.eql?("subscriptionPrices")
1094
+ itc_usa_latest_start_date = data_item[:attributes][:start_date]
1095
+ end
1096
+ end
1097
+
1098
+
1099
+ if !respose_price[:included].nil?
1100
+ include_item = respose_price[:included].last
1101
+ if include_item[:type].to_s.eql?("subscriptionPricePoints")
1102
+ itc_usa_latest_price = include_item[:attributes][:customer_price]
1103
+ puts " 最新线上价格:" + itc_usa_latest_price +"$"
1104
+ end
1105
+ end
1106
+
1107
+
1108
+ if !itc_usa_latest_price.nil? && itc_usa_latest_price.to_s.eql?(subscription_item["price"].to_s)
1109
+ need_modify_price = false
1110
+ end
1111
+
1112
+ end
1113
+
1114
+
1115
+
1116
+ if !need_modify_price
1117
+ puts " 与最新线上价格相同, 无需修改价格 !"
1118
+ return
1119
+ end
1120
+
1121
+
1122
+ respose_usa_price_points = appstore_client.list_subscription_price_points(
1123
+ id:subscription_id,
1124
+ include: 'territory',
1125
+ filter: {
1126
+ territory: 'USA'
1127
+ },
1128
+ limit:800
1129
+ )
1130
+
1131
+ price_point_id = nil
1132
+ respose_usa_price_points[:data].each do |price_item|
1133
+ if price_item[:attributes][:customer_price].to_s.eql?(subscription_item["price"].to_s)
1134
+ price_point_id = price_item[:id]
1135
+ puts " 创建价格:" + subscription_item["price"] +"$"
1136
+ # puts price_point_id
1137
+ break;
1138
+ end
1139
+ end
1140
+
1141
+ # itc_latest_price_point_id = nil
1142
+ # if subscription_item["state"].to_s.eql?("APPROVED") && !itc_usa_latest_price.nil?
1143
+ # respose_usa_price_points[:data].each do |price_item|
1144
+ # if price_item[:attributes][:customer_price].to_s.eql?(itc_usa_latest_price.to_s)
1145
+ # itc_latest_price_point_id = price_item[:id]
1146
+ # break;
1147
+ # end
1148
+ # end
1149
+ # end
1150
+
1151
+
1152
+
1153
+ if !price_point_id.nil?
1154
+
1155
+ attributes = {}
1156
+ time_tomo = Time.now + 1.day
1157
+ date_str_tomo = time_tomo.strftime('%Y-%m-%d')
1158
+ date_str_now = Time.now.strftime('%Y-%m-%d')
1159
+ if subscription_item["state"].to_s.eql?("APPROVED")
1160
+ attributes = {
1161
+ startDate:date_str_tomo,
1162
+ preserveCurrentPrice:true
1163
+ }
1164
+ end
1165
+
1166
+ respose_equalizations_id = appstore_client.list_subscription_price_points_equalizations(
1167
+ id:price_point_id,
1168
+ include:'territory',
1169
+ limit:200
1170
+ )
1171
+ # puts JSON.pretty_generate(respose_equalizations_id)
1172
+
1173
+ price_change_relationships_data = {
1174
+ newSubscriptionPricePoints:{
1175
+ data:[]
1176
+ },
1177
+ currentSubscriptionPricePoints:{
1178
+ data:[]
1179
+ }
1180
+
1181
+ }
1182
+
1183
+ relationships_data = {
1184
+ prices:{
1185
+ data:[]
1186
+ }
1187
+ }
1188
+
1189
+ included_data = []
1190
+
1191
+ if !respose_equalizations_id[:data].nil?
1192
+
1193
+ index_num = 0
1194
+
1195
+ relationships_data[:prices][:data] << {
1196
+ type: "subscriptionPrices",
1197
+ id: "${newprice-#{index_num}}"
1198
+ }
1199
+
1200
+
1201
+ included_data << {
1202
+ type: "subscriptionPrices",
1203
+ id: "${newprice-#{index_num}}",
1204
+ attributes: attributes,
1205
+ relationships:{
1206
+ subscriptionPricePoint:{
1207
+ data:{
1208
+ type:"subscriptionPricePoints",
1209
+ id: price_point_id
1210
+ }
1211
+ }
1212
+ }
1213
+ }
1214
+
1215
+ price_change_relationships_data[:newSubscriptionPricePoints][:data] << {
1216
+ type:"subscriptionPricePoints",
1217
+ id: price_point_id
1218
+ }
1219
+
1220
+ index_num = index_num +1
1221
+
1222
+ respose_equalizations_id[:data].each do |price_local_item|
1223
+
1224
+ local_price_point_id = price_local_item[:id]
1225
+ relationships_data[:prices][:data] << {
1226
+ type: "subscriptionPrices",
1227
+ id: "${newprice-#{index_num}}"
1228
+ }
1229
+ included_data << {
1230
+ type: "subscriptionPrices",
1231
+ id: "${newprice-#{index_num}}",
1232
+ attributes: attributes,
1233
+ relationships:{
1234
+ subscriptionPricePoint:{
1235
+ data:{
1236
+ type:"subscriptionPricePoints",
1237
+ id: local_price_point_id
1238
+ }
1239
+ }
1240
+ }
1241
+ }
1242
+
1243
+
1244
+ price_change_relationships_data[:newSubscriptionPricePoints][:data] << {
1245
+ type:"subscriptionPricePoints",
1246
+ id: local_price_point_id
1247
+ }
1248
+
1249
+ index_num = index_num +1
1250
+ end
1251
+
1252
+ # puts JSON.pretty_generate(relationships_data)
1253
+ # puts JSON.pretty_generate(included_data)
1254
+
1255
+
1256
+
1257
+ if subscription_item["state"].to_s.eql?("APPROVED")
1258
+
1259
+
1260
+
1261
+ respose_response = appstore_client.list_subscription_all_price(
1262
+ id:subscription_id,
1263
+ include:"subscriptionPricePoint",
1264
+ limit:200
1265
+ )
1266
+
1267
+ all_price_data = []
1268
+
1269
+
1270
+ next_respose_response = respose_response
1271
+ all_price_data = all_price_data + respose_response[:data]
1272
+ while !next_respose_response.nil? && !next_respose_response[:links].nil? && !next_respose_response[:links][:next].nil?
1273
+
1274
+ cursor = nil
1275
+ # puts next_respose_response[:links][:next]
1276
+ url_parse = URI.parse(next_respose_response[:links][:next])
1277
+ url_param_string = url_parse.query.split('&')
1278
+ cursor_string = url_param_string.find {|e| e.include?('cursor=')}
1279
+ cursor = cursor_string.split('=')[1]
1280
+
1281
+ next_respose_response = appstore_client.list_subscription_all_price(
1282
+ id:subscription_id,
1283
+ include:"subscriptionPricePoint",
1284
+ cursor:cursor,
1285
+ limit:200
1286
+ )
1287
+ all_price_data = all_price_data + next_respose_response[:data]
1288
+ end
1289
+
1290
+ # puts JSON.pretty_generate(all_price_data)
1291
+ # puts "all_price_data.size: #{all_price_data.size}"
1292
+
1293
+ # puts "respose_response[:included].size : #{respose_response[:included].size }"
1294
+ if !itc_usa_latest_start_date.nil? && !respose_response.nil? && !respose_response[:links].nil? && !respose_response[:links][:next].nil?
1295
+ last_data_items = all_price_data.select { |e| e[:attributes][:start_date].eql?(itc_usa_latest_start_date)}
1296
+ else
1297
+ last_data_items = all_price_data
1298
+ end
1299
+
1300
+
1301
+ if last_data_items.size > 0
1302
+ last_data_items.each do |last_data_item|
1303
+ if last_data_item[:type].to_s.eql?("subscriptionPrices")
1304
+ price_change_relationships_data[:currentSubscriptionPricePoints][:data] << {
1305
+ type:"subscriptionPricePoints",
1306
+ id: last_data_item[:relationships][:subscription_price_point][:data][:id]
1307
+ }
1308
+ end
1309
+ end
1310
+ end
1311
+
1312
+
1313
+ # puts JSON.pretty_generate(price_change_relationships_data)
1314
+ # puts "price_change_relationships_data[:currentSubscriptionPricePoints][:data].size #{price_change_relationships_data[:currentSubscriptionPricePoints][:data].size}"
1315
+ # puts "price_change_relationships_data[:newSubscriptionPricePoints][:data]..size #{price_change_relationships_data[:newSubscriptionPricePoints][:data].size}"
1316
+ body = {
1317
+ data: {
1318
+ type: "subscriptionPriceChangeConsentReasons",
1319
+ relationships: price_change_relationships_data
1320
+ }
1321
+ }
1322
+
1323
+ client = Spaceship::ConnectAPI
1324
+
1325
+ begin
1326
+
1327
+ respose_price = client.tunes_request_client.post("subscriptionPriceChangeConsentReasons", body)
1328
+
1329
+ # puts JSON.pretty_generate(respose_price)
1330
+ rescue => err
1331
+ # puts err
1332
+ # puts "subscriptionPriceChangeConsentReasons errors"
1333
+ end
1334
+ # respose_price = appstore_client.create_subscription_price_change_consent_reason(
1335
+ # relationships: price_change_relationships_data
1336
+ # )
1337
+ # puts JSON.pretty_generate(respose_price)
1338
+
1339
+
1340
+
1341
+ body = {
1342
+ data: {
1343
+ type: "subscriptions",
1344
+ id:subscription_id,
1345
+ relationships: relationships_data
1346
+ },
1347
+ included: included_data
1348
+ }
1349
+ # puts "relationships_data[:prices][:data].size #{relationships_data[:prices][:data].size}"
1350
+ # puts "included_data.size: #{included_data.size}"
1351
+ # puts JSON.pretty_generate(body)
1352
+
1353
+ respose_price = client.tunes_request_client.patch("subscriptions/#{subscription_id}", body)
1354
+ # respose_price = appstore_client.update_subscription(
1355
+ # id:subscription_id,
1356
+ # relationships: relationships_data,
1357
+ # included: included_data
1358
+ # )
1359
+ # puts JSON.pretty_generate(respose_price)
1360
+ puts " 更新订阅价格成功!!! 生效日期 : #{date_str_tomo}"
1361
+
1362
+ else
1363
+
1364
+ response = appstore_client.update_subscription(
1365
+ id:subscription_id,
1366
+ relationships: relationships_data,
1367
+ included: included_data
1368
+ )
1369
+
1370
+ puts " 创建订阅价格成功 !"
1371
+ # puts JSON.pretty_generate(response)
1372
+
1373
+ end
1374
+
1375
+
1376
+
1377
+ end
1378
+
1379
+ else
1380
+ puts "!!!! 更新价格错误!!! 价格:" + + subscription_item["price"] +"$"
1381
+ end
1382
+
1383
+ rescue => err
1384
+ puts "!!!! 更新价格错误!!! 价格:" + + subscription_item["price"] +"$"
1385
+ puts err
1386
+ end
1387
+
1388
+ end
1389
+
1390
+
1391
+ def update_subscription_item_introductory_offer(appstore_client:nil, subscription_id:nil, subscription_item:nil)
1392
+ puts " 设置Introductory Offer : "
1393
+ if !subscription_item["subscription_free_trial"].nil? && subscription_item["subscription_free_trial"].to_s.eql?("3d")
1394
+ puts " 3天 试用"
1395
+ create_subscription_item_introductory_offer(appstore_client:appstore_client, subscription_id:subscription_id, subscription_item:subscription_item)
1396
+ else
1397
+ puts " 无试用"
1398
+ end
1399
+
1400
+ end
1401
+
1402
+ def create_subscription_item_introductory_offer(appstore_client:nil, subscription_id:nil, subscription_item:nil)
1403
+
1404
+
1405
+ begin
1406
+
1407
+ territory_response = appstore_client.list_subscription_territory_availability(
1408
+ id:subscription_id,
1409
+ limit:200
1410
+ )
1411
+
1412
+ # puts JSON.pretty_generate(territory_response)
1413
+
1414
+ relationships_data = {
1415
+ introductoryOffers:{
1416
+ data:[]
1417
+ }
1418
+ }
1419
+
1420
+ included_data = []
1421
+
1422
+ if !territory_response[:data].nil?
1423
+ index_num = 0
1424
+ territory_response[:data].each do |territory_item|
1425
+ local_territory_id = territory_item[:id]
1426
+ relationships_data[:introductoryOffers][:data] << {
1427
+ type: "subscriptionIntroductoryOffers",
1428
+ id: "${newIntroOffer-#{index_num}}"
1429
+ }
1430
+
1431
+ included_data << {
1432
+ type: "subscriptionIntroductoryOffers",
1433
+ id: "${newIntroOffer-#{index_num}}",
1434
+ attributes: {
1435
+ duration:"THREE_DAYS",
1436
+ offerMode:"FREE_TRIAL",
1437
+ numberOfPeriods:1
1438
+ },
1439
+ relationships:{
1440
+ territory:{
1441
+ data:{
1442
+ type:"territories",
1443
+ id: local_territory_id
1444
+ }
1445
+ }
1446
+ }
1447
+ }
1448
+
1449
+ index_num = index_num +1
1450
+
1451
+ end
1452
+
1453
+ response = appstore_client.update_subscription(
1454
+ id:subscription_id,
1455
+ relationships: relationships_data,
1456
+ included: included_data
1457
+ )
1458
+ puts " 3天 试用 设置成功!"
1459
+ # puts JSON.pretty_generate(response)
1460
+ end
1461
+
1462
+ rescue => err
1463
+ puts " !!!! 设置Introductory Offer 失败 !!! "
1464
+ puts err
1465
+ end
1466
+
1467
+
1468
+ end
1469
+
1470
+
1471
+ def delete_subscription_item_introductory_offer(appstore_client:nil, subscription_id:nil, subscription_item:nil)
1472
+
1473
+ begin
1474
+
1475
+ introductory_response = appstore_client.list_all_introductory_offers_ids_for_subscription(
1476
+ id:subscription_id,
1477
+ limit:200
1478
+ )
1479
+
1480
+ # puts JSON.pretty_generate(introductory_response)
1481
+
1482
+ if !introductory_response[:data].nil? && introductory_response[:data].size > 0
1483
+
1484
+ # puts JSON.pretty_generate(introductory_response[:data])
1485
+ puts " 线上有试用,先删除"
1486
+ temp_data = [];
1487
+
1488
+ introductory_response[:data].each do |introductory_item|
1489
+ temp_data << {id: introductory_item[:id]}
1490
+ end
1491
+
1492
+
1493
+ introductory_response = appstore_client.delete_introductory_offers_for_subscription(
1494
+ id:subscription_id,
1495
+ data:temp_data
1496
+ )
1497
+
1498
+ puts " 线上试用删除成功!!!"
1499
+ # puts JSON.pretty_generate(introductory_response)
1500
+ else
1501
+ puts " 线上无试用, 无需删除!!!"
1502
+ end
1503
+
1504
+ rescue => err
1505
+ puts " !!!! 删除 试用 失败 !!!!"
1506
+ puts err
1507
+ end
1508
+
1509
+ end
1510
+
1511
+
1512
+
1513
+ def delete_subscription_item_introductory_offer_with_singlefunc(appstore_client:nil, subscription_id:nil)
1514
+
1515
+
1516
+ begin
1517
+
1518
+ response = appstore_client.list_subscription_introductory_offer_resoure_ids(
1519
+ id:subscription_id,
1520
+ limit:200
1521
+ )
1522
+ # puts JSON.pretty_generate(response)
1523
+
1524
+ index_item = 0
1525
+ if !response[:data].nil?
1526
+
1527
+ response[:data].each do |price_point_item|
1528
+
1529
+ index_item = index_item +1
1530
+
1531
+
1532
+ puts " 删除" + index_item.to_s+ "地区的Introductory Offer"
1533
+
1534
+ ret = appstore_client.delete_subscription_introductory_offer(id:price_point_item[:id])
1535
+ # puts JSON.pretty_generate(ret)
1536
+
1537
+ end
1538
+
1539
+ end
1540
+
1541
+
1542
+ rescue => err
1543
+
1544
+ puts err
1545
+ end
1546
+
1547
+ end
1548
+
1549
+
1550
+ def create_subscription_item_introductory_offer_with_singlefunc(appstore_client:nil, subscription_id:nil, price_point_id:nil, territory:nil)
1551
+
1552
+ puts " 设置Introductory Offer"
1553
+ begin
1554
+
1555
+ response = appstore_client.create_subscription_introductory_offer(
1556
+ duration:"THREE_DAYS",
1557
+ number_of_periods:1,
1558
+ offer_mode:'FREE_TRIAL',
1559
+ relationships: {
1560
+ subscription: {
1561
+ data: {
1562
+ type: 'subscriptions',
1563
+ id: subscription_id
1564
+ }
1565
+ },
1566
+ subscriptionPricePoint: {
1567
+ data: {
1568
+ type: 'subscriptionPricePoints',
1569
+ id: price_point_id
1570
+ }
1571
+ },
1572
+ territory: {
1573
+ data: {
1574
+ type: 'territories',
1575
+ id: territory
1576
+ }
1577
+ }
1578
+
1579
+ },
1580
+ included:[{
1581
+ type: "subscriptionPrices",
1582
+ id: price_point_id
1583
+ }]
1584
+ )
1585
+ # puts JSON.pretty_generate(response)
1586
+
1587
+ rescue => err
1588
+
1589
+ puts err
1590
+ end
1591
+ end
1592
+
1593
+
1594
+
1595
+ def create_subscription_item_price_with_singlefunc(appstore_client:nil, subscription_id:nil, subscription_item:nil)
1596
+ puts " 更新价格"
1597
+ begin
1598
+
1599
+ respose_price = appstore_client.list_subscription_price_points(
1600
+ id:subscription_id,
1601
+ include: 'territory',
1602
+ filter: {
1603
+ territory: 'USA'
1604
+ },
1605
+ limit:800
1606
+ )
1607
+
1608
+ price_point_id = nil
1609
+
1610
+ respose_price[:data].each do |price_item|
1611
+ if price_item[:attributes][:customer_price].to_s.eql?(subscription_item["price"].to_s)
1612
+ price_point_id = price_item[:id]
1613
+ puts " 1.更新价格 地区: USA 货币:USD 价格:" + + subscription_item["price"] +"$"
1614
+ break;
1615
+ end
1616
+ end
1617
+
1618
+ if !price_point_id.nil?
1619
+
1620
+ respose_price = appstore_client.create_subscription_price(
1621
+ preserve_current_price:true,
1622
+ relationships: {
1623
+ subscription: {
1624
+ data: {
1625
+ type: 'subscriptions',
1626
+ id: subscription_id
1627
+ }
1628
+ },
1629
+ subscriptionPricePoint: {
1630
+ data: {
1631
+ type: 'subscriptionPricePoints',
1632
+ id: price_point_id
1633
+ }
1634
+ }
1635
+ }
1636
+ )
1637
+
1638
+
1639
+
1640
+ if !subscription_item["subscription_free_trial"].nil? && subscription_item["subscription_free_trial"].to_s.eql?("3d")
1641
+
1642
+ create_subscription_item_introductory_offer_with_singlefunc(appstore_client:appstore_client, subscription_id:subscription_id, price_point_id:price_point_id, territory:'USA')
1643
+ end
1644
+
1645
+
1646
+
1647
+
1648
+ respose_price = appstore_client.list_subscription_price_points_equalizations(
1649
+ id:price_point_id,
1650
+ include:'territory',
1651
+ limit:200
1652
+ )
1653
+ # puts JSON.pretty_generate(respose_price)
1654
+
1655
+ index_item = 1
1656
+ if !respose_price[:data].nil?
1657
+
1658
+ respose_price[:data].each do |price_local_item|
1659
+ index_item = index_item +1
1660
+
1661
+ price_point_id = price_local_item[:id]
1662
+ territory_id = price_local_item[:relationships][:territory][:data][:id]
1663
+ puts " " + index_item.to_s + ".更新价格 地区:" + territory_id+ " 价格:" + price_local_item[:attributes][:customer_price]
1664
+
1665
+ respose_price = appstore_client.create_subscription_price(
1666
+ preserve_current_price:true,
1667
+ relationships: {
1668
+ subscription: {
1669
+ data: {
1670
+ type: 'subscriptions',
1671
+ id: subscription_id
1672
+ }
1673
+ },
1674
+ subscriptionPricePoint: {
1675
+ data: {
1676
+ type: 'subscriptionPricePoints',
1677
+ id: price_point_id
1678
+ }
1679
+ }
1680
+ }
1681
+ )
1682
+
1683
+ # puts JSON.pretty_generate(respose_price)
1684
+
1685
+ if !subscription_item["subscription_free_trial"].nil? && subscription_item["subscription_free_trial"].to_s.eql?("3d")
1686
+
1687
+ create_subscription_item_introductory_offer_with_singlefunc(appstore_client:appstore_client, subscription_id:subscription_id, price_point_id:price_point_id, territory:territory_id)
1688
+ end
1689
+
1690
+ end
1691
+
1692
+ end
1693
+
1694
+
1695
+ end
1696
+
1697
+ rescue => err
1698
+ puts "创建价格失败: " + subscription_item["product_id"]
1699
+ puts err
1700
+ end
1701
+ end
1702
+
1703
+ def update_subscription_item_screenshots(appstore_client:nil, subscription_id:nil, subscription_item:nil)
1704
+ puts " 更新截屏"
1705
+ begin
1706
+ response_iap_screenshot = appstore_client.read_review_screenshot_for_subscription(id:subscription_id)
1707
+
1708
+
1709
+ path = subscription_item["review_screenshot_fullpath"]
1710
+ filename = File.basename(path)
1711
+ filesize = File.size(path)
1712
+ bytes = File.binread(path)
1713
+
1714
+ checksum = Digest::MD5.hexdigest(bytes)
1715
+
1716
+ # puts JSON.pretty_generate(response_iap_screenshot)
1717
+
1718
+ need_upload_screenshot = true
1719
+
1720
+ if !response_iap_screenshot[:data].nil? && !response_iap_screenshot[:data][:attributes].nil? && !response_iap_screenshot[:data][:attributes][:asset_delivery_state].nil? && !response_iap_screenshot[:data][:attributes][:asset_delivery_state][:state].nil?
1721
+
1722
+ if response_iap_screenshot[:data][:attributes][:asset_delivery_state][:state].to_s.eql?("COMPLETE")
1723
+
1724
+ if !response_iap_screenshot[:data].nil? && !response_iap_screenshot[:data][:attributes].nil? && !response_iap_screenshot[:data][:attributes][:source_file_checksum].nil?
1725
+
1726
+ if checksum.to_s.eql?(response_iap_screenshot[:data][:attributes][:source_file_checksum].to_s)
1727
+ puts " 有截屏,截屏未修改,无需重新上传"
1728
+ need_upload_screenshot = false
1729
+
1730
+ end
1731
+ end
1732
+ end
1733
+ end
1734
+
1735
+
1736
+ if need_upload_screenshot && !response_iap_screenshot[:data].nil? && !response_iap_screenshot[:data][:attributes].nil? && !response_iap_screenshot[:data][:attributes][:file_name].nil?
1737
+ puts " 有截屏,先删除再更新"
1738
+ # puts JSON.pretty_generate(response_iap_screenshot)
1739
+ appstore_client.delete_subscription_review_screenshot(id:response_iap_screenshot[:data][:id])
1740
+ end
1741
+
1742
+
1743
+ if need_upload_screenshot
1744
+
1745
+ puts " 正在上传...."
1746
+ response_iap_screenshot = appstore_client.create_subscription_review_screenshot(
1747
+ file_name:filename,
1748
+ file_size: filesize,
1749
+ relationships: {
1750
+ subscription:{
1751
+ data:{
1752
+ id: subscription_id,
1753
+ type: 'subscriptions'
1754
+ }
1755
+ }
1756
+ }
1757
+ )
1758
+
1759
+ # puts JSON.pretty_generate(response_iap_screenshot)
1760
+
1761
+ if !response_iap_screenshot[:data].nil? && !response_iap_screenshot[:data][:id].nil?
1762
+
1763
+ upload_id = response_iap_screenshot[:data][:id]
1764
+ upload_operations = response_iap_screenshot[:data][:attributes][:upload_operations]
1765
+ upload_operations.each_with_index do |upload_operation, index|
1766
+ headers = {}
1767
+ upload_operation[:request_headers].each do |item|
1768
+ headers[item[:name]] = item[:value]
1769
+ end
1770
+ offset = upload_operation[:offset]
1771
+ length = upload_operation[:length]
1772
+ conn = Faraday.new
1773
+ res = conn.put(upload_operation[:url], bytes[offset, length], headers)
1774
+ end
1775
+
1776
+
1777
+
1778
+ in_app_purchase = appstore_client.update_subscription_review_screenshot(
1779
+ id:upload_id,
1780
+ uploaded: true,
1781
+ source_file_checksum:checksum
1782
+ )
1783
+ puts " 上传完成!!"
1784
+ # puts JSON.pretty_generate(in_app_purchase)
1785
+ end
1786
+
1787
+ else
1788
+
1789
+ puts " 存在图片,无需上传...."
1790
+ end
1791
+
1792
+
1793
+
1794
+
1795
+ rescue => err
1796
+ puts err
1797
+ puts " 更新截屏失败!!!"
1798
+ end
1799
+ end
1800
+
1801
+ end
1802
+
1803
+ end