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



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

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

获取用户手机号



193
194
195
196
197
198
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
# File 'lib/mini_program/client.rb', line 193

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::SuccessResult.new(
    message: "解密手机号成功",
    message_kind: :decrypt_phone_number_success,
    data: {
      openid: openid,
      phone_num: phone_num
    }
  )
rescue OpenSSL::Cipher::CipherError, ArgumentError => e
  message = "解密手机号失败"

  MiniProgram::Logger.error do
    { action: "decrypt_phone_num", message: message, error: e }.to_json
  end

  MiniProgram::FailureResult.new(
    message: message,
    message_kind: :decrypt_phone_number_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
# 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::SuccessResult.new(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



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/mini_program/client.rb', line 81

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"
    MiniProgram::Logger.error do
      { action: :login, params: params, response: result }.to_json
    end

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

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

  end
end

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

获取小程序二维码



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

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"]
    MiniProgram::Logger.error do
      { action: 'generate_code', params: params, response: result }.to_json
    end

    MiniProgram::ServiceResult.new(success: false,
                                   error: result,
                                   message: "获取二维码失败",
                                   message_kind: :get_unlimited_qrcode_failed)
  else
    MiniProgram::Logger.info do
      { action: 'generate_code', params: params, response: result }.to_json
    end

    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



51
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
# File 'lib/mini_program/client.rb', line 51

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"
    MiniProgram::Logger.error do
      { action: :request_access_token, params: params, response: result }.to_json
    end

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

#send_msg(msg, to:) ⇒ Object

发送订阅消息

Parameters:



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/mini_program/client.rb', line 114

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"
    MiniProgram::Logger.info do
      { action: :send_subscribed_message, params: payload, response: result }.to_json
    end

    MiniProgram::SuccessResult.new(data: { msgid: result.data["msgid"] },
                                   message: "发送订阅消息成功",
                                   message_kind: :send_subscribed_message_success)
  else
    MiniProgram::Logger.error do
      { action: :send_subscribed_message, params: payload, response: result }.to_json
    end

    MiniProgram::FailureResult.new(error: result,
                                   message: "发送订阅消息失败",
                                   message_kind: :send_subscribed_message_failed)
  end

end

#send_uniform_msg(msg, to:) ⇒ Object

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



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/mini_program/client.rb', line 152

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"
    message = "发送统一服务消息成功"

    MiniProgram::Logger.info do
      { action: :send_uniform_message, message: message, params: payload, response: result }.to_json
    end

    MiniProgram::SuccessResult.new(data: result,
                                   message: message,
                                   message_kind: :send_uniform_message_success)

  else
    message = "发送统一服务消息失败"

    MiniProgram::Logger.error do
      { action: :send_uniform_message, message: message, params: payload, response: result }.to_json
    end

    MiniProgram::FailureResult.new(error: result["errmsg"],
                                   message: message,
                                   message_kind: :send_uniform_message_failed)
  end
end