alipay 0.6.0.beta1 → 0.6.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/alipay.rb CHANGED
@@ -1,12 +1,16 @@
1
1
  require 'net/http'
2
+ require 'cgi'
2
3
  require 'alipay/version'
3
4
  require 'alipay/utils'
4
5
  require 'alipay/sign'
5
- require 'alipay/sign/wap'
6
+ require 'alipay/sign/md5'
7
+ require 'alipay/sign/rsa'
8
+ require 'alipay/sign/dsa'
6
9
  require 'alipay/service'
7
- require 'alipay/service/wap'
8
10
  require 'alipay/notify'
9
- require 'alipay/notify/wap'
11
+ require 'alipay/wap/service'
12
+ require 'alipay/wap/notify'
13
+ require 'alipay/wap/sign'
10
14
 
11
15
  module Alipay
12
16
  @debug_mode = true
data/lib/alipay/notify.rb CHANGED
@@ -1,12 +1,19 @@
1
1
  module Alipay
2
2
  module Notify
3
- def self.verify?(params)
3
+ def self.verify?(params, options = {})
4
4
  params = Utils.stringify_keys(params)
5
- Sign.verify?(params) && verify_notify_id?(params['notify_id'])
5
+ pid = options[:pid] || Alipay.pid
6
+ Sign.verify?(params, options) && verify_notify_id?(pid, params['notify_id'])
6
7
  end
7
8
 
8
- def self.verify_notify_id?(notify_id)
9
- Net::HTTP.get(URI("https://mapi.alipay.com/gateway.do?service=notify_verify&partner=#{Alipay.pid}&notify_id=#{CGI.escape(notify_id.to_s)}")) == 'true'
9
+ def self.verify_notify_id?(pid, notify_id)
10
+ uri = URI("https://mapi.alipay.com/gateway.do")
11
+ uri.query = URI.encode_www_form(
12
+ 'service' => 'notify_verify',
13
+ 'partner' => pid,
14
+ 'notify_id' => notify_id
15
+ )
16
+ Net::HTTP.get(uri) == 'true'
10
17
  end
11
18
  end
12
19
  end
@@ -1,188 +1,192 @@
1
- require 'cgi'
2
-
3
1
  module Alipay
4
2
  module Service
5
3
  GATEWAY_URL = 'https://mapi.alipay.com/gateway.do'
6
4
 
7
- CREATE_PARTNER_TRADE_BY_BUYER_REQUIRED_OPTIONS = %w( service partner _input_charset out_trade_no subject payment_type logistics_type logistics_fee logistics_payment seller_email price quantity )
5
+ CREATE_PARTNER_TRADE_BY_BUYER_REQUIRED_PARAMS = %w( out_trade_no subject logistics_type logistics_fee logistics_payment price quantity )
8
6
  # alipayescow
9
- def self.create_partner_trade_by_buyer_url(options)
10
- options = {
7
+ def self.create_partner_trade_by_buyer_url(params, options = {})
8
+ params = Utils.stringify_keys(params)
9
+ check_required_params(params, CREATE_PARTNER_TRADE_BY_BUYER_REQUIRED_PARAMS)
10
+
11
+ params = {
11
12
  'service' => 'create_partner_trade_by_buyer',
12
13
  '_input_charset' => 'utf-8',
13
- 'partner' => Alipay.pid,
14
- 'seller_email' => Alipay.seller_email,
14
+ 'partner' => options[:pid] || Alipay.pid,
15
+ 'seller_email' => options[:seller_email] || Alipay.seller_email,
15
16
  'payment_type' => '1'
16
- }.merge(Utils.stringify_keys(options))
17
+ }.merge(params)
17
18
 
18
- check_required_options(options, CREATE_PARTNER_TRADE_BY_BUYER_REQUIRED_OPTIONS)
19
-
20
- request_uri(options).to_s
19
+ request_uri(params, options).to_s
21
20
  end
22
21
 
23
- TRADE_CREATE_BY_BUYER_REQUIRED_OPTIONS = %w( service partner _input_charset out_trade_no subject payment_type logistics_type logistics_fee logistics_payment seller_email price quantity )
22
+ TRADE_CREATE_BY_BUYER_REQUIRED_PARAMS = %w( out_trade_no subject logistics_type logistics_fee logistics_payment price quantity )
24
23
  # alipaydualfun
