wechat-api 0.1.1 → 0.1.3

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: 719b629d7118b6d301d4aefe2f7672165dd911bf
4
- data.tar.gz: ef220a300a12fde99086b07d82146dec8778b28c
3
+ metadata.gz: 8a1da7465e7436ff9a4d1f959f198a63ffc3e028
4
+ data.tar.gz: 4bfc9ba3e18733fe9146679b32b295665934d2d8
5
5
  SHA512:
6
- metadata.gz: 1cfb62e73ee7d3b47ae830f98a3cfbe28ce65883b8cc33e2ebc49a13d363bdb0f25459d498508c1a307836871bfd890f8cd5096be42045ed7f16c3e335d7f44a
7
- data.tar.gz: 95e2407f7f8e3d0273424754ef9d7a2f1008ce1ea5055397878bcdf39b8ff78e82b5f2e57113a6bee31051c7e751a22d8ab32a638d944df488bc21b73cf310cb
6
+ metadata.gz: d79b3b01a2fbb922ea6019af273d12244cdda7e15bc250e30f648a2c9c7a94c76f8759619304edb91f911563a5c5e4e47ff62c035e70bab10bdd00abaaab2bf7
7
+ data.tar.gz: 4a7aba85ce5c46fb22b8101c25b97c28330b9795db8cbeaf5acb2fc1da5fd2526ae3fbef4279bf7b520c0454ca1392ca76ff1aae4f024bfcff5d1fdc3fe36ec4
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'http://ruby.taobao.org'
1
+ source 'https://ruby.taobao.org'
2
2
  # Specify your gem's dependencies in ucpaas.gemspec
3
3
  gemspec
4
4
 
@@ -1 +1,2 @@
1
1
  require 'wechat/api'
2
+ require 'wechat/pay'
@@ -42,7 +42,7 @@ module Wechat
42
42
  response = MultiJson.load(resp.body)
43
43
  return handle_error(response) if response['errcode']
44
44
  @access_token = response['access_token']
45
- File.open(@token_file, 'w') { |f| f.write(resp.body) } if token
45
+ File.open(@token_file, 'w') { |f| f.write(resp.body) } if @access_token
46
46
  @access_token
47
47
  end
48
48
 
@@ -27,6 +27,11 @@ module Wechat
27
27
 
28
28
  post 'qrcode/create', params
29
29
  end
30
+
31
+ def js_ticket
32
+ res = get 'ticket/getticket', type: :jsapi
33
+ res['ticket']
34
+ end
30
35
  end
31
36
  end
32
37
  end
@@ -2,6 +2,6 @@
2
2
  module Wechat
3
3
  #
4
4
  module Api
5
- VERSION = '0.1.1'
5
+ VERSION = '0.1.3'
6
6
  end
7
7
  end
