wechat_pay 0.1.0 → 0.2.0

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: 1de3b364757da264d21ac3b5bbbebf2b76f1ea78
4
- data.tar.gz: ef2ffe65e34a698dec0ac6c43a103ed9c17b916f
3
+ metadata.gz: 07e529110ae4ceb6bcdfe49478d9fa2793c5c08f
4
+ data.tar.gz: 63acebb5f8625dbab449bf8fbcef4df8dbff1dae
5
5
  SHA512:
6
- metadata.gz: 91e1f4d712eeb7dae91c8622fbfd367f3e0ca30faff807bb067d36d411ef4adbd0473ad0d6c0430f6a839dd4fd62a915e32352a732155f888976211b3a6ccd12
7
- data.tar.gz: 217fa61b7ee54d66db3b7af8faed2dac69d134b7bd56a01312b87ef6a19d55e85670905bdcb456908c6e2a1eac501aad863e291b40dcace5e61db5fa08c02a74
6
+ metadata.gz: 0a68658c3180520d68a7af857e8968750e3a1852a70be6ceda5a92631b115785bdb4c46af3f77e201dc422d3b96f5c4851524c4ca0c78ac27d46fbfe2cbfd56b
7
+ data.tar.gz: e5fc8dbc37a2338dbab9ca5b298cf01ac4a3a807a2edc9513651b3bb076aaf6a806cf5cd5b0772c6b7f77353a2622e1c3e3e557e8259b5c8c7c74aa0c476d6b2
data/CHANGELOG.md CHANGED
@@ -1,7 +1,13 @@
1
- # Change Log
1
+ # Changelog
2
+
3
+ ## Version 0.2.0
4
+
5
+ ### Add
6
+
7
+ * `WechatPay::Notify.verify?`
2
8
 
3
9
  ## Version 0.1.0
4
10
 
5
11
  ### Breaking Change
6
12
 
