simple_shipping 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.metrics +6 -0
  4. data/.rspec +4 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/.simplecov +43 -0
  8. data/Gemfile +26 -0
  9. data/Gemfile.lock +201 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.markdown +207 -0
  12. data/Rakefile +68 -0
  13. data/VERSION +1 -0
  14. data/coverage/.resultset.json +1579 -0
  15. data/lib/colorized_text.rb +34 -0
  16. data/lib/simple_shipping.rb +27 -0
  17. data/lib/simple_shipping/abstract.rb +11 -0
  18. data/lib/simple_shipping/abstract/builder.rb +47 -0
  19. data/lib/simple_shipping/abstract/client.rb +111 -0
  20. data/lib/simple_shipping/abstract/model.rb +40 -0
  21. data/lib/simple_shipping/abstract/request.rb +27 -0
  22. data/lib/simple_shipping/abstract/response.rb +26 -0
  23. data/lib/simple_shipping/address.rb +22 -0
  24. data/lib/simple_shipping/contact.rb +24 -0
  25. data/lib/simple_shipping/demo.rb +9 -0
  26. data/lib/simple_shipping/demo/base.rb +71 -0
  27. data/lib/simple_shipping/demo/fedex.rb +46 -0
  28. data/lib/simple_shipping/demo/ups.rb +68 -0
  29. data/lib/simple_shipping/exceptions.rb +40 -0
  30. data/lib/simple_shipping/fedex.rb +14 -0
  31. data/lib/simple_shipping/fedex/client.rb +41 -0
  32. data/lib/simple_shipping/fedex/package_builder.rb +24 -0
  33. data/lib/simple_shipping/fedex/party_builder.rb +50 -0
  34. data/lib/simple_shipping/fedex/request.rb +54 -0
  35. data/lib/simple_shipping/fedex/response.rb +5 -0
  36. data/lib/simple_shipping/fedex/shipment_builder.rb +123 -0
  37. data/lib/simple_shipping/fedex/shipment_request.rb +14 -0
  38. data/lib/simple_shipping/fedex/shipment_response.rb +12 -0
  39. data/lib/simple_shipping/package.rb +43 -0
  40. data/lib/simple_shipping/party.rb +21 -0
  41. data/lib/simple_shipping/shipment.rb +42 -0
  42. data/lib/simple_shipping/ups.rb +24 -0
  43. data/lib/simple_shipping/ups/client.rb +46 -0
  44. data/lib/simple_shipping/ups/package_builder.rb +101 -0
  45. data/lib/simple_shipping/ups/party_builder.rb +38 -0
  46. data/lib/simple_shipping/ups/request.rb +27 -0
  47. data/lib/simple_shipping/ups/response.rb +63 -0
  48. data/lib/simple_shipping/ups/ship_accept_request.rb +21 -0
  49. data/lib/simple_shipping/ups/ship_accept_response.rb +6 -0
  50. data/lib/simple_shipping/ups/ship_client.rb +70 -0
  51. data/lib/simple_shipping/ups/ship_confirm_request.rb +22 -0
  52. data/lib/simple_shipping/ups/ship_confirm_response.rb +6 -0
  53. data/lib/simple_shipping/ups/shipment_builder.rb +66 -0
  54. data/lib/simple_shipping/ups/shipment_request.rb +22 -0
  55. data/lib/simple_shipping/ups/shipment_response.rb +6 -0
  56. data/lib/simple_shipping/ups/void_client.rb +50 -0
  57. data/lib/simple_shipping/ups/void_request.rb +42 -0
  58. data/lib/simple_shipping/ups/void_response.rb +6 -0
  59. data/lib/tasks/demo.rake +58 -0
  60. data/script/ups_certification.rb +140 -0
  61. data/simple_shipping.gemspec +168 -0
  62. data/spec/fixtures/fedex_shipment_request.soap.xml.erb +85 -0
  63. data/spec/fixtures/fedex_shipment_response.soap.xml.erb +182 -0
  64. data/spec/fixtures/ups_shipment_request.soap.xml.erb +88 -0
  65. data/spec/fixtures/ups_shipment_response.soap.xml.erb +58 -0
  66. data/spec/fixtures/ups_shipment_response_with_faked_label_data.soap.xml.erb +54 -0
  67. data/spec/fixtures/ups_void_request.soap.xml.erb +29 -0
  68. data/spec/fixtures/ups_void_response.soap.xml.erb +21 -0
  69. data/spec/lib/simple_shipping/address_spec.rb +19 -0
  70. data/spec/lib/simple_shipping/contact_spec.rb +28 -0
  71. data/spec/lib/simple_shipping/exceptions_spec.rb +58 -0
  72. data/spec/lib/simple_shipping/fedex/package_builder_spec.rb +5 -0
  73. data/spec/lib/simple_shipping/fedex/party_builder_spec.rb +5 -0
  74. data/spec/lib/simple_shipping/fedex/response/shipment_reponse_spec.rb +5 -0
  75. data/spec/lib/simple_shipping/fedex/response_spec.rb +5 -0
  76. data/spec/lib/simple_shipping/fedex/shipment_builder_spec.rb +23 -0
  77. data/spec/lib/simple_shipping/package_spec.rb +32 -0
  78. data/spec/lib/simple_shipping/party_spec.rb +18 -0
  79. data/spec/lib/simple_shipping/shipment_spec.rb +35 -0
  80. data/spec/lib/simple_shipping/ups/package_builder_spec.rb +26 -0
  81. data/spec/lib/simple_shipping/ups/party_builder_spec.rb +47 -0
  82. data/spec/lib/simple_shipping/ups/response/shipment_response_spec.rb +5 -0
  83. data/spec/lib/simple_shipping/ups/response_spec.rb +33 -0
  84. data/spec/lib/simple_shipping/ups/shipment_builder_spec.rb +19 -0
  85. data/spec/requests/fedex_spec.rb +47 -0
  86. data/spec/requests/ups_spec.rb +75 -0
  87. data/spec/spec_helper.rb +47 -0
  88. data/spec/support/custom_matchers/basic_matcher.rb +13 -0
  89. data/spec/support/custom_matchers/have_attribute_matcher.rb +22 -0
  90. data/spec/support/custom_matchers/have_default_value_matcher.rb +26 -0
  91. data/spec/support/custom_matchers/have_errors_on_matcher.rb +23 -0
  92. data/spec/support/custom_matchers/validate_inclusion_of_matcher.rb +37 -0
  93. data/spec/support/custom_matchers/validate_presence_of_matcher.rb +24 -0
  94. data/spec/support/custom_matchers/validate_submodel_matcher.rb +44 -0
  95. data/spec/support/shared_behaviours/builders_behaviour.rb +9 -0
  96. data/spec/support/shared_behaviours/responses_behaviour.rb +10 -0
  97. data/tmp/metric_fu/_data/20131210.yml +9964 -0
  98. data/wsdl/fedex/ship_service_v10.wsdl +5566 -0
  99. data/wsdl/ups/Ship.wsdl +120 -0
  100. data/wsdl/ups/Void.wsdl +58 -0
  101. metadata +308 -0
