English
Groovy Code Example
About 565 wordsAbout 2 min
2026-01-09
class OauthServiceImpl implements AuthProviderPlugin {
/**
* The third-party URL redirected when opening {tenant domain}.my.fxiaoke.com during login
*/
@Override
String authorize(FunctionContext context, Map<String, List<String>> params) {
// Return the third-party login URL to browser, please refer to third-party documentation for specific parameters
return "https://www.otherdomain.com/oauth2/auth?" + "response_type=code&" +
"response_mode=query&" +
"scope=openid&" +
"redirect_uri={tenant domain}.my.fxiaoke.com/oauth2/sp/callback/{URL suffix}" + // Callback URL after third-party login
"client_id={third-party app ID}";
}
/**
* Callback function after third-party login completion, typically used to obtain user information
* @param params URL parameters from third-party callback
* @return Returns the Fxiaoke system employee ID
*/
@Override
Integer callback(FunctionContext context, Map<String, List<String>> params) {
// Tenant temporary authorization mode (refer to third-party documentation for other modes)
String token = getAccessToken(params);
log.info(token);
// Get Fxiaoke user ID from personnel object
Integer userId = openId2userId(token);
log.info(userId);
return userId;
}
/**
* The page to open after successful login (can be obtained from params or specified)
* @return URL to open after successful login
*/
@Override
String redirect(FunctionContext context, Map<String, List<String>> params) {
// 'encode' means URL encoding is required to make parameters URL-compliant
// For request parameter ?target=encode(/XV/UI/Home), use params.get("target").get(0), tenant domain will be automatically appended
// For request parameter ?target=encode(https://www.fxiaoke.com/XV/UI/Home), use params.get("target").get(0), will directly 302 redirect
// For request parameter ?target=encode(/hcrm/avah5/function/todo?id=xxx&apiName=xxxx), will automatically detect browser to open web or H5 (currently in beta)
// Return null or "" to open default homepage
// Code should handle cases where target doesn't exist
// 'target' is just an example variable name, can be changed according to protocol
// params is technically an array, but normally just use index 0
if (params.containsKey("target")) {
return params.get("target").get(0)
} else {
return null;
}
}
/**
* Redirect to third-party logout URL when logging out from Fxiaoke system
* @return Third-party logout URL, return null if no third-party logout needed
*/
@Override
String logoffUrl(FunctionContext context) {
return "https://www.otherdomain.com/oauth2/logoff"
}
String getAccessToken(Map<String, List<String>> parameterMap) {
// Example implementation (refer to third-party documentation)
FormBody body = FormBody.builder()
.field("client_id", { third-party app ID })
.field("scope", "openid")
.field("redirect_uri", "https://xxx.my.fxiaoke.com/oauth2/sp/callback/xxx")
.field("client_secret", { third-party app secret })
.field("code", parameterMap["code"].get(0))
.build()
Request request = Request.builder()
.method("POST")
.url("https://xxxx/oauth2/token")
.timeout(7000)
.retryCount(0)
.body(body)
.build()
HttpResult o = (HttpResult) http.execute(request).getData()
log.info(o)
return o.content["access_token"] as String
}
Integer openId2userId(String accessToken) {
// Get third-party user info
HttpResult o = (HttpResult) http.get("https://xxx/oauth2/userinfo", ["Authorization": accessToken]).getData();
String user = o.content["sub"] as String
log.info(user)
// Query personnel object to get binding info from third-party user info (recommend using custom fields)
APIResult data = Fx.object.find("PersonnelObj", // Query personnel object
FQLAttribute.builder()
.columns(["user_id"]) // Returned data ID
.queryTemplate(QueryTemplate.AND(["UserDefineField__c": QueryOperator.EQ(user)]))
.build(),
SelectAttribute.builder()
.build());
if(data.isError()){
message.throwErrorMessage("Failed to get user info: " + data.message())
}
List<Map> dataList = data.dataList
// Return error if user info not found
// Alternatively, create new personnel and set binding fields here
if (dataList.size() <= 0) {
message.throwErrorMessage("User not found, user:" + user)
}
if (dataList.size() > 1) {
message.throwErrorMessage("Multiple users found, user:" + user)
}
// Return user_id field from personnel object for subsequent login
return dataList[0]["user_id"].toString() as Integer
}
// Debug entry method
void debug(FunctionContext context, Map arg) {
}
}