wechat_pay 0.2.0 → 0.3.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: 07e529110ae4ceb6bcdfe49478d9fa2793c5c08f
4
- data.tar.gz: 63acebb5f8625dbab449bf8fbcef4df8dbff1dae
3
+ metadata.gz: 3bb85404b21e4c632faaf11bc41ac83afc2454cc
4
+ data.tar.gz: 496b4ab34af115b96ba39590f8edc9a0d14f3100
5
5
  SHA512:
6
- metadata.gz: 0a68658c3180520d68a7af857e8968750e3a1852a70be6ceda5a92631b115785bdb4c46af3f77e201dc422d3b96f5c4851524c4ca0c78ac27d46fbfe2cbfd56b
7
- data.tar.gz: e5fc8dbc37a2338dbab9ca5b298cf01ac4a3a807a2edc9513651b3bb076aaf6a806cf5cd5b0772c6b7f77353a2622e1c3e3e557e8259b5c8c7c74aa0c476d6b2
6
+ metadata.gz: 3f719333568cda9c390455acfb6bf6808745aac8afdfa6d92404fd4b3adbb5c7a2625a6841773a8fdb5789b28cc21342100ddef20d984510a00245872da6606b
7
+ data.tar.gz: b93d3a3dcae5d50b1ddf1f062e46d5506e51a94d41ee0cda88c04b71ccd797b9a3b2c0ddf1a5eca7b5c724f9bbae0034a01cfa9d1b65124ffda1f966ca40e9f3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ### Add
6
+
7
+ * `WechatPay::JS.payment`
8
+ * `WechatPay::DeliverNotify.request`
9
+ * `WechatPay::OrderQuery.request`
10
+
3
11
  ## Version 0.2.0
4
12
 
5
13
  ### Add
data/README.md CHANGED
@@ -5,10 +5,12 @@
5
5
  It contains:
6
6
 
7
7
  * generate access-token
8
- * App payment
8
+ * app payment
9
+ * js payment
10
+ * native payment (work in process)
9
11
  * verify notify
10
- * Native payment (Work In Process)
11
- * JS payment (Work In Process)
12
+ * deliver notify
13
+ * order query
12
14
 
13
15
  MRI Ruby 2.0.0 and newer are supported. 1.9.2 should work as well but not tested.
14
16
 
