Commit 7494c7379cc67f48fa44fb6f41aa3956f75cfe5e

Authored by lanrion
2 parents 085bd456 de47dcc6
Exists in master

Merge pull request #4 from lanrion/send-message

Send message
.gitignore
... ... @@ -20,3 +20,4 @@ tmp
20 20 *.o
21 21 *.a
22 22 mkmf.log
  23 +.DS_Store
... ...
README.md
... ... @@ -78,4 +78,23 @@ group_client.oauth.authorize_url("http://2458023e.ngrok.com", "state")
78 78 group_client.oauth.get_user_info("code", "app_id")
79 79 ```
80 80  
  81 +## 发送消息
  82 +
  83 +```ruby
  84 + # params: (users, parties, tags, agent_id, content, safe=0)
  85 + # users, parties, tags 如果是多个用户,传数组,如果是全部,则直接传 "@all"
  86 + group_client.message.send_text("@all", "@all", "@all", app_id, text_message)
  87 +```
  88 +**其他发送消息方法请查看 api/message.rb**
  89 +
  90 +## 上传多媒体文件
  91 +```ruby
  92 +# params: media, media_type
  93 +group_client.media.upload(image_jpg_file, "image")
  94 +
  95 +# 获取下载链接
  96 +# 返回一个URL,请开发者自行使用此url下载
  97 +group_client.media.get_media_by_id(media_id)
  98 +```
  99 +
81 100  
... ...
lib/qy_wechat_api.rb
1 1 # encoding: utf-8
2 2  
3 3 require "rest-client"
  4 +
  5 +require "carrierwave"
  6 +require "qy_wechat_api/carrierwave/qy_wechat_api_uploader"
  7 +
4 8 require 'yajl/json_gem'
5 9  
6 10 require "qy_wechat_api/client"
... ... @@ -13,29 +17,15 @@ module QyWechatApi
13 17 OK_CODE = 0.freeze
14 18  
15 19 class << self
16   - # for test
17   - def corpid
18   - "wxb9ce1d023fe6eb69"
19   - end
20   -
21   - # for test
22   - def corpsecret
23   - "UOofFIah4PVLmkG8xMH3lpDxj6NTnQSKMrFt-HubiPB4kjB09EmTVcUjgNeermps"
24   - end
25 20  
26 21 def http_get_without_token(url, params={})
27 22 get_api_url = ENDPOINT_URL + url
28   - puts get_api_url
29   - puts params
30 23 load_json(RestClient.get(get_api_url, params: params))
31 24 end
32 25  
33 26 def http_post_without_token(url, payload={}, params={})
34 27 post_api_url = ENDPOINT_URL + url
35   - puts post_api_url
36   - puts payload
37   - puts params
38   - payload = JSON.dump(payload)
  28 + payload = JSON.dump(payload) if !payload[:media].is_a?(File)
39 29 load_json(RestClient.post(post_api_url, payload, params: params))
40 30 end
41 31  
... ...
lib/qy_wechat_api/api/media.rb
... ... @@ -4,12 +4,16 @@ module QyWechatApi
4 4 module Api
5 5 class Media < Base
6 6  
7   - def upload
8   -
  7 + # 媒体文件类型,分别有图片(image)、语音(voice)、视频(video),普通文件(file)
  8 + # media: 支持传路径或者文件实例
  9 + def upload(media, media_type)
  10 + file = process_file(media)
  11 + http_post("upload", {media: file}, {type: media_type})
9 12 end
10 13  
  14 + # 返回一个URL,请开发者自行使用此url下载
11 15 def get_media_by_id(media_id)
12   -
  16 + http_get("get", {media_id: media_id})
13 17 end
14 18  
15 19 private
... ... @@ -18,6 +22,62 @@ module QyWechatApi
18 22 "/media"
19 23 end
20 24  
  25 + def process_file(media)
  26 + return media if media.is_a?(File) && jpep?(media)
  27 +
  28 + media_url = media
  29 + uploader = QyWechatApiUploader.new
  30 +
  31 + if http?(media_url) # remote
  32 + uploader.download!(media_url.to_s)
  33 + else # local
  34 + media_file = media.is_a?(File) ? media : File.new(media_url)
  35 + uploader.cache!(media_file)
  36 + end
  37 + file = process_media(uploader)
  38 + CarrierWave.clean_cached_files! # clear last one day cache
  39 + file
  40 + end
  41 +
  42 + def process_media(uploader)
  43 + uploader = covert(uploader)
  44 + uploader.file.to_file
  45 + end
  46 +
  47 + # JUST ONLY FOR JPG IMAGE
  48 + def covert(uploader)
  49 + # image process
  50 + unless (uploader.file.content_type =~ /image/).nil?
  51 + if !jpep?(uploader.file)
  52 + require "mini_magick"
  53 + # covert to jpeg
  54 + image = MiniMagick::Image.open(uploader.path)
  55 + image.format("jpg")
  56 + uploader.cache!(File.open(image.path))
  57 + image.destroy! # remove /tmp from MinMagick generate
  58 + end
  59 + end
  60 + uploader
  61 + end
  62 +
  63 + def http?(uri)
  64 + return false if !uri.is_a?(String)
  65 + uri = URI.parse(uri)
  66 + uri.scheme =~ /^https?$/
  67 + end
  68 +
  69 + def jpep?(file)
  70 + content_type = if file.respond_to?(:content_type)
  71 + file.content_type
  72 + else
  73 + content_type(file.path)
  74 + end
  75 + !(content_type =~ /jpeg/).nil?
  76 + end
  77 +
  78 + def content_type(media_path)
  79 + MIME::Types.type_for(media_path).first.content_type
  80 + end
21 81 end
22 82 end
23 83 end
... ...
lib/qy_wechat_api/api/menu.rb
... ... @@ -3,56 +3,6 @@ module QyWechatApi
3 3 module Api
4 4 class Menu < Base
5 5  
6   - # for example:
7   - MENU = '{
8   - "button": [
9   - {
10   - "name": "扫码",
11   - "sub_button": [
12   - {
13   - "type": "scancode_waitmsg",
14   - "name": "扫码带提示",
15   - "key": "rselfmenu_0_0",
16   - "sub_button": [ ]
17   - },
18   - {
19   - "type": "scancode_push",
20   - "name": "扫码推事件",
21   - "key": "rselfmenu_0_1",
22   - "sub_button": [ ]
23   - }
24   - ]
25   - },
26   - {
27   - "name": "发图",
28   - "sub_button": [
29   - {
30   - "type": "pic_sysphoto",
31   - "name": "系统拍照发图",
32   - "key": "rselfmenu_1_0",
33   - "sub_button": [ ]
34   - },
35   - {
36   - "type": "pic_photo_or_album",
37   - "name": "拍照或者相册发图",
38   - "key": "rselfmenu_1_1",
39   - "sub_button": [ ]
40   - },
41   - {
42   - "type": "pic_weixin",
43   - "name": "微信相册发图",
44   - "key": "rselfmenu_1_2",
45   - "sub_button": [ ]
46   - }
47   - ]
48   - },
49   - {
50   - "name": "发送位置",
51   - "type": "location_select",
52   - "key": "rselfmenu_2_0"
53   - }
54   - ]
55   - }'
56 6 def create(menu, agent_id)
57 7 menu = JSON.load(menu) if menu.is_a?(String)
58 8 http_post("create", menu, {agentid: agent_id})
... ...
lib/qy_wechat_api/api/message.rb
... ... @@ -4,8 +4,94 @@ module QyWechatApi
4 4 module Api
5 5 class Message < Base
6 6  
7   - def send
  7 + # 发送文本
  8 + def send_text(users, parties, tags, agent_id, content, safe=0)
  9 + params = common_params("text", agent_id, users, parties, tags, safe)
  10 + params.merge!({text: {content: content}})
  11 + http_post("send", params)
  12 + end
  13 +
  14 + # 发送图片
  15 + def send_image(users, parties, tags, agent_id, media_id, safe=0)
  16 + params = common_params("image", agent_id, users, parties, tags, safe)
  17 + params.merge!({image: {media_id: media_id}})
  18 + http_post("send", params)
  19 + end
  20 +
  21 + # 发送语音
  22 + def send_voice(users, parties, tags, agent_id, media_id, safe=0)
  23 + params = common_params("voice", agent_id, users, parties, tags, safe)
  24 + params.merge!({voice: {media_id: media_id}})
  25 + http_post("send", params)
  26 + end
  27 +
  28 + # 发送视频
  29 + # media_options: {title: "title", description: "Description"}
  30 + def send_video(users, parties, tags, agent_id, media_id, media_options={}, safe=0)
  31 + params = common_params("video", agent_id, users, parties, tags, safe)
  32 + params.merge!({
  33 + video: {
  34 + media_id: media_id,
  35 + title: media_options["title"],
  36 + description: media_options["description"],
  37 + }
  38 + })
  39 + http_post("send", params)
  40 + end
8 41  
  42 + # 文件信息
  43 + def send_file(users, parties, tags, agent_id, media_id, safe=0)
  44 + params = common_params("file", agent_id, users, parties, tags, safe)
  45 + params.merge!({file: {media_id: media_id}})
  46 + http_post("send", params)
  47 + end
  48 +
  49 + # news消息
  50 + # "articles":[
  51 + # {
  52 + # "title": "Title",
  53 + # "description": "Description",
  54 + # "url": "URL",
  55 + # "picurl": "PIC_URL"
  56 + # },
  57 + # {
  58 + # "title": "Title",
  59 + # "description": "Description",
  60 + # "url": "URL",
  61 + # "picurl": "PIC_URL"
  62 + # }
  63 + # ]
  64 + def send_news(users, parties, tags, agent_id, articles, safe=0)
  65 + params = common_params("news", agent_id, users, parties, tags, safe)
  66 + params.merge!({news: {articles: articles}})
  67 + http_post("send", params)
  68 + end
  69 +
  70 + # mpnews
  71 + # articles":[
  72 + # {
  73 + # "title": "Title",
  74 + # "thumb_media_id": "id",
  75 + # "author": "Author",
  76 + # "content_source_url": "URL",
  77 + # "content": "Content",
  78 + # "digest": "Digest description",
  79 + # "show_cover_pic": "0"
  80 + # },
  81 + # {
  82 + # "title": "Title",
  83 + # "thumb_media_id": "id",
  84 + # "author": "Author",
  85 + # "content_source_url": "URL",
  86 + # "content": "Content",
  87 + # "digest": "Digest description",
  88 + # "show_cover_pic": "0"
  89 + # }
  90 + # ]
  91 + def send_mpnews(users, parties, tags, agent_id, articles, safe=0)
  92 + params = common_params("mpnews", agent_id, users, parties, tags, safe)
  93 + params.merge!({mpnews: {articles: articles}})
  94 + http_post("send", params)
9 95 end
10 96  
11 97 private
... ... @@ -14,6 +100,24 @@ module QyWechatApi
14 100 "/message"
15 101 end
16 102  
  103 + # 通用函数
  104 + def common_params(msg_type, agent_id, users=[], parties=[], tags=[], safe=0)
  105 + params = {
  106 + touser: join(users),
  107 + toparty: join(parties),
  108 + msgtype: msg_type,
  109 + agentid: agent_id,
  110 + totag: join(tags)
  111 + }
  112 + params.merge!({safe: safe}) if msg_type != "news"
  113 + params
  114 + end
  115 +
  116 + def join(array, split="|")
  117 + return array if array.is_a?(String)
  118 + array.join(split)
  119 + end
  120 +
17 121 end
18 122 end
19 123 end
... ...
lib/qy_wechat_api/carrierwave/qy_wechat_api_uploader.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +# encoding: utf-8
  2 +module QyWechatApi
  3 + class QyWechatApiUploader < CarrierWave::Uploader::Base
  4 + end
  5 +end
... ...
lib/qy_wechat_api/client.rb
... ... @@ -44,7 +44,7 @@ module QyWechatApi
44 44  
45 45 private
46 46 def get_access_token
47   - self.access_token ||= get_token.result[:access_token]
  47 + self.access_token ||= get_token.result["access_token"]
48 48 end
49 49  
50 50 # 获取token
... ...
qy_wechat_api.gemspec
... ... @@ -24,6 +24,9 @@ Gem::Specification.new do |spec|
24 24 # https://github.com/brianmario/yajl-ruby
25 25 spec.add_dependency "yajl-ruby", "~> 1.2.0"
26 26  
  27 + spec.add_dependency "carrierwave", "~> 0.10.0"
  28 + spec.add_dependency 'mini_magick', '~> 3.7.0'
  29 +
27 30 spec.add_development_dependency "bundler", "~> 1.6"
28 31 spec.add_development_dependency "rake"
29 32 end
... ...
spec/api/media_spec.rb 0 → 100644
... ... @@ -0,0 +1,72 @@
  1 +require "spec_helper"
  2 +
  3 +describe QyWechatApi::Api::Media do
  4 +
  5 + let(:image_jpg_path) do
  6 + "#{File.dirname(__FILE__)}/medias/ruby-logo.jpg"
  7 + end
  8 +
  9 + let(:image_ico_path) do
  10 + "#{File.dirname(__FILE__)}/medias/favicon.ico"
  11 + end
  12 +
  13 + let(:image_jpg_file) do
  14 + File.new(image_jpg_path)
  15 + end
  16 +
  17 + let(:image_ico_file) do
  18 + File.new(image_ico_path)
  19 + end
  20 +
  21 + let(:remote_png_path) do
  22 + "https://ruby-china-files.b0.upaiyun.com/user/big_avatar/273.jpg"
  23 + end
  24 +
  25 + let(:remote_jpg_path) do
  26 + "http://g.hiphotos.baidu.com/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=ce55457e4334970a537e187df4a3baad/03087bf40ad162d99455ef4d13dfa9ec8b13632762d0ed14.jpg"
  27 + end
  28 +
  29 + it "can upload a jpg File image" do
  30 + response = $client.media.upload(image_jpg_file, "image")
  31 + expect(response.code).to eq(QyWechatApi::OK_CODE)
  32 + expect(response.result.keys).to eq(["type", "media_id", "created_at"])
  33 + end
  34 +
  35 + it "can upload a ico File image" do
  36 + response = $client.media.upload(image_ico_file, "image")
  37 + expect(response.code).to eq(QyWechatApi::OK_CODE)
  38 + expect(response.result.keys).to eq(["type", "media_id", "created_at"])
  39 + end
  40 +
  41 + it "can upload a local image" do
  42 + response = $client.media.upload(image_jpg_path, "image")
  43 + expect(response.code).to eq(QyWechatApi::OK_CODE)
  44 + expect(response.result.keys).to eq(["type", "media_id", "created_at"])
  45 + end
  46 +
  47 + it "can upload a local ico image" do
  48 + response = $client.media.upload(image_ico_path, "image")
  49 + expect(response.code).to eq(QyWechatApi::OK_CODE)
  50 + expect(response.result.keys).to eq(["type", "media_id", "created_at"])
  51 + end
  52 +
  53 + it "can upload a remote png image" do
  54 + response = $client.media.upload(remote_png_path, "image")
  55 + expect(response.code).to eq(QyWechatApi::OK_CODE)
  56 + expect(response.result.keys).to eq(["type", "media_id", "created_at"])
  57 + end
  58 +
  59 + it "can upload a remote jpg image" do
  60 + response = $client.media.upload(remote_jpg_path, "image")
  61 + expect(response.code).to eq(QyWechatApi::OK_CODE)
  62 + expect(response.result.keys).to eq(["type", "media_id", "created_at"])
  63 + end
  64 +
  65 + # it "#download_media_url return a String url" do
  66 + # image = $client.media.upload(image_ico_path, "image")
  67 + # media_id = image.result["media_id"]
  68 + # image_url = $client.download_media_url(media_id)
  69 + # expect(image_url.class).to eq(String)
  70 + # end
  71 +
  72 +end
... ...
spec/api/medias/favicon.ico 0 → 100644
No preview for this file type
spec/api/medias/ruby-logo.jpg 0 → 100644

7.24 KB

spec/api/menu_spec.rb 0 → 100644
... ... @@ -0,0 +1,60 @@
  1 +require "spec_helper"
  2 +
  3 +describe QyWechatApi::Api::Menu do
  4 + let(:menu_string) do
  5 + '{
  6 + "button": [
  7 + {
  8 + "name": "扫码",
  9 + "sub_button": [
  10 + {
  11 + "type": "scancode_waitmsg",
  12 + "name": "扫码带提示",
  13 + "key": "rselfmenu_0_0",
  14 + "sub_button": [ ]
  15 + },
  16 + {
  17 + "type": "scancode_push",
  18 + "name": "扫码推事件",
  19 + "key": "rselfmenu_0_1",
  20 + "sub_button": [ ]
  21 + }
  22 + ]
  23 + },
  24 + {
  25 + "name": "发图",
  26 + "sub_button": [
  27 + {
  28 + "type": "pic_sysphoto",
  29 + "name": "系统拍照发图",
  30 + "key": "rselfmenu_1_0",
  31 + "sub_button": [ ]
  32 + },
  33 + {
  34 + "type": "pic_photo_or_album",
  35 + "name": "拍照或者相册发图",
  36 + "key": "rselfmenu_1_1",
  37 + "sub_button": [ ]
  38 + },
  39 + {
  40 + "type": "pic_weixin",
  41 + "name": "微信相册发图",
  42 + "key": "rselfmenu_1_2",
  43 + "sub_button": [ ]
  44 + }
  45 + ]
  46 + },
  47 + {
  48 + "name": "发送位置",
  49 + "type": "location_select",
  50 + "key": "rselfmenu_2_0"
  51 + }
  52 + ]
  53 + }'
  54 + end
  55 +
  56 + it "#create" do
  57 + response = $client.menu.create(menu_string, 1)
  58 + expect(response.code).to eq(QyWechatApi::OK_CODE)
  59 + end
  60 +end
... ...
spec/api/message_spec.rb 0 → 100644
... ... @@ -0,0 +1,50 @@
  1 +require "spec_helper"
  2 +describe QyWechatApi::Api::Message do
  3 + let(:text_message) do
  4 + "text message"
  5 + end
  6 +
  7 + let(:image_path) do
  8 + "#{File.dirname(__FILE__)}/medias/ruby-logo.jpg"
  9 + end
  10 +
  11 + let(:image_file) do
  12 + File.new(image_path)
  13 + end
  14 +
  15 + it "#send_text_message" do
  16 + response = $client.message.send_text("@all", "@all", "@all", 1, text_message)
  17 + expect(response.code).to eq(QyWechatApi::OK_CODE)
  18 + end
  19 +
  20 + it "#send_image_message" do
  21 + response = $client.media.upload(image_path, "image").result
  22 + response = $client.message.send_image("@all", "@all", "@all", 1, response["media_id"])
  23 + expect(response.code).to eq(QyWechatApi::OK_CODE)
  24 + end
  25 +
  26 +
  27 + it "#send_news" do
  28 + articles = [{
  29 + "title" => "Happy Day",
  30 + "description" => "Is Really A Happy Day",
  31 + "url" => "http://www.baidu.com",
  32 + "picurl" => "http://www.baidu.com/img/bdlogo.gif"
  33 + },
  34 + {
  35 + "title" => "Happy Day",
  36 + "description" => "Is Really A Happy Day",
  37 + "url" => "http://www.baidu.com",
  38 + "picurl"=> "http://www.baidu.com/img/bdlogo.gif"
  39 + }]
  40 + response = $client.message.send_news("@all", "@all", "@all", 1, articles)
  41 + expect(response.code).to eq(QyWechatApi::OK_CODE)
  42 + end
  43 +
  44 + it "#send_file" do
  45 + response = $client.media.upload(image_path, "image").result
  46 + response = $client.message.send_file("@all", "@all", "@all", 1, response["media_id"])
  47 + expect(response.code).to eq(QyWechatApi::OK_CODE)
  48 + end
  49 +
  50 +end
... ...
spec/spec_helper.rb
... ... @@ -14,6 +14,15 @@
14 14 # users commonly want.
15 15 #
16 16 # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
  17 +require "qy_wechat_api"
  18 +require "pry-rails"
  19 +
  20 +corpid = "wxb9ce1d023fe6eb69"
  21 +corpsecret = "UOofFIah4PVLmkG8xMH3lpDxj6NTnQSKMrFt-HubiPB4kjB09EmTVcUjgNeermps"
  22 +
  23 +
  24 +$client = QyWechatApi::Client.new(corpid, corpsecret)
  25 +
17 26 RSpec.configure do |config|
18 27 # rspec-expectations config goes here. You can use an alternate
19 28 # assertion/expectation library such as wrong or the stdlib/minitest
... ...