Giter Club home page Giter Club logo

passbook's Introduction

Build Status

passbook

The passbook gem let's you create a pkpass for passbook in iOS 6+

Installation

Include the passbook gem in your project.

IE: In your Gemfile

gem 'passbook'

Quick Start

If you want to jump in without having to integrate this into your code you can use the command line options to get started. Start by installing the gem

gem install passbook

Then go to a directory that you want to generate your pass under and use the "pk generate command". (note: do not use spaces in your passname or else strange things will happen.)

pk generate your_pass_name

This will generate a directory called your_pass_name. Edit your pass.json file in the your_pass_directory to have a valid team identifier and passTypeIdentifier and create your certificates if you haven't yet. See this article for information on how to do this.

Assuming that you have put your certificate files etc. in your working directory.

pk build your_pass_name -w ./wwdc.pem -c ./your_pass_name.p12 -p ''

The wwdc.pem file is the exported Apple World Wide Developer Relations Certification Authority certificate file from your key manager and the your_pass_name.p12 is the exported p12 file from your pass certificate.

If you are not building your passes on a mac or just prefer to use the pass certificate and key pem file.

pk build passbook_gem_name -w ./wwdc.pem -c ./your_pass_name_certificate.pem -k your_pass_name_key.pem -p '12345'

Now you can drag the file over to a simulator or send it to your iPhone via e-mail to view your pass.

Configuration

Create initializer

    rails g passbook:config
    or with params
    rails g passbook:config [Absolute path to the wwdc cert file] [Absolute path to your cert.p12 file] [Password for your certificate]

Configure your config/initializers/passbook.rb

    Passbook.configure do |passbook|
      passbook.wwdc_cert = Rails.root.join('wwdc_cert.pem')
      passbook.p12_certificate = Rails.root.join('cert.p12')
      passbook.p12_password = 'cert password'
    end

If you are running this on a different machine from what you used to create your WWDC keys

    Passbook.configure do |passbook|
      passbook.wwdc_cert = Rails.root.join('wwdc_cert.pem')
      passbook.p12_key = Rails.root.join('key.pem')
      passbook.p12_certificate = Rails.root.join('certificate.pem')
      passbook.p12_password = 'cert password'
    end

If you are using Sinatra you can place this in the file you are executing or in a file that you do a require on. You would also not reference Rails.root when specifying your file path.

If You are doing push notifications then you will need to add some extra configuration options, namely a push notification certificate and a notification gateway certificate. Look at the Grocer gem documentation to find information on how to create this certificate. Settings you will want to use for the notification gateway are either 'gateway.push.apple.com' for production, 'gateway.sandbox.push.apple.com' for development and 'localhost' for unit tests.

    Passbook.configure do |passbook|
      .....other settings.....
      passbook.notification_gateway = 'gateway.push.apple.com'
      passbook.notification_passphrase = 'my_hard_password' (optional)
      passbook.notification_cert = 'lib/assets/my_notification_cert.pem'
    end

If you want to also support the push notification endpoints you will also need to include the Rack::PassbookRack middleware. In rails your config will look something like this.

  config.middleware.use Rack::PassbookRack

Usage

Please refer to apple iOS dev center for how to build cert and json. This article is also helpful.

    pass = Passbook::PKPass.new 'your json data'

    # Add file from disk
    pass.addFile 'file_path'

    # Add file from memory
    file[:name] = 'file name'
    file[:content] = 'whatever you want'
    pass.addFile file

    # Add multiple files
    pass.addFiles [file_path_1, file_path_2, file_path_3]

    # Add multiple files from memory
    pass.addFiles [{name: 'file1', content: 'content1'}, {name: 'file2', content: 'content2'}, {name: 'file3', content: 'content3'}]

    # Output a Tempfile

    pkpass = pass.file
    send_file pkpass.path, type: 'application/vnd.apple.pkpass', disposition: 'attachment', filename: "pass.pkpass"

    # Or a stream

    pkpass = pass.stream
    send_data pkpass.string, type: 'application/vnd.apple.pkpass', disposition: 'attachment', filename: "pass.pkpass"

If you are using Sinatra you will need to include the 'active_support' gem and will need to require 'active_support/json/encoding'. Here is an example using the streaming mechanism.

require 'sinatra'
require 'passbook'
require 'active_support/json/encoding'

Passbook.configure do |passbook|
  passbook.p12_password = '12345'
  passbook.p12_key = 'passkey.pem'
  passbook.p12_certificate = 'passcertificate.pem'
  passbook.wwdc_cert = 'WWDR.pem'
