diff --git a/README.md b/README.md index 3243a8e..2bec95d 100644 --- a/README.md +++ b/README.md @@ -36,13 +36,15 @@ Create `config/initializers/wx_pay.rb` and put following configurations into it. WxPay.appid = 'YOUR_APPID' WxPay.key = 'YOUR_KEY' WxPay.mch_id = 'YOUR_MCH_ID' -WxPay.appsecret = 'YOUR_SECREDT' WxPay.debug_mode = true # default is `true` # cert, see https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3 # using PCKS12 WxPay.set_apiclient_by_pkcs12(File.read(pkcs12_filepath), pass) +# if you want to use `generate_authorize_req` and `authenticate` +WxPay.appsecret = 'YOUR_SECRET' + # optional - configurations for RestClient timeout, etc. WxPay.extra_rest_client_options = {timeout: 2, open_timeout: 3} ``` @@ -89,13 +91,9 @@ r = WxPay::Service.invoke_unifiedorder params # } ``` -"JSAPI" requires openid in params, authenticate_openid can be used to get it, in case there is not wechat auth integration. - -```ruby -code = params[:code] -r = WxPay::Service.authenticate_openid code -# => 'OPENID' -``` +> "JSAPI" requires openid in params, +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, +but `wx_pay` provides `generate_authorize_url` and `authenticate` to help you get Wechat authorization in simple case. If your trade type is "NATIVE", the result would be like this. @@ -188,7 +186,7 @@ def notify end ``` -### Integretion with QRCode(二维码) +### Integrate with QRCode(二维码) 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`. diff --git a/lib/wx_pay/service.rb b/lib/wx_pay/service.rb index a95a68a..c963200 100644 --- a/lib/wx_pay/service.rb +++ b/lib/wx_pay/service.rb @@ -1,35 +1,27 @@ require 'rest_client' require 'json' -require 'rails' +require 'securerandom' require 'active_support/core_ext/hash/conversions' module WxPay module Service GATEWAY_URL = 'https://api.mch.weixin.qq.com' - def self.authenticate_openid(code) - """ - Acquire openid from wechat server. - When trade type is JSAPI, openid is required in params to do unifiedorder. - If application does not integrate wechat auth plugin, this function can be used to get openid. - Wechat doc for explaining acquire openid: http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html - - params: - code, the code return by wechat server after user authentification - return: - openid - """ - # step 1. Redirect to wechat server to get code. If code exits, it can be skiped. - if code.nil? - 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" - end + def self.generate_authorize_url(redirect_uri, state = nil) + state ||= SecureRandom.hex 16 + "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{WxPay.appid}&redirect_uri=#{redirect_uri}&response_type=code&scope=snsapi_base&state=#{state}" + end - # step 2. Get Auth Info and openid from wechat server with code - begin - url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=#{WxPay.appid}&secret=#{WxPay.appsecret}&code=#{code}&grant_type=authorization_code" - weixin_openid = JSON.parse(URI.parse(url).read)["openid"] - end - weixin_openid + def self.authenticate(authorization_code, options = {}) + options = WxPay.extra_rest_client_options.merge(options) + url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=#{WxPay.appid}&secret=#{WxPay.appsecret}&code=#{authorization_code}&grant_type=authorization_code" + + ::JSON.parse(RestClient::Request.execute( + { + method: :get, + url: url + }.merge(options) + ), quirks_mode: true) end INVOKE_UNIFIEDORDER_REQUIRED_FIELDS = [:body, :out_trade_no, :total_fee, :spbill_create_ip, :notify_url, :trade_type] @@ -220,9 +212,9 @@ module WxPay nonce_str: SecureRandom.uuid.tr('-', '') }.merge(params) - check_required_options(params, ORDER_QUERY_REQUIRED_FIELDS) r = WxPay::Result.new(Hash.from_xml(invoke_remote("#{GATEWAY_URL}/pay/orderquery", make_payload(params), options))) + check_required_options(params, ORDER_QUERY_REQUIRED_FIELDS) yield r if block_given? @@ -294,7 +286,7 @@ module WxPay private def check_required_options(options, names) - return if !WxPay.debug_mode? + return unless WxPay.debug_mode? names.each do |name| warn("WxPay Warn: missing required option: #{name}") unless options.has_key?(name) end -- libgit2 0.21.0