7
- * 修改 `WechatPay::App.payment` 返回值 [c10c1c](https://github.com/HungYuHei/wechat_pay/commit/c10c1cc40ff54c584f3855d0d3264207e45778d0)
13
+ * 修改 `WechatPay::App.payment` 返回值 [c10c1c](https://github.com/HungYuHei/wechat_pay/commit/c10c1cc40ff54c584f3855d0d3264207e45778d0)
data/README.md CHANGED
@@ -1,17 +1,22 @@
1
1
  # WechatPay
2
2
 
3
- Wechat Pay: https://open.weixin.qq.com/cgi-bin/frame?t=home/pay_tmpl&lang=zh_CN
3
+ 微信支付: https://open.weixin.qq.com/cgi-bin/frame?t=home/pay_tmpl&lang=zh_CN
4
4
 
5
5
  It contains:
6
6
 
7
- * generate access_token
8
- * generate payment params for App
7
+ * generate access-token
8
+ * App payment
9
+ * verify notify
10
+ * Native payment (Work In Process)
11
+ * JS payment (Work In Process)
12
+
13
+ MRI Ruby 2.0.0 and newer are supported. 1.9.2 should work as well but not tested.
9
14
 
10
15
  ## Installation
11
16
 
12
17
  Add this line to your application's Gemfile:
13
18
 
14
- gem 'wechat_pay', '~> 0.1.0'
19
+ gem 'wechat_pay'
15
20
 
16
21
  And then execute:
17
22
 
@@ -39,7 +44,7 @@ WechatPay.partner_key = 'YOUR_PARTNER_KEY'
39
44
  WechatPay::AccessToken.generate # => { access_token: 'ACCESS_TOKEN', expires_in: 7200 }
40
45
  ```
41
46
 
42
- Your should cache the `access_token`, see [http://mp.weixin.qq.com/wiki...](http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token)
47
+ Your should cache the `access_token`, see [http://mp.weixin.qq.com/wiki/index.php...](http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token)
43
48
 
44
49
  You may wanna do something like this in Rails:
45
50
 
@@ -73,6 +78,26 @@ WechatPay::App.payment('ACCESS_TOKEN', params)
73
78
  # sign: 'sign'
74
79
  # }
75
80
  ```
81
+ ### Verify notify
82
+
83
+ ```ruby
84
+ # Rails example
85
+
86
+ def app_notify
87
+ # except :controller_name, :action_name, :host, etc.
88
+ notify_params = params.except(*request.path_parameters.keys)
89
+
90
+ if WechatPay::Notify.verify?(notify_params)
91
+ # Valid notify status
92
+ if params[:trade_state] == '0'
93
+ # Code your business logic
94
+ end
95
+ render text: 'success'
96
+ else
97
+ render text: 'error'
98
+ end
99
+ end
100
+ ```
76
101
 
77
102
  ## Contributing
78
103
 
@@ -81,3 +106,7 @@ WechatPay::App.payment('ACCESS_TOKEN', params)
81
106
  3. Commit your changes (`git commit -am 'Add some feature'`)
82
107
  4. Push to the branch (`git push origin my-new-feature`)
83
108
  5. Create a new Pull Request
109
+
110
+ ## License
111
+
112
+ [WTFPL](http://wtfpl.org)
@@ -1,9 +1,3 @@
1
- require 'uri'
2
- require 'json'
3
- require 'rest_client'
4
- require 'securerandom'
5
- require 'digest/md5'
6
-
7
1
  module WechatPay
8
2
  module App
9
3
 
@@ -12,22 +6,14 @@ module WechatPay
12
6
  def self.payment(access_token, params)
13
7
  noncestr = SecureRandom.hex(16)
14
8
  timestamp = Time.now.to_i.to_s
15
- package = generate_package(params)
9
+ package = Package::App.generate(params)
16
10
 
17
- app_signature = generate_app_signature(
11
+ prepay_id = PrepayId::App.generate(
12
+ access_token,
13
+ traceid: params[:traceid],
18
14
  noncestr: noncestr,
19
- timestamp: timestamp,
20
15
  package: package,
21
- traceid: params[:traceid],
22
- )
23
-
24
- prepay_id = generate_prepay_id(
25
- access_token,
26
- traceid: params[:traceid],
27
- noncestr: noncestr,
28
- package: package,
29
- timestamp: timestamp,
30
- app_signature: app_signature
16
+ timestamp: timestamp
31
17
  )
32
18
 
33
19
  attrs = {
@@ -39,7 +25,7 @@ module WechatPay
39
25
  prepayid: prepay_id,
40
26
  timestamp: timestamp
41
27
  }
42
- sign = Sign.generate(attrs)
28
+ sign = Sign.sha1(attrs)
43
29
 
44
30
  {
45
31
  sign: sign,
@@ -51,67 +37,5 @@ module WechatPay
51
37
  }
52
38
  end
53
39
 
54
- private
55
-
56
- def self.generate_prepay_id(access_token, params)
57
- url = "https://api.weixin.qq.com/pay/genprepay?access_token=#{access_token}"
58
-
59
- params = {
60
- appid: WechatPay.app_id,
61
- traceid: params[:traceid],
62
- noncestr: params[:noncestr],
63
- package: params[:package],
64
- timestamp: params[:timestamp],
65
- app_signature: params[:app_signature],
66
- sign_method: 'sha1'
67
- }
68
-
69
- RestClient.post(url, JSON.generate(params)) do |response|
70
- JSON.parse(response.body)['prepayid']
71
- end
72
- end
73
-
74
- PACKAGE_PARAMS = [
75
- :bank_type, :body, :attach, :partner, :out_trade_no, :total_fee, :fee_type,
76
- :notify_url, :spbill_create_ip, :time_start, :time_expire, :transport_fee,
77
- :product_fee, :goods_tag, :input_charset
78
- ]
79
-
80
- def self.generate_package(package_params)
81
- package_params = Utils.slice_hash(package_params, *PACKAGE_PARAMS)
82
-
83
- params = {
84
- bank_type: 'WX',
85
- fee_type: '1',
86
- input_charset: 'UTF-8',
87
- partner: WechatPay.partner_id
88
- }.merge(package_params)
89
-
90
- regexp = Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
91
- escaped_params_str = params.sort.map do |key, value|
92
- "#{key}=#{URI.escape(value.to_s, regexp)}"
93
- end.join('&')
94
-
95
- "#{escaped_params_str}&sign=#{package_sign(params)}"
96
- end
97
-
98
- def self.generate_app_signature(signature_params)
99
- params = {
100
- appid: WechatPay.app_id,
101
- appkey: WechatPay.pay_sign_key,
102
- noncestr: signature_params[:noncestr],
103
- package: signature_params[:package],
104
- timestamp: signature_params[:timestamp],
105
- traceid: signature_params[:traceid]
106
- }
107
-
108
- Sign.generate(params)
109
- end
110
-
111
- def self.package_sign(params)
112
- str = params.sort.map { |item| item.join('=') }.join('&')
113
- str << "&key=#{WechatPay.partner_key}"
114
- Digest::MD5.hexdigest(str).upcase
115
- end
116
40
  end
117
41
  end
@@ -0,0 +1,8 @@
1
+ module WechatPay
2
+ module Notify
3
+ def self.verify?(params)
4
+ sign = params.delete(:sign) || params.delete('sign')
5
+ !!sign && sign == Sign.md5(params)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,29 @@
1
+ module WechatPay
2
+ module Package
3
+ module App
4
+ PACKAGE_PARAMS = [
5
+ :bank_type, :body, :attach, :partner, :out_trade_no, :total_fee, :fee_type,
6
+ :notify_url, :spbill_create_ip, :time_start, :time_expire, :transport_fee,
7
+ :product_fee, :goods_tag, :input_charset
8
+ ]
9
+
10
+ def self.generate(package_params)
11
+ package_params = Utils.slice_hash(package_params, *PACKAGE_PARAMS)
12
+
13
+ params = {
14
+ bank_type: 'WX',
15
+ fee_type: '1',
16
+ input_charset: 'UTF-8',
17
+ partner: WechatPay.partner_id
18
+ }.merge(package_params)
19
+
20
+ regexp = Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
21
+ escaped_params_str = params.sort.map do |key, value|
22
+ "#{key}=#{URI.escape(value.to_s, regexp)}"
23
+ end.join('&')
24
+
25
+ "#{escaped_params_str}&sign=#{Sign.md5(params)}"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,45 @@
1
+ require 'json'
2
+ require 'rest_client'
3
+
4
+ module WechatPay
5
+ module PrepayId
6
+ module App
7
+
8
+ # required params:
9
+ # traceid, noncestr, package, timestamp
10
+ def self.generate(access_token, params)
11
+ url = "https://api.weixin.qq.com/pay/genprepay?access_token=#{access_token}"
12
+ app_signature = generate_app_signature(params)
13
+
14
+ prepay_params = {
15
+ appid: WechatPay.app_id,
16
+ app_signature: app_signature,
17
+ traceid: params[:traceid],
18
+ noncestr: params[:noncestr],
19
+ package: params[:package],
20
+ timestamp: params[:timestamp],
21
+ sign_method: 'sha1'
22
+ }
23
+
24
+ RestClient.post(url, JSON.generate(prepay_params)) do |response|
25
+ JSON.parse(response.body)['prepayid']
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def self.generate_app_signature(signature_params)
32
+ params = {
33
+ appid: WechatPay.app_id,
34
+ appkey: WechatPay.pay_sign_key,
35
+ noncestr: signature_params[:noncestr],
36
+ package: signature_params[:package],
37
+ timestamp: signature_params[:timestamp],
38
+ traceid: signature_params[:traceid]
39
+ }
40
+
41
+ Sign.sha1(params)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,10 +1,17 @@
1
1
  require 'digest/sha1'
2
+ require 'digest/md5'
2
3
 
3
4
  module WechatPay
4
5
  module Sign
5
- def self.generate(params)
6
+ def self.sha1(params)
6
7
  str = params.sort.map { |item| item.join('=') }.join('&')
7
8
  Digest::SHA1.hexdigest(str)
8
9
  end
10
+
11
+ def self.md5(params)
12
+ str = params.sort.map { |item| item.join('=') }.join('&')
13
+ str << "&key=#{WechatPay.partner_key}"
14
+ Digest::MD5.hexdigest(str).upcase
15
+ end
9
16
  end
10
17
  end
@@ -1,3 +1,3 @@
1
1
  module WechatPay
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/wechat_pay.rb CHANGED
@@ -1,15 +1,14 @@
1
- require 'wechat_pay/version'
2
- require 'wechat_pay/access_token'
3
1
  require 'wechat_pay/app'
4
2
  require 'wechat_pay/sign'
5
3
  require 'wechat_pay/utils'
4
+ require 'wechat_pay/notify'
5
+ require 'wechat_pay/version'
6
+ require 'wechat_pay/package'
7
+ require 'wechat_pay/prepay_id'
8
+ require 'wechat_pay/access_token'
6
9
 
7
10
  module WechatPay
8
11
  class << self
9
- attr_accessor :app_id
10
- attr_accessor :app_secret
11
- attr_accessor :pay_sign_key
12
- attr_accessor :partner_id
13
- attr_accessor :partner_key
12
+ attr_accessor :app_id, :app_secret, :pay_sign_key, :partner_id, :partner_key
14
13
  end
15
14
  end
@@ -1,10 +1,18 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe WechatPay::App do
4
+ let(:prepay_id) { 'TEST_PREPAY_ID' }
5
+
6
+ before do
7
+ FakeWeb.register_uri(
8
+ :post,
9
+ %r|https://api\.weixin\.qq\.com/pay/genprepay.+|,
10
+ body: %Q({"prepayid":"#{prepay_id}","errcode":0,"errmsg":"Success"})
11
+ )
12
+ end
4
13
 
5
14
  it ".payment" do
6
- prepay_id = "PREPAY_ID"
7
- prepay_params = {
15
+ params = {
8
16
  traceid: 'traceid',
9
17
  body: 'body',
10
18
  out_trade_no: 'out_trade_no',
@@ -13,13 +21,7 @@ describe WechatPay::App do
13
21
  spbill_create_ip: '192.168.1.1'
14
22
  }
15
23
 
16
- FakeWeb.register_uri(
17
- :post,
18
- %r|https://api\.weixin\.qq\.com/pay/genprepay.+|,
19
- body: %Q({"prepayid":"#{prepay_id}","errcode":0,"errmsg":"Success"})
20
- )
21
-
22
- payment = WechatPay::App.payment('access_token', prepay_params)
24
+ payment = WechatPay::App.payment('access_token', params)
23
25
 
24
26
  payment[:partner_id].must_equal WechatPay.partner_id
25
27
  payment[:nonce_str].wont_be_empty
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe WechatPay::Notify do
4
+ describe ".verify?" do
5
+ it "with nil sign" do
6
+ WechatPay::Notify.verify?({}).must_equal(false)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe WechatPay::Package do
4
+ it ".generate" do
5
+ params = {
6
+ body: 'body',
7
+ out_trade_no: 'out_trade_no',
8
+ total_fee: '1',
9
+ notify_url: 'http://test.com',
10
+ spbill_create_ip: '127.0.0.1'
11
+ }
12
+
13
+ WechatPay::Package::App.generate(params).must_include '&sign='
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe WechatPay::PrepayId do
4
+ let(:prepay_id) { 'TEST_PREPAY_ID' }
5
+
6
+ before do
7
+ FakeWeb.register_uri(
8
+ :post,
9
+ %r|https://api\.weixin\.qq\.com/pay/genprepay.+|,
10
+ body: %Q({"prepayid":"#{prepay_id}","errcode":0,"errmsg":"Success"})
11
+ )
12
+ end
13
+
14
+ it ".generate" do
15
+ params = {
16
+ traceid: 'traceid',
17
+ noncestr: 'noncestr',
18
+ package: 'package',
19
+ timestamp: Time.now.to_i.to_s,
20
+ }
21
+ WechatPay::PrepayId::App.generate('ACCESS_TOKEN', params).must_equal(prepay_id)
22
+ end
23
+ end
@@ -1,8 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe WechatPay::Sign do
4
- it ".generate" do
4
+ it ".sha1" do
5
5
  params = { appid: 'appid', appkey: 'appkey' }
6
- WechatPay::Sign.generate(params).wont_be_empty
6
+ WechatPay::Sign.sha1(params).wont_be_empty
7
+ end
8
+
9
+ it ".md5" do
10
+ params = { appid: 'appid' }
11
+ WechatPay::Sign.sha1(params).wont_be_empty
7
12
  end
8
13
  end
data/wechat_pay.gemspec CHANGED
@@ -8,10 +8,10 @@ Gem::Specification.new do |spec|
8
8
  spec.version = WechatPay::VERSION
9
9
  spec.authors = ["HungYuHei"]
10
10
  spec.email = ["kongruxi@gmail.com"]
11
- spec.summary = "Wechat pay"
12
- spec.description = "Wechat pay"
11
+ spec.summary = "微信支付"
12
+ spec.description = "微信支付"
13
13
  spec.homepage = "https://github.com/HungYuHei/wechat_pay"
14
- spec.license = "MIT"
14
+ spec.license = "WTFPL"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wechat_pay
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - HungYuHei
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-19 00:00:00.000000000 Z
11
+ date: 2014-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -66,7 +66,7 @@ dependencies:
66
66
  - - ~>
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.3'
69
- description: Wechat pay
69
+ description: 微信支付
70
70
  email:
71
71
  - kongruxi@gmail.com
72
72
  executables: []
@@ -76,24 +76,29 @@ files:
76
76
  - .gitignore
77
77
  - CHANGELOG.md
78
78
  - Gemfile
79
- - LICENSE.txt
80
79
  - README.md
81
80
  - Rakefile
82
81
  - lib/wechat_pay.rb
83
82
  - lib/wechat_pay/access_token.rb
84
83
  - lib/wechat_pay/app.rb
84
+ - lib/wechat_pay/notify.rb
85
+ - lib/wechat_pay/package.rb
86
+ - lib/wechat_pay/prepay_id.rb
85
87
  - lib/wechat_pay/sign.rb
86
88
  - lib/wechat_pay/utils.rb
87
89
  - lib/wechat_pay/version.rb
88
90
  - spec/spec_helper.rb
89
91
  - spec/wechat_pay/access_token_spec.rb
90
92
  - spec/wechat_pay/app_spec.rb
93
+ - spec/wechat_pay/notify_spec.rb
94
+ - spec/wechat_pay/package_spec.rb
95
+ - spec/wechat_pay/prepay_id_spec.rb
91
96
  - spec/wechat_pay/sign_spec.rb
92
97
  - spec/wechat_pay/utils_spec.rb
93
98
  - wechat_pay.gemspec
94
99
  homepage: https://github.com/HungYuHei/wechat_pay
95
100
  licenses:
96
- - MIT
101
+ - WTFPL
97
102
  metadata: {}
98
103
  post_install_message:
99
104
  rdoc_options: []
@@ -114,10 +119,13 @@ rubyforge_project:
114
119
  rubygems_version: 2.2.2
115
120
  signing_key:
116
121
  specification_version: 4
117
- summary: Wechat pay
122
+ summary: 微信支付
118
123
  test_files:
119
124
  - spec/spec_helper.rb
120
125
  - spec/wechat_pay/access_token_spec.rb
121
126
  - spec/wechat_pay/app_spec.rb
127
+ - spec/wechat_pay/notify_spec.rb
128
+ - spec/wechat_pay/package_spec.rb
129
+ - spec/wechat_pay/prepay_id_spec.rb
122
130
  - spec/wechat_pay/sign_spec.rb
123
131
  - spec/wechat_pay/utils_spec.rb
data/LICENSE.txt DELETED
@@ -1,22 +0,0 @@
1
- Copyright (c) 2014 HungYuHei
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.