25
- def self.trade_create_by_buyer_url(options = {})
26
- options = {
24
+ def self.trade_create_by_buyer_url(params, options = {})
25
+ params = Utils.stringify_keys(params)
26
+ check_required_params(params, TRADE_CREATE_BY_BUYER_REQUIRED_PARAMS)
27
+
28
+ params = {
27
29
  'service' => 'trade_create_by_buyer',
28
30
  '_input_charset' => 'utf-8',
29
- 'partner' => Alipay.pid,
30
- 'seller_email' => Alipay.seller_email,
31
+ 'partner' => options[:pid] || Alipay.pid,
32
+ 'seller_email' => options[:seller_email] || Alipay.seller_email,
31
33
  'payment_type' => '1'
32
- }.merge(Utils.stringify_keys(options))
34
+ }.merge(params)
33
35
 
34
- check_required_options(options, TRADE_CREATE_BY_BUYER_REQUIRED_OPTIONS)
35
-
36
- request_uri(options).to_s
36
+ request_uri(params, options).to_s
37
37
  end
38
38
 
39
- CREATE_DIRECT_PAY_BY_USER_REQUIRED_OPTIONS = %w( service partner _input_charset out_trade_no subject payment_type seller_email )
39
+ CREATE_DIRECT_PAY_BY_USER_REQUIRED_PARAMS = %w( out_trade_no subject )
40
40
  # direct
41
- def self.create_direct_pay_by_user_url(options)
42
- options = {
43
- 'service' => 'create_direct_pay_by_user',
44
- '_input_charset' => 'utf-8',
45
- 'partner' => Alipay.pid,
46
- 'seller_email' => Alipay.seller_email,
47
- 'payment_type' => '1'
48
- }.merge(Utils.stringify_keys(options))
49
-
50
- check_required_options(options, CREATE_DIRECT_PAY_BY_USER_REQUIRED_OPTIONS)
41
+ def self.create_direct_pay_by_user_url(params, options = {})
42
+ params = Utils.stringify_keys(params)
43
+ check_required_params(params, CREATE_DIRECT_PAY_BY_USER_REQUIRED_PARAMS)
51
44
 
52
- if options['total_fee'].nil? and (options['price'].nil? || options['quantity'].nil?)
45
+ if params['total_fee'].nil? and (params['price'].nil? || params['quantity'].nil?)
53
46
  warn("Ailpay Warn: total_fee or (price && quantiry) must have one")
54
47
  end
55
48
 
56
- request_uri(options).to_s
49
+ params = {
50
+ 'service' => 'create_direct_pay_by_user',
51
+ '_input_charset' => 'utf-8',
52
+ 'partner' => options[:pid] || Alipay.pid,
53
+ 'seller_email' => options[:seller_email] || Alipay.seller_email,
54
+ 'payment_type' => '1'
55
+ }.merge(params)
56
+
57
+ request_uri(params, options).to_s
57
58
  end
58
59
 
59
- CREATE_REFUND_URL_REQUIRED_OPTIONS = %w( batch_no data notify_url )
60
+ CREATE_REFUND_URL_REQUIRED_PARAMS = %w( batch_no data notify_url )
60
61
  # 支付宝即时到帐批量退款有密接口(此为异步接口,有密指通过此接口打开 url 后需要用户输入支付宝的支付密码进行退款)
61
- def self.create_refund_url(options)
62
- options = Utils.stringify_keys(options)
63
- check_required_options(options, CREATE_REFUND_URL_REQUIRED_OPTIONS)
62
+ def self.refund_fastpay_by_platform_pwd_url(params, options = {})
63
+ params = Utils.stringify_keys(params)
64
+ check_required_params(params, CREATE_REFUND_URL_REQUIRED_PARAMS)
64
65
 
65
- data = options.delete('data')
66
+ data = params.delete('data')
66
67
  detail_data = data.map do|item|
67
68
  item = Utils.stringify_keys(item)
68
69
  "#{item['trade_no']}^#{item['amount']}^#{item['reason']}"
69
70
  end.join('#')
70
71
 
71
- options = {
72
+ params = {
72
73
  'service' => 'refund_fastpay_by_platform_pwd', # 接口名称
73
74
  '_input_charset' => 'utf-8',
74
- 'partner' => Alipay.pid,
75
- 'seller_email' => Alipay.seller_email,
75
+ 'partner' => options[:pid] || Alipay.pid,
76
+ 'seller_email' => options[:seller_email] || Alipay.seller_email,
76
77
  'refund_date' => Time.now.strftime('%Y-%m-%d %H:%M:%S'), # 申请退款时间
77
78
  'batch_num' => data.size, # 总笔数
78
79
  'detail_data' => detail_data # 转换后的单笔数据集字符串
79
- }.merge(options)
80
+ }.merge(params)
80
81
 