@@ -0,0 +1,21 @@
1
+ module SimpleShipping::Ups
2
+ # Shipping accept request.
3
+ class ShipAcceptRequest < Request
4
+ def initialize(credentials, shipment_digest, options = {})
5
+ @credentials = credentials
6
+ @shipment_digest = shipment_digest
7
+ @options = options
8
+ @type = :prcoess_ship_accept
9
+ end
10
+
11
+ # :nodoc:
12
+ def body
13
+ { 'common:Request' => {
14
+ 'common:RequestOption' => REQUEST_OPTION
15
+ },
16
+ 'ShipmentDigest' => @shipment_digest,
17
+ :order! => ['common:Request', 'ShipmentDigest']
18
+ }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,6 @@
1
+ # A wrapper for UPS response
2
+ module SimpleShipping::Ups
3
+ # Response to {ShipAcceptRequest}.
4
+ class ShipAcceptResponse < Response
5
+ end
6
+ end
@@ -0,0 +1,70 @@
1
+ module SimpleShipping::Ups
2
+ # Required credentials:
3
+ # * _username_
4
+ # * _password_
5
+ # * _access_license_number_
6
+ #
7
+ # = Usage
8
+ # client = SimpleShipping::Ups::ShipClient.new(:username => "USER NAME",
9
+ # :password => "PASSWORD",
10
+ # :access_license_number => "LICENSE NUMBER")
11
+ # client.request(shipper, recipient, package) # => #<SimpleShipping::Ups::Response ...>
12
+ class ShipClient < Client
13
+ set_required_credentials :username, :password, :access_license_number
14
+
15
+ set_wsdl_document File.join(SimpleShipping::WSDL_DIR, "ups/Ship.wsdl")
16
+ set_production_address "https://onlinetools.ups.com/webservices/Ship"
17
+ set_testing_address "https://wwwcie.ups.com/webservices/Ship"
18
+
19
+ # @param shipper [::SimpleShipping::Party]
20
+ # @param recipient [::SimpleShipping::Party]
21
+ # @param package [::SimpleShipping::Package]
22
+ # @param options [Hash] ({})
23
+ #
24
+ # @return [::SimpleShipping::ShipmentResponse]
25
+ #
26
+ # @raise [::SimpleShipping::RequestError] in case of SOAP errors
27
+ def shipment_request(shipper, recipient, package, options = {})
28
+ shipment = create_shipment(shipper, recipient, package, options)
29
+ request = ShipmentRequest.new(@credentials, shipment, options)
30
+ execute(request)
31
+ end
32
+
33
+ # Send shipment confirmation request.
34
+ def ship_confirm_request(shipper, recipient, package, options = {})
35
+ shipment = create_shipment(shipper, recipient, package, options)
36
+ request = ShipConfirmRequest.new(@credentials, shipment, options)
37
+ execute(request)
38
+ end
39
+
40
+
41
+ # Perform shipping accept request.
42
+ def ship_accept_request(shipment_digest, options = {})
43
+ request = ShipAcceptRequest.new(@credentials, shipment_digest, options)
44
+ execute(request)
45
+ end
46
+
47
+ # @param [Hash] options Savon client options
48
+ def client_options(options = {})
49
+ super.deep_merge(
50
+ :namespaces => {
51
+ # Savon parses have WSDL instead of XMLSchema which is not accepted by UPS
52
+ # So we have to again set namespace explicitly :( -- aignatev 20130204
53
+ 'xmlns:ship' => "http://www.ups.com/XMLSchema/XOLTWS/Ship/v1.0"
54
+ }
55
+ )
56
+ end
57
+ protected :client_options
58
+
59
+
60
+ # Perform ShipmentRequest to UPS service.
61
+ def execute(request)
62
+ savon_response = @client.call(request.type, :message => request.body)
63
+ log_response(savon_response)
64
+ request.response(savon_response)
65
+ rescue Savon::SOAPFault => e
66
+ raise SimpleShipping::RequestError.new(e)
67
+ end
68
+ private :execute
69
+ end
70
+ end
@@ -0,0 +1,22 @@
1
+ module SimpleShipping::Ups
2
+ # Request to verify a shipment was delivered.
3
+ class ShipConfirmRequest < Request
4
+ def initialize(credentials, shipment, options = {})
5
+ @credentials = credentials
6
+ @shipment = shipment
7
+ @options = options
8
+ @type = :process_ship_confirm
9
+ end
10
+
11
+ # Builds a request from {Shipment shipment} object.
12
+ def body
13
+ { 'common:Request' => {
14
+ 'common:RequestOption' => REQUEST_OPTION
15
+ },
16
+ 'Shipment' => ShipmentBuilder.build(@shipment, @options),
17
+ 'LabelSpecification' => label_specification,
18
+ :order! => ['common:Request', 'Shipment', 'LabelSpecification']
19
+ }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,6 @@
1
+ # A wrapper for a UPS response.
2
+ module SimpleShipping::Ups
3
+ # Response to {ShipConfirmResponse}.
4
+ class ShipConfirmResponse < Response
5
+ end
6
+ end
@@ -0,0 +1,66 @@
1
+ module SimpleShipping::Ups
2
+ # Builds shipment element for UPS SOAP service.
3
+ class ShipmentBuilder < SimpleShipping::Abstract::Builder
4
+ # The type of payment for this shipment.
5
+ PAYMENT_TYPE = '01' # 01 - Transportation, 02 - Duties and Taxes
6
+
7
+ # Service codes in UPS terminology.
8
+ SERVICE_TYPES = {:next_day_air => '01',
9
+ :second_day_air => '02',
10
+ :ground => '03',
11
+ :express => '07',
12
+ :expedited => '08',
13
+ :standard => '11',
14
+ :three_day_select => '12',
15
+ :next_day_air_saver => '13',
16
+ :next_day_air_early_am => '14',
17
+ :express_plus => '54',
18
+ :second_day_air_am => '59',
19
+ :saver => '65',
20
+ :today_standard => '82',
21
+ :today_dedicated_courier => '83',
22
+ :today_intercity => '84',
23
+ :today_express => '85',
24
+ :today_express_saver => '86'}
25
+
26
+ set_default_opts :service_type => :second_day_air
27
+
28
+ # Return a hash for Savon representing a shipment model.
29
+ def build
30
+ { 'Shipper' => PartyBuilder.build(@model.shipper, :shipper => true),
31
+ 'ShipTo' => PartyBuilder.build(@model.recipient),
32
+ 'PaymentInformation' => build_payment_info,
33
+ 'Service' => build_service,
34
+ 'Package' => PackageBuilder.build(@model.package),
35
+ :order! => ['Shipper', 'ShipTo', 'PaymentInformation', 'Service', 'Package'] }
36
+ end
37
+
38
+ # Return the PaymentInformation hash.
39
+ def build_payment_info
40
+ {'ShipmentCharge' => build_shipment_charge }
41
+ end
42
+
43
+ # Return the shipment charge for the PaymentInformation hash.
44
+ def build_shipment_charge
45
+ result = {'Type' => PAYMENT_TYPE, :order! => ['Type']}
46
+ if @model.payor == :shipper
47
+ result['BillShipper'] = {'AccountNumber' => @model.shipper.account_number}
48
+ result[:order!] << 'BillShipper'
49
+ else
50
+ result['BillReceiver'] = {'AccountNumber' => @model.recipient.account_number}
51
+ result[:order!] << 'BillReceiver'
52
+ end
53
+ result
54
+ end
55
+
56
+ # Return the hash representing the Service.
57
+ def build_service
58
+ {'Code' => SERVICE_TYPES[@opts[:service_type]]}
59
+ end
60
+
61
+ # Validate that the service type is included.
62
+ def validate
63
+ validate_inclusion_of(:service_type, SERVICE_TYPES)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,22 @@
1
+ module SimpleShipping::Ups
2
+ # Shipment request model.
3
+ class ShipmentRequest < Request
4
+ def initialize(credentials, shipment, options = {})
5
+ @credentials = credentials
6
+ @shipment = shipment
7
+ @options = options
8
+ @type = :process_shipment
9
+ end
10
+
11
+ # Builds a request from {Shipment shipment} object.
12
+ def body
13
+ { 'common:Request' => {
14
+ 'common:RequestOption' => REQUEST_OPTION
15
+ },
16
+ 'Shipment' => ShipmentBuilder.build(@shipment, @options),
17
+ 'LabelSpecification' => label_specification,
18
+ :order! => ['common:Request', 'Shipment', 'LabelSpecification']
19
+ }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,6 @@
1
+ # A wrapper for a UPS ShipmentResponse.
2
+ module SimpleShipping::Ups
3
+ # Response to ShipmentRequest.
4
+ class ShipmentResponse < Response
5
+ end
6
+ end
@@ -0,0 +1,50 @@
1
+ module SimpleShipping::Ups
2
+ # Required credentials:
3
+ # * _username_
4
+ # * _password_
5
+ # * _access_license_number_
6
+ #
7
+ # = Usage
8
+ # client = SimpleShipping::Ups::VoidClient.new(:username => "USER NAME",
9
+ # :password => "PASSWORD",
10
+ # :access_license_number => "LICENSE NUMBER")
11
+ # client.request(shipper, recipient, package) # => #<SimpleShipping::Ups::Response ...>
12
+ class VoidClient < Client
13
+ set_required_credentials :username, :password, :access_license_number
14
+
15
+ set_wsdl_document File.join(SimpleShipping::WSDL_DIR, "ups/Void.wsdl")
16
+ set_production_address "https://onlinetools.ups.com/webservices/Void"
17
+ set_testing_address "https://wwwcie.ups.com/webservices/Void"
18
+
19
+ # Build VoidRequest and perform the request.
20
+ #
21
+ # @param shipment_identification_number [String]
22
+ # @param options [Hash]
23
+ def void_request(shipment_identification_number, options = {})
24
+ request = VoidRequest.new(@credentials, shipment_identification_number, options)
25
+ execute(request)
26
+ end
27
+
28
+ # @param [Hash] options Savon client options
29
+ def client_options(options = {})
30
+ super.deep_merge(
31
+ :namespaces => {
32
+ # Savon parses have WSDL instead of XMLSchema which is not accepted by UPS
33
+ # So we have to again set namespace explicitly :( -- aignatev 20130204
34
+ 'xmlns:void' => "http://www.ups.com/XMLSchema/XOLTWS/Void/v1.1"
35
+ }
36
+ )
37
+ end
38
+ protected :client_options
39
+
40
+ # Perform ShipmentRequest to UPS service.
41
+ def execute(request)
42
+ savon_response = @client.call(request.type, :message => request.body)
43
+ log_response(savon_response)
44
+ request.response(savon_response)
45
+ rescue Savon::SOAPFault => err
46
+ raise SimpleShipping::RequestError.new(err)
47
+ end
48
+ private :execute
49
+ end
50
+ end
@@ -0,0 +1,42 @@
1
+ module SimpleShipping::Ups
2
+ # UPS request to void shipment.
3
+ class VoidRequest < Request
4
+
5
+ # @param credentials [Hash]
6
+ # @param shipment_identification_number [String]
7
+ # @param options [Hash]
8
+ def initialize(credentials, shipment_identification_number, options = {})
9
+ @credentials = credentials
10
+ @shipment_identification_number = shipment_identification_number
11
+ @tracking_number = options[:tracking_number]
12
+ @options = options
13
+ @type = :process_void
14
+ end
15
+
16
+ # Build a request from a {Shipment shipment} object.
17
+ def body
18
+ {
19
+ 'common:Request' => {
20
+ 'common:RequestOption' => REQUEST_OPTION
21
+ },
22
+ 'VoidShipment' => void_shipment,
23
+ :order! => ['common:Request', 'VoidShipment']
24
+ }
25
+ end
26
+
27
+ # Data for VoidShipment.
28
+ #
29
+ # @return [Hash]
30
+ def void_shipment
31
+ data = { 'ShipmentIdentificationNumber' => @shipment_identification_number }
32
+
33
+ if @tracking_number
34
+ data['TrackingNumber'] = @tracking_number
35
+ data[:order!] = ['ShipmentIdentificationNumber', 'TrackingNumber']
36
+ end
37
+
38
+ data
39
+ end
40
+ private :void_shipment
41
+ end
42
+ end
@@ -0,0 +1,6 @@
1
+ # A wrapper for a UPS response.
2
+ module SimpleShipping::Ups
3
+ # Response to VoidRequest.
4
+ class VoidResponse < Response
5
+ end
6
+ end
@@ -0,0 +1,58 @@
1
+ namespace :demo do
2
+ task :environment do
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ Bundler.require
6
+
7
+ $LOAD_PATH.unshift File.expand_path('../../', __FILE__)
8
+
9
+ require 'simple_shipping'
10
+ require 'RMagick'
11
+ end
12
+
13
+
14
+ namespace :fedex do
15
+ desc 'Call real FedEx API with shipment_request'
16
+ task :shipment_request, [:credentials_file, :output_filename] => :environment do |task, args|
17
+ args.with_defaults(:output_filename => File.join(Dir.tmpdir, 'fedex_shipment_request_output.png'))
18
+
19
+ credentials = YAML.load_file(args[:credentials_file])['fedex'].symbolize_keys!
20
+
21
+ demo = SimpleShipping::Demo::Fedex.new(credentials)
22
+ resp = demo.shipment_request
23
+ img = Magick::Image.read_inline(resp.label_image_base64).first
24
+
25
+ img.write(args[:output_filename])
26
+ puts "Label received. #{args[:output_filename]} written"
27
+ end
28
+ end
29
+
30
+ namespace :ups do
31
+ desc 'Call real UPS API with shipment_request'
32
+ task :shipment_request, [:credentials_file, :output_filename] => :environment do |task, args|
33
+ args.with_defaults(:output_filename => File.join(Dir.tmpdir, 'ups_shipment_request_output.png'))
34
+
35
+ credentials = YAML.load_file(args[:credentials_file])['ups'].symbolize_keys!
36
+
37
+ demo = SimpleShipping::Demo::Ups.new(credentials)
38
+
39
+ resp = demo.shipment_request
40
+ img = Magick::Image.read_inline(resp.label_image_base64).first
41
+
42
+ img.write(args[:output_filename])
43
+ puts "Label received. #{args[:output_filename]} written"
44
+ end
45
+
46
+ desc 'Call real UPS API with void_request'
47
+ task :void_request, [:credentials_file] => :environment do |task, args|
48
+ credentials = YAML.load_file(args[:credentials_file])['ups'].symbolize_keys!
49
+ demo = SimpleShipping::Demo::Ups.new(credentials)
50
+
51
+ begin
52
+ resp = demo.void_request
53
+ rescue SimpleShipping::RequestError => exc
54
+ raise exc unless exc.message =~ /No shipment found within the allowed void period/
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
+
5
+ require 'rubygems'
6
+ require 'simple_shipping'
7
+ require 'simple_shipping/ups'
8
+ require 'RMagick'
9
+ require 'fileutils'
10
+ require 'forgery'
11
+ require 'yaml'
12
+
13
+ package_path_base = File.expand_path('../ups_certification_package/', __FILE__)
14
+ FileUtils.rm_rf(package_path_base) if File.directory?(package_path_base)
15
+
16
+ # YAML file with credentials
17
+ unless credentials_file = ARGV.pop
18
+ abort "Usage:\n #{$0} <PATH_TO_CREDENTIALS.yml>"
19
+ end
20
+
21
+ CREDENTIALS = YAML.load_file(credentials_file )['ups'].symbolize_keys!
22
+ ACCOUNT_NUMBER = CREDENTIALS.delete(:account_number)
23
+
24
+ 5.times do |iteration|
25
+ package_path = File.join(package_path_base, iteration.to_s)
26
+ FileUtils.mkdir_p(package_path)
27
+
28
+ shipper_address = SimpleShipping::Address.new(
29
+ :country_code => 'US',
30
+ :state_code => 'IL',
31
+ :postal_code => '60201',
32
+ :city => Forgery::Address.city,
33
+ :street_line => Forgery::Address.street_address
34
+ )
35
+ shipper_contact = SimpleShipping::Contact.new(
36
+ :person_name => Forgery::Name.full_name,
37
+ :phone_number => Forgery::Address.phone
38
+ )
39
+ shipper = SimpleShipping::Party.new(
40
+ :address => shipper_address,
41
+ :contact => shipper_contact,
42
+ :account_number => ACCOUNT_NUMBER
43
+ )
44
+ recipient_address = SimpleShipping::Address.new(
45
+ :country_code => 'US',
46
+ :state_code => 'SC',
47
+ :postal_code => '29072',
48
+ :city => Forgery::Address.city,
49
+ :street_line => Forgery::Address.street_address
50
+ )
51
+ recipient_contact = SimpleShipping::Contact.new(
52
+ :person_name => Forgery::Name.full_name,
53
+ :phone_number => Forgery::Address.phone
54
+ )
55
+ recipient = SimpleShipping::Party.new(
56
+ :address => recipient_address,
57
+ :contact => recipient_contact
58
+ )
59
+ package = SimpleShipping::Package.new(
60
+ :weight => 0.5,
61
+ :packaging_type => :envelope,
62
+ :insured_value => iteration * 250.0,
63
+ :declared_value => iteration * 250.0
64
+ )
65
+
66
+ confirm_path = File.join(package_path, "confirm")
67
+ FileUtils.mkdir_p(confirm_path)
68
+
69
+ confirm_client = SimpleShipping::Ups::ShipClient.new(
70
+ :debug => true,
71
+ :debug_path => confirm_path,
72
+ :credentials => CREDENTIALS
73
+ )
74
+
75
+ puts "CONFIRM REQUEST #{iteration}"
76
+ confirm = confirm_client.ship_confirm_request(shipper, recipient, package)
77
+
78
+ accept_path = File.join(package_path, "accept")
79
+ FileUtils.mkdir_p(accept_path)
80
+ accept_client = SimpleShipping::Ups::ShipClient.new(
81
+ :debug => true,
82
+ :debug_path => accept_path,
83
+ :credentials => CREDENTIALS
84
+ )
85
+
86
+ puts "ACCEPT REQUEST #{iteration}"
87
+ accept = accept_client.ship_accept_request(confirm.digest)
88
+
89
+ puts "SAVING LABEL HTML"
90
+ File.open(File.join(package_path, "label.html"), "w") {|f| f.write accept.label_html}
91
+
92
+ puts "SAVING LABEL GIF"
93
+ image_name = "label#{accept.tracking_number}.gif"
94
+ img = Magick::Image.read_inline(accept.label_image_base64).first
95
+ img.write(File.join(package_path, image_name))
96
+
97
+
98
+ # Apparently, the HTML version is OK:
99
+ # http://www.corecommerce.com/kb/328/ups_label_certification_requiring_39th_file
100
+ if accept.receipt_html
101
+ puts "SAVING HIGH VALUE REPORT HTML"
102
+ File.open(File.join(package_path, "high_value_report.html"), "w") {|f| f.write accept.receipt_html}
103
+ end
104
+ end
105
+
106
+ VOID_NUMBERS = [
107
+ # A successful XML response will be returned for a shipment level void request.
108
+ ['1ZISDE016691676846'],
109
+ # A successful XML response will be returned for a shipment level void request.
110
+ ['1Z2220060290602143'],
111
+ # A successful XML response will be returned for a package level void request. The request will void the package in the shipment.
112
+ ['1Z2220060294314162', '1Z2220060291994175'],
113
+ # A successful XML response will be returned for a package level void request. The request will void the package in the shipment. .
114
+ ['1Z2220060292690189', '1Z2220060292002190'],
115
+
116
+ # Multiple tracking numbers for each shipment identifier. These don't seem to
117
+ # work, but implementing them is unnecessary.
118
+
119
+ # A successful XML response will be returned for a package level void request. The request will void all the packages.
120
+ # ['1ZISDE016691609089', '1ZISDE016694068891'],
121
+ # A successful XML response will be returned for a package level void request. The request will void all the packages.
122
+ # ['1ZISDE016691609089', '1ZISDE016690889305'],
123
+ # A successful XML response will be returned with a partial void for a package level void request. The request will void package 1Z2220060293874210 but package 1Z2220060292634221 cannot be voided.
124
+ # ['1Z2220060290530202', '1Z2220060293874210'],
125
+ # A successful XML response will be returned with a partial void for a package level void request. The request will void package 1Z2220060293874210 but package 1Z2220060292634221 cannot be voided.
126
+ # ['1Z2220060290530202', '1Z2220060292634221']
127
+ ]
128
+
129
+ VOID_NUMBERS.each do |identifier, tracking_number|
130
+ package_path = File.join(package_path_base, "void/#{identifier}")
131
+ FileUtils.mkdir_p(package_path)
132
+
133
+ void_client = SimpleShipping::Ups::VoidClient.new(
134
+ :debug => true,
135
+ :debug_path => package_path,
136
+ :credentials => CREDENTIALS
137
+ )
138
+ puts "VOID REQUEST: #{identifier}"
139
+ void_client.void_request(identifier, :tracking_number => tracking_number)
140
+ end