Commit 1fa6ade437289662de34647f24a1910df7dcff3b

Authored by jasl
1 parent 48419b64
Exists in master

first functional version

README.md
... ... @@ -30,14 +30,47 @@ $ bundle
30 30 ### Config
31 31  
32 32 ```ruby
  33 +# required
33 34 WxPay.appid = 'YOUR_APPID'
34 35 WxPay.key = 'YOUR_KEY'
35 36 WxPay.mch_id = 'YOUR_MCH_ID'
  37 +
  38 +# optional
  39 +WxPay.extra_rest_client_options = {timeout: 2, open_timeout: 3}
36 40 ```
37 41  
38 42 ### APIs
39 43  
40   -**PLACEHOLDER**
  44 +**Check official document for detailed request params and return fields**
  45 +
  46 +#### unifiedorder
  47 +
  48 +```ruby
  49 +# required fields
  50 +params = {
  51 +body: '测试商品',
  52 +out_trade_no: 'test003',
  53 +total_fee: 1,
  54 +spbill_create_ip: '127.0.0.1',
  55 +notify_url: 'http://making.dev',
  56 +trade_type: 'JSAPI'
  57 +}
  58 +
  59 +# Return a WxPay::Result instance(subclass of Hash) contains parsed result
  60 +r = WxPay::Service.invoke_unifiedorder params
  61 +# => {"return_code"=>"SUCCESS",
  62 +# "return_msg"=>"OK",
  63 +# "appid"=>"YOUR APPID",
  64 +# "mch_id"=>"YOUR MCH_ID",
  65 +# "nonce_str"=>"8RN7YfTZ3OUgWX5e",
  66 +# "sign"=>"623AE90C9679729DDD7407DC7A1151B2",
  67 +# "result_code"=>"SUCCESS",
  68 +# "prepay_id"=>"wx2014111104255143b7605afb0314593866",
  69 +# "trade_type"=>"JSAPI"}
  70 +
  71 +# Return true if both return_code and result_code equal SUCCESS
  72 +r.success? # => true
  73 +```
41 74  
42 75 ## Contributing
43 76  
... ...
lib/wx_pay.rb
1   -require 'wx_pay/utils'
  1 +require 'wx_pay/result'
2 2 require 'wx_pay/sign'
3 3 require 'wx_pay/service'
4   -require 'wx_pay/notify'
5 4  
6 5 module WxPay
7 6 class<< self
... ...
lib/wx_pay/notify.rb
... ... @@ -1,18 +0,0 @@
1   -module WxPay
2   - module Notify
3   - GATEWAY = 'https://gw.tenpay.com/gateway/simpleverifynotifyid.xml'
4   - SUCCESS_STR = '<retcode>0</retcode>'
5   -
6   - def self.verify?(params)
7   - return false unless Sign.verify?(params)
8   -
9   - params = {
10   - 'input_charset' => 'UTF-8',
11   - 'partner' => WxPay.appid,
12   - 'notify_id' => CGI.escape(params[:notify_id].to_s)
13   - }
14   -
15   - open("#{GATEWAY}?#{Utils.make_query_string(params)}").read.include?(SUCCESS_STR)
16   - end
17   - end
18   -end
lib/wx_pay/result.rb 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +module WxPay
  2 + class Result < ::Hash
  3 + SUCCESS_FLAG = 'SUCCESS'.freeze
  4 +
  5 + def initialize(result)
  6 + super
  7 +
  8 + if result['xml'].class == Hash
  9 + result['xml'].each_pair do |k, v|
  10 + self[k] = v
  11 + end
  12 + end
  13 + end
  14 +
  15 + def success?
  16 + self['return_code'] == SUCCESS_FLAG && self['result_code'] == SUCCESS_FLAG
  17 + end
  18 + end
  19 +end
... ...
lib/wx_pay/service.rb
... ... @@ -8,14 +8,18 @@ module WxPay
8 8 INVOKE_UNIFIEDORDER_REQUIRED_FIELDS = %i(body out_trade_no total_fee spbill_create_ip notify_url trade_type)
9 9 def self.invoke_unifiedorder(params)
10 10 params = {
11   - app_id: WxPay.appid,
  11 + appid: WxPay.appid,
12 12 mch_id: WxPay.mch_id,
13 13 nonce_str: SecureRandom.uuid.tr('-', ''),
14 14 }.merge(params)
15 15  
16 16 check_required_options(params, INVOKE_UNIFIEDORDER_REQUIRED_FIELDS)
17 17  
18   - WxPay::Utils.invoke_remote("#{GATEWAY_URL}/unifiedorder", WxPay::Utils.make_payload(params))
  18 + r = invoke_remote("#{GATEWAY_URL}/unifiedorder", make_payload(params))
  19 +
  20 + yield r if block_given?
  21 +
  22 + r