@@ -49,12 +51,12 @@ Your should cache the `access_token`, see [http://mp.weixin.qq.com/wiki/index.ph
49
51
  You may wanna do something like this in Rails:
50
52
 
51
53
  ```ruby
52
- Rails.cache.fetch(:wechat_pay_access_token, expires_in: 7200.seconds raw: true) do
54
+ Rails.cache.fetch(:wechat_pay_access_token, expires_in: 7200.seconds, raw: true) do
53
55
  WechatPay::AccessToken.generate[:access_token]
54
56
  end
55
57
  ```
56
58
 
57
- ### Payment params
59
+ ### App Payment params
58
60
 
59
61
  ```ruby
60
62
  # Please keep in mind that all key MUST be Symbol
@@ -78,11 +80,64 @@ WechatPay::App.payment('ACCESS_TOKEN', params)
78
80
  # sign: 'sign'
79
81
  # }
80
82
  ```
83
+
84
+ ### JS Payment params
85
+
86
+ ###### In Controller
87
+
88
+ ```ruby
89
+ params = {
90
+ body: 'body',
91
+ out_trade_no: 'out_trade_no'
92
+ total_fee: '100'
93
+ notify_url: 'http://your_domain.com/notify',
94
+ spbill_create_ip: '192.168.1.1'
95
+ }
96
+
97
+ @order_params = WechatPay::JS.payment(params)
98
+
99
+ # =>
100
+ # {
101
+ # app_id: "app_id",
102
+ # timestamp: "1407165191",
103
+ # nonce_str: "noncestr",
104
+ # package: "Sign=WXpay",
105
+ # pay_sign: "pay_sign",
106
+ # sign_type: 'SHA1'
107
+ # }
108
+ ```
109
+
110
+ ###### In View (slim)
111
+
112
+ ```ruby
113
+ = link_to "wechat_payment_btn", "javascript:void(0)", id: "wechatPaymentBtn"
114
+
115
+ javascript:
116
+ var orderParams = {
117
+ appId: "#{@order_params[:app_id]}",
118
+ timeStamp: "#{@order_params[:timestamp]}",
119
+ nonceStr: "#{@order_params[:nonce_str]}",
120
+ package: "#{@order_params[:package]}",
121
+ paySign: "#{@order_params[:pay_sign]}",
122
+ signType: "#{@order_params[:sign_type]}"
123
+ };
124
+ document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
125
+ $('#wechatPaymentBtn').click(function(){
126
+ WeixinJSBridge.invoke('getBrandWCPayRequest', orderParams, function(res) {
127
+ if (res.err_msg == "get_brand_wcpay_request:ok") {
128
+ alert('pay for success!');
129
+ } else {
130
+ alert(res.err_msg);
131
+ }
132
+ });
133
+ });
134
+ }, false);
135
+ ```
136
+
81
137
  ### Verify notify
82
138
 
83
139
  ```ruby
84
140
  # Rails example
85
-
86
141
  def app_notify
87
142
  # except :controller_name, :action_name, :host, etc.
88
143
  notify_params = params.except(*request.path_parameters.keys)
@@ -99,6 +154,30 @@ def app_notify
99
154
  end
100
155
  ```
101
156
 
157
+ ### Deliver Notify
158
+
159
+ ```ruby
160
+ # Please keep in mind that all key MUST be Symbol
161
+ params = {
162
+ openid: 'openid',
163
+ transid: 'transid',
164
+ out_trade_no: 'out_trade_no',
165
+ deliver_msg: 'ok', # optional, default is 'ok'
166
+ deliver_status: '1', # optional, default is '1'
167
+ deliver_timestamp: '1410105134' # optional, default is `Time.now.to_i.to_s`
168
+ }
169
+
170
+ WechatPay::DeliverNotify.request('ACCESS_TOKEN', params)
171
+ # => { errcode: 0, errmsg: 'ok' }
172
+ ```
173
+
174
+ ### Order Query
175
+
176
+ ```ruby
177
+ WechatPay::OrderQuery.request('ACCESS_TOKEN', 'YOUR_OUT_TRADE_NO')
178
+ # => { errcode: 0, errmsg: 'ok', order_info: { ret_code: 0, ... } }
179
+ ```
180
+
102
181
  ## Contributing
103
182
 
104
183
  1. Fork it
data/lib/wechat_pay.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'wechat_pay/js'
1
2
  require 'wechat_pay/app'
2
3
  require 'wechat_pay/sign'
3
4
  require 'wechat_pay/utils'
@@ -5,7 +6,9 @@ require 'wechat_pay/notify'
5
6
  require 'wechat_pay/version'
6
7
  require 'wechat_pay/package'
7
8
  require 'wechat_pay/prepay_id'
9
+ require 'wechat_pay/order_query'
8
10
  require 'wechat_pay/access_token'
11
+ require 'wechat_pay/deliver_notify'
9
12
 
10
13
  module WechatPay
11
14
  class << self
@@ -6,7 +6,7 @@ module WechatPay
6
6
  def self.payment(access_token, params)
7
7
  noncestr = SecureRandom.hex(16)
8
8
  timestamp = Time.now.to_i.to_s
9
- package = Package::App.generate(params)
9
+ package = Package.generate(params)
10
10
 
11
11
  prepay_id = PrepayId::App.generate(
12
12
  access_token,
@@ -0,0 +1,45 @@
1
+ require 'json'
2
+ require 'rest_client'
3
+
4
+ module WechatPay
5
+ module DeliverNotify
6
+ def self.request(access_token, params)
7
+ url = "https://api.weixin.qq.com/pay/delivernotify?access_token=#{access_token}"
8
+
9
+ params = {
10
+ deliver_msg: 'ok',
11
+ deliver_status: '1',
12
+ deliver_timestamp: Time.now.to_i.to_s
13
+ }.merge(params)
14
+
15
+ app_signature = generate_app_signature(params)
16
+
17
+ data = {
18
+ appid: WechatPay.app_id,
19
+ openid: params[:openid],
20
+ transid: params[:transid],
21
+ sign_method: "sha1",
22
+ deliver_msg: params[:deliver_msg],
23
+ out_trade_no: params[:out_trade_no],
24
+ app_signature: app_signature,
25
+ deliver_status: params[:deliver_status],
26
+ deliver_timestamp: params[:deliver_timestamp]
27
+ }
28
+
29
+ RestClient.post(url, JSON.generate(data)) do |response|
30
+ JSON.parse(response.body, symbolize_names: true)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def self.generate_app_signature(params)
37
+ attrs = {
38
+ appid: WechatPay.app_id,
39
+ appkey: WechatPay.pay_sign_key
40
+ }.merge(params)
41
+
42
+ Sign.sha1(attrs)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,23 @@
1
+ module WechatPay
2
+ module JS
3
+ def self.payment(params)
4
+ sign_attrs = {
5
+ package: Package.generate(params),
6
+ appid: WechatPay.app_id,
7
+ appkey: WechatPay.pay_sign_key,
8
+ noncestr: SecureRandom.hex(16),
9
+ timestamp: Time.now.to_i.to_s
10
+ }
11
+ pay_sign = Sign.sha1(sign_attrs)
12
+
13
+ {
14
+ app_id: sign_attrs[:appid],
15
+ timestamp: sign_attrs[:timestamp],
16
+ nonce_str: sign_attrs[:noncestr],
17
+ package: sign_attrs[:package],
18
+ pay_sign: pay_sign,
19
+ sign_type: 'SHA1'
20
+ }
21
+ end
22
+ end
23
+ end
@@ -2,7 +2,7 @@ module WechatPay
2
2
  module Notify
3
3
  def self.verify?(params)
4
4
  sign = params.delete(:sign) || params.delete('sign')
5
- !!sign && sign == Sign.md5(params)
5
+ !!sign && sign == Sign.md5_with_partner_key(params)
6
6
  end
7
7
  end
8
8
  end
@@ -0,0 +1,42 @@
1
+ require 'json'
2
+ require 'rest_client'
3
+
4
+ module WechatPay
5
+ module OrderQuery
6
+ def self.request(access_token, out_trade_no)
7
+ url = "https://api.weixin.qq.com/pay/orderquery?access_token=#{access_token}"
8
+ timestamp = Time.now.to_i.to_s
9
+ package = generate_package(out_trade_no)
10
+ app_signature = generate_app_signature(timestamp, package)
11
+
12
+ data = {
13
+ appid: WechatPay.app_id,
14
+ package: package,
15
+ timestamp: timestamp,
16
+ sign_method: "sha1",
17
+ app_signature: app_signature
18
+ }
19
+
20
+ RestClient.post(url, JSON.generate(data)) do |response|
21
+ JSON.parse(response.body, symbolize_names: true)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def self.generate_package(out_trade_no)
28
+ attrs = { out_trade_no: out_trade_no, partner: WechatPay.partner_id }
29
+ package = attrs.sort.map { |item| item.join('=') }.join('&')
30
+ "#{package}&sign=#{Sign.md5_with_partner_key(attrs)}"
31
+ end
32
+
33
+ def self.generate_app_signature(timestamp, package)
34
+ Sign.sha1(
35
+ appid: WechatPay.app_id,
36
+ appkey: WechatPay.pay_sign_key,
37
+ package: package,
38
+ timestamp: timestamp
39
+ )
40
+ end
41
+ end
42
+ end
@@ -1,29 +1,27 @@
1
1
  module WechatPay
2
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
- ]
3
+ PACKAGE_PARAMS = [
4
+ :bank_type, :body, :attach, :partner, :out_trade_no, :total_fee, :fee_type,
5
+ :notify_url, :spbill_create_ip, :time_start, :time_expire, :transport_fee,
6
+ :product_fee, :goods_tag, :input_charset
7
+ ]
9
8
 
10
- def self.generate(package_params)
11
- package_params = Utils.slice_hash(package_params, *PACKAGE_PARAMS)
9
+ def self.generate(package_params)
10
+ package_params = Utils.slice_hash(package_params, *PACKAGE_PARAMS)
12
11
 
13
- params = {
14
- bank_type: 'WX',
15
- fee_type: '1',
16
- input_charset: 'UTF-8',
17
- partner: WechatPay.partner_id
18
- }.merge(package_params)
12
+ params = {
13
+ bank_type: 'WX',
14
+ fee_type: '1',
15
+ input_charset: 'UTF-8',
16
+ partner: WechatPay.partner_id
17
+ }.merge(package_params)
19
18
 
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('&')
19
+ regexp = Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
20
+ escaped_params_str = params.sort.map do |key, value|
21
+ "#{key}=#{URI.escape(value.to_s, regexp)}"
22
+ end.join('&')
24
23
 
25
- "#{escaped_params_str}&sign=#{Sign.md5(params)}"
26
- end
24
+ "#{escaped_params_str}&sign=#{Sign.md5_with_partner_key(params)}"
27
25
  end
28
26
  end
29
27
  end
@@ -8,7 +8,7 @@ module WechatPay
8
8
  Digest::SHA1.hexdigest(str)
9
9
  end
10
10
 
11
- def self.md5(params)
11
+ def self.md5_with_partner_key(params)
12
12
  str = params.sort.map { |item| item.join('=') }.join('&')
13
13
  str << "&key=#{WechatPay.partner_key}"
14
14
  Digest::MD5.hexdigest(str).upcase
@@ -1,3 +1,3 @@
1
1
  module WechatPay
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe WechatPay::DeliverNotify do
4
+ before do
5
+ FakeWeb.register_uri(
6
+ :post,
7
+ %r|https://api\.weixin\.qq\.com/pay/delivernotify.+|,
8
+ body: %Q({"errcode":0,"errmsg":"ok"})
9
+ )
10
+ end
11
+
12
+ it ".request" do
13
+ params = {
14
+ openid: 'openid',
15
+ transid: 'transid',
16
+ out_trade_no: 'out_trade_no'
17
+ }
18
+
19
+ response = WechatPay::DeliverNotify.request('ACCESS_TOKEN', params)
20
+ response[:errcode].must_equal 0
21
+ response[:errmsg].must_equal 'ok'
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe WechatPay::JS do
4
+ it ".payment" do
5
+ params = {
6
+ body: 'body',
7
+ out_trade_no: 'out_trade_no',
8
+ total_fee: '2',
9
+ notify_url: 'http://your_domain.com/notify',
10
+ spbill_create_ip: '192.168.1.1'
11
+ }
12
+
13
+ package = WechatPay::Package.generate(params)
14
+ payment = WechatPay::JS.payment(params)
15
+
16
+ payment[:app_id].must_equal WechatPay.app_id
17
+ payment[:package].must_equal package
18
+ payment[:timestamp].wont_be_empty
19
+ payment[:nonce_str].wont_be_empty
20
+ payment[:pay_sign].wont_be_empty
21
+ payment[:sign_type].must_equal 'SHA1'
22
+ end
23
+ end
@@ -5,5 +5,14 @@ describe WechatPay::Notify do
5
5
  it "with nil sign" do
6
6
  WechatPay::Notify.verify?({}).must_equal(false)
7
7
  end
8
+
9
+ it "success" do
10
+ params = {b: 'b', a: 'a'}
11
+ str = params.sort.map { |i| i.join('=') }.join('&')
12
+ str << "&key=#{WechatPay.partner_key}"
13
+ sign = Digest::MD5.hexdigest(str).upcase
14
+
15
+ WechatPay::Notify.verify?(params.merge(sign: sign)).must_equal(true)
16
+ end
8
17
  end
9
18
  end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe WechatPay::OrderQuery do
4
+ before do
5
+ FakeWeb.register_uri(
6
+ :post,
7
+ %r|https://api\.weixin\.qq\.com/pay/orderquery.+|,
8
+ body: %Q({"errcode":0,"errmsg":"ok","order_info":{"ret_code":0}})
9
+ )
10
+ end
11
+
12
+ it ".request" do
13
+ response = WechatPay::OrderQuery.request('ACCESS_TOKEN', 'OUT_TRADE_NO')
14
+ response[:errcode].must_equal 0
15
+ response[:errmsg].must_equal 'ok'
16
+ response[:order_info].wont_be_nil
17
+ end
18
+ end
@@ -10,6 +10,6 @@ describe WechatPay::Package do
10
10
  spbill_create_ip: '127.0.0.1'
11
11
  }