81
- request_uri(options).to_s
82
+ request_uri(params, options).to_s
82
83
  end
83
84
 
84
- CREATE_FOREX_SINGLE_REFUND_URL_REQUIRED_OPTIONS = %w( out_return_no out_trade_no return_amount currency reason )
85
+ CREATE_FOREX_SINGLE_REFUND_URL_REQUIRED_PARAMS = %w( out_return_no out_trade_no return_amount currency reason )
85
86
  # 支付宝境外收单单笔退款接口
86
87
  # out_return_no 退款流水单号
87
88
  # out_trade_no 交易创建时的订单号
88
89
  # return_amount 退款金额
89
90
  # currency 退款币种,与交易创建时的币种一致
90
- def self.create_forex_single_refund_url(options)
91
- options = {
91
+ def self.forex_refund_url(params, options = {})
92
+ params = Utils.stringify_keys(params)
93
+ check_required_params(params, CREATE_FOREX_SINGLE_REFUND_URL_REQUIRED_PARAMS)
94
+
95
+ params = {
92
96
  'service' => 'forex_refund',
93
- 'partner' => Alipay.pid,
97
+ 'partner' => options[:pid] || Alipay.pid,
94
98
  '_input_charset' => 'utf-8',
95
99
  'gmt_return' => Time.now.strftime('%Y%m%d%H%M%S')
96
- }.merge(Utils.stringify_keys(options))
100
+ }.merge(params)
97
101
 
98
- check_required_options(options, CREATE_FOREX_SINGLE_REFUND_URL_REQUIRED_OPTIONS)
99
-
100
- request_uri(options).to_s
102
+ request_uri(params, options).to_s
101
103
  end
102
104
 
103
- SEND_GOODS_CONFIRM_BY_PLATFORM_REQUIRED_OPTIONS = %w( service partner _input_charset trade_no logistics_name )
104
- def self.send_goods_confirm_by_platform(options)
105
- options = {
106
- 'service' => 'send_goods_confirm_by_platform',
107
- 'partner' => Alipay.pid,
108
- '_input_charset' => 'utf-8'
109
- }.merge(Utils.stringify_keys(options))
110
-
111
- check_required_options(options, SEND_GOODS_CONFIRM_BY_PLATFORM_REQUIRED_OPTIONS)
105
+ SEND_GOODS_CONFIRM_BY_PLATFORM_REQUIRED_PARAMS = %w( trade_no logistics_name )
106
+ def self.send_goods_confirm_by_platform(params, options = {})
107
+ params = Utils.stringify_keys(params)
108
+ check_required_params(params, SEND_GOODS_CONFIRM_BY_PLATFORM_REQUIRED_PARAMS)
112
109
 
113
- if options['transport_type'].nil? and options['create_transport_type'].nil?
110
+ if params['transport_type'].nil? and params['create_transport_type'].nil?
114
111
  warn("Ailpay Warn: transport_type or create_transport_type must have one")
115
112
  end
116
113
 
117
- Net::HTTP.get(request_uri(options))
114
+ params = {
115
+ 'service' => 'send_goods_confirm_by_platform',
116
+ 'partner' => options[:pid] || Alipay.pid,
117
+ '_input_charset' => 'utf-8'
118
+ }.merge(params)
119
+
120
+ Net::HTTP.get(request_uri(params, options))
118
121
  end
119
122
 
120
- CREATE_FOREX_TRADE_REQUIRED_OPTIONS = %w(service partner _input_charset notify_url subject out_trade_no currency total_fee)
121
- def self.create_forex_trade(options)
122
- options = {
123
+ CREATE_FOREX_TRADE_REQUIRED_PARAMS = %w( notify_url subject out_trade_no currency total_fee)
124
+ def self.create_forex_trade_url(params, options = {})
125
+ params = Utils.stringify_keys(params)
126
+ check_required_params(params, CREATE_FOREX_TRADE_REQUIRED_PARAMS)
127
+
128
+ params = {
123
129
  'service' => 'create_forex_trade',
124
130
  '_input_charset' => 'utf-8',
125
- 'partner' => Alipay.pid,
126
- 'seller_email' => Alipay.seller_email
127
- }.merge(Utils.stringify_keys(options))
128
-
129
- check_required_options(options, CREATE_FOREX_TRADE_REQUIRED_OPTIONS)
131
+ 'partner' => options[:pid] || Alipay.pid,
132
+ 'seller_email' => options[:seller_email] || Alipay.seller_email
133
+ }.merge(params)
130
134
 
