alipay 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,6 +5,7 @@ require 'alipay/utils'
5
5
  require 'alipay/sign'
6
6
  require 'alipay/sign/md5'
7
7
  require 'alipay/sign/rsa'
8
+ require 'alipay/sign/rsa2'
8
9
  require 'alipay/sign/dsa'
9
10
  require 'alipay/service'
10
11
  require 'alipay/notify'
@@ -13,8 +14,7 @@ require 'alipay/wap/notify'
13
14
  require 'alipay/wap/sign'
14
15
  require 'alipay/mobile/service'
15
16
  require 'alipay/mobile/sign'
16
- require 'alipay/app/service'
17
- require 'alipay/app/sign'
17
+ require 'alipay/client'
18
18
 
19
19
  module Alipay
20
20
  @debug_mode = true
@@ -0,0 +1,194 @@
1
+ module Alipay
2
+ class Client
3
+ # Create a client to manage all API request.
4
+ #
5
+ # Example:
6
+ #
7
+ # alipay_client = Alipay::Client.new(
8
+ # url: 'https://openapi.alipaydev.com/gateway.do',
9
+ # app_id: '2016000000000000',
10
+ # app_private_key: APP_PRIVATE_KEY,
11
+ # alipay_public_key: ALIPAY_PUBLIC_KEY
12
+ # )
13
+ #
14
+ # Options:
15
+ #
16
+ # [:url] Alipay Open API gateway,
17
+ # 'https://openapi.alipaydev.com/gateway.do'(Sandbox) or
18
+ # 'https://openapi.alipay.com/gateway.do'(Production).
19
+ #
20
+ # [:app_id] Your APP ID.
21
+ #
22
+ # [:app_private_key] APP private key.
23
+ #
24
+ # [:alipay_public_key] Alipay public key.
25
+ #
26
+ # [:format] default is 'json', only support 'json'.
27
+ #
28
+ # [:charset] default is 'UTF-8', only support 'UTF-8'.
29
+ #
30
+ # [:sign_type] default is 'RSA2', support 'RSA2', 'RSA', 'RSA2' is recommended.
31
+ def initialize(options)
32
+ options = ::Alipay::Utils.stringify_keys(options)
33
+ @url = options['url']
34
+ @app_id = options['app_id']
35
+ @app_private_key = options['app_private_key']
36
+ @alipay_public_key = options['alipay_public_key']
37
+ @format = options['format'] || 'json'
38
+ @charset = options['charset'] || 'UTF-8'
39
+ @sign_type = options['sign_type'] || 'RSA2'
40
+ end
41
+
42
+ # Generate a query string that use for APP SDK excute.
43
+ #
44
+ # Example:
45
+ #
46
+ # alipay_client.sdk_execute(
47
+ # method: 'alipay.trade.page.pay',
48
+ # biz_content: {
49
+ # out_trade_no: '20160401000000',
50
+ # product_code: 'QUICK_MSECURITY_PAY',
51
+ # total_amount: '0.01',
52
+ # subject: 'test'
53
+ # }.to_json,
54
+ # timestamp: '2016-04-01 00:00:00'
55
+ # )
56
+ # # => 'app_id=2016000000000000&charset=utf-8&sig....'
57
+ def sdk_execute(params)
58
+ params = prepare_params(params)
59
+
60
+ URI.encode_www_form(params)
61
+ end
62
+
63
+ # Generate a url that use to redirect user to Alipay payment page.
64
+ #
65
+ # Example:
66
+ #
67
+ # assert_equal url, @client.page_execute_url(
68
+ # method: 'alipay.trade.page.pay',
69
+ # biz_content: {
70
+ # out_trade_no: '20160401000000',
71
+ # product_code: 'FAST_INSTANT_TRADE_PAY',
72
+ # total_amount: '0.01',
73
+ # subject: 'test'
74
+ # }.to_json,
75
+ # timestamp: '2016-04-01 00:00:00'
76
+ # )
77
+ # # => 'https://openapi.alipaydev.com/gateway.do?app_id=2016...'
78
+ def page_execute_url(params)
79
+ params = prepare_params(params)
80
+
81
+ uri = URI(@url)
82
+ uri.query = URI.encode_www_form(params)
83
+ uri.to_s
84
+ end
85
+
86
+ # Generate a form string that use to render in view and auto POST to
87
+ # Alipay server.
88
+ #
89
+ # Example:
90
+ #
91
+ # assert_equal url, @client.page_execute_form(
92
+ # method: 'alipay.trade.page.pay',
93
+ # biz_content: {
94
+ # out_trade_no: '20160401000000',
95
+ # product_code: 'FAST_INSTANT_TRADE_PAY',
96
+ # total_amount: '0.01',
97
+ # subject: 'test'
98
+ # }.to_json,
99
+ # timestamp: '2016-04-01 00:00:00'
100
+ # )
101
+ # # => '<form id='alipaysubmit' name='alipaysubmit' action=...'
102
+ def page_execute_form(params)
103
+ params = prepare_params(params)
104
+
105
+ html = %Q(<form id='alipaysubmit' name='alipaysubmit' action='#{@url}' method='POST'>)
106
+ params.each do |key, value|
107
+ html << %Q(<input type='hidden' name='#{key}' value='#{value.gsub("'", "&apos;")}'/>)
108
+ end
109
+ html << "<input type='submit' value='ok' style='display:none'></form>"
110
+ html << "<script>document.forms['alipaysubmit'].submit();</script>"
111
+ html
112
+ end
113
+
114
+ # Immediately make a API request to Alipay and return response body.
115
+ #
116
+ # Example:
117
+ #
118
+ # @client.execute(
119
+ # method: 'alipay.data.dataservice.bill.downloadurl.query',
120
+ # biz_content: {
121
+ # bill_type: 'trade',
122
+ # bill_date: '2016-04-01'
123
+ # }.to_json
124
+ # )
125
+ # # => '{ "alipay_data_dataservice_bill_downloadurl_query_response":{...'
126
+ def execute(params)
127
+ params = prepare_params(params)
128
+
129
+ Net::HTTP.post_form(URI(@url), params).body
130
+ end
131
+
132
+ # Generate sign for params.
133
+ def sign(params)
134
+ string = params_to_string(params)
135
+
136
+ case @sign_type
137
+ when 'RSA'
138
+ ::Alipay::Sign::RSA.sign(@app_private_key, string)
139
+ when 'RSA2'
140
+ ::Alipay::Sign::RSA2.sign(@app_private_key, string)
141
+ else
142
+ raise "Unsupported sign_type: #{@sign_type}"
143
+ end
144
+ end
145
+
146
+ # Verify Alipay notification.
147
+ #
148
+ # Example:
149
+ #
150
+ # params = {
151
+ # out_trade_no: '20160401000000',
152
+ # trade_status: 'TRADE_SUCCESS'
153
+ # sign_type: 'RSA2',
154
+ # sign: '...'
155
+ # }
156
+ # alipay_client.verify?(params)
157
+ # # => true / false
158
+ def verify?(params)
159
+ params = Utils.stringify_keys(params)
160
+ return false if params['sign_type'] != @sign_type
161
+
162
+ sign = params.delete('sign')
163
+ # sign_type does not use in notify sign
164
+ params.delete('sign_type')
165
+ string = params_to_string(params)
166
+ case @sign_type
167
+ when 'RSA'
168
+ ::Alipay::Sign::RSA.verify?(@alipay_public_key, string, sign)
169
+ when 'RSA2'
170
+ ::Alipay::Sign::RSA2.verify?(@alipay_public_key, string, sign)
171
+ else
172
+ raise "Unsupported sign_type: #{@sign_type}"
173
+ end
174
+ end
175
+
176
+ private
177
+
178
+ def prepare_params(params)
179
+ params = {
180
+ 'app_id' => @app_id,
181
+ 'charset' => @charset,
182
+ 'sign_type' => @sign_type,
183
+ 'version' => '1.0',
184
+ 'timestamp' => Time.now.localtime('+08:00').strftime("%Y-%m-%d %H:%M:%S")
185
+ }.merge(::Alipay::Utils.stringify_keys(params))
186
+ params['sign'] = sign(params)
187
+ params
188
+ end
189
+
190
+ def params_to_string(params)
191
+ params.sort.map { |item| item.join('=') }.join('&')
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,18 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+
4
+ module Alipay
5
+ module Sign
6
+ class RSA2
7
+ def self.sign(key, string)
8
+ rsa = OpenSSL::PKey::RSA.new(key)
9
+ Base64.strict_encode64(rsa.sign('sha256', string))
10
+ end
11
+
12
+ def self.verify?(key, string, sign)
13
+ rsa = OpenSSL::PKey::RSA.new(key)
14
+ rsa.verify('sha256', Base64.strict_decode64(sign), string)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module Alipay
2
- VERSION = "0.14.0"
2
+ VERSION = "0.15.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alipay
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rei
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-28 00:00:00.000000000 Z
11
+ date: 2017-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -81,9 +81,11 @@ files:
81
81
  - README.md
82
82
  - Rakefile
83
83
  - alipay.gemspec
84
+ - bin/console
85
+ - config.yml.example
86
+ - doc/legacy_api.md
84
87
  - lib/alipay.rb
85
- - lib/alipay/app/service.rb
86
- - lib/alipay/app/sign.rb
88
+ - lib/alipay/client.rb
87
89
  - lib/alipay/mobile/service.rb
88
90
  - lib/alipay/mobile/sign.rb
89
91
  - lib/alipay/notify.rb
@@ -92,26 +94,12 @@ files:
92
94
  - lib/alipay/sign/dsa.rb
93
95
  - lib/alipay/sign/md5.rb
94
96
  - lib/alipay/sign/rsa.rb
97
+ - lib/alipay/sign/rsa2.rb
95
98
  - lib/alipay/utils.rb
96
99
  - lib/alipay/version.rb
97
100
  - lib/alipay/wap/notify.rb
98
101
  - lib/alipay/wap/service.rb
99
102
  - lib/alipay/wap/sign.rb
100
- - test/alipay/app/service_test.rb
101
- - test/alipay/app/sign_test.rb
102
- - test/alipay/mobile/service_test.rb
103
- - test/alipay/mobile/sign_test.rb
104
- - test/alipay/notify_test.rb
105
- - test/alipay/service_test.rb
106
- - test/alipay/sign/md5_test.rb
107
- - test/alipay/sign/rsa_test.rb
108
- - test/alipay/sign_test.rb
109
- - test/alipay/utils_test.rb
110
- - test/alipay/wap/notify_test.rb
111
- - test/alipay/wap/service_test.rb
112
- - test/alipay/wap/sign_test.rb
113
- - test/alipay_test.rb
114
- - test/test_helper.rb
115
103
  homepage: https://github.com/chloerei/alipay
116
104
  licenses:
117
105
  - MIT
@@ -132,23 +120,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
120
  version: '0'
133
121
  requirements: []
134
122
  rubyforge_project:
135
- rubygems_version: 2.5.2
123
+ rubygems_version: 2.6.11
136
124
  signing_key:
137
125
  specification_version: 4
138
126
  summary: An unofficial simple alipay gem
139
- test_files:
140
- - test/alipay/app/service_test.rb
141
- - test/alipay/app/sign_test.rb
142
- - test/alipay/mobile/service_test.rb
143
- - test/alipay/mobile/sign_test.rb
144
- - test/alipay/notify_test.rb
145
- - test/alipay/service_test.rb
146
- - test/alipay/sign/md5_test.rb
147
- - test/alipay/sign/rsa_test.rb
148
- - test/alipay/sign_test.rb
149
- - test/alipay/utils_test.rb
150
- - test/alipay/wap/notify_test.rb
151
- - test/alipay/wap/service_test.rb
152
- - test/alipay/wap/sign_test.rb
153
- - test/alipay_test.rb
154
- - test/test_helper.rb
127
+ test_files: []
@@ -1,27 +0,0 @@
1
- module Alipay
2
- module App
3
- module Service
4
- ALIPAY_TRADE_APP_PAY_REQUIRED_PARAMS = %w( app_id biz_content notify_url )
5
-
6
- def self.alipay_trade_app_pay(params, options = {})
7
- params = Utils.stringify_keys(params)
8
- Alipay::Service.check_required_params(params, ALIPAY_TRADE_APP_PAY_REQUIRED_PARAMS)
9
- key = options[:key] || Alipay.key
10
-
11
- params = {
12
- 'method' => 'alipay.trade.app.pay',
13
- 'charset' => 'utf-8',
14
- 'version' => '1.0',
15
- 'timestamp' => Time.now.utc.strftime('%Y-%m-%d %H:%M:%S').to_s,
16
- 'sign_type' => 'RSA'
17
- }.merge(params)
18
-
19
- string = Alipay::App::Sign.params_to_sorted_string(params)
20
- sign = CGI.escape(Alipay::Sign::RSA.sign(key, string))
21
- encoded_string = Alipay::App::Sign.params_to_encoded_string(params)
22
-
23
- %Q(#{encoded_string}&sign=#{sign})
24
- end
25
- end
26
- end
27
- end
@@ -1,39 +0,0 @@
1
- require 'erb'
2
-
3
- module Alipay
4
- module App
5
- module Sign
6
- ALIPAY_RSA_PUBLIC_KEY = <<-EOF
7
- -----BEGIN PUBLIC KEY-----
8
- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkr
9
- IvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsra
10
- prwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUr
11
- CmZYI/FCEa3/cNMW0QIDAQAB
12
- -----END PUBLIC KEY-----
13
- EOF
14
-
15
- def self.verify?(params)
16
- params = ::Alipay::Utils.stringify_keys(params)
17
-
18
- sign_type = params.delete('sign_type')
19
- sign = params.delete('sign')
20
- string = ::Alipay::Sign.params_to_string(params)
21
-
22
- case sign_type
23
- when 'RSA'
24
- ::Alipay::Sign::RSA.verify?(ALIPAY_RSA_PUBLIC_KEY, string, sign)
25
- else
26
- false
27
- end
28
- end
29
-
30
- def self.params_to_sorted_string(params)
31
- params.sort.map { |key, value| %Q(#{key}=#{value.to_s}) }.join('&')
32
- end
33
-
34
- def self.params_to_encoded_string(params)
35
- params.sort.map { |key, value| %Q(#{key}=#{ERB::Util.url_encode(value.to_s)}) }.join('&')
36
- end
37
- end
38
- end
39
- end
@@ -1,20 +0,0 @@
1
- require 'test_helper'
2
-
3
- class Alipay::Mobile::ServiceTest < Minitest::Test
4
- def test_mobile_securitypay_pay_string
5
- assert_equal %q(app_id=2015052600090779&biz_content=%7B%3Atimeout_express%3D%3E%2230m%22%2C%20%3Aseller_id%3D%3E%22%22%2C%20%3Aproduct_code%3D%3E%22QUICK_MSECURITY_PAY%22%2C%20%3Atotal_amount%3D%3E%220.01%22%2C%20%3Asubject%3D%3E%221%22%2C%20%3Abody%3D%3E%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22%2C%20%3Aout_trade_no%3D%3E%22IQJZSRC1YMQB5HU%22%7D&charset=utf-8&format=json&method=alipay.trade.app.pay&notify_url=http%3A%2F%2Fdomain.merchant.com%2Fpayment_notify&sign_type=RSA&timestamp=2016-08-25%2020%3A26%3A31&version=1.0&sign=lT%2BwWRpKYDP4QLm8Ore6ngGQv8aHGPw1OuI2e8pRf5aWO55sTAYqN01uJyKDe3Swzat8UYdvby8o9haA3LPQibYXB2sezkZxOBHpfdKVRjXe0u9qTMlACAQUQLQeXQFNfcWRgKUGNLMHARv7ajqz8tCnDN2B3mlAmKs0r4qb6IM%3D), Alipay::App::Service.alipay_trade_app_pay({
6
- app_id: '2015052600090779',
7
- biz_content: {:timeout_express=>"30m",:seller_id=>"",:product_code=>"QUICK_MSECURITY_PAY",:total_amount=>"0.01",:subject=>"1",:body=>"我是测试数据",:out_trade_no=>"IQJZSRC1YMQB5HU"},
8
- charset: 'utf-8',
9
- format: 'json',
10
- method: 'alipay.trade.app.pay',
11
- notify_url: 'http://domain.merchant.com/payment_notify',
12
- sign_type: 'RSA',
13
- timestamp: '2016-08-25 20:26:31',
14
- version: '1.0'
15
- }, {
16
- sign_type: 'RSA',
17
- key: TEST_RSA_PRIVATE_KEY
18
- })
19
- end
20
- end
@@ -1,15 +0,0 @@
1
- require 'test_helper'
2
-
3
- class Alipay::App::SignTest < Minitest::Test
4
- def test_params_to_sorted_string
5
- assert_equal %q(a=2&b=1), Alipay::App::Sign.params_to_sorted_string(b: 1, a: 2)
6
- end
7
-
8
- def test_params_to_encoded_string
9
- assert_equal %q(biz_content=%7B%3Aname%3D%3E%22%E9%A1%BA%E9%81%93%22%7D&out_trade_no=MEM1234567&total_amount=0.01), Alipay::App::Sign.params_to_encoded_string(
10
- biz_content: {:name=>'顺道'},
11
- out_trade_no: 'MEM1234567',
12
- total_amount: '0.01'
13
- )
14
- end
15
- end
@@ -1,16 +0,0 @@
1
- require 'test_helper'
2
-
3
- class Alipay::Mobile::ServiceTest < Minitest::Test
4
- def test_mobile_securitypay_pay_string
5
- assert_equal %q(service="mobile.securitypay.pay"&_input_charset="utf-8"&partner="1000000000000000"&seller_id="1000000000000000"&payment_type="1"&out_trade_no="1"&notify_url="/some_url"&subject="subject"&total_fee="0.01"&body="test"&sign="if1qjK4qnT7eQ5fw%2BBddHhO1LY6iuPY9Xmhkx81YKuCdceKWBdv798j%2BrxF9ZAhNW4Y3TMURm%2BXpgxhOh8lj8vorFup%2BMJ6fe2rXRWgxFhK9B8xuP2XH%2F3878g6d8Jq2D2gINTgDDL7%2BB5%2FIWWlwInas40cQTsVngG8mWkzB788%3D"&sign_type="RSA"), Alipay::Mobile::Service.mobile_securitypay_pay_string({
6
- out_trade_no: '1',
7
- notify_url: '/some_url',
8
- subject: 'subject',
9
- total_fee: '0.01',
10
- body: 'test'
11
- }, {
12
- sign_type: 'RSA',
13
- key: TEST_RSA_PRIVATE_KEY
14
- })
15
- end
16
- end
@@ -1,7 +0,0 @@
1
- require 'test_helper'
2
-
3
- class Alipay::Mobile::SignTest < Minitest::Test
4
- def test_params_to_string
5
- assert_equal %q(a="1"&b="2"), Alipay::Mobile::Sign.params_to_string(a: 1, b: 2)
6
- end
7
- end