使用脚本批量上传内购商品

0

最近项目有很多内购商品要上传,满满的一表格。如果在平常,商品信息不多的情况下,我就手动一个个添加了。但是现在为了提高效率,我不得不下决心封装一个脚本,批量上传,解放双手,一劳永逸,谁叫我是个程序猿呢。

像往常一样,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 。

原文链接

你可能感兴趣的:(Ruby,iOS笔记)