131
- request_uri(options).to_s
135
+ request_uri(params, options).to_s
132
136
  end
133
137
 
134
- CLOSE_TRADE_REQUIRED_OPTIONS = %w( service partner _input_charset)
135
- CLOSE_TRADE_REQUIRED_OPTIONAL_OPTIONS = %w( trade_no out_order_no )
136
- def self.close_trade(options)
137
- options = {
138
+ CLOSE_TRADE_REQUIRED_OPTIONAL_PARAMS = %w( trade_no out_order_no )
139
+ def self.close_trade(params, options = {})
140
+ params = Utils.stringify_keys(params)
141
+ check_optional_params(params, CLOSE_TRADE_REQUIRED_OPTIONAL_PARAMS)
142
+
143
+ params = {
138
144
  'service' => 'close_trade',
139
145
  '_input_charset' => 'utf-8',
140
- 'partner' => Alipay.pid
141
- }.merge(Utils.stringify_keys(options))
146
+ 'partner' => options[:pid] || Alipay.pid
147
+ }.merge(params)
142
148
 
143
- check_required_options(options, CLOSE_TRADE_REQUIRED_OPTIONS)
144
- check_optional_options(options, CLOSE_TRADE_REQUIRED_OPTIONAL_OPTIONS)
145
-
146
- Net::HTTP.get(request_uri(options))
149
+ Net::HTTP.get(request_uri(params, options))
147
150
  end
148
151
 
149
- SINGLE_TRADE_QUERY_OPTIONS = %w( service partner _input_charset)
150
- SINGLE_TRADE_QUERY_OPTIONAL_OPTIONS = %w( trade_no out_trade_no )
151
- def self.single_trade_query(options)
152
- options = {
152
+ SINGLE_TRADE_QUERY_OPTIONAL_PARAMS = %w( trade_no out_trade_no )
153
+ def self.single_trade_query(params, options = {})
154
+ params = Utils.stringify_keys(params)
155
+ check_optional_params(params, SINGLE_TRADE_QUERY_OPTIONAL_PARAMS)
156
+
157
+ params = {
153
158
  "service" => 'single_trade_query',
154
159
  "_input_charset" => "utf-8",
155
- "partner" => Alipay.pid,
156
- }.merge(Utils.stringify_keys(options))
157
-
158
- check_required_options(options, SINGLE_TRADE_QUERY_OPTIONS)
159
- check_optional_options(options, SINGLE_TRADE_QUERY_OPTIONAL_OPTIONS)
160
+ "partner" => options[:pid] || Alipay.pid,
161
+ }.merge(params)
160
162
 
161
- Net::HTTP.get(request_uri(options))
163
+ Net::HTTP.get(request_uri(params, options))
162
164
  end
163
165
 
164
- def self.request_uri(options)
166
+ def self.request_uri(params, options = {})
165
167
  uri = URI(GATEWAY_URL)
166
- uri.query = URI.encode_www_form(sign_params(options))
168
+ uri.query = URI.encode_www_form(sign_params(params, options))
167
169
  uri
168
170
  end
169
171
 
170
- def self.sign_params(params)
171
- params = params.merge('sign_type' => Alipay.sign_type) if params['sign_type'].nil?
172
- params.merge('sign' => Alipay::Sign.generate(params))
172
+ def self.sign_params(params, optinos = {})
173
+ params.merge(
174
+ 'sign_type' => (optinos[:sign_type] || Alipay.sign_type),
175
+ 'sign' => Alipay::Sign.generate(params, optinos)
176
+ )
173
177
  end
174
178
 
175
- def self.check_required_options(options, names)
179
+ def self.check_required_params(params, names)
176
180
  return if !Alipay.debug_mode?
177
181
 
178
182
  names.each do |name|
179
- warn("Ailpay Warn: missing required option: #{name}") unless options.has_key?(name)
183
+ warn("Ailpay Warn: missing required option: #{name}") unless params.has_key?(name)
180
184
  end
181
185
  end
182
186
 
183
- def self.check_optional_options(options, names)
187
+ def self.check_optional_params(params, names)
184
188
  return if !Alipay.debug_mode?
185
- warn("Ailpay Warn: must specify either #{names.join(' or ')}") if names.all? {|name| options[name].nil? }
189
+ warn("Ailpay Warn: must specify either #{names.join(' or ')}") if names.all? {|name| params[name].nil? }
186
190
  end
187
191
  end
188
192
  end
data/lib/alipay/sign.rb CHANGED
@@ -1,72 +1,54 @@
1
- require 'digest/md5'
2
- require 'openssl'
3
- require 'base64'
4
-
5
1
  module Alipay
