wechat_pay 0.2.0 → 0.3.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.
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