express-checkout 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e016efaa655a370f36a5480ef0b65c28590c576d
4
- data.tar.gz: 6c4e0e630d86d54107877f0c9274068f34108091
3
+ metadata.gz: c7019fc3b0f27e0ba38c68edff4bc4c07d87f3c1
4
+ data.tar.gz: 77fc1279c58d5373b98d5c36944f51821899073f
5
5
  SHA512:
6
- metadata.gz: 69da75217e4720eecc22b99d0f2999f42912f27a332e66233a3f1ad0d07d1070579cad3f9ba3d9b04f8b3c35ed56c466bfe5355bc47af0bfe45e59bb04dfe53e
7
- data.tar.gz: 4408c17eac1331e66895b369ac241eaef7b14829fdad914f070cc09dd0f2a1f6ea9be460b1da29a8e6b108a3cd8df3551f399d14ef9e237241b59b07f8666dc8
6
+ metadata.gz: be6b78d98106f7a75282cc47c4534dd6ec03682b7a267e8dc9ff8b44d10a0201b85089e52cc324410ce061b4ad47269b0f56b37bc09909687334acd1f9c0105c
7
+ data.tar.gz: 4f799585716cfedf9eb60b7443b820880927896db20579e225cb8d51f8b0e29fc60e47112ab6b64c54e21e7b9c99d042026d029e7811800da3792db4f6ebd0d0
@@ -1,11 +1,11 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'express/checkout/version'
4
+ require 'express/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "express-checkout"
8
- spec.version = Express::Checkout::VERSION
8
+ spec.version = Express::VERSION
9
9
  spec.authors = ["Wei-Yi Chiu"]
10
10
  spec.email = ["bird1204@gmail.com"]
11
11
 
@@ -27,6 +27,12 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
29
 
30
+ spec.add_dependency "activesupport", ">= 2.3"
31
+ spec.add_dependency "rest-client"
32
+ spec.add_dependency "attr_required", ">= 0.0.5"
30
33
  spec.add_development_dependency "bundler", "~> 1.9"
31
- spec.add_development_dependency "rake", "~> 10.0"
34
+ spec.add_development_dependency "rake", ">= 0.8"
35
+ spec.add_development_dependency "simplecov"
36
+ spec.add_development_dependency "rspec", "< 2.99"
37
+ spec.add_development_dependency "fakeweb", ">= 1.3.0"
32
38
  end