6
2
  module Sign
7
- def self.generate(params)
3
+ def self.generate(params, options = {})
8
4
  params = Utils.stringify_keys(params)
9
- sign_type = params.delete('sign_type') || Alipay.sign_type
10
- key = params.delete('key') || Alipay.key
5
+ sign_type = options[:sign_type] || Alipay.sign_type
6
+ key = options[:key] || Alipay.key
7
+ string = params_to_string(params)
11
8
 
12
9
  case sign_type
13
10
  when 'MD5'
14
- generate_md5(key, params)
11
+ MD5.sign(key, string)
15
12
  when 'RSA'
16
- raise NotImplementedError, "RSA sign is unimplemented"
13
+ RSA.sign(key, string)
17
14
  when 'DSA'
18
- raise NotImplementedError, "DSA sign is unimplemented"
15
+ DSA.sign(key, string)
19
16
  else
20
- raise ArgumentError, "wrong sign_type #{sign_type}, allow values: 'MD5', 'RSA', 'DSA'"
17
+ raise ArgumentError, "[Alipay] Invalid sign_type #{sign_type}, allow value: 'MD5', 'RSA', 'DSA'"
21
18
  end
22
19
  end
23
20
 
24
- def self.generate_md5(key, params)
25
- Digest::MD5.hexdigest("#{params_to_string(params)}#{key}")
26
- end
27
-
28
- def self.params_to_string(params)
29
- params.sort.map { |item| item.join('=') }.join('&')
30
- end
21
+ ALIPAY_RSA_PUBLIC_KEY = <<-EOF
22
+ -----BEGIN PUBLIC KEY-----
23
+ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRA
24
+ FljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQE
25
+ B/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5Ksi
26
+ NG9zpgmLCUYuLkxpLQIDAQAB
27
+ -----END PUBLIC KEY-----
28
+ EOF
31
29
 
32
- def self.verify?(params)
30
+ def self.verify?(params, options = {})
33
31
  params = Utils.stringify_keys(params)
34
32
 
35
33
  sign_type = params.delete('sign_type')
34
+ sign = params.delete('sign')
35
+ string = params_to_string(params)
36
36
 
37
37
  case sign_type
38
38
  when 'MD5'
39
- verify_md5?(params)
39
+ key = options[:key] || Alipay.key
40
+ MD5.verify?(key, string, sign)
40
41
  when 'RSA'
41
- verify_rsa?(params)
42
+ RSA.verify?(ALIPAY_RSA_PUBLIC_KEY, string, sign)
42
43
  when 'DSA'
43
- raise NotImplementedError, "DSA verify is unimplemented"
44
+ DSA.verify?(string, sign)
44
45
  else
45
- raise ArgumentError, "wrong sign_type #{sign_type}, allow values: 'MD5', 'RSA', 'DSA'"
46
+ raise ArgumentError, "[Alipay] Invalid sign_type #{sign_type}, allow values: 'MD5', 'RSA', 'DSA'"
46
47
  end
47
48
  end
48
49
 
49
- def self.verify_md5?(params)
50
- key = params.delete('key') || Alipay.key
51
- sign = params.delete('sign')
52
- generate_md5(key, params) == sign
53
- end
54
-
55
- ALIPAY_RSA_PUBLIC_KEY = <<-EOF
56
- -----BEGIN PUBLIC KEY-----
57
- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRA
58
- FljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQE
59
- B/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5Ksi
60
- NG9zpgmLCUYuLkxpLQIDAQAB
61
- -----END PUBLIC KEY-----
62
- EOF
63
-
64
- def self.verify_rsa?(params)
65
- pkey = OpenSSL::PKey::RSA.new(ALIPAY_RSA_PUBLIC_KEY)
66
- digest = OpenSSL::Digest::SHA1.new
67
- sign = params.delete('sign')
68
-
69
- pkey.verify(digest, Base64.decode64(sign), params_to_string(params))
50
+ def self.params_to_string(params)
51
+ params.sort.map { |item| item.join('=') }.join('&')
70
52
  end
71
53
  end
72
54
  end
@@ -0,0 +1,13 @@
1
+ module Alipay
2
+ module Sign
3
+ class DSA
4
+ def self.sign(key, string)
5
+ raise NotImplementedError, '[Alipay] DSA sign is not implemented'
6
+ end
7
+
8
+ def self.verify?(string, sign)
9
+ raise NotImplementedError, '[Alipay] DSA verify is not implemented'
10
+ end
11
+ end
12
+ end
13
+ end