Commit 19660247ff6b8047be081ad44d0334ab9a833434
1 parent
17de31b7
Exists in
master
Separate authenticate_open_id to two functions
Showing
2 changed files
with
24 additions
and
34 deletions
Show diff stats
README.md
@@ -36,13 +36,15 @@ Create `config/initializers/wx_pay.rb` and put following configurations into it. | @@ -36,13 +36,15 @@ Create `config/initializers/wx_pay.rb` and put following configurations into it. | ||
36 | WxPay.appid = 'YOUR_APPID' | 36 | WxPay.appid = 'YOUR_APPID' |
37 | WxPay.key = 'YOUR_KEY' | 37 | WxPay.key = 'YOUR_KEY' |
38 | WxPay.mch_id = 'YOUR_MCH_ID' | 38 | WxPay.mch_id = 'YOUR_MCH_ID' |
39 | -WxPay.appsecret = 'YOUR_SECREDT' | ||
40 | WxPay.debug_mode = true # default is `true` | 39 | WxPay.debug_mode = true # default is `true` |
41 | 40 | ||
42 | # cert, see https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3 | 41 | # cert, see https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3 |
43 | # using PCKS12 | 42 | # using PCKS12 |
44 | WxPay.set_apiclient_by_pkcs12(File.read(pkcs12_filepath), pass) | 43 | WxPay.set_apiclient_by_pkcs12(File.read(pkcs12_filepath), pass) |
45 | 44 | ||
45 | +# if you want to use `generate_authorize_req` and `authenticate` | ||
46 | +WxPay.appsecret = 'YOUR_SECRET' | ||
47 | + | ||
46 | # optional - configurations for RestClient timeout, etc. | 48 | # optional - configurations for RestClient timeout, etc. |
47 | WxPay.extra_rest_client_options = {timeout: 2, open_timeout: 3} | 49 | WxPay.extra_rest_client_options = {timeout: 2, open_timeout: 3} |
48 | ``` | 50 | ``` |
@@ -89,13 +91,9 @@ r = WxPay::Service.invoke_unifiedorder params | @@ -89,13 +91,9 @@ r = WxPay::Service.invoke_unifiedorder params | ||
89 | # } | 91 | # } |
90 | ``` | 92 | ``` |
91 | 93 | ||
92 | -"JSAPI" requires openid in params, authenticate_openid can be used to get it, in case there is not wechat auth integration. | ||
93 | - | ||
94 | -```ruby | ||
95 | -code = params[:code] | ||
96 | -r = WxPay::Service.authenticate_openid code | ||
97 | -# => 'OPENID' | ||
98 | -``` | 94 | +> "JSAPI" requires openid in params, |
95 | +in most cases I suggest you using [omniauth](https://github.com/omniauth/omniauth) with [omniauth-wechat-oauth2](https://github.com/skinnyworm/omniauth-wechat-oauth2) to resolve this, | ||
96 | +but `wx_pay` provides `generate_authorize_url` and `authenticate` to help you get Wechat authorization in simple case. | ||
99 | 97 | ||
100 | If your trade type is "NATIVE", the result would be like this. | 98 | If your trade type is "NATIVE", the result would be like this. |
101 | 99 | ||
@@ -188,7 +186,7 @@ def notify | @@ -188,7 +186,7 @@ def notify | ||
188 | end | 186 | end |
189 | ``` | 187 | ``` |
190 | 188 | ||
191 | -### Integretion with QRCode(二维码) | 189 | +### Integrate with QRCode(二维码) |
192 | 190 | ||
193 | Wechat payment integrating with QRCode is a recommended process flow which will bring users comfortable experience. It is recommended to generate QRCode using `rqrcode` and `rqrcode_png`. | 191 | Wechat payment integrating with QRCode is a recommended process flow which will bring users comfortable experience. It is recommended to generate QRCode using `rqrcode` and `rqrcode_png`. |
194 | 192 |
lib/wx_pay/service.rb
1 | require 'rest_client' | 1 | require 'rest_client' |
2 | require 'json' | 2 | require 'json' |
3 | -require 'rails' | 3 | +require 'securerandom' |
4 | require 'active_support/core_ext/hash/conversions' | 4 | require 'active_support/core_ext/hash/conversions' |
5 | 5 | ||
6 | module WxPay | 6 | module WxPay |
7 | module Service | 7 | module Service |
8 | GATEWAY_URL = 'https://api.mch.weixin.qq.com' | 8 | GATEWAY_URL = 'https://api.mch.weixin.qq.com' |
9 | 9 | ||
10 | - def self.authenticate_openid(code) | ||
11 | - """ | ||
12 | - Acquire openid from wechat server. | ||
13 | - When trade type is JSAPI, openid is required in params to do unifiedorder. | ||
14 | - If application does not integrate wechat auth plugin, this function can be used to get openid. | ||
15 | - Wechat doc for explaining acquire openid: http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html | ||
16 | - | ||
17 | - params: | ||
18 | - code, the code return by wechat server after user authentification | ||
19 | - return: | ||
20 | - openid | ||
21 | - """ | ||
22 | - # step 1. Redirect to wechat server to get code. If code exits, it can be skiped. | ||
23 | - if code.nil? | ||
24 | - redirect_to "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{WxPay.appid}&redirect_uri=#{request.url}&response_type=code&scope=snsapi_base&state=#{request.url}#wechat_redirect" | ||
25 | - end | 10 | + def self.generate_authorize_url(redirect_uri, state = nil) |
11 | + state ||= SecureRandom.hex 16 | ||
12 | + "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{WxPay.appid}&redirect_uri=#{redirect_uri}&response_type=code&scope=snsapi_base&state=#{state}" | ||
13 | + end | ||
26 | 14 | ||
27 | - # step 2. Get Auth Info and openid from wechat server with code | ||
28 | - begin | ||
29 | - url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=#{WxPay.appid}&secret=#{WxPay.appsecret}&code=#{code}&grant_type=authorization_code" | ||
30 | - weixin_openid = JSON.parse(URI.parse(url).read)["openid"] | ||
31 | - end | ||
32 | - weixin_openid | 15 | + def self.authenticate(authorization_code, options = {}) |
16 | + options = WxPay.extra_rest_client_options.merge(options) | ||
17 | + url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=#{WxPay.appid}&secret=#{WxPay.appsecret}&code=#{authorization_code}&grant_type=authorization_code" | ||
18 | + | ||
19 | + ::JSON.parse(RestClient::Request.execute( | ||
20 | + { | ||
21 | + method: :get, | ||
22 | + url: url | ||
23 | + }.merge(options) | ||
24 | + ), quirks_mode: true) | ||
33 | end | 25 | end |
34 | 26 | ||
35 | INVOKE_UNIFIEDORDER_REQUIRED_FIELDS = [:body, :out_trade_no, :total_fee, :spbill_create_ip, :notify_url, :trade_type] | 27 | INVOKE_UNIFIEDORDER_REQUIRED_FIELDS = [:body, :out_trade_no, :total_fee, :spbill_create_ip, :notify_url, :trade_type] |
@@ -220,9 +212,9 @@ module WxPay | @@ -220,9 +212,9 @@ module WxPay | ||
220 | nonce_str: SecureRandom.uuid.tr('-', '') | 212 | nonce_str: SecureRandom.uuid.tr('-', '') |
221 | }.merge(params) | 213 | }.merge(params) |
222 | 214 | ||
223 | - check_required_options(params, ORDER_QUERY_REQUIRED_FIELDS) | ||
224 | 215 | ||
225 | r = WxPay::Result.new(Hash.from_xml(invoke_remote("#{GATEWAY_URL}/pay/orderquery", make_payload(params), options))) | 216 | r = WxPay::Result.new(Hash.from_xml(invoke_remote("#{GATEWAY_URL}/pay/orderquery", make_payload(params), options))) |
217 | + check_required_options(params, ORDER_QUERY_REQUIRED_FIELDS) | ||
226 | 218 | ||
227 | yield r if block_given? | 219 | yield r if block_given? |
228 | 220 | ||
@@ -294,7 +286,7 @@ module WxPay | @@ -294,7 +286,7 @@ module WxPay | ||
294 | private | 286 | private |
295 | 287 | ||
296 | def check_required_options(options, names) | 288 | def check_required_options(options, names) |
297 | - return if !WxPay.debug_mode? | 289 | + return unless WxPay.debug_mode? |
298 | names.each do |name| | 290 | names.each do |name| |
299 | warn("WxPay Warn: missing required option: #{name}") unless options.has_key?(name) | 291 | warn("WxPay Warn: missing required option: #{name}") unless options.has_key?(name) |
300 | end | 292 | end |