├── config ├── sys.config └── vm.args ├── rebar3 ├── .gitignore ├── README.md ├── apps └── wechat │ ├── src │ ├── wechat_signature.erl │ ├── wechat.app.src │ ├── wechat.erl │ ├── wechat_handler.erl │ ├── wechat_sup.erl │ ├── wechat_menu.erl │ ├── wechat_app.erl │ ├── wechat_media.erl │ ├── wechat_util.erl │ └── wechat_message.erl │ └── include │ └── wechat.hrl ├── rebar.config └── LICENSE /config/sys.config: -------------------------------------------------------------------------------- 1 | [ 2 | { wechat, []} 3 | ]. 4 | -------------------------------------------------------------------------------- /rebar3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sidwubf/wechat-erlang-sdk/HEAD/rebar3 -------------------------------------------------------------------------------- /config/vm.args: -------------------------------------------------------------------------------- 1 | -sname wechat 2 | 3 | -setcookie wechat_cookie 4 | 5 | +K true 6 | +A30 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .eunit 2 | deps 3 | *.o 4 | *.beam 5 | *.plt 6 | erl_crash.dump 7 | ebin 8 | rel/example_project 9 | test 10 | .concrete/DEV_MODE 11 | .rebar 12 | rebar.lock 13 | _build/ 14 | log/ 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 可能是目前唯一的微信公众平台Erlang SDK 2 | ===== 3 | 4 | Build 5 | ----- 6 | 7 | $ rebar3 compile 8 | 9 | Release 10 | ----- 11 | 12 | $ rebar3 release 13 | or 14 | $ rebar3 as prod tar 15 | 16 | Run 17 | ----- 18 | 19 | wechat_handler中处理微信接收文本或事件等 20 | -------------------------------------------------------------------------------- /apps/wechat/src/wechat_signature.erl: -------------------------------------------------------------------------------- 1 | -module(wechat_signature). 2 | 3 | -export([check/3]). 4 | 5 | check(Signature, Timestamp, Nonce) -> 6 | Token = "yourtoken", 7 | TmpList = [Token, Timestamp, Nonce], 8 | TmpList2 = lists:sort(TmpList), 9 | TmpStr = string:join(TmpList2, ""), 10 | Hash = wechat_util:hexstring(TmpStr), 11 | string:equal(Signature, Hash). 12 | -------------------------------------------------------------------------------- /apps/wechat/src/wechat.app.src: -------------------------------------------------------------------------------- 1 | {application, wechat, 2 | [{description, "An OTP application"}, 3 | {vsn, "0.1.0"}, 4 | {registered, []}, 5 | {mod, { wechat_app, []}}, 6 | {applications, 7 | [kernel, 8 | stdlib, 9 | hackney, 10 | jiffy, 11 | eredis, 12 | cowboy, 13 | lager 14 | ]}, 15 | {env,[]}, 16 | {modules, []}, 17 | 18 | {maintainers, []}, 19 | {licenses, []}, 20 | {links, []} 21 | ]}. 22 | -------------------------------------------------------------------------------- /apps/wechat/src/wechat.erl: -------------------------------------------------------------------------------- 1 | -module(wechat). 2 | 3 | -export([get_access_token/2, get_callback_ip/1]). 4 | -export([create_menu/2]). 5 | 6 | -include("include/wechat.hrl"). 7 | 8 | %{"access_token":"ACCESS_TOKEN","expires_in":7200} 9 | get_access_token(AppId, AppSecret) -> 10 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/token?grant_type=client_credential&appid="++AppId++"&secret="++AppSecret), 11 | wechat_util:http_get(URL). 12 | 13 | %{"ip_list": ["127.0.0.1", "127.0.0.2", "101.226.103.0/25"]} 14 | get_callback_ip(AccessToken) -> 15 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/getcallbackip?access_token="++AccessToken), 16 | wechat_util:http_get(URL). 17 | 18 | %{"errcode":0,"errmsg":"ok"} 19 | create_menu(AccessToken, Menu) -> 20 | wechat_menu:create(AccessToken, Menu). 21 | -------------------------------------------------------------------------------- /apps/wechat/src/wechat_handler.erl: -------------------------------------------------------------------------------- 1 | -module(wechat_handler). 2 | 3 | -export([init/3, handle/2, terminate/3]). 4 | 5 | init(_, Req, Opts) -> 6 | {Signature, _Req} = cowboy_req:qs_val(<<"signature">>, Req), 7 | {Timestamp, _Req} = cowboy_req:qs_val(<<"timestamp">>, Req), 8 | {Nonce, _Req} = cowboy_req:qs_val(<<"nonce">>, Req), 9 | Result = wechat_signature:check(binary_to_list(Signature), binary_to_list(Timestamp), binary_to_list(Nonce)), 10 | if 11 | Result == false -> 12 | {error, Req, Opts}; 13 | true -> 14 | Req2 = cowboy_req:reply(200, [ 15 | {<<"content-type">>, <<"text/plain">>} 16 | ], <<"Hello world!">>, Req), 17 | {ok, Req2, Opts} 18 | end. 19 | 20 | handle(Req, State) -> 21 | {ok, Req2} = cowboy_req:reply(200, [ 22 | {<<"content-type">>, <<"text/plain">>} 23 | ], <<"Hello World!">>, Req), 24 | {ok, Req2, State}. 25 | 26 | terminate(_Reason, Req, State) -> 27 | ok. 28 | -------------------------------------------------------------------------------- /apps/wechat/src/wechat_sup.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc wechat top level supervisor. 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(wechat_sup). 7 | 8 | -behaviour(supervisor). 9 | 10 | %% API 11 | -export([start_link/0]). 12 | 13 | %% Supervisor callbacks 14 | -export([init/1]). 15 | 16 | -define(SERVER, ?MODULE). 17 | 18 | %%==================================================================== 19 | %% API functions 20 | %%==================================================================== 21 | 22 | start_link() -> 23 | supervisor:start_link({local, ?SERVER}, ?MODULE, []). 24 | 25 | %%==================================================================== 26 | %% Supervisor callbacks 27 | %%==================================================================== 28 | 29 | %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} 30 | init([]) -> 31 | {ok, { {one_for_all, 0, 1}, []} }. 32 | 33 | %%==================================================================== 34 | %% Internal functions 35 | %%==================================================================== 36 | -------------------------------------------------------------------------------- /apps/wechat/src/wechat_menu.erl: -------------------------------------------------------------------------------- 1 | -module(wechat_menu). 2 | %自定义菜单 3 | -export([create/2, get/1, delete/1, add_conditional/2, get_info/1]). 4 | 5 | -include("include/wechat.hrl"). 6 | 7 | create(AccessToken, Menu) -> 8 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/menu/create?access_token="++AccessToken), 9 | MenuBinary = list_to_binary(Menu), 10 | wechat_util:http_post(URL, MenuBinary). 11 | 12 | get(AccessToken) -> 13 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/menu/get?access_token="++AccessToken), 14 | wechat_util:http_get(URL). 15 | 16 | delete(AccessToken) -> 17 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/menu/delete?access_token="++AccessToken), 18 | wechat_util:http_get(URL). 19 | 20 | add_conditional(AccessToken, MenuConditional) -> 21 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/menu/addconditional?access_token="++AccessToken), 22 | MenuConditionalBinary = list_to_binary(MenuConditional), 23 | wechat_util:http_post(URL, MenuConditionalBinary). 24 | 25 | get_info(AccessToken) -> 26 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/get_current_selfmenu_info?access_token="++AccessToken), 27 | wechat_util:http_get(URL). 28 | -------------------------------------------------------------------------------- /apps/wechat/src/wechat_app.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc wechat public API 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | 6 | -module(wechat_app). 7 | 8 | -behaviour(application). 9 | 10 | %% Application callbacks 11 | -export([start/2, stop/1]). 12 | 13 | %%==================================================================== 14 | %% API 15 | %%==================================================================== 16 | 17 | start(_StartType, _StartArgs) -> 18 | application:start(cowboy), 19 | application:start(crypto), 20 | application:start(public_key), 21 | application:start(ssl), 22 | application:start(hackney), 23 | application:start(jiffy), 24 | Dispatch = cowboy_router:compile([ 25 | {'_', [ 26 | {"/wechat", wechat_handler, []} 27 | ]} 28 | ]), 29 | {ok, _} = cowboy:start_http(http, 100, [{port, 8081}], [ 30 | {env, [{dispatch, Dispatch}]} 31 | ]), 32 | wechat_sup:start_link(). 33 | 34 | %%-------------------------------------------------------------------- 35 | stop(_State) -> 36 | ok. 37 | 38 | %%==================================================================== 39 | %% Internal functions 40 | %%==================================================================== 41 | -------------------------------------------------------------------------------- /rebar.config: -------------------------------------------------------------------------------- 1 | {erl_opts, [debug_info]}. 2 | {deps, [ 3 | {hackney, ".*", {git, "https://github.com/benoitc/hackney.git", {branch, "master"}}}, 4 | {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {branch, "master"}}}, 5 | {eredis, ".*", {git, "https://github.com/wooga/eredis.git", {branch, "master"}}}, 6 | {cowboy, "1.0.4"}, 7 | {cowboy, {git, "git://github.com/ninenines/cowboy.git", {tag, "1.0.4"}}}, 8 | {lager, ".*", {git, "https://github.com/basho/lager.git", {branch, "master"}}}, 9 | {erlsom, ".*", {git, "https://github.com/willemdj/erlsom.git", {branch, "master"}}} 10 | ]}. 11 | 12 | {relx, [{release, { wechat, "0.1.0" }, 13 | [wechat, 14 | sasl]}, 15 | 16 | {sys_config, "./config/sys.config"}, 17 | {vm_args, "./config/vm.args"}, 18 | 19 | {dev_mode, true}, 20 | {include_erts, false}, 21 | 22 | {extended_start_script, true}] 23 | }. 24 | 25 | {profiles, [{prod, [{relx, [{dev_mode, false}, 26 | {include_erts, true}]}] 27 | }] 28 | }. 29 | 30 | {profiles, [ 31 | {test, [{deps, [ 32 | {meck, ".*", 33 | {git, "git://github.com/eproxus/meck.git", {tag, "0.8.2"}}} 34 | ]} 35 | ]} 36 | ] 37 | }. 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, <>. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | * The names of its contributors may not be used to endorse or promote 16 | products derived from this software without specific prior written 17 | permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /apps/wechat/src/wechat_media.erl: -------------------------------------------------------------------------------- 1 | -module(wechat_media). 2 | %素材管理 3 | -export([get_media/2, add_news/2, get_material/2, delete_material/2, 4 | update_news/2, get_material_count/1, get_batch_material/2]). 5 | 6 | get_media(AccessToken, MediaId) -> 7 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/media/get?access_token="++AccessToken++"&media_id="++MediaId), 8 | wechat_util:http_get(URL). 9 | 10 | add_news(AccessToken, News) -> 11 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/material/add_news?access_token="++AccessToken), 12 | NewsBinary = list_to_binary(News), 13 | wechat_util:http_post(URL, NewsBinary). 14 | 15 | get_material(AccessToken, MediaId) -> 16 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/material/get_material?access_token="++AccessToken), 17 | MediaIdBinary = list_to_binary(MediaId), 18 | wechat_util:http_post(URL, MediaIdBinary). 19 | 20 | delete_material(AccessToken, MediaId) -> 21 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/material/del_material?access_token="++AccessToken), 22 | MediaIdBinary = list_to_binary(MediaId), 23 | wechat_util:http_post(URL, MediaIdBinary). 24 | 25 | update_news(AccessToken, News) -> 26 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/material/update_news?access_token="++AccessToken), 27 | NewsBinary = list_to_binary(News), 28 | wechat_util:http_post(URL, NewsBinary). 29 | 30 | get_material_count(AccessToken) -> 31 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/material/get_materialcount?access_token="++AccessToken), 32 | wechat_util:http_get(URL). 33 | 34 | get_batch_material(AccessToken, Query) -> 35 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/material/batchget_material?access_token="++AccessToken), 36 | QueryBinary = list_to_binary(Query), 37 | wechat_util:http_post(URL, QueryBinary). 38 | -------------------------------------------------------------------------------- /apps/wechat/include/wechat.hrl: -------------------------------------------------------------------------------- 1 | -define(WECHAT_HRL, "wechat.hrl"). 2 | 3 | -define(WECHAT_API_URI, "api.weixin.qq.com"). 4 | 5 | -define(MSGTYPE_TEXT, "text"). 6 | -define(MSGTYPE_IMAGE, "image"). 7 | -define(MSGTYPE_LOCATION, "location"). 8 | -define(MSGTYPE_LINK, "link"). 9 | -define(MSGTYPE_EVENT, "event"). 10 | -define(MSGTYPE_MUSIC, "music"). 11 | -define(MSGTYPE_NEWS, "news"). 12 | -define(MSGTYPE_VOICE, "voice"). 13 | -define(MSGTYPE_VIDEO, "video"). 14 | -define(API_URL_PREFIX, "https://api.weixin.qq.com"). 15 | -define(AUTH_URL, "/token?grant_type=client_credential&"). 16 | -define(MENU_CREATE_URL, "/menu/create?"). 17 | -define(MENU_GET_URL, "/menu/get?"). 18 | -define(MENU_DELETE_URL, "/menu/delete?"). 19 | -define(MEDIA_GET_URL, "/media/get?"). 20 | -define(QRCODE_CREATE_URL, "/qrcode/create?"). 21 | -define(QR_SCENE, 0). 22 | -define(QR_LIMIT_SCENE, 1). 23 | -define(QRCODE_IMG_URL, "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="). 24 | -define(SHORT_URL, "/shorturl?"). 25 | -define(USER_GET_URL, "/user/get?"). 26 | -define(USER_INFO_URL, "/user/info?"). 27 | -define(USER_UPDATEREMARK_URL, "/user/info/updateremark?"). 28 | -define(GROUP_GET_URL, "/groups/get?"). 29 | -define(USER_GROUP_URL, "/groups/getid?"). 30 | -define(GROUP_CREATE_URL, "/groups/create?"). 31 | -define(GROUP_UPDATE_URL, "/groups/update?"). 32 | -define(GROUP_MEMBER_UPDATE_URL, "/groups/members/update?"). 33 | -define(CUSTOM_SEND_URL, "/message/custom/send?"). 34 | -define(MEDIA_UPLOADNEWS_URL, "/media/uploadnews?"). 35 | -define(MASS_SEND_URL, "/message/mass/send?"). 36 | -define(TEMPLATE_SEND_URL, "/message/template/send?"). 37 | -define(MASS_SEND_GROUP_URL, "/message/mass/sendall?"). 38 | -define(MASS_DELETE_URL, "/message/mass/delete?"). 39 | -define(UPLOAD_MEDIA_URL, "http://file.api.weixin.qq.com/cgi-bin"). 40 | -define(MEDIA_UPLOAD, "/media/upload?"). 41 | -define(OAUTH_PREFIX, "https://open.weixin.qq.com/connect/oauth2"). 42 | -define(OAUTH_AUTHORIZE_URL, "/authorize?"). 43 | -define(OAUTH_TOKEN_PREFIX, "https://api.weixin.qq.com/sns/oauth2"). 44 | -define(OAUTH_TOKEN_URL, "/access_token?"). 45 | -define(OAUTH_REFRESH_URL, "/refresh_token?"). 46 | -define(OAUTH_USERINFO_URL, "https://api.weixin.qq.com/sns/userinfo?"). 47 | -define(OAUTH_AUTH_URL, "https://api.weixin.qq.com/sns/auth?"). 48 | -define(PAY_DELIVERNOTIFY, "https://api.weixin.qq.com/pay/delivernotify?"). 49 | -define(PAY_ORDERQUERY, "https://api.weixin.qq.com/pay/orderquery?"). 50 | -define(CUSTOM_SERVICE_GET_RECORD, "/customservice/getrecord?"). 51 | -define(CUSTOM_SERVICE_GET_KFLIST, "/customservice/getkflist?"). 52 | -define(CUSTOM_SERVICE_GET_ONLINEKFLIST, "/customservice/getkflist?"). 53 | -define(SEMANTIC_API_URL, "https://api.weixin.qq.com/semantic/semproxy/search?"). 54 | -------------------------------------------------------------------------------- /apps/wechat/src/wechat_util.erl: -------------------------------------------------------------------------------- 1 | -module(wechat_util). 2 | 3 | -export([http_get/1, http_post/2]). 4 | 5 | -export([binstring/1, hexstring/1, binfile/1, hexfile/1]). 6 | -import(lists, [nth/2, map/2, foldl/3]). 7 | -import(erlang,[integer_to_list/2, list_to_integer/2]). 8 | 9 | http_get(URL) -> 10 | Method = get, 11 | Headers = [{<<"Content-Type">>, <<"application/json">>}], 12 | Payload = <<>>, 13 | Options = [], 14 | {ok, _StatusCode, _RespHeaders, ClientRef} = hackney:request(Method, URL, Headers, Payload, Options), 15 | {ok, Body} = hackney:body(ClientRef), 16 | Response = jiffy:decode(Body), 17 | Response. 18 | 19 | http_post(URL, Body) -> 20 | Method = post, 21 | ReqHeaders = [{<<"Content-Type">>, <<"application/json">>}], 22 | {ok, ClientRef} = hackney:request(Method, URL, ReqHeaders, stream, []), 23 | ok = hackney:send_body(ClientRef, Body), 24 | {ok, _Status, _Headers, ClientRef} = hackney:start_response(ClientRef), 25 | {ok, Body} = hackney:body(ClientRef), 26 | Response = jiffy:decode(Body), 27 | Response. 28 | 29 | binstring(S) -> fun_apply(S, fun list_to_binary/1, fun(X)->X end). 30 | hexstring(S) -> fun_apply(S, fun list_to_binary/1, fun bin2hex/1). 31 | binfile(S) -> fun_apply(S, fun read_unsafe/1, fun(X)->X end). 32 | hexfile(S) -> fun_apply(S, fun read_unsafe/1, fun bin2hex/1). 33 | 34 | fun_apply(S, FunRead, FunTransform) -> 35 | case catch binstring_unsafe(FunRead(S)) of 36 | {'EXIT', Stuff} -> {error, Stuff}; 37 | Data -> FunTransform(Data) 38 | end. 39 | 40 | read_unsafe(File) -> {ok, L} = file:read_file(File), L. 41 | 42 | bin2hex(B) -> 43 | L = binary_to_list(B), 44 | LH0 = map(fun(X)->integer_to_list(X,16) end, L), 45 | LH = map(fun([X,Y])->[X,Y];([X])->[$0,X] end, LH0), % add zeros 46 | lists:flatten(LH). 47 | 48 | binstring_unsafe(S) -> 49 | X = pad_str(S), 50 | N = length(binary_to_list(X)) div 64, 51 | Hs = {16#67452301, 16#EFCDAB89, 16#98BADCFE, 16#10325476, 16#C3D2E1F0}, 52 | compute(X, N, Hs). 53 | 54 | pad_str(B) -> 55 | L = 8 * size(B), 56 | D = (512 + ((447 - L) rem 512)) rem 512, % negative (447-L) handled 57 | <>. % hehe i like how 0:D looks 58 | 59 | 60 | add([]) -> 0; 61 | add([H|T]) -> (H + add(T)) rem 16#100000000. 62 | 63 | 64 | compute(<<>>, 0, {H0,H1,H2,H3,H4}) -> <>; 65 | 66 | compute(<>, I, {H0,H1,H2,H3,H4} = Hs) -> 67 | W0_15 = compute_ws(<>), 68 | Ws = compute_wt(W0_15), 69 | {A,B,C,D,E} = inner_loop(0, Hs, Ws), 70 | compute(Other, I-1, {add([H0,A]), add([H1,B]), add([H2,C]), 71 | add([H3,D]),add([H4,E])}). 72 | 73 | %% generates K_i 74 | k(I) when 0 =< I, I =< 19 -> 16#5A827999; 75 | k(I) when 20 =< I, I =< 39 -> 16#6ED9EBA1; 76 | k(I) when 40 =< I, I =< 59 -> 16#8F1BBCDC; 77 | k(I) when 60 =< I, I =< 79 -> 16#CA62C1D6. 78 | 79 | %% f_t 80 | f(T, B,C,D) when 0 =< T, T =< 19 -> (B band C) bor ((bnot B) band D); 81 | f(T, B,C,D) when 20 =< T, T =< 39 -> B bxor C bxor D; 82 | f(T, B,C,D) when 40 =< T, T =< 59 -> (B band C) bor (B band D) bor (C band D); 83 | f(T, B,C,D) when 60 =< T, T =< 79 -> B bxor C bxor D. 84 | 85 | %% rotates S bytes to the left on 32 bits 86 | rotl(S, Num) -> 87 | Max = 16#ffffffff, 88 | LMask = (Max bsl (32-S)) , 89 | RMask = (Max bsr (S)) , 90 | L = Num band LMask, 91 | R = Num band RMask, 92 | NewL = (R bsl S) , 93 | NewR = (L bsr (32-S)) , 94 | NewL + NewR. 95 | 96 | compute_ws(<<>>) -> []; 97 | compute_ws(<>) -> [Wi] ++ compute_ws(Other). 98 | 99 | %% generates W_t. 100 | compute_wt(Ws) -> compute_wt(Ws, 16). 101 | compute_wt(Ws, 80) -> Ws; 102 | compute_wt(Ws, T) -> 103 | Wp = map(fun(X)->nth(1 + T - X, Ws) end, [3,8,14,16]), 104 | Wt_pre = foldl(fun(X,Y)->X bxor Y end, 0, Wp), 105 | Wt = rotl(1, Wt_pre), 106 | compute_wt(Ws ++ [Wt], T+1). 107 | 108 | %% the SHA-1 inner loop 109 | inner_loop(80, {A,B,C,D,E}, _Ws) -> {A,B,C,D,E}; 110 | inner_loop(T, {A,B,C,D,E}, Ws) -> 111 | Temp = add([rotl(5, A), f(T, B,C,D), E, nth(1+T, Ws), k(T)]), 112 | inner_loop(T+1, {Temp, A, rotl(30, B), C, D}, Ws). 113 | -------------------------------------------------------------------------------- /apps/wechat/src/wechat_message.erl: -------------------------------------------------------------------------------- 1 | -module(wechat_message). 2 | %消息管理 3 | -export([add_kf_account/2, update_kf_account/2, delete_kf_account/2, 4 | get_kf_list/1, send_message/2, send_message_by_group/2, 5 | send_message_by_openid_list/2, delete_message/2, 6 | get_info_of_message/2, set_industry_for_template/2, 7 | get_industry/1, get_template_id/1, get_private_template_list/1, 8 | delete_private_template/2, send_template_message/2, 9 | get_autoreply_info/1]). 10 | 11 | -include("include/wechat.hrl"). 12 | 13 | add_kf_account(AccessToken, Account) -> 14 | URL = list_to_binary(?API_URL_PREFIX ++ "/customservice/kfaccount/add?access_token="++AccessToken), 15 | AccountBinary = list_to_binary(Account), 16 | wechat_util:http_post(URL, AccountBinary). 17 | 18 | update_kf_account(AccessToken, Account) -> 19 | URL = list_to_binary(?API_URL_PREFIX ++ "/customservice/kfaccount/update?access_token="++AccessToken), 20 | AccountBinary = list_to_binary(Account), 21 | wechat_util:http_post(URL, AccountBinary). 22 | 23 | delete_kf_account(AccessToken, Account) -> 24 | URL = list_to_binary(?API_URL_PREFIX ++ "/customservice/kfaccount/del?access_token="++AccessToken), 25 | AccountBinary = list_to_binary(Account), 26 | wechat_util:http_post(URL, AccountBinary). 27 | 28 | get_kf_list(AccessToken) -> 29 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/customservice/getkflist?access_token="++AccessToken), 30 | wechat_util:http_get(URL). 31 | 32 | send_message(AccessToken, Message) -> 33 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/message/custom/send?access_token="++AccessToken), 34 | MessageBinary = list_to_binary(Message), 35 | wechat_util:http_post(URL, MessageBinary). 36 | 37 | send_message_by_group(AccessToken, Message) -> 38 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/message/mass/sendall?access_token="++AccessToken), 39 | MessageBinary = list_to_binary(Message), 40 | wechat_util:http_post(URL, MessageBinary). 41 | 42 | send_message_by_openid_list(AccessToken, Message) -> 43 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/message/mass/send?access_token="++AccessToken), 44 | MessageBinary = list_to_binary(Message), 45 | wechat_util:http_post(URL, MessageBinary). 46 | 47 | delete_message(AccessToken, MessageId) -> 48 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/message/mass/delete?access_token="++AccessToken), 49 | MessageIdBinary = list_to_binary(MessageId), 50 | wechat_util:http_post(URL, MessageIdBinary). 51 | 52 | get_info_of_message(AccessToken, MessageId) -> 53 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/message/mass/get?access_token="++AccessToken), 54 | MessageIdBinary = list_to_binary(MessageId), 55 | wechat_util:http_post(URL, MessageIdBinary). 56 | 57 | set_industry_for_template(AccessToken, Industry) -> 58 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/template/api_set_industry?access_token="++AccessToken), 59 | IndustryBinary = list_to_binary(Industry), 60 | wechat_util:http_post(URL, IndustryBinary). 61 | 62 | get_industry(AccessToken) -> 63 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/template/get_industry?access_token="++AccessToken), 64 | wechat_util:http_get(URL). 65 | 66 | get_template_id(AccessToken) -> 67 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/template/api_add_template?access_token="++AccessToken), 68 | wechat_util:http_get(URL). 69 | 70 | get_private_template_list(AccessToken) -> 71 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/template/get_all_private_template?access_token="++AccessToken), 72 | wechat_util:http_get(URL). 73 | 74 | delete_private_template(AccessToken, TemplateId) -> 75 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/template/del_private_template?access_token="++AccessToken), 76 | TemplateIdBinary = list_to_binary(TemplateId), 77 | wechat_util:http_post(URL, TemplateIdBinary). 78 | 79 | send_template_message(AccessToken, Message) -> 80 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/message/template/send?access_token="++AccessToken), 81 | MessageBinary = list_to_binary(Message), 82 | wechat_util:http_post(URL, MessageBinary). 83 | 84 | get_autoreply_info(AccessToken) -> 85 | URL = list_to_binary(?API_URL_PREFIX ++ "/cgi-bin/get_current_autoreply_info?access_token="++AccessToken), 86 | wechat_util:http_get(URL). 87 | --------------------------------------------------------------------------------