12
12
 
13
- WechatPay::Package::App.generate(params).must_include '&sign='
13
+ WechatPay::Package.generate(params).must_include '&sign='
14
14
  end
15
15
  end
@@ -6,8 +6,8 @@ describe WechatPay::Sign do
6
6
  WechatPay::Sign.sha1(params).wont_be_empty
7
7
  end
8
8
 
9
- it ".md5" do
9
+ it ".md5_with_partner_key" do
10
10
  params = { appid: 'appid' }
11
- WechatPay::Sign.sha1(params).wont_be_empty
11
+ WechatPay::Sign.md5_with_partner_key(params).wont_be_empty
12
12
  end
13
13
  end
metadata CHANGED
@@ -1,79 +1,79 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wechat_pay
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.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-21 00:00:00.000000000 Z
11
+ date: 2014-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: 1.6.7
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.6.7
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.6'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.6'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: fakeweb
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '1.3'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.3'
69
- description: 微信支付
69
+ description: "微信支付"
70
70
  email:
71
71
  - kongruxi@gmail.com
72
72
  executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
- - .gitignore
76
+ - ".gitignore"
77
77
  - CHANGELOG.md
78
78
  - Gemfile
79
79
  - README.md
@@ -81,7 +81,10 @@ files:
81
81
  - lib/wechat_pay.rb
