Firebase与xero-node的功能集成

时间:2020-09-28 04:48:39

标签: node.js firebase google-cloud-platform google-cloud-functions xero-api

尝试创建由某些数据库或onRequest事件触发的firebase函数,该事件在Xero上创建付款以更好地管理收到的发票。

不确定我是否了解如何从firebase函数运行xero-node库。

我一直在搞砸这两个,这似乎不像用秘密ID初始化对象并像我期望的那样调用函数那样简单:

const xero = new XeroClient({
  clientId: '230823jff',
  clientSecret: 'sdfh39fhsdaf',
  redirectUris: [`http://localhost:3000/xero`],
  scopes: 'openid profile email accounting.transactions offline_access'.split(' '),
})

xero.accountingApi.getInvoices('tennetid093242')

似乎我需要使用以下内容生成访问密钥(该密钥将在12分钟后过期):

let consentUrl = await xero.buildConsentUrl()
res.redirect(consentUrl)

在邮递员中使用api进行处理,这种流程感觉就像是我使它变得比应有的更加复杂。

有没有一种方法可以用管理范围或其他东西初始化它,而不必担心访问键... 还是我应该在客户端使用xero-node ...(当然不能)

有带有xero-node的expressjs版本,所以我是否通过将redirectUri设置为另一个firebase函数的地址来获取会话密钥来与firebase onrequest函数等效?


我正在慢慢到达某个地方。

我的firebase函数如下:

const xero = new XeroClient({
  clientId: '123213123123',
  clientSecret: '123123123123',
  redirectUris: ['http://localhost:5001/example/us-central1/xeroAuthCode'],
  scopes: ['openid', 'profile', 'email', 'accounting.transactions', 'accounting.settings', 'offline_access']
})

exports.xeroInit = functions.https.onRequest(async (req, res) => {
  let consentUrl = await xero.buildConsentUrl()
  res.redirect(consentUrl)
})

exports.xeroAuthCode = functions.https.onRequest(async (req, res) => {
  let tokenSet = await xero.apiCallback(req.url)
  console.log(tokenSet)
})

这个想法是我调用xeroInit并将令牌发送到xeroAuth 这似乎可行,因为控制台记录req.url可以提供:

/?code=c5105f6ce943....230a23fsadf&scope=openid%20profile%20email%20accounting.transactions%20accounting.settings&session_state=tFC6G9Go_zBguCjIpy8-9gl6-9SWLTlUmY5CXMq49es.3c42d9ca9e53285596193bf423f791f3

但是尝试将其设置为apiCallback时出现此错误

TypeError: Cannot read property 'callbackParams' of undefined

使用纯Express应用程序进行测试,可以完美运行,我希望这是Firebase函数模拟器的错误...

因为这与express一起使用,所以我在firebase函数中使用了express,并使用request.url调用apiCallback起作用了... 当我对要同时使用Firebase和xero-node的其他人充分使用它时,问题将不断更新。

2 个答案:

答案 0 :(得分:2)

编辑: 嗯,我认为您需要做的只是使用第二次初始化客户端:

await xero.initialize()

需要调用它以在XeroClient上设置相关的openid-client

buildConsentUrl还可以在后台调用await xero.initialize(),因此,由于您在初始线程中调用了它,因此可以正确设置客户端。由于Firebase函数被隔离,我认为您只需要调用initialize()fn。



您需要有一个要通过API与之通信的Xero org用户,需要通过整个OAuth2.0流程来生成access_token。

我建议您检出一个很棒的示例应用程序,以显示整个流程:https://github.com/XeroAPI/xero-node-oauth2-app/blob/master/src/app.ts#L172


您的目标是促进许多用户使用您的应用程序对其组织进行读写吗?还是只是尝试为单个组织连接和自动化内容?

如果您要尝试第二步,则该视频显示了如何在REST客户端中生成初始access_token并将其插入代码流以不断刷新。 https://www.youtube.com/watch?v=Zcf_64yreVI

答案 1 :(得分:1)

非常感谢SerKnight帮助我在Firebase功能上进行此工作,以供将来参考,这是我正在使用的配置。

一些笔记

  • 仅出于某种原因在firebase函数中调用xero.initialize()作为回调均不起作用,所以我使用express处理初始设置。
  • 一旦数据库中有了刷新令牌,我的connect函数就会发挥作用,因此我不需要每次调用函数时都需要buildConsentUrl。
  • 如果需要,您可以继续使用express来调用函数。

确保将Firebase函数的网址完整地放入xeros myapps页面上的OAuth 2.0 redirect URIs中,如您在示例中所看到的。 localhost if using firebase emulators

const app = express()
app.use(cors())

let x_client_id = functions.config().xero.client_id
let x_client_sectet = functions.config().xero.client_secret

const xero = new XeroClient({
  clientId: x_client_id,
  clientSecret: x_client_sectet,
  redirectUris: ['http://localhost:5001/example/us-central1/xeroInit/callback'],
  scopes: ['openid', 'profile', 'email', 'accounting.transactions', 'accounting.settings', 'offline_access'],
  httpTimeout: 3000,
  state: 123
})

const connect = () =>
  new Promise(async (res, rej) => {
    let snapshot = await db.ref('xero-config').once('value')
    let tokenSet = snapshot.val()
    try {
      xero.initialize()
      const newTokenSet = await xero.refreshWithRefreshToken(x_client_id, x_client_sectet, tokenSet.refresh_token)
      db.ref('xero-config').set(newTokenSet)
      xero.setTokenSet(newTokenSet)
      res()
    } catch (error) {
      rej(error)
    }
  })

app.get('/connect', async (req, res) => {
  try {
    await connect()
    res.send('Connection established')
  } catch (error) {
    let consentUrl = await xero.buildConsentUrl()
    res.redirect(consentUrl)
  }
})
app.get('/callback', async (req, res) => {
  let TokenSet = await xero.apiCallback(req.url)
  db.ref('xero-config').set(TokenSet)
  res.send('Token updated ?')
})
exports.xeroInit = functions.https.onRequest(app)

exports.xeroOrganisation = functions.https.onRequest(async (req, res) => {
  await connect() //Doesn't handle errors and will break if inactive for 60 days but you get the idea
  await xero.updateTenants()
  res.json(xero.tenants[0])
})
  1. 使用http://localhost:5001/example/us-central1/xeroInit/connect调用connect函数
  2. 确保重定向后,您收到了token updated消息
  3. 调用您的xeroOrganisation函数以确保其正常工作(: