如何向Xero Webhook内部的Xero API提交帖子请求



我的Xero发票账户上有一个Webhook。当创建新发票时,我想使用Webhook中的数据访问Xero Api,向用户发送发票电子邮件。我有所有的代码,但我的问题是Webhook期望200的响应,当我从Webhook中调用Xero Api代码时,我在Xero上得到一个错误,说响应包含一个正文。这是有道理的,因为我正在提交和从Api获得数据。

那么,如何在不干扰Xero Webhook响应的情况下向Xero Api发出请求呢?

Webhook代码:

<?php
///////////////////////////////////////////////////////////////////////////
// WEBHOOK AUTHENTICATION - START
///////////////////////////////////////////////////////////////////////////
//hook section
$rawPayload = file_get_contents("php://input");
// Update your webhooks key here
$webhookKey = 'myWebhookKey';
// Compute the payload with HMACSHA256 with base64 encoding
$computedSignatureKey = base64_encode(
hash_hmac('sha256', $rawPayload, $webhookKey, true)
);
// Signature key from Xero request
$xeroSignatureKey = $_SERVER['HTTP_X_XERO_SIGNATURE'];
$isEqual = false;
if (hash_equals($computedSignatureKey, $xeroSignatureKey)) {
$isEqual = true;
http_response_code(200);

// getting and passing the data to the api functionality
$data = json_decode($rawPayload);
xero_api($data);
} else {
http_response_code(401);
}
///////////////////////////////////////////////////////////////////////////
// WEBHOOK AUTHENTICATION - END
///////////////////////////////////////////////////////////////////////////
?>

Api代码:

<?php
///////////////////////////////////////////////////////////////////////////
// XERO API FUNCITONALITY - START
///////////////////////////////////////////////////////////////////////////
function xero_api($data) {
if ($data->events[0]->eventType === 'CREATE') {
$resourseId = $data->events[0]->resourceId;
///////////////////////////////////////////////////////////////////////////
// GET XERO CREDENTIALS - START
///////////////////////////////////////////////////////////////////////////
global $wpdb;
$xeroKeys = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}xero_keys WHERE ID = 0", ARRAY_A);
$clientId = $xeroKeys['client_id'];
$clientSecret = $xeroKeys['client_secret'];
$refreshToken = $xeroKeys['refresh_token'];
$tenantId = $xeroKeys['tenant_id'];
///////////////////////////////////////////////////////////////////////////
// GET XERO CREDENTIALS - END
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// GET ACCESS TOKEN AND GENERATE NEW REFRESH TOKEN - START
///////////////////////////////////////////////////////////////////////////
$args = array(
'headers' => array(
'grant_type' => 'refresh_token',
),
'body' => array(
'grant_type' => 'refresh_token',
'refresh_token' => $refreshToken,
'client_id' => $clientId,
'client_secret' => $clientSecret
)
);
$refreshTokenRes = wp_remote_post('https://identity.xero.com/connect/token?=', $args);
$refreshTokenBody = json_decode($refreshTokenRes['body']);
if (isset($refreshTokenBody->refresh_token) && isset($refreshTokenBody->access_token)) {
$updateTokens = $wpdb->update(
$wpdb->prefix . 'xero_keys',
array(
'refresh_token' => $refreshTokenBody->refresh_token,
'access_token' => $refreshTokenBody->access_token
),
array('ID' => 0),
array('%s', '%s'),
array('%d')
);
}
///////////////////////////////////////////////////////////////////////////
// GET ACCESS TOKEN AND GENERATE NEW REFRESH TOKEN - End
///////////////////////////////////////////////////////////////////////////
$args = array(
'headers' => array(
'xero-tenant-id' => $tenantId,
'Authorization' => 'Bearer ' . $refreshTokenBody->access_token,
'Accept' => 'application/json',
'Content-Type' => 'application/json'
),
); 
$response = wp_remote_post('https://api.xero.com/api.xro/2.0/Invoices/' . $resourseId . '/Email', $args);
}
}
///////////////////////////////////////////////////////////////////////////
// XERO API FUNCITONALITY - END
///////////////////////////////////////////////////////////////////////////
?>

问题是需要将这些调用分开。

正如对您问题的评论所说,您需要首先处理webhook,然后对将触发API的作业进行排队。像这样的东西可以做