end

get '/passbook' do
  pass = # valid passbook json.  refer to the wwdc documentation.
  passbook = Passbook::PKPass.new pass
  passbook.addFiles ['logo.png', '[email protected]', 'icon.png', '[email protected]']
  response['Content-Type'] = 'application/vnd.apple.pkpass'
  attachment 'mypass.pkpass'
  passbook.stream.string
end

We will try to make this cleaner in subsequent releases.

Using Different Certificates For Different Passes

Sometime you might want to be able to use different certificates for different passes. This can be done by passing in a Signer class into your PKPass initializer like so

  signer = Passbook::Signer.new {certificate: some_cert, password: some_password, key: some_key, wwdc_cert: some_wwdc_cert}
  pk_pass = Passbook::PKPass.new your_json_data, signer

  ....

Push Notifications

If you want to support passbook push notification updates you will need to configure the appropriate bits above.

In order to support push notifications you will need to have a basic understanding of the way that push notifications work and how the data is passed back and forth. See this for basic information about passes and this to understand the information that needs to be exchanged between each device and your application to support the update service.

Your pass will need to have a field called 'webServiceURL' with the base url to your site and a field called 'authenticationToken'. The json snippet should look like this. Note that your url needs to be a valid signed https endpoint for production. You can put your phone in dev mode to test updates against a insecure http endpoint (under settings => developer => passkit testing).

...
  "webserviceURL" : "https://www.honeybadgers.com/",
  "authenticationToken" : "yummycobras"
...

Passbook includes rack middleware to make the job of supporting the passbook endpoints easier. You will need to configure the middleware as outlined above and then implement a class called Passbook::PassbookNotification. Below is an annotated implementation.

module Passbook
  class PassbookNotification

    # This is called whenever a new pass is saved to a users passbook or the
    # notifications are re-enabled.  You will want to persist these values to
    # allow for updates on subsequent calls in the call chain.  You can have
    # multiple push tokens and serial numbers for a specific
    # deviceLibraryIdentifier.

    def self.register_pass(options)
      the_passes_serial_number = options['serialNumber']
      the_devices_device_library_identifier = options['deviceLibraryIdentifier']
      the_devices_push_token = options['pushToken']
      the_pass_type_identifier = options["passTypeIdentifier"]
      the_authentication_token = options['authToken']

      # this is if the pass registered successfully
      # change the code to 200 if the pass has already been registered
      # 404 if pass not found for serialNubmer and passTypeIdentifier
      # 401 if authorization failed
      # or another appropriate code if something went wrong.
      {:status => 201}
    end

    # This is called when the device receives a push notification from apple.
    # You will need to return the serial number of all passes associated with
    # that deviceLibraryIdentifier.

    def self.passes_for_device(options)
      device_library_identifier = options['deviceLibraryIdentifier']
      passes_updated_since = options['passesUpdatedSince']

      # the 'lastUpdated' uses integers values to tell passbook if the pass is
      # more recent than the current one.  If you just set it is the same value
      # every time the pass will update and you will get a warning in the log files.
      # you can use the time in milliseconds,  a counter or any other numbering scheme.
      # you then also need to return an array of serial numbers.
      {'lastUpdated' => '1', 'serialNumbers' => ['various', 'serial', 'numbers']}
    end

    # this is called when a pass is deleted or the user selects the option to disable pass updates.
    def self.unregister_pass(options)
      # a solid unique pair of identifiers to identify the pass are
      serial_number = options['serialNumber']
      device_library_identifier = options['deviceLibraryIdentifier']
      the_pass_type_identifier = options["passTypeIdentifier"]
      the_authentication_token = options['authToken']
      # return a status 200 to indicate that the pass was successfully unregistered.
      {:status => 200}
    end

    # this returns your updated pass
    def self.latest_pass(options)
      the_pass_serial_number = options['serialNumber']
      # create your PkPass the way you did when your first created the pass.
      # you will want to return
      my_pass = PkPass.new 'your pass json'
      # you will want to return the string from the stream of your PkPass object.
      {:status => 200, :latest_pass => mypass.stream.string, :last_modified => '1442120893'}
    end

    # This is called whenever there is something from the update process that is a warning
    # or error
    def self.passbook_log(log)
      # this is a VERY crude logging example.  use the logger of your choice here.
      p "#{Time.now} #{log}"
    end

  end
end

To send a push notification for a updated pass simply call Passbook::PushNotification.send_notification with the push token for the device you are updating

  Passbook::PushNotification.send_notification the_device_push_token

