weixin 1.0.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.
- data/Gemfile +3 -0
- data/Gemfile.lock +24 -0
- data/README.md +72 -0
- data/Rakefile +10 -0
- data/lib/weixin.rb +8 -0
- data/lib/weixin/app.rb +36 -0
- data/lib/weixin/sign.rb +55 -0
- data/test/test_helper.rb +9 -0
- data/test/weixin/app_test.rb +35 -0
- data/weixin.gemspec +19 -0
- metadata +130 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
weixin (1.0.0)
|
|
5
|
+
faraday
|
|
6
|
+
httpclient
|
|
7
|
+
json
|
|
8
|
+
|
|
9
|
+
GEM
|
|
10
|
+
remote: https://ruby.taobao.org/
|
|
11
|
+
specs:
|
|
12
|
+
faraday (0.9.0)
|
|
13
|
+
multipart-post (>= 1.2, < 3)
|
|
14
|
+
httpclient (2.5.3.2)
|
|
15
|
+
json (1.8.1)
|
|
16
|
+
minitest (5.4.2)
|
|
17
|
+
multipart-post (2.0.0)
|
|
18
|
+
|
|
19
|
+
PLATFORMS
|
|
20
|
+
ruby
|
|
21
|
+
|
|
22
|
+
DEPENDENCIES
|
|
23
|
+
minitest (~> 5)
|
|
24
|
+
weixin!
|
data/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Winxin
|
|
2
|
+
|
|
3
|
+
A simple Wechat pay ruby gem.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
Add this line to your Gemfile:
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
gem 'weixin'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
And then execute:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
$ bundle
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Config
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
# required
|
|
26
|
+
Weixin.appid = 'YOUR_APPID'
|
|
27
|
+
Weixin.appsecret = 'YOUR_APPSECRET'
|
|
28
|
+
Weixin.partnerid = 'YOUR_PARTNERID'
|
|
29
|
+
Weixin.partnerkey = 'YOUR_PARTNERKEY'
|
|
30
|
+
Weixin.appkey = 'YOUR_APPKEY'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### APIs
|
|
34
|
+
|
|
35
|
+
**Check official document for detailed request params and return fields**
|
|
36
|
+
|
|
37
|
+
#### unifiedorder
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
# required fields
|
|
41
|
+
params = {
|
|
42
|
+
'bank_type' => 'WX'
|
|
43
|
+
'body' => 'test',
|
|
44
|
+
'fee_type' => '',
|
|
45
|
+
'out_trade_no' => '123456789',
|
|
46
|
+
'total_fee' 1,
|
|
47
|
+
'spbill_create_ip' '127.0.0.1',
|
|
48
|
+
'notify_url' 'http://making.dev'
|
|
49
|
+
}
|
|
50
|
+
Weixin::App.prepay_id(params, 'YOUR_ACCESS_TOKEN')
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## Contributing
|
|
55
|
+
|
|
56
|
+
Bug report or pull request are welcome.
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
### Make a pull request
|
|
60
|
+
|
|
61
|
+
1. Fork it
|
|
62
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
63
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
64
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
65
|
+
5. Create new Pull Request
|
|
66
|
+
|
|
67
|
+
Please write unit test with your code if necessary.
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
This project rocks and uses MIT-LICENSE.
|
data/Rakefile
ADDED
data/lib/weixin.rb
ADDED
data/lib/weixin/app.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'faraday'
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Weixin
|
|
6
|
+
module App
|
|
7
|
+
class << self
|
|
8
|
+
|
|
9
|
+
def prepay_id(params, access_token)
|
|
10
|
+
Weixin.noncestr = rand(10**33).to_s
|
|
11
|
+
Weixin.timestamp = Time.now.to_i.to_s
|
|
12
|
+
|
|
13
|
+
package = Weixin::Sign.gen_package(params)
|
|
14
|
+
app_signature = Weixin::Sign.gen_app_signature(package)
|
|
15
|
+
|
|
16
|
+
data = { 'appid' => Weixin.appid,
|
|
17
|
+
'traceid' => 'weixin',
|
|
18
|
+
'noncestr' => Weixin.noncestr,
|
|
19
|
+
'package' => package,
|
|
20
|
+
'timestamp' => Weixin.timestamp,
|
|
21
|
+
'app_signature' => app_signature,
|
|
22
|
+
'sign_method' => 'sha1' }
|
|
23
|
+
|
|
24
|
+
url = "https://api.weixin.qq.com/pay/genprepay?access_token=#{access_token}"
|
|
25
|
+
response = Faraday.new(url){ |f| f.adapter :httpclient }.post do |req|
|
|
26
|
+
req.headers['Content-Type'] = 'application/json'
|
|
27
|
+
req.body = data.to_json
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
result = JSON.parse response.body
|
|
31
|
+
result['errcode'] == 0 ? result['prepayid'] : nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
data/lib/weixin/sign.rb
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require 'digest/sha1'
|
|
3
|
+
require 'digest/md5'
|
|
4
|
+
|
|
5
|
+
module Weixin
|
|
6
|
+
module Sign
|
|
7
|
+
class << self
|
|
8
|
+
|
|
9
|
+
def gen_package(sign_params)
|
|
10
|
+
sign_params = sign_params.merge('partner' => Weixin.partnerid)
|
|
11
|
+
requires = %w(bank_type body fee_type input_charset notify_url out_trade_no partner spbill_create_ip total_fee)
|
|
12
|
+
check(sign_params, requires)
|
|
13
|
+
md5_string = Digest::MD5.hexdigest(join(sign_params, Weixin.partnerkey))
|
|
14
|
+
|
|
15
|
+
"#{join(sign_params, nil, true)}&sign=#{md5_string.upcase}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def gen_app_signature(package)
|
|
19
|
+
sign_params = { 'appid' => Weixin.appid,
|
|
20
|
+
'appkey' => Weixin.appkey,
|
|
21
|
+
'noncestr' => Weixin.noncestr,
|
|
22
|
+
'package' => package,
|
|
23
|
+
'timestamp' => Weixin.timestamp,
|
|
24
|
+
'traceid' => 'weixin' }
|
|
25
|
+
Digest::SHA1.hexdigest(join(sign_params))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def check(hash_params, requires)
|
|
31
|
+
requires.each do |r|
|
|
32
|
+
if !hash_params.include?(r)
|
|
33
|
+
raise "Require parameter #{r}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
if hash_params['out_trade_no'] && (hash_params['out_trade_no'].length > 32 || hash_params['out_trade_no'].length < 8)
|
|
37
|
+
raise "Package Error, out_trade_no's length must be between 8 and 32"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
hash_params
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def join(sign_params, partnerkey = nil, url_encode = false)
|
|
44
|
+
result_string = sign_params.sort.reduce('') do |string, array|
|
|
45
|
+
value = array.last.to_s
|
|
46
|
+
value = URI.escape(value) if url_encode
|
|
47
|
+
string + array.first.to_s + '=' + value + '&'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
partnerkey ? "#{result_string}key=#{partnerkey}" : result_string[0, result_string.length - 1]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class Weixin::AppTest < MiniTest::Test
|
|
4
|
+
|
|
5
|
+
def test_prepayid_lack_params
|
|
6
|
+
begin
|
|
7
|
+
Weixin::App.prepay_id({}, '123')
|
|
8
|
+
assert false, "should raise an error"
|
|
9
|
+
rescue
|
|
10
|
+
assert true
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_out_trade_no_length
|
|
15
|
+
begin
|
|
16
|
+
Weixin::App.prepay_id({'bank_type' => '', 'body' => '', 'fee_type' => '',
|
|
17
|
+
'input_charset' => '', 'notify_url' => '', 'out_trade_no' => '',
|
|
18
|
+
'spbill_create_ip' => ''}, '123')
|
|
19
|
+
assert false, "should raise an error"
|
|
20
|
+
rescue
|
|
21
|
+
assert true
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_total_fee_params
|
|
26
|
+
begin
|
|
27
|
+
Weixin::App.prepay_id({'bank_type' => '', 'body' => '', 'fee_type' => '',
|
|
28
|
+
'input_charset' => '', 'notify_url' => '', 'out_trade_no' => '123456789',
|
|
29
|
+
'spbill_create_ip' => ''}, '123')
|
|
30
|
+
assert false, "should raise an error"
|
|
31
|
+
rescue
|
|
32
|
+
assert true
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/weixin.gemspec
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
Gem::Specification.new do |spec|
|
|
3
|
+
spec.authors = ["Kungs"]
|
|
4
|
+
spec.description = %q(weixin is ruby SDK for weixin pay.)
|
|
5
|
+
spec.email = "kungs.yung@gmail.com"
|
|
6
|
+
spec.homepage = "https://github.com/kungs/weixin"
|
|
7
|
+
spec.licenses = %w[MIT]
|
|
8
|
+
spec.name = "weixin"
|
|
9
|
+
spec.files = `git ls-files`.split("\n")
|
|
10
|
+
spec.require_paths = %w[lib]
|
|
11
|
+
spec.summary = %q(weixin SDK for ruby)
|
|
12
|
+
spec.version = '1.0.0'
|
|
13
|
+
|
|
14
|
+
spec.add_dependency("faraday")
|
|
15
|
+
spec.add_dependency("httpclient")
|
|
16
|
+
spec.add_dependency("json")
|
|
17
|
+
|
|
18
|
+
spec.add_development_dependency "minitest", '~> 5'
|
|
19
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: weixin
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: 23
|
|
5
|
+
prerelease:
|
|
6
|
+
segments:
|
|
7
|
+
- 1
|
|
8
|
+
- 0
|
|
9
|
+
- 0
|
|
10
|
+
version: 1.0.0
|
|
11
|
+
platform: ruby
|
|
12
|
+
authors:
|
|
13
|
+
- Kungs
|
|
14
|
+
autorequire:
|
|
15
|
+
bindir: bin
|
|
16
|
+
cert_chain: []
|
|
17
|
+
|
|
18
|
+
date: 2014-11-12 00:00:00 Z
|
|
19
|
+
dependencies:
|
|
20
|
+
- !ruby/object:Gem::Dependency
|
|
21
|
+
name: faraday
|
|
22
|
+
prerelease: false
|
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
24
|
+
none: false
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
hash: 3
|
|
29
|
+
segments:
|
|
30
|
+
- 0
|
|
31
|
+
version: "0"
|
|
32
|
+
type: :runtime
|
|
33
|
+
version_requirements: *id001
|
|
34
|
+
- !ruby/object:Gem::Dependency
|
|
35
|
+
name: httpclient
|
|
36
|
+
prerelease: false
|
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
|
38
|
+
none: false
|
|
39
|
+
requirements:
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
hash: 3
|
|
43
|
+
segments:
|
|
44
|
+
- 0
|
|
45
|
+
version: "0"
|
|
46
|
+
type: :runtime
|
|
47
|
+
version_requirements: *id002
|
|
48
|
+
- !ruby/object:Gem::Dependency
|
|
49
|
+
name: json
|
|
50
|
+
prerelease: false
|
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
|
52
|
+
none: false
|
|
53
|
+
requirements:
|
|
54
|
+
- - ">="
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
hash: 3
|
|
57
|
+
segments:
|
|
58
|
+
- 0
|
|
59
|
+
version: "0"
|
|
60
|
+
type: :runtime
|
|
61
|
+
version_requirements: *id003
|
|
62
|
+
- !ruby/object:Gem::Dependency
|
|
63
|
+
name: minitest
|
|
64
|
+
prerelease: false
|
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
|
66
|
+
none: false
|
|
67
|
+
requirements:
|
|
68
|
+
- - ~>
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
hash: 9
|
|
71
|
+
segments:
|
|
72
|
+
- 5
|
|
73
|
+
version: "5"
|
|
74
|
+
type: :development
|
|
75
|
+
version_requirements: *id004
|
|
76
|
+
description: weixin is ruby SDK for weixin pay.
|
|
77
|
+
email: kungs.yung@gmail.com
|
|
78
|
+
executables: []
|
|
79
|
+
|
|
80
|
+
extensions: []
|
|
81
|
+
|
|
82
|
+
extra_rdoc_files: []
|
|
83
|
+
|
|
84
|
+
files:
|
|
85
|
+
- Gemfile
|
|
86
|
+
- Gemfile.lock
|
|
87
|
+
- README.md
|
|
88
|
+
- Rakefile
|
|
89
|
+
- lib/weixin.rb
|
|
90
|
+
- lib/weixin/app.rb
|
|
91
|
+
- lib/weixin/sign.rb
|
|
92
|
+
- test/test_helper.rb
|
|
93
|
+
- test/weixin/app_test.rb
|
|
94
|
+
- weixin.gemspec
|
|
95
|
+
homepage: https://github.com/kungs/weixin
|
|
96
|
+
licenses:
|
|
97
|
+
- MIT
|
|
98
|
+
post_install_message:
|
|
99
|
+
rdoc_options: []
|
|
100
|
+
|
|
101
|
+
require_paths:
|
|
102
|
+
- lib
|
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
|
+
none: false
|
|
105
|
+
requirements:
|
|
106
|
+
- - ">="
|
|
107
|
+
- !ruby/object:Gem::Version
|
|
108
|
+
hash: 3
|
|
109
|
+
segments:
|
|
110
|
+
- 0
|
|
111
|
+
version: "0"
|
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
|
+
none: false
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
hash: 3
|
|
118
|
+
segments:
|
|
119
|
+
- 0
|
|
120
|
+
version: "0"
|
|
121
|
+
requirements: []
|
|
122
|
+
|
|
123
|
+
rubyforge_project:
|
|
124
|
+
rubygems_version: 1.8.29
|
|
125
|
+
signing_key:
|
|
126
|
+
specification_version: 3
|
|
127
|
+
summary: weixin SDK for ruby
|
|
128
|
+
test_files: []
|
|
129
|
+
|
|
130
|
+
has_rdoc:
|