Class: MiniProgram::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/mini_program/client.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(appid: config.appid, app_secret: config.app_secret) ⇒ Client

Returns a new instance of Client.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/mini_program/client.rb', line 5

def initialize(appid: config.appid, app_secret: config.app_secret)
  @appid = appid
  @app_secret = app_secret

  if appid == 'your appid'
    warn "\e[33m" + "*" * 80 + "\e[0m"
    warn "\e[33m警告: 请将 config/initializer/mini_program.rb 中的 appid 修改成你实际的appid\e[0m"
    warn "\e[33m" + "*" * 80 + "\e[0m"
  end

  if app_secret == 'your app_secret'
    warn "\e[33m" + "*" * 80 + "\e[0m"
    warn "\e[33m警告: 请将 config/initializer/mini_program.rb 中的 app_secret 修改成你实际的app_secret\e[0m"
    warn "\e[33m" + "*" * 80 + "\e[0m"
  end
end

Instance Attribute Details

#app_secretObject (readonly)

Returns the value of attribute app_secret.



3
4
5
# File 'lib/mini_program/client.rb', line 3

def app_secret
  @app_secret
end

#appidObject (readonly)

Returns the value of attribute appid.



3
4
5
# File 'lib/mini_program/client.rb', line 3

def appid
  @appid
end

Instance Method Details

#configObject



227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/mini_program/client.rb', line 227

def config
  appid, app_secret = if MiniProgram.appid && MiniProgram.app_secret
                        [MiniProgram.appid, MiniProgram.app_secret]

                        # 如果有挂载 WechatPayment 的 engine 时,使用里边的小程序配置
                      elsif Object.const_defined? "WechatPayment"
                        [WechatPayment.sub_appid || WechatPayment.appid, WechatPayment.sub_app_secret || WechatPayment.app_secret]
                      else
                        [nil, nil]
                      end

  Struct.new(:appid, :app_secret).new(appid, app_secret)
end

#decrypt_phone_num(code:, encrypted_data:, iv:) ⇒ Object

获取用户手机号



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/mini_program/client.rb', line 199

def decrypt_phone_num(code:, encrypted_data:, iv:)
   = (code)
  return  if .failure?

  openid = .data[:openid]
  session_key = .data[:session_key]

  data = decrypt_phone_data(encrypted_data, iv, session_key)

  phone_num = JSON.parse(data)["phoneNumber"]

  MiniProgram::ServiceResult.new(
    success: true,
    message: "解密手机号成功",
    message_kind: :decrypt_phone_number_success,
    data: {
      openid: openid,
      phone_num: phone_num
    })
rescue OpenSSL::Cipher::CipherError, ArgumentError => e
  MiniProgram::ServiceResult.new(
    success: false,
    message: "解密手机号失败",
    message_kind: :decrypt_phone_data_failed,
    error: e
  )
end

#get_access_token(fresh: false) {|result| ... } ⇒ Object

Yields:

  • (result)


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/mini_program/client.rb', line 22

def get_access_token(fresh: false)
  access_token = Rails.cache.read(access_token_store_key)

  if access_token.present? && !fresh
    return MiniProgram::ServiceResult.new(success: true,
                                          data: { access_token: access_token },
                                          message: "获取 access token 成功",
                                          message_kind: :get_access_token_success)
  end

  result = request_access_token

  if result.success?
    Rails.cache.write(access_token_store_key,
                      result.data["access_token"],
                      expires_in: 1.5.hours.to_i,
                      race_condition_ttl: 10)

    result.message = "获取 access token 成功"
    result.message_kind = :get_access_token_success
  end

  yield result if block_given?

  result
end

#login(code) ⇒ Object

调用微信授权登录 api



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/mini_program/client.rb', line 88

def (code)
  api = "https://api.weixin.qq.com/sns/jscode2session"
  params = {
    appid: appid,
    secret: app_secret,
    js_code: code,
    grant_type: :authorization_code
  }

  response = get(api, params)

  result = JSON.parse(response)

  if result["errcode"] && result["errcode"].to_s != "0"
    logger.tagged "login mini program"
    logger.error <<~ERROR
      Get session key failed.
      api: #{api}
      result: #{result}
    ERROR

    MiniProgram::ServiceResult.new(success: false,
                                   error: result,
                                   message: result["errmsg"],
                                   message_kind: :login_failed)

  else
    MiniProgram::ServiceResult.new(success: true,
                                   data: result,
                                   message: "小程序登录成功",
                                   message_kind: :login_success)
  end

