wechat_pay 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -20,3 +20,4 @@ tmp
20
20
  *.o
21
21
  *.a
22
22
  mkmf.log
23
+ .ruby-version
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem 'rest-client', '~> 1.6.7'
4
+
3
5
  gemspec
data/README.md CHANGED
@@ -1,6 +1,11 @@
1
1
  # WechatPay
2
2
 
3
- Wechat Pay: https://open.weixin.qq.com
3
+ Wechat Pay: https://open.weixin.qq.com/cgi-bin/frame?t=home/pay_tmpl&lang=zh_CN
4
+
5
+ It contains:
6
+
7
+ * generate access_token
8
+ * generate payment params for App
4
9
 
5
10
  ## Installation
6
11
 
@@ -18,11 +23,56 @@ Or install it yourself as:
18
23
 
19
24
  ## Usage
20
25
 
21
- TODO: Write usage instructions here
26
+ ### Config
27
+
28
+ ```ruby
29
+ WechatPay.app_id = 'YOUR_APP_ID'
30
+ WechatPay.app_secret = 'YOUR_APP_SECRET'
31
+ WechatPay.pay_sign_key = 'YOUR_PAY_SIGN_KEY'
32
+ WechatPay.partner_id = 'YOUR_PARTNER_ID'
33
+ WechatPay.partner_key = 'YOUR_PARTNER_KEY'
34
+ ```
35
+
36
+ ### Access Token
37
+
38
+ ```ruby
39
+ WechatPay::AccessToken.generate # => { access_token: 'ACCESS_TOKEN', expires_in: 7200 }
40
+ ```
41
+
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)
43
+
44
+ You may wanna do something like this in Rails:
45
+
46
+ ```ruby
47
+ Rails.cache.fetch(:wechat_pay_access_token, expires: 7200.seconds raw: true) do
48
+ WechatPay::AccessToken.generate[:access_token]
49
+ end
50
+ ```
51
+
52
+ ### Payment params
53
+
54
+ ```ruby
55
+ # Please keep in mind that all key MUST be Symbol
56
+ params = {
57
+ body: 'body',
58
+ traceid: 'traceid', # Your user id
59
+ out_trade_no: 'out_trade_no', # Your order id
60
+ total_fee: '100', # 注意:单位是分,不是元
61
+ notify_url: 'http://your_domain.com/notify',
62
+ spbill_create_ip: '192.168.1.1'
63
+ }
64
+
65
+ WechatPay::App.payment('ACCESS_TOKEN', params)
66
+ # =>
67
+ # {
68
+ # prepay_id: 'PREPAY_ID',
69
+ # pay_sign: 'PAY_SIGN'
70
+ # }
71
+ ```
22
72
 
23
73
  ## Contributing
24
74
 