data/lib/express.rb ADDED
@@ -0,0 +1,85 @@
1
+ require 'express/checkout/version'
2
+ require 'logger'
3
+ require 'active_support'
4
+ require 'active_support/core_ext'
5
+ require 'attr_required'
6
+ require 'attr_optional'
7
+ require 'rest_client'
8
+
9
+ module Express
10
+ mattr_accessor :api_version
11
+ self.api_version = '88.0'
12
+
13
+ ENDPOINT = {
14
+ production: 'https://www.paypal.com/cgi-bin/webscr',
15
+ sandbox: 'https://www.sandbox.paypal.com/cgi-bin/webscr'
16
+ }
17
+ POPUP_ENDPOINT = {
18
+ production: 'https://www.paypal.com/incontext',
19
+ sandbox: 'https://www.sandbox.paypal.com/incontext'
20
+ }
21
+
22
+ def self.endpoint
23
+ if sandbox?
24
+ Paypal::ENDPOINT[:sandbox]
25
+ else
26
+ Paypal::ENDPOINT[:production]
27
+ end
28
+ end
29
+ def self.popup_endpoint
30
+ if sandbox?
31
+ Paypal::POPUP_ENDPOINT[:sandbox]
32
+ else
33
+ Paypal::POPUP_ENDPOINT[:production]
34
+ end
35
+ end
36
+
37
+ def self.log(message, mode = :info)
38
+ logger.send mode, message
39
+ end
40
+ def self.logger
41
+ @@logger
42
+ end
43
+ def self.logger=(logger)
44
+ @@logger = logger
45
+ end
46
+
47
+ @@logger = Logger.new(STDERR)
48
+ @@logger.progname = 'Express::Checkout'
49
+
50
+ def self.sandbox?
51
+ @@sandbox
52
+ end
53
+ def self.sandbox!
54
+ self.sandbox = true
55
+ end
56
+ def self.sandbox=(boolean)
57
+ @@sandbox = boolean
58
+ end
59
+ self.sandbox = false
60
+ end
61
+
62
+ require 'paypal/util'
63
+ require 'paypal/exception'
64
+ require 'paypal/exception/http_error'
65
+ require 'paypal/exception/api_error'
66
+ require 'paypal/base'
67
+ require 'paypal/ipn'
68
+ require 'paypal/nvp/request'
69
+ require 'paypal/nvp/response'
70
+ require 'paypal/payment/common/amount'
71
+ require 'paypal/express/request'
72
+ require 'paypal/express/response'
73
+ require 'paypal/payment/request'
74
+ require 'paypal/payment/request/item'
75
+ require 'paypal/payment/response'
76
+ require 'paypal/payment/response/info'
77
+ require 'paypal/payment/response/item'
78
+ require 'paypal/payment/response/payer'
79
+ require 'paypal/payment/response/reference'
80
+ require 'paypal/payment/response/refund'
81
+ require 'paypal/payment/response/address'
82
+ require 'paypal/payment/recurring'
83
+ require 'paypal/payment/recurring/activation'
84
+ require 'paypal/payment/recurring/billing'
85
+ require 'paypal/payment/recurring/summary'
@@ -0,0 +1,19 @@
1
+ module Express
2
+ class Base
3
+ include AttrRequired, AttrOptional, Util
4
+
5
+ def initialize(attributes = {})
6
+ if attributes.is_a?(Hash)
7
+ (required_attributes + optional_attributes).each do |key|
8
+ value = if numeric_attribute?(key)
9
+ Util.to_numeric(attributes[key])
10
+ else
11
+ attributes[key]
12
+ end
13
+ send "#{key}=", value
14
+ end
15
+ end
16
+ attr_missing!
17
+ end
18
+ end
19
+ end
@@ -1,7 +1 @@
1
- require "express/checkout/version"
2
-
3
- module Express
4
- module Checkout
5
- # Your code goes here...
6
- end
7
- end
1
+ require 'paypal'
@@ -0,0 +1,194 @@
1
+ module Express
2
+ module Checkout
3
+ class Request < NVP::Request
4
+
5
+ # Common
6
+
7
+ def setup(payment_requests, return_url, cancel_url, options = {})
8
+ params = {
9
+ :RETURNURL => return_url,
10
+ :CANCELURL => cancel_url
11
+ }
12
+ if options[:no_shipping]
13
+ params[:REQCONFIRMSHIPPING] = 0
14
+ params[:NOSHIPPING] = 1
15
+ end
16
+
17
+ params[:ALLOWNOTE] = 0 if options[:allow_note] == false
18
+
19
+ {
20
+ :solution_type => :SOLUTIONTYPE,
21
+ :landing_page => :LANDINGPAGE,
22
+ :email => :EMAIL,
23
+ :brand => :BRANDNAME,
24
+ :locale => :LOCALECODE,
25
+ :logo => :LOGOIMG,
26
+ :cart_border_color => :CARTBORDERCOLOR,
27
+ :payflow_color => :PAYFLOWCOLOR
28
+ }.each do |option_key, param_key|
29
+ params[param_key] = options[option_key] if options[option_key]
30
+ end
31
+ Array(payment_requests).each_with_index do |payment_request, index|
32
+ params.merge! payment_request.to_params(index)
33
+ end
34
+ response = self.request :SetExpressCheckout, params
35
+ Response.new response, options
36
+ end
37
+
38
+ def details(token)
39
+ response = self.request :GetExpressCheckoutDetails, {:TOKEN => token}
40
+ Response.new response
41
+ end
42
+
43
+ def transaction_details(transaction_id)
44
+ response = self.request :GetTransactionDetails, {:TRANSACTIONID=> transaction_id}
45
+ Response.new response
46
+ end
47
+
48
+ def checkout!(token, payer_id, payment_requests)
49
+ params = {
50
+ :TOKEN => token,
51
+ :PAYERID => payer_id
52
+ }
53
+ Array(payment_requests).each_with_index do |payment_request, index|
54
+ params.merge! payment_request.to_params(index)
55
+ end
56
+ response = self.request :DoExpressCheckoutPayment, params
57
+ Response.new response
58
+ end
59
+
60
+ def capture!(authorization_id, amount, currency_code, complete_type = 'Complete')
61
+ params = {
62
+ :AUTHORIZATIONID => authorization_id,
63
+ :COMPLETETYPE => complete_type,
64
+ :AMT => amount,
65
+ :CURRENCYCODE => currency_code
66
+ }
67
+
68
+ response = self.request :DoCapture, params
69
+ Response.new response
70
+ end
71
+
72
+ def void!(authorization_id, params={})
73
+ params = {
74
+ :AUTHORIZATIONID => authorization_id,
75
+ :NOTE => params[:note]
76
+ }
77
+
78
+ response = self.request :DoVoid, params
79
+ Response.new response
80
+ end
81
+
82
+ # Recurring Payment Specific
83
+
84
+ def subscribe!(token, recurring_profile)
85
+ params = {
86
+ :TOKEN => token
87
+ }
88
+ params.merge! recurring_profile.to_params
89
+ response = self.request :CreateRecurringPaymentsProfile, params
90
+ Response.new response
91
+ end
92
+
93
+ def subscription(profile_id)
94
+ params = {
95
+ :PROFILEID => profile_id
96
+ }
97
+ response = self.request :GetRecurringPaymentsProfileDetails, params
98
+ Response.new response
99
+ end
100
+
101
+ def renew!(profile_id, action, options = {})
102
+ params = {
103
+ :PROFILEID => profile_id,
104
+ :ACTION => action
105
+ }
106
+ if options[:note]
107
+ params[:NOTE] = options[:note]
108
+ end
109
+ response = self.request :ManageRecurringPaymentsProfileStatus, params
110
+ Response.new response
111
+ end
112
+
113
+ def suspend!(profile_id, options = {})
114
+ renew!(profile_id, :Suspend, options)
115
+ end
116
+
117
+ def cancel!(profile_id, options = {})
118
+ renew!(profile_id, :Cancel, options)
119
+ end
120
+
121
+ def reactivate!(profile_id, options = {})
122
+ renew!(profile_id, :Reactivate, options)
123
+ end
124
+
125
+
126
+ # Reference Transaction Specific
127
+
128
+ def agree!(token, options = {})
129
+ params = {
130
+ :TOKEN => token
131
+ }
132
+ if options[:max_amount]
133
+ params[:MAXAMT] = Util.formatted_amount options[:max_amount]
134
+ end
135
+ response = self.request :CreateBillingAgreement, params
136
+ Response.new response
137
+ end
138
+
139
+ def agreement(reference_id)
140
+ params = {
141
+ :REFERENCEID => reference_id
142
+ }
143
+ response = self.request :BillAgreementUpdate, params
144
+ Response.new response
145
+ end
146
+
147
+ def charge!(reference_id, amount, options = {})
148
+ params = {
149
+ :REFERENCEID => reference_id,
150
+ :AMT => Util.formatted_amount(amount),
151
+ :PAYMENTACTION => options[:payment_action] || :Sale
152
+ }
153
+ if options[:currency_code]
154
+ params[:CURRENCYCODE] = options[:currency_code]
155
+ end
156
+ response = self.request :DoReferenceTransaction, params
157
+ Response.new response
158
+ end
159
+
160
+ def revoke!(reference_id)
161
+ params = {
162
+ :REFERENCEID => reference_id,
163
+ :BillingAgreementStatus => :Canceled
164
+ }
165
+ response = self.request :BillAgreementUpdate, params
166
+ Response.new response
167
+ end
168
+
169
+
170
+ # Refund Specific
171
+
172
+ def refund!(transaction_id, options = {})
173
+ params = {
174
+ :TRANSACTIONID => transaction_id,
175
+ :REFUNDTYPE => :Full
176
+ }
177
+ if options[:invoice_id]
178
+ params[:INVOICEID] = options[:invoice_id]
179
+ end
180
+ if options[:type]
181
+ params[:REFUNDTYPE] = options[:type]
182
+ params[:AMT] = options[:amount]
183
+ params[:CURRENCYCODE] = options[:currency_code]
184
+ end
185
+ if options[:note]
186
+ params[:NOTE] = options[:note]
187
+ end
188
+ response = self.request :RefundTransaction, params
189
+ Response.new response
190
+ end
191
+
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,35 @@
1
+ module Express
2
+ module Check
3
+ class Response < NVP::Response
4
+ attr_accessor :pay_on_paypal, :mobile
5
+
6
+ def initialize(response, options = {})
7
+ super response
8
+ @pay_on_paypal = options[:pay_on_paypal]
9
+ @mobile = options[:mobile]
10
+ end
11
+
12
+ def redirect_uri
13
+ endpoint = URI.parse Paypal.endpoint
14
+ endpoint.query = query(:with_cmd).to_query
15
+ endpoint.to_s
16
+ end
17
+
18
+ def popup_uri
19
+ endpoint = URI.parse Paypal.popup_endpoint
20
+ endpoint.query = query.to_query
21
+ endpoint.to_s
22
+ end
23
+
24
+ private
25
+
26
+ def query(with_cmd = false)
27
+ _query_ = {:token => self.token}
28
+ _query_.merge!(:cmd => '_express-checkout') if with_cmd
29
+ _query_.merge!(:cmd => '_express-checkout-mobile') if mobile
30
+ _query_.merge!(:useraction => 'commit') if pay_on_paypal
31
+ _query_
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,4 @@
1
+ module Express
2
+ class Exception < StandardError
3
+ end
4
+ end
@@ -0,0 +1,94 @@
1
+ module Express
2
+ class Exception
3
+ class APIError < Exception
4
+ attr_accessor :response
5
+ def initialize(response = {})
6
+ @response = if response.is_a?(Hash)
7
+ Response.new response
8
+ else
9
+ response
10
+ end
11
+ end
12
+
13
+ def message
14
+ if response.respond_to?(:short_messages) && response.short_messages.any?
15
+ "PayPal API Error: " <<
16
+ response.short_messages.map{ |m| "'#{m}'" }.join(", ")
17
+ else
18
+ "PayPal API Error"
19
+ end
20
+ end
21
+
22
+ class Response
23
+ cattr_reader :attribute_mapping
24
+ @@attribute_mapping = {
25
+ :ACK => :ack,
26
+ :BUILD => :build,
27
+ :CORRELATIONID => :correlation_id,
28
+ :TIMESTAMP => :timestamp,
29
+ :VERSION => :version,
30
+ :ORDERTIME => :order_time,
31
+ :PENDINGREASON => :pending_reason,
32
+ :PAYMENTSTATUS => :payment_status,
33
+ :PAYMENTTYPE => :payment_type,
34
+ :REASONCODE => :reason_code,
35
+ :TRANSACTIONTYPE => :transaction_type
36
+ }
37
+ attr_accessor *@@attribute_mapping.values
38
+ attr_accessor :raw, :details
39
+ alias_method :colleration_id, :correlation_id # NOTE: I made a typo :p
40
+
41
+ class Detail
42
+ cattr_reader :attribute_mapping
43
+ @@attribute_mapping = {
44
+ :ERRORCODE => :error_code,
45
+ :SEVERITYCODE => :severity_code,
46
+ :LONGMESSAGE => :long_message,
47
+ :SHORTMESSAGE => :short_message
48
+ }
49
+ attr_accessor *@@attribute_mapping.values
50
+
51
+ def initialize(attributes = {})
52
+ @raw = attributes
53
+ attrs = attributes.dup
54
+ @@attribute_mapping.each do |key, value|
55
+ self.send "#{value}=", attrs.delete(key)
56
+ end
57
+
58
+ # warn ignored params
59
+ attrs.each do |key, value|
60
+ Paypal.log "Ignored Parameter (#{self.class}): #{key}=#{value}", :warn
61
+ end
62
+ end
63
+ end
64
+
65
+ def initialize(attributes = {})
66
+ attrs = attributes.dup
67
+ @raw = attributes
68
+ @@attribute_mapping.each do |key, value|
69
+ self.send "#{value}=", attrs.delete(key)
70
+ end
71
+ details = []
72
+ attrs.keys.each do |attribute|
73
+ key, index = attribute.to_s.scan(/^L_(\S+)(\d+)$/).first
74
+ next if [key, index].any?(&:blank?)
75
+ details[index.to_i] ||= {}
76
+ details[index.to_i][key.to_sym] = attrs.delete(attribute)
77
+ end
78
+ @details = details.collect do |_attrs_|
79
+ Detail.new _attrs_
80
+ end
81
+
82
+ # warn ignored params
83
+ attrs.each do |key, value|
84
+ Paypal.log "Ignored Parameter (#{self.class}): #{key}=#{value}", :warn
85
+ end
86
+ end
87
+
88
+ def short_messages
89
+ details.map(&:short_message).compact
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end