19 23 end
20 24  
21 25 private
... ... @@ -25,5 +29,26 @@ module WxPay
25 29 warn("WxPay Warn: missing required option: #{name}") unless options.has_key?(name)
26 30 end
27 31 end
  32 +
  33 + def self.make_payload(params)
  34 + "<xml>#{params.map { |k, v| "<#{k}>#{v}</#{k}>" }.join}<sign>#{WxPay::Sign.generate(params)}</sign></xml>"
  35 + end
  36 +
  37 + def self.invoke_remote(url, payload)
  38 + r = RestClient::Request.execute(
  39 + {
  40 + method: :post,
  41 + url: url,
  42 + payload: payload,
  43 + headers: { content_type: 'application/xml' }
  44 + }.merge(WxPay.extra_rest_client_options)
  45 + )
  46 +
  47 + if r
  48 + WxPay::Result.new Hash.from_xml(r)
  49 + else
  50 + nil
  51 + end
  52 + end
28 53 end
29 54 end
... ...
lib/wx_pay/sign.rb
... ... @@ -11,8 +11,8 @@ module WxPay
11 11 end
12 12  
13 13 def self.verify?(params)
14   - params = Utils.stringify_keys(params)
15   - sign = params.delete('sign')
  14 + params = params.dup
  15 + sign = params.delete('sign') || params.delete(:sign)
16 16  
17 17 generate(params) == sign
18 18 end
... ...
lib/wx_pay/utils.rb
... ... @@ -1,27 +0,0 @@
1   -module WxPay
2   - module Utils
3   - def self.stringify_keys(hash)
4   - new_hash = {}
5   - hash.each do |key, value|
6   - new_hash[(key.to_s rescue key) || key] = value
7   - end
8   - new_hash
9   - end
10   -
11   - def self.make_payload(params)
12   - "<xml>#{params.map {|k, v| "<#{k}>#{v}</#{k}>"}.join}<sign>#{WxPay::Sign.generate(params)}</sign></xml>"
13   - end
14   -
15   - def self.invoke_remote(url, payload)
16   - Hash.from_xml(
17   - RestClient::Request.execute(
18   - {
19   - method: :post,
20   - url: url,
21   - payload: payload,
22   - headers: {content_type: 'application/xml'}
23   - }.merge(WxPay.extra_rest_client_options))
24   - )
25   - end
26   - end
27   -end
lib/wx_pay/version.rb
1 1 module WxPay
2   - VERSION = "0.0.1"
  2 + VERSION = "0.0.2"
3 3 end
... ...
test/test_helper.rb
  1 +require 'active_support/core_ext/hash/conversions'
1 2 require 'minitest/autorun'
2 3 require 'wx_pay'
3 4 require 'fakeweb'
... ...
test/wx_pay/result_test.rb 0 → 100644
... ... @@ -0,0 +1,29 @@
  1 +require 'test_helper'
  2 +
  3 +class WxPay::ResultTest < MiniTest::Test
  4 + def test_success_method_with_true
  5 + r = WxPay::Result.new(
  6 + Hash.from_xml(
  7 + <<-XML
  8 + <xml>
  9 + <return_code>SUCCESS</return_code>
  10 + <result_code>SUCCESS</result_code>
  11 + </xml>
  12 + XML
  13 + ))
  14 +
  15 + assert_equal r.success?, true
  16 + end
  17 +
  18 + def test_success_method_with_false
  19 + r = WxPay::Result.new(
  20 + Hash.from_xml(
  21 + <<-XML
  22 + <xml>
  23 + </xml>
  24 + XML
  25 + ))
  26 +
  27 + assert_equal r.success?, false
  28 + end
  29 +end
... ...
test/wx_pay/sign_test.rb
1 1 require 'test_helper'
2 2  
3   -class WxPay::SignTest < MiniTest::Unit::TestCase
  3 +class WxPay::SignTest < MiniTest::Test
4 4 def setup
5 5 @params = {
6 6 appid: 'wxd930ea5d5a258f4f',
... ...
test/wx_pay/utils_test.rb
... ... @@ -1,8 +0,0 @@
1   -require 'test_helper'
2   -
3   -class WxPay::UtilsTest < MiniTest::Unit::TestCase
4   - def test_stringify_keys
5   - hash = { 'a' => 1, :b => 2 }
6   - assert_equal({ 'a' => 1, 'b' => 2 }.sort, WxPay::Utils.stringify_keys(hash).sort)
7   - end
8   -end