<?php
///////////////////////////////////////////////////////////////////////////
// WEBHOOK AUTHENTICATION - START
///////////////////////////////////////////////////////////////////////////
//hook section
$rawPayload = file_get_contents("php://input");
// Update your webhooks key here
$webhookKey = 'myWebhookKey';
// Compute the payload with HMACSHA256 with base64 encoding
$computedSignatureKey = base64_encode(
hash_hmac('sha256', $rawPayload, $webhookKey, true)
);
// Signature key from Xero request
$xeroSignatureKey = $_SERVER['HTTP_X_XERO_SIGNATURE'];
$isEqual = false;
if (hash_equals($computedSignatureKey, $xeroSignatureKey)) {
$isEqual = true;
http_response_code(200);

// getting and passing the data to the api functionality
$data = json_decode($rawPayload);
wp_schedule_single_event(
time() + 10,
'send_xero_api_call',
['data' => $data]
);
} else {
http_response_code(401);
}
///////////////////////////////////////////////////////////////////////////
// WEBHOOK AUTHENTICATION - END
///////////////////////////////////////////////////////////////////////////

然后你需要注册一个WP Cron

add_action('send_xero_api_call', 'xero_api_cron', 10);
function xero_api_cron($data) {
if ($data->events[0]->eventType === 'CREATE') {
$resourseId = $data->events[0]->resourceId;
///////////////////////////////////////////////////////////////////////////
// GET XERO CREDENTIALS - START
///////////////////////////////////////////////////////////////////////////
global $wpdb;
$xeroKeys = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}xero_keys WHERE ID = 0", ARRAY_A);
$clientId = $xeroKeys['client_id'];
$clientSecret = $xeroKeys['client_secret'];
$refreshToken = $xeroKeys['refresh_token'];
$tenantId = $xeroKeys['tenant_id'];
///////////////////////////////////////////////////////////////////////////
// GET XERO CREDENTIALS - END
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// GET ACCESS TOKEN AND GENERATE NEW REFRESH TOKEN - START
///////////////////////////////////////////////////////////////////////////
$args = array(
'headers' => array(
'grant_type' => 'refresh_token',
),
'body' => array(
'grant_type' => 'refresh_token',
'refresh_token' => $refreshToken,
'client_id' => $clientId,
'client_secret' => $clientSecret
)
);
$refreshTokenRes = wp_remote_post('https://identity.xero.com/connect/token?=', $args);
$refreshTokenBody = json_decode($refreshTokenRes['body']);
if (isset($refreshTokenBody->refresh_token) && isset($refreshTokenBody->access_token)) {
$updateTokens = $wpdb->update(
$wpdb->prefix . 'xero_keys',
array(
'refresh_token' => $refreshTokenBody->refresh_token,
'access_token' => $refreshTokenBody->access_token
),
array('ID' => 0),
array('%s', '%s'),
array('%d')
);
}
///////////////////////////////////////////////////////////////////////////
// GET ACCESS TOKEN AND GENERATE NEW REFRESH TOKEN - End
///////////////////////////////////////////////////////////////////////////
$args = array(
'headers' => array(
'xero-tenant-id' => $tenantId,
'Authorization' => 'Bearer ' . $refreshTokenBody->access_token,
'Accept' => 'application/json',
'Content-Type' => 'application/json'
),
); 
$response = wp_remote_post('https://api.xero.com/api.xro/2.0/Invoices/' . $resourseId . '/Email', $args);
}
}

某种程度上。$data参数应该包含您传递的数据(不能100%确定它看起来如何(。此外,您还需要检查API的节流,这样您就可以调整作业的执行时间。如果你的后台工作成功完成,请确保你有存储的地方。

由于您将敏感信息存储在数据库中(访问和刷新令牌(,我建议您在将其存储在数据库时对其进行加密,并在获取它们时进行解密。

你可以查看我是如何在我的插件中实现后台作业的

https://github.com/dingo-d/woo-solo-api/tree/develop/src/BackgroundJobshttps://github.com/dingo-d/woo-solo-api/blob/develop/src/Request/SoloApiRequest.php#L428-L438

您可以使用熟食店的WP队列库:https://github.com/deliciousbrains/wp-queue/

它是一个围绕WP Cron的包装器,带有用于处理队列的自定义DB表,这将允许您检查作业是否正确执行。

相关内容

  • 没有找到相关文章

最新更新