alipay 0.14.0 → 0.15.0

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.
@@ -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