25
- 1. Fork it ( https://github.com/[my-github-username]/wechat_pay/fork )
75
+ 1. Fork it
26
76
  2. Create your feature branch (`git checkout -b my-new-feature`)
27
77
  3. Commit your changes (`git commit -am 'Add some feature'`)
28
78
  4. Push to the branch (`git push origin my-new-feature`)
data/Rakefile CHANGED
@@ -1,2 +1,9 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
2
3
 
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'spec'
6
+ t.pattern = 'spec/**/*_spec.rb'
7
+ end
8
+
9
+ task(default: :test)
@@ -0,0 +1,14 @@
1
+ require 'json'
2
+ require 'rest_client'
3
+
4
+ module WechatPay
5
+ module AccessToken
6
+ def self.generate
7
+ url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=#{WechatPay.app_id}&secret=#{WechatPay.app_secret}"
8
+
9
+ RestClient.get(url) do |response|
10
+ JSON.parse(response.body, symbolize_names: true)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,109 @@
1
+ require 'uri'
2
+ require 'json'
3
+ require 'rest_client'
4
+ require 'securerandom'
5
+ require 'digest/md5'
6
+
7
+ module WechatPay
8
+ module App
9
+
10
+ # required params:
11
+ # traceid, body, out_trade_no, total_fee, notify_url, spbill_create_ip
12
+ def self.payment(access_token, params)
13
+ noncestr = SecureRandom.hex(16)
14
+ timestamp = Time.now.to_i.to_s
15
+ package = generate_package(params)
16
+
17
+ app_signature = generate_app_signature(
18
+ noncestr: noncestr,
19
+ timestamp: timestamp,
20
+ 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
31
+ )
32
+
33
+ pay_sign = Sign.generate(
34
+ appid: WechatPay.app_id,
35
+ appkey: WechatPay.pay_sign_key,
36
+ noncestr: noncestr,
37
+ package: 'Sign=WXpay',
38
+ partnerid: WechatPay.partner_id,
39
+ prepayid: prepay_id,
40
+ timestamp: timestamp
41
+ )
42
+
43
+ { prepay_id: prepay_id, pay_sign: pay_sign }
44
+ end
45
+
46
+ private
47
+
48
+ def self.generate_prepay_id(access_token, params)
49
+ url = "https://api.weixin.qq.com/pay/genprepay?access_token=#{access_token}"
50
+
51
+ params = {
52
+ appid: WechatPay.app_id,
53
+ traceid: params[:traceid],
54
+ noncestr: params[:noncestr],
55
+ package: params[:package],
56
+ timestamp: params[:timestamp],
57
+ app_signature: params[:app_signature],
58
+ sign_method: 'sha1'
59
+ }
60
+
61
+ RestClient.post(url, JSON.generate(params)) do |response|
62
+ JSON.parse(response.body)['prepayid']
63
+ end
64
+ end
65
+
66
+ PACKAGE_PARAMS = [
67
+ :bank_type, :body, :attach, :partner, :out_trade_no, :total_fee, :fee_type,
68
+ :notify_url, :spbill_create_ip, :time_start, :time_expire, :transport_fee,
69
+ :product_fee, :goods_tag, :input_charset
70
+ ]
71
+
72
+ def self.generate_package(package_params)
73
+ package_params = Utils.slice_hash(package_params, *PACKAGE_PARAMS)
74
+
75
+ params = {
76
+ bank_type: 'WX',
77
+ fee_type: '1',
78
+ input_charset: 'UTF-8',
79
+ partner: WechatPay.partner_id
80
+ }.merge(package_params)
81
+
82
+ regexp = Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
83
+ escaped_params_str = params.sort.map do |key, value|
84
+ "#{key}=#{URI.escape(value.to_s, regexp)}"
85
+ end.join('&')
86
+
87
+ "#{escaped_params_str}&sign=#{package_sign(params)}"
88
+ end
89
+
90
+ def self.generate_app_signature(signature_params)
91
+ params = {
92
+ appid: WechatPay.app_id,
93
+ appkey: WechatPay.pay_sign_key,
94
+ noncestr: signature_params[:noncestr],
95
+ package: signature_params[:package],
96
+ timestamp: signature_params[:timestamp],
97
+ traceid: signature_params[:traceid]
98
+ }
99
+
100
+ Sign.generate(params)
101
+ end
102
+
103
+ def self.package_sign(params)
104
+ str = params.sort.map { |item| item.join('=') }.join('&')
105
+ str << "&key=#{WechatPay.partner_key}"
106
+ Digest::MD5.hexdigest(str).upcase
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,10 @@
1
+ require 'digest/sha1'
2
+
3
+ module WechatPay
4
+ module Sign
5
+ def self.generate(params)
6
+ str = params.sort.map { |item| item.join('=') }.join('&')
7
+ Digest::SHA1.hexdigest(str)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ module WechatPay
2
+ module Utils
3
+ def self.slice_hash(hash, *keys)
4
+ keys.each_with_object({}) { |k, h| h[k] = hash[k] if hash.has_key?(k) }
5
+ end
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module WechatPay
2
- VERSION = "0.0.0"
2
+ VERSION = "0.0.1"
3
3
  end
data/lib/wechat_pay.rb CHANGED
@@ -1,5 +1,15 @@
1
- require "wechat_pay/version"
1
+ require 'wechat_pay/version'
2
+ require 'wechat_pay/access_token'
3
+ require 'wechat_pay/app'
4
+ require 'wechat_pay/sign'
5
+ require 'wechat_pay/utils'
2
6
 
3
7
  module WechatPay
4
- # Your code goes here...
8
+ 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
14
+ end
5
15
  end
@@ -0,0 +1,10 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+ require 'wechat_pay'
4
+ require 'fakeweb'
5
+
6
+ WechatPay.app_id = 'app_id'
7
+ WechatPay.app_secret = 'app_secret'
8
+ WechatPay.pay_sign_key = 'pay_sign_key'
9
+ WechatPay.partner_id = 'partner_id'
10
+ WechatPay.partner_key = 'partner_key'
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe WechatPay::AccessToken do
4
+ before do
5
+ @access_token = "ACCESS_TOKEN"
6
+ FakeWeb.register_uri(
7
+ :get,
8
+ %r|https://api\.weixin\.qq\.com/cgi-bin/token.+|,
9
+ body: %Q({"access_token":"#{@access_token}","expires_in":7200})
10
+ )
11
+ end
12
+
13
+ it ".generate" do
14
+ data = WechatPay::AccessToken.generate
15
+ data[:access_token].must_equal @access_token
16
+ data[:expires_in].must_be_kind_of Fixnum
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe WechatPay::App do
4
+
5
+ it ".payment" do
6
+ prepay_id = "PREPAY_ID"
7
+ prepay_params = {
8
+ traceid: 'traceid',
9
+ body: 'body',
10
+ out_trade_no: 'out_trade_no',
11
+ total_fee: '2',
12
+ notify_url: 'http://your_domain.com/notify',
13
+ spbill_create_ip: '192.168.1.1'
14
+ }
15
+
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)
23
+
24
+ payment[:prepay_id].must_equal prepay_id
25
+ payment[:pay_sign].wont_be_empty
26
+ end
27
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe WechatPay::Sign do
4
+ it ".generate" do
5
+ params = { appid: 'appid', appkey: 'appkey' }
6
+ WechatPay::Sign.generate(params).wont_be_empty
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe WechatPay::Utils do
4
+ it ".slice_hash" do
5
+ hash = { allowed: 'allowed', not_allowed: 'not_allowed' }
6
+ data = WechatPay::Utils.slice_hash(hash, :allowed, :other)
7
+
8
+ data[:allowed].wont_be_empty
9
+ data[:not_allowed].must_be_nil
10
+ end
11
+ end
data/wechat_pay.gemspec CHANGED
@@ -18,6 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_dependency "rest-client", "~> 1.6.7"
22
+
21
23
  spec.add_development_dependency "bundler", "~> 1.6"