Apple will send out a notification to your phone (usually within 15 minutes or less), which will cause the phone that this push notification is associated with to make a call to your server to get pass serial numbers and to then get the updated pass. Each phone/pass combination has it's own push token whch will require a separate call for every phone that has push notifications enabled for a pass (this is an Apple thing). In the future we may look into offering background process support for this as part of this gem. For now, if you have a lot of passes to update you will need to do this yourself.

Tests

To launch tests :

  bundle exec rake spec

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Changelog

0.0.4

Allow passbook gem to return a ZipOutputStream (needed when garbage collector delete tempfile before beeing able to use it) [Thx to applidget]

0.2.0

Adding support for push notification updates for passes.

0.4.0

Adding support for using multiple signatures per gem configuration and introducing command line helpers. More in this blog post.

0.4.1

Update rubyzip dependency to >= 1.0.0

License

passbook is released under the MIT license:

passbook's People

Contributors

afallou avatar avinoth avatar cjeffries avatar frozon avatar jspooner avatar lgleasain avatar nikoroberts avatar nov avatar ronakjangir47 avatar stereoscott avatar thejchap avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

passbook's Issues

Can't open .pkpass file

We've been using this gem for a few years, but suddenly we're unable to open generated .pkpass files and all we've done is generated a new Pass Type certificate from Apple. Has anyone else had any issues lately?

Signature error unter iOS 7

I'm seeing this error when I try to download and open a pkpass under iOS 7

Invalid data error reading pass pass.com.domain.discount/2500000.
The passTypeIdentifier or teamIdentifier provided may not match your certificate, or the certificate trust chain could not be verified.
Error adding pass The pass cannot be read because it isn’t valid.

However ,the passTypeIdentifier and teamIdentifier seem to be correct since everything works fine under iOS 6 and even Safari from Mavericks.

As far as I can tell, the only difference in the signing process with iOS 7 is that the signature needs to contain a signing date.

No method error on Heroku.

Hi,

I made a simple Sinatra app that uses this Gem. It runs fine on localhost, but when I deploy to Heroku I get the error NoMethodError - undefined method 'write_buffer' for Zip::ZipOutputStream:Class: which is being raised by the line /app/vendor/bundle/ruby/2.0.0/gems/passbook-0.2.1/lib/passbook/pkpass.rb:122:in outputZip.

Any idea what the cause of this could be?

I posted on StackOverflow with the same problem, more detailed description here

invalid option -w

pk build your_pass_name -w ./wwdc.pem -c ./your_pass_name.p12 -p ''

➜ repo git:(master) ✗ pk build mypass -w ./wwdc.pem -c ./mypass.p12 -p ''
invalid option: -w

notification_passphrase missing

Hy,

I'm creating a rails app with passbook.

Now i have problems with sending pushes for notification.
How i can set the notification_cert.pem - password to the passbook.rb?

I downloaded the version 0.4.1 of the passbook gem and it seems the Key ":notification_passphrase" in the line of the "mattr_accessor" in the passbook module is missing.

Is there another way to set the password?

Thanks for your help