end

#qrcode_unlimited(scene:, page:, width: 280, check_path: true, env_version: "release") ⇒ Object

获取小程序二维码



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/mini_program/client.rb', line 242

def qrcode_unlimited(scene:, page:, width: 280, check_path: true, env_version: "release")
  get_token_result = get_access_token.on_failure do |result|
    return result
  end

  api = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=#{get_token_result["access_token"]}"
  params = { scene:, page:, width:, check_path:, env_version: }

  result = post(api, params)

  if result["errcode"]
    logger.error { "{ action: 'generate qrcode', params: #{params}, response: #{result}}" }
    MiniProgram::ServiceResult.new(success: false,
                                   error: result,
                                   message: "获取二维码失败",
                                   message_kind: :get_unlimited_qrcode_failed)
  else
    logger.info { "{ action: 'generate qrcode',  params: #{params}, response: #{result} }" }
    MiniProgram::ServiceResult.new(success: true,
                                   data: { image: result },
                                   message: "获取二维码成功",
                                   message_kind: :get_unlimited_qrcode_success)
  end
end

#request_access_tokenObject

调用微信 api 获取 access_token

Returns:

  • MiniProgram::ServiceResult



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/mini_program/client.rb', line 52

def request_access_token
  api = "https://api.weixin.qq.com/cgi-bin/token"
  params = {
    appid: appid,
    secret: app_secret,
    grant_type: :client_credential
  }

  response = get(api, params)

  result = JSON.parse(response)

  if result["errcode"] && result["errcode"].to_s != "0"
    logger.tagged "request access token" do
      logger.error <<~ERROR
      Get access token failed.
      api: #{api} 
      error: #{result}
      ERROR
    end

    MiniProgram::ServiceResult.new(success: false,
                                   error: result,
                                   message: result["errmsg"],
                                   message_kind: :request_access_token_failed)
  else
    MiniProgram::ServiceResult.new(success: true,
                                   data: { access_token: result["access_token"] },
                                   message: "请求 access token 成功",
                                   message_kind: :request_access_token_success)
  end
end

#send_msg(msg, to:) ⇒ Object

发送订阅消息

Parameters:



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/mini_program/client.rb', line 126

def send_msg(msg, to:)
  openid = to.try(:openid) || to

  payload = msg.as_json.merge!(touser: openid)

  # 获取 access_token
  get_token_result = get_access_token
  if get_token_result.failure?
    return get_token_result
  end

  api = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=#{get_token_result["access_token"]}"
  result = post(api, payload)

  if result["errcode"].to_s != "0"
    logger.tagged "Subscribe Message" do
      logger.error { "{params: #{payload}, response: #{result}}" }
    end

    MiniProgram::ServiceResult.new(success: false,
                                   error: result,
                                   message: "发送订阅消息失败",
                                   message_kind: :send_subscribed_message_failed)
  else
    logger.tagged "Subscribe Message" do
      logger.info { "{params: #{payload}, response: #{result}}" }
    end

    MiniProgram::ServiceResult.new(success: true,
                                   data: {
                                     msgid: result.data["msgid"]
                                   },
                                   message: "发送订阅消息成功",
                                   message_kind: :send_subscribed_message_success)
  end

end

#send_uniform_msg(msg, to:) ⇒ Object

「发送统一服务消息」 统一服务消息原本是可以从调用小程序的 api ,通过用户小程序的 openid 发送模板消息到小程序和公众号那里去, 现在小程序的模板消息功能关闭了,就只剩下发送模板消息到公众号这个功能了



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/mini_program/client.rb', line 168

def send_uniform_msg(msg, to:)
  openid = to.try(:openid) || to

  payload = msg.as_json

  get_token_result = get_access_token
  if get_access_token.failure?
    return get_token_result
  end

  api = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=#{get_token_result["access_token"]}"
  result = post(api, {
    touser: openid,
    mp_template_msg: payload
  })

  if result["errcode"].to_s != "0"
    MiniProgram::ServiceResult.new(success: false,
                                   error: result,
                                   message: "发送统一服务消息失败",
                                   message_kind: :send_uniform_message_failed)
  else
    MiniProgram::ServiceResult.new(success: true,
                                   data: result,
                                   message: "发送统一服务消息成功",
                                   message_kind: :send_uniform_message_success)
  end

end