82
82
  - lib/wechat_pay/access_token.rb
83
83
  - lib/wechat_pay/app.rb
84
+ - lib/wechat_pay/deliver_notify.rb
85
+ - lib/wechat_pay/js.rb
84
86
  - lib/wechat_pay/notify.rb
87
+ - lib/wechat_pay/order_query.rb
85
88
  - lib/wechat_pay/package.rb
86
89
  - lib/wechat_pay/prepay_id.rb
87
90
  - lib/wechat_pay/sign.rb
@@ -90,7 +93,10 @@ files:
90
93
  - spec/spec_helper.rb
91
94
  - spec/wechat_pay/access_token_spec.rb
92
95
  - spec/wechat_pay/app_spec.rb
96
+ - spec/wechat_pay/deliver_notify_spec.rb
97
+ - spec/wechat_pay/js_spec.rb
93
98
  - spec/wechat_pay/notify_spec.rb
99
+ - spec/wechat_pay/order_query_spec.rb
94
100
  - spec/wechat_pay/package_spec.rb
95
101
  - spec/wechat_pay/prepay_id_spec.rb
96
102
  - spec/wechat_pay/sign_spec.rb
@@ -106,12 +112,12 @@ require_paths:
106
112
  - lib
107
113
  required_ruby_version: !ruby/object:Gem::Requirement
108
114
  requirements:
109
- - - '>='
115
+ - - ">="
110
116
  - !ruby/object:Gem::Version
111
117
  version: '0'
112
118
  required_rubygems_version: !ruby/object:Gem::Requirement
113
119
  requirements:
114
- - - '>='
120
+ - - ">="
115
121
  - !ruby/object:Gem::Version
116
122
  version: '0'
117
123
  requirements: []
@@ -119,12 +125,15 @@ rubyforge_project:
119
125
  rubygems_version: 2.2.2
120
126
  signing_key:
121
127
  specification_version: 4
122
- summary: 微信支付
128
+ summary: "微信支付"
123
129
  test_files:
124
130
  - spec/spec_helper.rb
125
131
  - spec/wechat_pay/access_token_spec.rb
126
132
  - spec/wechat_pay/app_spec.rb
133
+ - spec/wechat_pay/deliver_notify_spec.rb
134
+ - spec/wechat_pay/js_spec.rb
127
135
  - spec/wechat_pay/notify_spec.rb
136
+ - spec/wechat_pay/order_query_spec.rb
128
137
  - spec/wechat_pay/package_spec.rb
129
138
  - spec/wechat_pay/prepay_id_spec.rb
130
139
  - spec/wechat_pay/sign_spec.rb