@@ -0,0 +1,7 @@
1
+ require 'wechat/pay/client'
2
+
3
+ module Wechat
4
+ #
5
+ module Pay
6
+ end
7
+ end
@@ -0,0 +1,116 @@
1
+ require 'rest-client'
2
+ require 'logger'
3
+ require 'multi_json'
4
+ require 'openssl'
5
+ require 'nori'
6
+ require 'gyoku'
7
+
8
+ require 'wechat/pay/redpack'
9
+
10
+ module Wechat
11
+ module Pay
12
+ class PayError < StandardError; end
13
+ class NoAuthError < PayError; end
14
+ class NotEnoughError < PayError; end
15
+ class TimeLimitedError < PayError; end
16
+ class MoneyLimitedError < PayError; end
17
+
18
+ #
19
+ class Client
20
+ include Redpack
21
+ BASE_URL = 'https://api.mch.weixin.qq.com'
22
+ REQUIRED_OPTS = %w(key password cert sign_key).map(&:to_sym).freeze
23
+ ERRORS = {
24
+ 'NO_AUTH' => NoAuthError,
25
+ 'NOTENOUGH' => NotEnoughError,
26
+ 'TIME_LIMITED' => TimeLimitedError,
27
+ 'MONEY_LIMITED' => MoneyLimitedError
28
+ }
29
+
30
+ attr_accessor :logger
31
+
32
+ def initialize(mch_id, wxappid, opts = {})
33
+ @mch_id = mch_id
34
+ @wxappid = wxappid
35
+ @opts = Hash[opts.map { |k, v| [k.to_sym, v] }]
36
+ unless (REQUIRED_OPTS - @opts.keys).empty?
37
+ fail format('%s required', REQUIRED_OPTS.join(','))
38
+ end
39
+ @logger = Logger.new(STDOUT)
40
+ rsa_setup
41
+ @parser = Nori.new
42
+ end
43
+
44
+ def post(path, params)
45
+ merged_params = merge(params)
46
+ logger.debug { merged_params }
47
+ resp = resource(path).post(xml(sign(merged_params)))
48
+ handle(resp)
49
+ rescue RestClient::ExceptionWithResponse => err
50
+ raise PayError, err.response
51
+ end
52
+
53
+ private
54
+
55
+ def handle(resp)
56
+ response = parser.parse(resp)
57
+ check(response)
58
+ response
59
+ end
60
+
61
+ def check(r)
62
+ return if r['xml']['result_code'] == 'SUCCESS'
63
+ handle_error(r['xml']['err_code'], r)
64
+ end
65
+
66
+ def handle_error(error_code, response)
67
+ fail ERRORS[error_code] || PayError, response.inspect
68
+ end
69
+
70
+ def rsa_setup
71
+ @rsa_key = OpenSSL::PKey::RSA.new @opts[:key], @opts[:password]
72
+ @rsa_cert = OpenSSL::X509::Certificate.new @opts[:cert]
73
+ rescue StandardError => e
74
+ logger.error { e.inspect }
75
+ end
76
+
77
+ def resource(path)
78
+ RestClient.log = logger
79
+ RestClient::Resource.new\
80
+ [BASE_URL, path].join,
81
+ ssl_client_key: @rsa_key,
82
+ ssl_client_cert: @rsa_cert,
83
+ verify_ssl: OpenSSL::SSL::VERIFY_NONE
84
+ end
85
+
86
+ def xml(hash)
87
+ Gyoku.xml({ xml: hash }, key_converter: :none)
88
+ end
89
+
90
+ def sign(params)
91
+ ordered = trim_and_sort(params)
92
+ keystr = format('key=%s', @opts[:sign_key])
93
+ origin =
94
+ ordered.map { |k, v| [k, v].join('=') }.push(keystr).join('&')
95
+ sign = Digest::MD5.hexdigest(origin).upcase
96
+ logger.debug { format('origin: %s, sign: %s', origin, sign) }
97
+ params.merge(sign: sign)
98
+ end
99
+
100
+ def trim_and_sort(params)
101
+ params.delete_if { |_k, v| v.blank? }
102
+ Hash[params.sort]
103
+ end
104
+
105
+ def merge(params)
106
+ params.reverse_merge\
107
+ mch_id: @mch_id,
108
+ nonce_str: nonce_str
109
+ end
110
+
111
+ def nonce_str
112
+ SecureRandom.hex
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,39 @@
1
+ require 'securerandom'
2
+
3
+ module Wechat
4
+ module Pay
5
+ #
6
+ module Redpack
7
+ def redpack(transaction_id, openid, params = {})
8
+ post\
9
+ '/mmpaymkttransfers/sendredpack',
10
+ params.merge(
11
+ mch_billno: tran_id(transaction_id),
12
+ wxappid: @wxappid, re_openid: openid
13
+ )
14
+ end
15
+
16
+ def group_redpack(transaction_id, openid, params = {})
17
+ post\
18
+ '/mmpaymkttransfers/sendgroupredpack',
19
+ params.merge(
20
+ mch_billno: tran_id(transaction_id),
21
+ wxappid: @wxappid, re_openid: openid
22
+ )
23
+ end
24
+
25
+ def redpack_info(transaction_id)
26
+ post\
27
+ '/mmpaymkttransfers/gethbinfo',
28
+ mch_billno: tran_id(transaction_id),
29
+ bill_type: 'MCHT', appid: @wxappid
30
+ end
31
+
32
+ private
33
+
34
+ def tran_id(origin)
35
+ format('%s%s', @mch_id, origin)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ RSpec.describe Wechat::Pay::Client do
4
+ subject do
5
+ described_class.new\
6
+ 'mch_id', 'wxappid',
7
+ key: 'key', password: 'password', cert: 'cert',
8
+ sign_key: 'sign_key'
9
+ end
10
+
11
+ it :trim_and_sort do
12
+ expect(
13
+ subject.send(:trim_and_sort, b: 2, c: 3, a: 1).values
14
+ ).to start_with(1)
15
+ end
16
+
17
+ it :sign do
18
+ expect(subject.send(:sign, b: 2, a: 1)).to have_key(:sign)
19
+ end
20
+
21
+ it :xml do
22
+ expect(subject.send(:xml, b_1: 2, a: 1)).to match(/xml/)
23
+ end
24
+ end
@@ -17,8 +17,11 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_runtime_dependency "faraday", "~> 0.9"
21
- spec.add_runtime_dependency "multi_json", "~> 1.2"
20
+ spec.add_runtime_dependency "faraday", ">= 0.9"
21
+ spec.add_runtime_dependency "rest-client", ">= 1.7.0"
22
+ spec.add_runtime_dependency "multi_json", ">= 1.2"
23
+ spec.add_runtime_dependency 'gyoku', '>= 1.0.0'
24
+ spec.add_runtime_dependency 'nori'
22
25
  spec.add_development_dependency "bundler"
23
26
  spec.add_development_dependency "rake"
24
27
  spec.add_development_dependency "pry"
metadata CHANGED
@@ -1,43 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wechat-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Wong
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-25 00:00:00.000000000 Z
11
+ date: 2015-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0.9'
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: '0.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rest-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.7.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.7.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: multi_json
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - "~>"
45
+ - - ">="
32
46
  - !ruby/object:Gem::Version
33
47
  version: '1.2'
34
48
  type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - "~>"
52
+ - - ">="
39
53
  - !ruby/object:Gem::Version
40
54
  version: '1.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: gyoku
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 1.0.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 1.0.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: nori
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
41
83
  - !ruby/object:Gem::Dependency
42
84
  name: bundler
43
85
  requirement: !ruby/object:Gem::Requirement
@@ -129,8 +171,12 @@ files:
129
171
  - lib/wechat/api/user.rb
130
172
  - lib/wechat/api/util.rb
131
173
  - lib/wechat/api/version.rb
174
+ - lib/wechat/pay.rb
175
+ - lib/wechat/pay/client.rb
176
+ - lib/wechat/pay/redpack.rb
132
177
  - spec/spec_helper.rb
133
178
  - spec/wechat/api/client_spec.rb
179
+ - spec/wechat/pay/client_spec.rb
134
180
  - wechat-api.gemspec
135
181
  homepage: https://github.com/lazing/wechat-api
136
182
  licenses:
@@ -159,4 +205,5 @@ summary: Wechat API wrapper
159
205
  test_files:
160
206
  - spec/spec_helper.rb
161
207
  - spec/wechat/api/client_spec.rb
208
+ - spec/wechat/pay/client_spec.rb
162
209
  has_rdoc: