最近项目有很多内购商品要上传,满满的一表格。如果在平常,商品信息不多的情况下,我就手动一个个添加了。但是现在为了提高效率,我不得不下决心封装一个脚本,批量上传,解放双手,一劳永逸,谁叫我是个程序猿呢。
像往常一样,google 一下有没有现成的解决方式。网上的相关信息很少,找到 fastlate 一个插件 spaceship ,可以用来上传商品信息。
之前也有了解过 fastlate,使用 fastlate 可以用来做很多事情,比如持续集成、自动打包等、上传包到服务器等等。今天我们来封装一下 fastlate 这个 spaceship 插件。
fastlate 使用 Ruby 脚本开发。Ruby 脚本简单易学,代码写起来很漂亮,很适合做这种事情。
先把 excel 表格解析出来,表格的一行就代表一个商品。商品的信息包括:商品 id、商品名、金额、商品信息、审核备注及商品截图。
excel 表格的要事先定义好一个固定格式解析的时候才不会出错。
调用 spaceship 把商品信息一个一个地上传到 itunesconnect。
每个 App 单独一个目录,先把相关的信息准备好,包括账号信息、App 信息、excel 表格及商品截图。
1.安装 Xcode 工具: xcode-select --install
2.安装 fastlane: [sudo] gem install fastlane -NV
3.安装 excel 解析库 roo : [sudo] gem install roo
Mac 系统本身自带 Ruby,所以如果是 Win 请自行安装。
我们先看下如何解析 excel 表格。
Ruby 有现成的 excel 解析库:roo,安装完 roo 就可以开始使用了。先导入 roo:
require 'roo'
打开文件,并选择第一张表:
xlsx = Roo::Spreadsheet.open(path, extension: :xlsx)
sheet = xlsx.sheet(0)
要取出每个单元格的内容,单元格是用坐标来表示的,所以我们先要获取它的总行数和总列数,然后再来迭代它。记住表格的行和列的计数是从 1 开始的。这边我们先把表格的标题拿出来,作为 key ,单元格的内容作为 value,每一行的内容作为一个字典,整个表格的格式为一个数组嵌套数个字典。
rows_count = sheet.last_row # 总行数
colunms_count = sheet.last_column # 总列数
titles = []
rows_count.times do |r|
# 将第一行的标题取出
if r == 0
colunms_count.times do |c|
res = sheet.cell(r + 1, c + 1)
titles << res
end
next
end
rows = {}
colunms_count.times do |c|
res = sheet.cell(r + 1, c + 1)
rows[titles[c]] = res # 将标题作为 key ,将单元格的内容作为 value
end
@result << rows
end
这样表格的内容就解析出来了,保存在 result 。
接下来我们要将内容传到 itunesconnect。导入 spaceship:
require 'spaceship'
登录一下开发账号,首次执行到以下代码会让你在控制台输入你的账号和密码:
Spaceship::Tunes.login(account)
然后使用 bundle id 来查找到你要添加商品的那个 app :
app = Spaceship::Application.find(bundle_id)
开始创建商品,把刚刚表格解析出来的数组迭代循环,依次调用。
def create()
type = Spaceship::Tunes::IAPType::CONSUMABLE
@products.each do |product|
tier = get_tier(product['amount']) # 获取商品价格等级
product_id = "#{@bundle_id}.#{product['id']}"
review_image_path = File::join(@path, "#{product['review_image']}.jpg")
abort("#review_image=#{review_image_path} not exist") unless File::exist?(review_image_path)
puts "#uploading ... product=#{product}"
begin
@app.in_app_purchases.create!( # 创建商品
type: type,
versions: {
'zh-CN': {
name: product['name'],
description: product['desc']
}
},
reference_name: product['name'],
product_id: product_id,
cleared_for_sale: true,
review_notes: product['review_desc'], # 审核备注
review_screenshot: review_image_path, # 商品截图
pricing_intervals: [
{
country: "WW",
begin_date: nil,
end_date: nil,
tier: tier
}
]
)
puts "#upload success"
rescue Exception => error
puts "#upload failure, error=#{error}"
end
end
end
这边 type 是商品类型,有消耗型、订阅型等,我们这里假定所有商品为消耗型。
product id, 由 bundle id 和商品 id 组成,所以填写表格的时候记得只填写后面半段商品 id,代码会自动加上前面 bundle id。
成功创建会执行下一个任务,如果创建失败会捕获异常,然后继续执行。一般捕获到的异常是因为已经存在该商品了,所以不能够重复创建。还有就是审核备注或者商品截图填写不正确也会异常。
get_tier 是获取商品价格等级的方法,我们将传入的价格转换为 itunesconnect 的价格等级:
def get_tier(amount)
tier = {
6 => 1,
30 => 5,
50 => 8,
88 => 13,
98 => 15,
128 => 20,
198 => 30,
228 => 34,
288 => 46,
328 => 50,
548 => 57,
648 => 60
}
abort("#tier not exist when amount=#{amount}") unless tier[amount]
tier[amount]
end
价格等级有非常多,常用的就这几个,以后用到再慢慢拓展。
修改商品信息的原理是把修改后的表格再跑一遍。 注意 product id 不可修改:
def modify()
@products.each do |product|
product_id = "#{@bundle_id}.#{product['id']}"
tier = get_tier(product['amount'])
review_image_path = File::join(@path, "#{product['review_image']}.jpg")
abort("#review_image=#{review_image_path} not exist") unless File::exist?(review_image_path)
puts "#modify ... product=#{product}"
begin
purch = @app.in_app_purchases.find(product_id) # 查找商品
e = purch.edit # 编辑商品
e.versions = {
'zh-CN': {
name: product['name'],
description: product['desc']
}
}
e.reference_name = product['name']
e.review_notes = product['review_desc']
e.review_screenshot = review_image_path
e.pricing_intervals = [
{
country: "WW",
begin_date: nil,
end_date: nil,
tier: tier
}
]
e.save!
puts "#modify success"
rescue Exception => error
puts "#modify failure, error=#{error}"
end
end
end
完整代码和使用方法请看 IAPProductTool 。
原文链接