22
24
  spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "fakeweb", "~> 1.3"
23
26
  end
metadata CHANGED
@@ -1,43 +1,80 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wechat_pay
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - HungYuHei
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-06-25 00:00:00.000000000 Z
12
+ date: 2014-07-18 00:00:00.000000000 Z
12
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.6.7
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.6.7
13
30
  - !ruby/object:Gem::Dependency
14
31
  name: bundler
15
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
16
34
  requirements:
17
- - - "~>"
35
+ - - ~>
18
36
  - !ruby/object:Gem::Version
19
37
  version: '1.6'
20
38
  type: :development
21
39
  prerelease: false
22
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
23
42
  requirements:
24
- - - "~>"
43
+ - - ~>
25
44
  - !ruby/object:Gem::Version
26
45
  version: '1.6'
27
46
  - !ruby/object:Gem::Dependency
28
47
  name: rake
29
48
  requirement: !ruby/object:Gem::Requirement
49
+ none: false
30
50
  requirements:
31
- - - ">="
51
+ - - ! '>='
32
52
  - !ruby/object:Gem::Version
33
53
  version: '0'
34
54
  type: :development
35
55
  prerelease: false
36
56
  version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
37
58
  requirements:
38
- - - ">="
59
+ - - ! '>='
39
60
  - !ruby/object:Gem::Version
