wechat_pay 0.0.0 → 0.0.1

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/.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