forked from xunyangjian/meteor-account-wechat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwebwechat_server.js
137 lines (117 loc) · 4.26 KB
/
webwechat_server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
48
49
50
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
77
78
79
80
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
Accounts.oauth.registerService('webwechat');
MeteorWebWeChat = {};
MeteorWebWeChat.whitelistedFields = ['nickname', 'sex', 'province', 'city', 'country',
'headimgurl', 'privilege'];
var OAuth = Package.oauth.OAuth;
var serviceName = 'webwechat';
var serviceVersion = 2;
var serviceUrls = null;
var serviceHandler = function(query) {
var response = getTokenResponse(query);
var expiresAt = (+new Date) + (1000 * parseInt(response.expiresIn, 10));
var accessToken = response.accessToken;
var scope = response.scope;
var openId = response.openId;
var unionId = response.unionId;
var serviceData = {
accessToken: accessToken,
expiresAt: expiresAt,
openId: openId,
unionId: unionId,
scope: scope,
id: unionId // id is required by Meteor, using openId since it's not given by WeChat
};
// only set the token in serviceData if it's there. this ensures
// that we don't lose old ones
if (response.refreshToken)
serviceData.refreshToken = response.refreshToken;
var identity = getIdentity(accessToken, openId);
var fields = _.pick(identity, MeteorWebWeChat.whitelistedFields);
_.extend(serviceData, fields);
return {
serviceData: serviceData,
options: {
profile: fields
}
};
};
var getTokenResponse = function (query) {
var config = ServiceConfiguration.configurations.findOne({service: 'webwechat'});
if (!config)
throw new ServiceConfiguration.ConfigError();
var response;
try {
//Request an access token
response = HTTP.get(
"https://api.weixin.qq.com/sns/oauth2/access_token", {
params: {
code: query.code,
appid: config.appId,
secret: OAuth.openSecret(config.secret),
grant_type: 'authorization_code'
}
}
);
if (response.error) // if the http response was an error
throw response.error;
if (typeof response.content === "string")
response.content = JSON.parse(response.content);
if (response.content.error)
throw response.content;
} catch (err) {
throw _.extend(new Error("Failed to complete OAuth handshake with WeChat. " + err.message),
{response: err.response});
}
return {
accessToken: response.content.access_token,
expiresIn: response.content.expires_in,
refreshToken: response.content.refresh_token,
openId: response.content.openid,
scope: response.content.scope,
unionId: response.content.unionid
};
};
var getIdentity = function (accessToken, openId) {
try {
var response = HTTP.get("https://api.weixin.qq.com/sns/userinfo", {
params: {access_token: accessToken, openid: openId, lang: 'en'}}
);
if (response.error) // if the http response was an error
throw response.error;
if (typeof response.content === "string")
return JSON.parse(response.content);
if (response.content.error)
throw response.content;
} catch (err) {
throw _.extend(new Error("Failed to fetch identity from WeChat. " + err.message),
{response: err.response});
}
};
// register OAuth service
OAuth.registerService(serviceName, serviceVersion, serviceUrls, serviceHandler);
// retrieve credential
MeteorWebWeChat.retrieveCredential = function(credentialToken, credentialSecret) {
return OAuth.retrieveCredential(credentialToken, credentialSecret);
};
Meteor.methods({
handleWebWeChatOauthRequest: function(query) {
// allow the client with 3rd party authorization code to directly ask server to handle it
check(query.code, String);
var oauthResult = serviceHandler(query);
var credentialSecret = Random.secret();
//var credentialToken = OAuth._credentialTokenFromQuery(query);
var credentialToken = query.state;
// Store the login result so it can be retrieved in another
// browser tab by the result handler
OAuth._storePendingCredential(credentialToken, {
serviceName: serviceName,
serviceData: oauthResult.serviceData,
options: oauthResult.options
}, credentialSecret);
// return the credentialToken and credentialSecret back to client
return {
'credentialToken': credentialToken,
'credentialSecret': credentialSecret
};
}
});