使用 Workday 憑證提出 Adaptive Planning API 要求
Some links in this article go to the Workday Community. If you don't have
a Community account, request
one.
登入 Workday 並使用 Workday 同步使用者
Adaptive Planning
Worklet 可執行 Adaptive Planning
公開 API使用者必須建立專門的 ISU,才能發出這些 API 要求。這些使用者必須在 credentials
元素 Adaptive Planning
API 要求,而不是使用者名稱和密碼。您可以快取此權杖,並在其到期前使用。到期後,您必須取得新的權杖。
Prerequisites
Prerequisites
Workday 網域和安全群組
- 確認需要 API 存取權的 ISU 使用者是Set Up: Adaptive Planning API Access安全網域的一部分。
Workday 設定任務
- 確認已啟用單點登入 (SSO)任務的「使用者登入」分頁。Adaptive Planning分頁。
- 確認已在「公開 API」分頁中啟用「公開 API設定」任務。Adaptive Planning分頁。
- 確認整合系統使用者 (ISU) 設定任務已建立專門用於提出 Workday Adaptive Planning API 要求的 ISU,並將其對應至Adaptive Planning使用者帳戶。
Adaptive Planning
使用者管理者- 確認您看到的 ISU 開頭為PublicAPIISU_在管理 > 使用者內的使用者清單中。
- 確認此使用者是否具有執行其 API 所需的層級存取權。預設情況下,新的 ISU 不會收到層級存取權。
Steps
Steps
- 取得憑證並擷取您的公開金鑰。
- 使用該憑證在 Workday 中註冊 API 用戶端。
- 產生 JWT 權杖、擷取 Workday access_token 和擷取 AdaptiveAPIAccessToken。
- 在Adaptive PlanningAPI 要求
取得憑證並擷取您的公開金鑰
您可以自行建立憑證,也可以從知名的憑證授權機構購買憑證。如需 Workday 中 X.509 憑證所需參數的詳細資料,請參閱 「概念︰Workday 中的 X.509 憑證」。
- 從憑證中擷取公開金鑰,以上傳至 Workday。
- 請保留您的私人金鑰,以便在呼叫應用程式中使用。
- 在註冊您的 JWT Bearer 權杖時,將憑證貼到 Workday 中。在指令碼中參照您的私人金鑰。
註冊 Workday API 用戶端
- 在 Workday 中使用「用戶端授予類型︰JWT Bearer 授予」註冊 API 用戶端。請參閱 「註冊 API 用戶端」 以取得更多資訊。
- 在 Workday 的「註冊 API 用戶端」頁面中,將從您的憑證衍生的公開金鑰複製到x.509 憑證中。
- 針對范圍 (功能區),選取。Adaptive Planning
- 完成 API 用戶端的註冊後,請將頁面底部的產生欄位複製到文字檔案中,以備日後使用。
- Workday REST API 端點
- 權杖端點
- 授權端點
產生 JWT 權杖、擷取 Workday access_token 和擷取 AdaptiveAPIAccessToken
- 使用您的私人金鑰,並透過執行下列偽代碼來產生 JWT 權杖。
- 若要擷取 Workday 存取權杖,請建立POST對權杖端點的要求,通過grant_type和assertion。使用在 Workday 中註冊您的 API 用戶端后複製的權杖端點。範例權杖端點︰https://{host or gateway}/ccx/oauth2/{tenant}/token範例CURL對權杖端點的要求curl --request POST 'https://{host or gateway}/ccx/oauth2/{tenant}/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer' \ --data-urlencode 'assertion={{the jwt assertion from your certificate}}'
- 使用 Workday 存取權杖呼叫 Workday 端點,以擷取 AdaptiveAPIAccessToken。使用先前的access_token值做為 Bearer 權杖Auth此項目的標頭GET.存取權杖範例︰https://{host or gateway}/ccx/api/planning/v1/{tenant}/adaptiveAPIAccessToken範例CURLAdaptiveAPIAccessToken 的要求︰curl --request GET 'https://{host or gateway}/ccx/api/planning/v1/{tenant}/adaptiveAPIAccessToken' \ --header 'Authorization: Bearer {{the prior access_token value}}' \ --data-raw ''
- 呼叫Adaptive Planning在 HTTP 中 XML 的憑證元素中使用 AdaptiveAPIAccessToken 的 APIPOST。範例︰curl -H "Content-Type: text/xml" -d '<?xml version='1.0' encoding='UTF-8'?><call method="exportLevels" callerName="a string that identifies your client application"><credentials token="ID eyJhbDci0iJSUzUxMiIsUmtpZCI6IdvcmtkYXlfa2V5In0.eyJpc3KiOiJXb3JrZGFZIiwiYXV0aF90aW1lIjoxNTczMTY3NjU2LBjzeXnfynnJd.bztQzBmHeTj1amnHA-r96TdrJK0MXMghUFF1KyjxqIq6ruHU63dJp3JAJn3Eche7SEcoZBVGX4wJgna106pmCqgrrVWMf13Hg_sb_szabal2XN1KEEk1qh8z1IDlbt6qJIL_xyW3J2nNSs5ima3vJUYU5sRQXwXst0GuFWXpy464GyB4oKcscrg28X3dnPO_ytdohMKHsWkqyHQKXFQwoQezFaGy10sp4RRUj0lpOZX8C9oBHDYA58IXxGkqKLJVNPvDND6rGY5fTHQ-yxpe1nz-WqB0boiq9a-dv8b3EBzbelxj2fCPdMbng6kzygDcA2at_7BNQiyzfIovS5AG"/><include versionID="3" inaccessibleValues="false"/><sheet id="3" /></call>' -X POST https://api.adaptiveplanning.com/api/v23
用於產生 JWT 權杖的範例 Java 應用程式
此範例 Java 應用程式會產生 JWT 權杖。
//********************************************************************** // // File: TestPublicAPISample.java // // Copyright 2004-2019 Workday Adaptive Planning. // All Rights Reserved. // // This work contains trade secrets and confidential material of // Workday Adaptive Planning and its use or disclosure in whole or in part // without the express written permission of Workday Adaptive Planning is prohibited. // //********************************************************************** import java.io.FileInputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Signature; import java.text.MessageFormat; //import java.util.Base64; import org.apache.commons.codec.binary.Base64; public class AccessAdaptiveAPI { public static void main(String args[]) { String jwtKeyStoreFileString = "/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre/lib/security/JWTkeystore.jks"; String clientIDString = "BlywNDM1NmMtZTk2Mi00NTZiTWEyZjktZWM1NGJiOGQ3Yjca"; String userIdString = "PublicAPIISU_Test"; System.out.println(GetAccessToken(clientIDString,userIdString,jwtKeyStoreFileString)); } public void callAPI() { } public String getAdaptiveAPIToken() { return ""; } public String getJWTToken(String privateKey, String username) { return ""; } public void callWorkdayAPI() { } public static String GetAccessToken(String clientId, String userId, String jwtKeyStore) { String header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}"; String claimTemplate = "'{'\"iss\": \"{0}\", \"sub\": \"{1}\", \"aud\": \"{2}\", \"exp\": \"{3}\"'}'"; try { StringBuffer token = new StringBuffer(); //Encode the JWT Header and add it to our string to sign token.append(Base64.encodeBase64URLSafeString(header.getBytes("UTF-8"))); //Separate with a period token.append("."); //Create the JWT Claims Object String[] claimArray = new String[4]; //iss claimArray[0] = clientId; //sub claimArray[1] = userId; //aud claimArray[2] = "wd"; //exp claimArray[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300); MessageFormat claims; claims = new MessageFormat(claimTemplate); String payload = claims.format(claimArray); //Add the encoded claims object token.append(Base64.encodeBase64URLSafeString(payload.getBytes("UTF-8"))); //token.append(Base64.encodeBase64URLSafeString(payload.getBytes("UTF-8"))); //Load the private key from a keystore KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream(jwtKeyStore), "Workday123!".toCharArray()); PrivateKey privateKey = (PrivateKey) keystore.getKey("Workday", "Workday123!".toCharArray()); //Sign the JWT Header + "." + JWT Claims Object Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(privateKey); signature.update(token.toString().getBytes("UTF-8")); String signedPayload = Base64.encodeBase64URLSafeString(signature.sign()); //Separate with a period token.append("."); //Add the encoded signature token.append(signedPayload); return token.toString(); //System.out.println(token.toString()); } catch (Exception e) { e.printStackTrace(); } return ""; } }
用於產生 JWT 權杖的範例 C# 應用程式
此範例 C# 應用程式會產生一個 JWT 權杖,該權杖會取代憑證的憑證元素中的使用者名稱和密碼。
Adaptive Planning
API 要求此範例代碼需要有 NuGet 頁面。必要的 NuGet 包︰
System.IdentityModel.Tokens.Jwt
var clientId = "BlywNDM1NmMtZTk2Mi00NTZiTWEyZjktZWM1NGJiOGQ3Yjca";//Client ID from workday API Client var isu = "PublicAPIISU_Test"; //the ISU var timeout = (DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() / 1000 + 300).ToString(CultureInfo.InvariantCulture); var environment = "wd"; var pfxFilePath = @"C:\temp\JWTkeystore2.pfx"; var pfxPassword = "Workday123!"; var payload = new JwtPayload { {"iss", clientId}, {"sub", isu}, {"aud", environment}, {"exp", timeout }, }; var signingCredentials = new X509SigningCredentials(new X509Certificate2(pfxFilePath, pfxPassword), SecurityAlgorithms.RsaSha256); // the matching PKCS #12 file with private key var jwtHeader = new JwtHeader(signingCredentials); var secToken = new JwtSecurityToken(jwtHeader, payload); var handler = new JwtSecurityTokenHandler(); var tokenToWorkday = handler.WriteToken(secToken); Console.WriteLine(tokenToWorkday);
在 Adaptive Planning API 要求
Adaptive Planning
API 要求設定 Workday 後
Adaptive Planning
公開 API 存取權、憑證元素︰ Adaptive Planning
API 要求使用 AdaptiveAPIAccessToken (而非使用者名稱和密碼)。無法使用使用者名稱和密碼進行基本驗證。請參閱 「Adaptive Planning REST API 和 API 方法」 以取得更多資訊。範例中的 AdaptiveAPIAccessToken Adaptive PlanningAPI 要求
Adaptive Planning
API 要求<?xml version='1.0' encoding='UTF-8'?> <call method="exportLevels" callerName="a string that identifies your client application"> <credentials token="ID eyJhbDci0iJSUzUxMiIsUmtpZCI6IdvcmtkYXlfa2V5In0.eyJpc3KiOiJXb3JrZGFZIiwiYXV0aF90aW1lIjoxNTczMTY3NjU2LBjzeXnfynnJd.bztQzBmHeTj1amnHA-r96TdrJK0MXMghUFF1KyjxqIq6ruHU63dJp3JAJn3Eche7SEcoZBVGX4wJgna106pmCqgrrVWMf13Hg_sb_szabal2XN1KEEk1qh8z1IDlbt6qJIL_xyW3J2nNSs5ima3vJUYU5sRQXwXst0GuFWXpy464GyB4oKcscrg28X3dnPO_ytdohMKHsWkqyHQKXFQwoQezFaGy10sp4RRUj0lpOZX8C9oBHDYA58IXxGkqKLJVNPvDND6rGY5fTHQ-yxpe1nz-WqB0boiq9a-dv8b3EBzbelxj2fCPdMbng6kzygDcA2at_7BNQiyzfIovS5AG"/> <include versionID="3" inaccessibleValues="false"/> <sheet id="3" /> </call>