NoMethodError: undefined method `pusher' for Grocer:Module

I'm setting up push notifications and I'm getting a no method error for Grocer when calling Passbook::PushNotification.send_notification

➜  wallet git:(62) ✗ rails c
Loading development environment (Rails 4.2.0)
irb: warn: can't alias context from irb_context.
2.2.0 :001 > Passbook::PushNotification.send_notification 'SNIP'
NoMethodError: undefined method `pusher' for Grocer:Module
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/passbook-0.4.1/lib/passbook/push_notification.rb:4:in `send_notification'
    from (irb):1
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/railties-4.2.0/lib/rails/commands/console.rb:110:in `start'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/railties-4.2.0/lib/rails/commands/console.rb:9:in `start'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:68:in `console'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/railties-4.2.0/lib/rails/commands.rb:17:in `<top (required)>'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `require'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `block in require'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `require'
    from /Users/jspooner/v/wallet/bin/rails:8:in `<top (required)>'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `block in load'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/spring-1.4.0/lib/spring/commands/rails.rb:6:in `call'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/spring-1.4.0/lib/spring/command_wrapper.rb:38:in `call'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/spring-1.4.0/lib/spring/application.rb:183:in `block in serve'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/spring-1.4.0/lib/spring/application.rb:156:in `fork'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/spring-1.4.0/lib/spring/application.rb:156:in `serve'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/spring-1.4.0/lib/spring/application.rb:131:in `block in run'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/spring-1.4.0/lib/spring/application.rb:125:in `loop'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/spring-1.4.0/lib/spring/application.rb:125:in `run'
    from /Users/jspooner/.rvm/gems/ruby-2.2.0/gems/spring-1.4.0/lib/spring/application/boot.rb:18:in `<top (required)>'
    from /Users/jspooner/.rvm/rubies/ruby-2.2.0/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /Users/jspooner/.rvm/rubies/ruby-2.2.0/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from -e:1:in `<main>'2.2.0 :002 > 

Safari cannot download this file

Hi,

I make my pass. It's work fine, and I can download it from my web browser. And the content of the pass is OK, manifest, signature, json... . But on IOS 6 Beta 3, Safari say Download Failed. Nothing in the console ...

Any idea ?

My json :

'{
"passTypeIdentifier": "pass.xxxx.yyyy",
"formatVersion": 1,
"organizationName": "Flight Express",
"serialNumber": "123456",
"teamIdentifier": "SAB5MVXXXX",
"backgroundColor": "rgb(107,156,196)",
"logoText": "Flight info",
"description": "Demo pass",
"boardingPass": {
"primaryFields": [
{
"key" : "origin",
"label" : "San Francisco",
"value" : "SFO"
},
{
"key" : "destination",
"label" : "London",
"value" : "LHR"
}
],
"secondaryFields": [
{
"key": "gate",
"label": "Gate",
"value": "F12"
},
{
"key": "date",
"label": "Departure date",
"value": "07/11/2012 10:22"
}

    ],
    "backFields": [
        {
            "key": "passenger-name",
            "label": "Passenger",
            "value": "John Appleseed"
        }
    ],
    "transitType" : "PKTransitTypeAir"
},
"barcode": {
    "format": "PKBarcodeFormatQR",
    "message": "Flight-GateF12-ID6643679AH7B",
    "messageEncoding": "iso-8859-1"
}

}'

I use ruby 1.9.3 and rails 3.2.6

sinatra with passbook has error....

in my rails web...
in Gemfile

gem 'passbook', :git => 'git://github.com/frozon/passbook.git'

and works well!

but sinatra... ( I'm beginner in sinatra app dev)

require 'passbook'
require 'active_support/json/encoding'

has error...

no such file to load -- passbook

How can I do fix it??? plz... help me...

stream vs temp

Pardon the newb question, but could you detail differences between your tempfile implementaiton vs stream and any impacts to the user experience?

Thanks

S

config/initializers/passbook.rb:9:in `block in <top (required)>': undefined method `p12_cert=' for Passbook:Module (NoMethodError)

Hello All,

I followed below steps:-

  1. Added gem in Gemfile and installed it.
  2. rails g passbook:config
  3. Passbook.configure do |passbook|
    passbook.wwdc_cert = Rails.root.join('my.pem')
    passbook.p12_certificate = Rails.root.join('my.p12')
    passbook.p12_password = 'my_password'
    end

Once I start server then facing below error:-

config/initializers/passbook.rb:9:in block in <top (required)>': undefined methodp12_cert=' for Passbook:Module (NoMethodError)

Thanks! in advance.

Anyone else having their expiration/relevant dates set to the day before the one you specify?

I'm setting my expiration dates in the required rfc3339 format using either:
DateTime.parse(Date.today.to_s).to_s
or
Date.today.strftime(""%Y-%m-%dT%H:%M:%S%:z"")

In the simulator and Safari on a mac, this is yielding correct results. But on an ios7 phone, It's subtracting 1 day from my date for the expiration date. I suspect this is a question for StackOverflow, but was hoping someone here might have seen this before.

Pass signing does not use WWDR cert

Hello,

As of the September 12th conference Apple has changed their pass signing to include the WWDR in the signing process. I have integrated your gem into my app and it works great (Thanks by the way ;) ) however I can not open them on a device because it is missing this part of the signature.

Problems with JRuby?

I hit problems using this Gem with latest JRuby 9.1.8.0 and latest JRuby-OpenSSL.

This monkey-patch may be useful - it addresses a bug in JRuby-OpenSSL (by explicitly passing pk7.data as a second argument to the write_smime method), as well as problems with str_debut and str_end being in a slightly different format in the JRuby output.

Hope its useful to someone :)