40
61
  version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: fakeweb
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.3'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '1.3'
41
78
  description: Wechat pay
42
79
  email:
43
80
  - kongruxi@gmail.com
@@ -45,36 +82,57 @@ executables: []
45
82
  extensions: []
46
83
  extra_rdoc_files: []
47
84
  files:
48
- - ".gitignore"
85
+ - .gitignore
49
86
  - Gemfile
50
87
  - LICENSE.txt
51
88
  - README.md
52
89
  - Rakefile
53
90
  - lib/wechat_pay.rb
91
+ - lib/wechat_pay/access_token.rb
92
+ - lib/wechat_pay/app.rb
93
+ - lib/wechat_pay/sign.rb
94
+ - lib/wechat_pay/utils.rb
54
95
  - lib/wechat_pay/version.rb
96
+ - spec/spec_helper.rb
97
+ - spec/wechat_pay/access_token_spec.rb
98
+ - spec/wechat_pay/app_spec.rb
99
+ - spec/wechat_pay/sign_spec.rb
100
+ - spec/wechat_pay/utils_spec.rb
55
101
  - wechat_pay.gemspec
56
102
  homepage: https://github.com/HungYuHei/wechat_pay
57
103
  licenses:
58
104
  - MIT
59
- metadata: {}
60
105
  post_install_message:
61
106
  rdoc_options: []
62
107
  require_paths:
63
108
  - lib
64
109
  required_ruby_version: !ruby/object:Gem::Requirement
110
+ none: false
65
111
  requirements:
66
- - - ">="
112
+ - - ! '>='
67
113
  - !ruby/object:Gem::Version
68
114
  version: '0'
115
+ segments:
116
+ - 0
117
+ hash: -3477914996839962559
69
118
  required_rubygems_version: !ruby/object:Gem::Requirement
119
+ none: false
70
120
  requirements:
71
- - - ">="
121
+ - - ! '>='
72
122
  - !ruby/object:Gem::Version
73
123
  version: '0'
124
+ segments:
125
+ - 0
126
+ hash: -3477914996839962559
74
127
  requirements: []
75
128
  rubyforge_project:
76
- rubygems_version: 2.2.2
129
+ rubygems_version: 1.8.23
77
130
  signing_key:
78
- specification_version: 4
131
+ specification_version: 3
79
132
  summary: Wechat pay
80
- test_files: []
133
+ test_files:
134
+ - spec/spec_helper.rb
135
+ - spec/wechat_pay/access_token_spec.rb
136
+ - spec/wechat_pay/app_spec.rb
137
+ - spec/wechat_pay/sign_spec.rb
138
+ - spec/wechat_pay/utils_spec.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 9c6e656add44c9dcdbd5cacfd0a4668c2aba0b3d
4
- data.tar.gz: 752cd3c99e54c2136a403fe7d23d3b5d3d38c2b8
5
- SHA512:
6
- metadata.gz: 05acf47fb42f9746c73817e241385d361f78f4c61f40141bf186718f1b2f34a2e7644656bd3b2f7abb0d2930ec566e5098f593afe3d23a7e9fa2ca33d0c3a18f
7
- data.tar.gz: 4dd135ba24d228e0874ae56e76ff2a4fcf5ab7a84a39a6162d06d8f55a2f1957f72c790f48866d081cd31cff5924ee8c609767955a4d09c35036e7dfa9eaa217