如何用Apex实现Xero与Salesforce免重复鉴权?解决令牌过期问题
解决Xero与Salesforce Apex鉴权无需重复授权的方案
针对你遇到的Xero刷新令牌60天过期、需要重复鉴权的问题,有两种可靠的解决方案,可根据集成场景选择:
方案1:使用Xero私有应用(Private App)实现永久鉴权
私有应用是Xero面向内部集成场景提供的鉴权方式,无需OAuth2流程,直接通过RSA证书和API密钥鉴权,只要证书不过期即可永久使用,完全规避刷新令牌过期问题。
实施步骤:
- 在Xero开发者后台创建私有应用:
- 登录Xero Developer Portal,新建Private App
- 用OpenSSL生成RSA密钥对,将公钥上传至Xero,本地留存私钥文件
- 记录Xero分配的Consumer Key
- 在Salesforce中安全存储敏感信息:
- 将私钥和Consumer Key存入自定义设置或Named Credential的加密字段,禁止硬编码
- Apex实现签名逻辑调用Xero API:
public class XeroPrivateAppAuth { // 从自定义设置读取密钥配置 private static final String CONSUMER_KEY = Xero_Settings__c.getInstance().Consumer_Key__c; private static final String PRIVATE_KEY = Xero_Settings__c.getInstance().Private_Key__c; public static HttpResponse callXeroApi(String endpoint, String method) { HttpRequest req = new HttpRequest(); req.setEndpoint('https://api.xero.com' + endpoint); req.setMethod(method); // 生成并设置鉴权头部 req.setHeader('Authorization', generateAuthHeader(req, method)); req.setHeader('Accept', 'application/json'); Http http = new Http(); return http.send(req); } private static String generateAuthHeader(HttpRequest req, String method) { String timestamp = String.valueOf(System.currentTimeMillis() / 1000); String nonce = String.valueOf(Crypto.getRandomLong()); // 构造签名基础串 String baseString = method + '&' + EncodingUtil.urlEncode(req.getEndpoint(), 'UTF-8') + '&' + EncodingUtil.urlEncode('oauth_consumer_key=' + CONSUMER_KEY + '&oauth_nonce=' + nonce + '&oauth_signature_method=RSA-SHA1&oauth_timestamp=' + timestamp + '&oauth_version=1.0', 'UTF-8'); // 用私钥签名 Blob privateKeyBlob = Blob.valueOf(PRIVATE_KEY); Blob signatureBlob = Crypto.sign('RSA-SHA1', Blob.valueOf(baseString), privateKeyBlob); String signature = EncodingUtil.base64Encode(signatureBlob); // 组装Authorization头部 return 'OAuth oauth_consumer_key="' + CONSUMER_KEY + '", oauth_nonce="' + nonce + '", oauth_signature="' + EncodingUtil.urlEncode(signature, 'UTF-8') + '", oauth_signature_method="RSA-SHA1", oauth_timestamp="' + timestamp + '", oauth_version="1.0"'; } }
方案2:升级为Xero Partner应用获取永久刷新令牌
如果集成需要面向多Xero租户(如ISV场景),可申请加入Xero Partner Program,通过Partner应用获取永久刷新令牌,该令牌不会过期,只需定期自动用它刷新访问令牌,无需用户重新授权。
实施步骤:
- 申请Xero Partner Program:
- 提交Partner应用申请,通过Xero审核后即可获得永久刷新令牌权限
- 在Salesforce中存储永久刷新令牌:
- 将刷新令牌、客户端ID、客户端密钥存入安全位置(如自定义对象加密字段、Named Credential)
- Apex实现自动令牌刷新逻辑:
public class XeroPartnerAuth { private static final String CLIENT_ID = Xero_Partner_Settings__c.getInstance().Client_ID__c; private static final String CLIENT_SECRET = Xero_Partner_Settings__c.getInstance().Client_Secret__c; private static final String REFRESH_TOKEN = Xero_Partner_Settings__c.getInstance().Refresh_Token__c; private static String accessToken; private static Long tokenExpiryTime; public static HttpResponse callXeroApi(String endpoint, String method) { // 检查访问令牌是否过期,过期则自动刷新 if (accessToken == null || System.currentTimeMillis() >= tokenExpiryTime) { refreshAccessToken(); } HttpRequest req = new HttpRequest(); req.setEndpoint('https://api.xero.com' + endpoint); req.setMethod(method); req.setHeader('Authorization', 'Bearer ' + accessToken); req.setHeader('Accept', 'application/json'); Http http = new Http(); return http.send(req); } private static void refreshAccessToken() { HttpRequest req = new HttpRequest(); req.setEndpoint('https://identity.xero.com/connect/token'); req.setMethod('POST'); req.setHeader('Content-Type', 'application/x-www-form-urlencoded'); String body = 'grant_type=refresh_token&client_id=' + CLIENT_ID + '&client_secret=' + CLIENT_SECRET + '&refresh_token=' + REFRESH_TOKEN; req.setBody(body); Http http = new Http(); HttpResponse res = http.send(req); if (res.getStatusCode() == 200) { Map<String, Object> tokenResponse = (Map<String, Object>)JSON.deserializeUntyped(res.getBody()); accessToken = (String)tokenResponse.get('access_token'); // 计算令牌过期时间 tokenExpiryTime = System.currentTimeMillis() + ((Integer)tokenResponse.get('expires_in') * 1000); } else { throw new CalloutException('Xero令牌刷新失败: ' + res.getBody()); } } }
注意事项:
- 所有敏感信息(私钥、密钥、令牌)必须按Salesforce安全规范存储,禁止明文或硬编码
- 私有应用的RSA证书需定期更新(建议每年一次),避免证书过期导致集成中断
- Partner应用需遵守Xero的Partner规则,确保集成符合平台条款
内容的提问来源于stack exchange,提问作者Rutu PATEL
相关产品推荐
相关产品推荐