module Passbook
  class Signer

    # this works around a bug in JRuby-OpenSSL related to writing of SMIME,
    # as well as discrepancies in the SMIME output compared to what the 
    # passbook gem expects by default.
    
    def sign(data)
      wwdc  = OpenSSL::X509::Certificate.new File.read(wwdc_cert)
      pk7   = OpenSSL::PKCS7.sign key_hash[:cert], key_hash[:key], data.to_s, [wwdc], OpenSSL::PKCS7::BINARY | OpenSSL::PKCS7::DETACHED
      data  = OpenSSL::PKCS7.write_smime pk7, pk7.data

      str_debut = "filename=smime.p7s"
      data      = data[data.index(str_debut)+str_debut.length..data.length-1]
      str_end   = "\n------"
      data      = data[0..data.index(str_end)-1]

      Base64.decode64(data)
    end
  end
end

How to install?

Until this gem is on rubygems.org... I have tried in vain to install this but keep failing miserably. There is not even a .gem file, so I try to build the .gem myself by doing

gem build ~/Downloads/passbook-0.0.4/passbook.gemspec

But I get

ERROR: While executing gem ... (Gem::InvalidSpecificationException)
["LICENSE", "README.md"] are not files

Any ideas?

PKCS12_parse: unsupported error with Ruby 3.2

Ruby 3.2 includes OpenSSL 3. This causes issues signed Passbook passes using a p12 archive.

The fix is to extract the certificate and private key from your p12 file and pass those individually to the Passbook gem.

Passbook.configure do |passbook|
  passbook.wwdc_cert = Rails.root.join('config/apple/wwdr.pem')


  # no longer works in Ruby 3.2 / OpenSSL 3
  # passbook.p12_certificate = Rails.root.join('config/apple/whatever.p12')
  # passbook.p12_password = ''

  # this works in Ruby 3.2
  passbook.p12_certificate = Rails.root.join('config/apple/whatever.crt')
  passbook.p12_key = Rails.root.join('config/apple/whatever.key')
end

uninitialized constant Rack::PassbookRack (NameError)

Added config.middleware.use Rack::PassbookRack to application.rb and have gem 'passbook' in my gemfile. I have added all of my certs to the config file, and when I start the server I get the error message below.

/rails/test_project/config/application.rb:63:in class:Application': uninitialized constant Rack::PassbookRack (NameError)
from /rails/test_project/config/application.rb:13:in <module:TestProject>' from /rails/test_project/config/application.rb:12:in <top (required)>'
from /Users/jbadger/.rvm/gems/ruby-1.9.3-p362/gems/railties-3.2.12/lib/rails/commands.rb:53:in require' from /Users/jbadger/.rvm/gems/ruby-1.9.3-p362/gems/railties-3.2.12/lib/rails/commands.rb:53:in block in <top (required)>'
from /Users/jbadger/.rvm/gems/ruby-1.9.3-p362/gems/railties-3.2.12/lib/rails/commands.rb:50:in tap' from /Users/jbadger/.rvm/gems/ruby-1.9.3-p362/gems/railties-3.2.12/lib/rails/commands.rb:50:in <top (required)>'
from script/rails:6:in require' from script/rails:6:in

'`

The pass "pass.pkpass" could not be opened

I keep getting this error: The pass "pass.pkpass" could not be opened. Below's my code. I've re-done the cert process like 3 times. Not sure where it's failing because the package seems intact.

def show
   pass = Pass.find(params[:id])
   pass_path = ENV['passes_folder_path'] + "/passes/#{pass.id}"
   pass_json = File.read(pass_path + "/pass.json")
   pkpass = Passbook::PKPass.new pass_json
   files = []
   Dir.foreach(pass_path) do |file|
     next if file == '.' or file == '..' or file == '.DS_Store'
     files << file
   end
   pkpass.addFiles files
   send_data(pkpass, type: 'application/vnd.apple.pkpass', disposition: 'attachment', filename: 'pass.pkpass', status: 201, location: [:api, pass])
 end

Is there a step missing to make this work on a device?

Hi.

I can see the passbook on a Mac when visiting the URL, but when I try to send it to my phone or view the exact same URL on the phone it ays "Safari cannot download this file"?

Am I missing a configuration? I have all the assets and information (which properly display on a browser)

screen shot 2014-02-15 at 13 41 34

Thanks!

Encoding::UndefinedConversionError ("\x9F" from ASCII-8BIT to UTF-8):

Hi, I've got this error:

Encoding::UndefinedConversionError ("\x9F" from ASCII-8BIT to UTF-8):

passbook = Passbook::PKPass.new json passbook.addFiles [Rails.root.join('certificates/icon.png'), Rails.root.join('certificates/[email protected]')] gen_pass = passbook.file send_file(gen_pass.path, type: 'application/vnd.apple.pkpass', disposition: 'attachment', filename: "pass.pkpass")

What I do wrong?
Rais 6, ruby 2.7.1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.