Dialogflow agent responses are intermittently failing - twilio-api

I have a Dialogflow agent integrated with Twillio. Before the integration model change, all agent responses came smoothly. Since I changed the integration method following the instructions published by Dialogflow, the agent's responses fail intermittently generating the message 14103-Invalid Body in Twilio:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message/>
</Response>
The agent's response comes to Twilio in some cases but not in others. I observe this behavior repeating the same intent several times in the agent.
The fullfillment webhook was developed in NodeJs and is deployed in a different Google Cloud project than the Agent.
I did try two methods:
Direct method
if (estCuenta.msg == 'OK') {
console.log('trace 1');
await validaDisclaimer(`${cedula}`);
if (!disclaimerOk) {
console.log('trace 2');
agent.context.set({ 'name': 'esperadisclaimer-followup', 'lifespan': 1 });
agent.add('Some message')
sendWhatsAppMedia('https://someFile.pdf?alt=media&token=18ebc493-27fc-4c46-96eb-e80f05716acc',
'someFileDescription');
}
Function method
if (estCuenta.msg == 'OK') {
console.log('trace 1');
await validaDisclaimer(`${cedula}`);
if (!disclaimerOk) {
console.log('trace 2');
agent.context.set({ 'name': 'esperadisclaimer-followup', 'lifespan': 1 });
await sendAgentResponse(agent, 'Some message')
sendWhatsAppMedia('https://someFile.pdf?alt=media&token=18ebc493-27fc-4c46-96eb-e80f05716acc',
'someFileDescription');
}
... the funtion that try to send response to Dialogflow agent
function sendAgentResponse(agent, message) {
const promise = new Promise(resolve => {
// logic goes here
resolve(agent.add(message));
});
return promise;
}

Related

Flutter web index.html not same as examples for fcm what to do now

I am building a flutter web app. Using flutter 3.0.7. I need to send push notifications and it looks like the only real way is with fcm. So I created a project and with the cli I created a firebase_options.dart file. Then I created a firebase-messaging-sw.js file.
If I send a message from the console I recieve the message but as soon as I try to send the message from y app to a topic or registration key I get no message.
I red in the examples the few out there to change my index.html file.
To theThis code is not in my index.html, dont know if it is because I am working with flutter 3.0.7
<script>
if ("serviceWorker" in navigator) {
window.addEventListener("load", function () {
mine looks like this
<script>
// The value below is injected by flutter build, do not touch.
var serviceWorkerVersion = null;
So could that be the problem that I can not send with legacy fcm api to my app users?
The send method I use is as follows
sendPushMessageToWeb(String? fcm_token) async {
if (fcm_token == null) {
print('Unable to send FCM message, no token exists.');
return;
}
try {
await http
.post(
Uri.parse('https://fcm.googleapis.com/fcm/send'),
headers: <String, String>{
'Content-Type': 'application/json',
'Authorization':
'key=my server key'
},
body: json.encode({
'to': "${fcm_token}",
'message': {
'token': "${fcm_token}",
},
"notification": {
"title": "Push Notification",
"body": "Firebase push notification"
}
}),
)
.then((value) => print(value.body));
print('FCM request for web sent!');
} catch (e) {
print(e);
}
}
When I send the message the method it tells me the message was send but no message is recieved. But when using console with the registration key it sends the message. Could it be because I did not change my index.html?
Thank you

Service workers "sync" operation is working while its offline?

I have a PWA project where I send the data to server. During this process, if the user is offline then the data is stored in indexedDb and a sync tag is registered. So, then when the user comes online that data can sent to the server.
But In my case the sync event gets executed immediately when the we register a sync event tag, which means the data is tried to be sent to server while its offline, which is not going to work.
I think the sync event supposed to fire while its online only, what could be issue here ?
The service worker's sync event works accordingly when I tried to enable and disable the offline option of chrome devtools, and also works correctly in my android phone.
This is how I register my sync tag
function onFailure() {
var form = document.querySelector("form");
//Register the sync on post form error
if ('serviceWorker' in navigator && 'SyncManager' in window) {
navigator.serviceWorker.ready
.then(function (sw) {
var post = {
datetime1: form.datetime1.value,
datetime: form.datetime.value,
name: form.name.value,
image: form.url.value,
message: form.comment.value
};
writeData('sync-comments', post)
.then(function () {
return sw.sync.register('sync-new-comment');
})
.then(function () {
console.log("[Sync tag registered]");
})
.catch(function (err) {
console.log(err);
});
});
}
}
And this is how the sync event is called
self.addEventListener('sync', function (event) {
console.log("[Service worker] Sync new comment", event);
if (event.tag === 'sync-new-comment') {
event.waitUntil(
readAllData('sync-comments')
.then(function (data) {
setTimeout(() => {
data.forEach(async (dt) => {
const url = "/api/post_data/post_new_comment";
const parameters = {
method: 'POST',
headers: {
'Content-Type': "application/json",
'Accept': 'application/json'
},
body: JSON.stringify({
datetime: dt.datetime,
name: dt.name,
url: dt.image,
comment: dt.message,
datetime1: dt.datetime1,
})
};
fetch(url, parameters)
.then((res) => {
return res.json();
})
.then(response => {
if (response && response.datetimeid) deleteItemFromData('sync-comments', response.datetimeid);
}).catch((error) => {
console.log('[error post message]', error.message);
})
})
}, 5000);
})
);
}
});
you mention
The service worker's sync event works accordingly when I tried to enable and disable the offline option of chrome devtools, and also works correctly in my android phone.
So I'm not sure which case is the one failing.
You are right that the sync will be triggered when the browser thinks the user is online, if the browser detects that the user is online at the time of the sync registration it will trigger the sync:
In true extensible web style, this is a low level feature that gives you the freedom to do what you need. You ask for an event to be fired when the user has connectivity, which is immediate if the user already has connectivity. Then, you listen for that event and do whatever you need to do.
Also, from the workbox documentation
Browsers that support the BackgroundSync API will automatically replay failed requests on your behalf at an interval managed by the browser, likely using exponential backoff between replay attempts.

Capture Error on Subscription Smart Button Integration with SDK - Both Sandbox and Live

Case: Error when setting up a subscription via Smart Payment Buttons
Remark: In the Live environment I did get charged in my account for the transaction
Error: There is a capture error, and from 3 days of testing in both Sandbox AND Live cases there is not one solution found
For Sandbox Mode, I found a few references for the exact same error, but for those people it a. seems to have vanished overnight and 2. those weren't subscription models but regular purchase modes.
The following are the scripts and it shouldn't be that hard as I am making it, we set up a similar billing environment couple years ago and that worked almost immediately, that wasn't a subscription though.
Further details:
- I did setup the correct env settings as well in the composer files.
- Product is there
- Plan is there
- We use Seat based Pricing (0.01 cent and then we multiply the total amount in dollars *100)
////////////////////////////////////
// Error 500
////////////////////////////////////
// Via Console
POST https://www.paypal.com/smart/api/order/9VU587...34202/capture 500
// Via Network
{ack: "error", message: "Unhandled api error", meta: {calc: "4ac27dc9b8a70",…},…}
////////////////////////////////////
// Smart Button Script
////////////////////////////////////
<script src="https://www.paypal.com/sdk/js?vault=true&client-id=<?= $paypal_sandbox_id ?>&currency=<?php echo $currency ?? "USD"; ?>&debug=false"></script>
<script>
paypal.Buttons({
// Set up the subscription
createSubscription: function (data, actions) {
return actions.subscription.create({
'plan_id': 'P-6NH76920JR31236564LYU3X4Y',
'quantity': total_billed_vat * 100
});
},
// Finalize the transaction
onApprove: function (data, actions) {
console.log('onApprove', data);
// Authorize the transaction
return actions.order.capture().then(function (details) {
console.log('capture', details);
// Show a success message to the buyer
alert('Transaction completed by ' + details.payer.name.given_name + '!');
// Call your server to save the transaction
return fetch('../api/paypal/paypal-transaction-complete.php', {
method: 'post',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
orderID: data.orderID
})
});
}).then(function (response) {
// Show a success message to the buyer
alert('actions.order.capture done ' + details.payer.name.given_name + '!');
});
},
onCancel: function (data, actions) {
// Show a cancel page or return to cart
alert('Feel free to retry when you are ready');
}
}).render('#paypal-button-container');
</script>
The PHP Serverside Script:
////////////////////////////////////
// ../api/paypal/paypal-transaction-complete.php
////////////////////////////////////
<?php
namespace Sample;
require __DIR__ . '/vendor/autoload.php';
//1. Import the PayPal SDK client that was created in `Set up Server-Side SDK`.
use Sample\PayPalClient;
use PayPalCheckoutSdk\Orders\OrdersGetRequest;
class GetOrder
{
// 2. Set up your server to receive a call from the client
/**
*You can use this function to retrieve an order by passing order ID as an argument.
*/
public static function getOrder($orderId)
{
// 3. Call PayPal to get the transaction details
$client = PayPalClient::client();
$response = $client->execute(new OrdersGetRequest($orderId));
/**
*Enable the following line to print complete response as JSON.
*/
//print json_encode($response->result);
print "Status Code: {$response->statusCode}\n";
print "Status: {$response->result->status}\n";
print "Order ID: {$response->result->id}\n";
print "Intent: {$response->result->intent}\n";
print "Links:\n";
foreach($response->result->links as $link)
{
print "\t{$link->rel}: {$link->href}\tCall Type: {$link->method}\n";
}
// 4. Save the transaction in your database. Implement logic to save transaction to your database for future reference.
print "Gross Amount: {$response->result->purchase_units[0]->amount->currency_code} {$response->result->purchase_units[0]->amount->value}\n";
// To print the whole response body, uncomment the following line
// echo json_encode($response->result, JSON_PRETTY_PRINT);
}
}
/**
*This driver function invokes the getOrder function to retrieve
*sample order details.
*
*To get the correct order ID, this sample uses createOrder to create a new order
*and then uses the newly-created order ID with GetOrder.
*/
if (!count(debug_backtrace()))
{
GetOrder::getOrder($data->orderID, true);
}
The SDK Used for v2 of the PayPal integration.
////////////////////////////////////
// SDK Installed in ../api/paypal/
////////////////////////////////////
{
"require": {
"paypal/paypal-checkout-sdk": "^1.0"
}
}
Used Manual Source: https://developer.paypal.com/docs/subscriptions/integrate/
One of the Found Issue Resources: https://www.paypal-community.com/t5/REST-APIs/BASIC-Smart-Payment-buttons-integration-help/td-p/1844051
This is the type of "500 Internal Service Error" API response that you're best off reaching out to PayPal's support for (MTS), rather than Stack Overflow, since it's effectively being thrown on the PayPal server end without details and needs to be traced back. However, I do happen to have some knowledge and in this case my suspicion would be that the transaction amount is not matching the purchase unit amount. Maybe this is something you can correct with a simpler request, i.e. test with a simple static number like $10 from start to finish and see if the problem does not occur.

Does testcafe support testing of rest api

Tests hang in the testcafe browser when you try to test a rest api url directly.
I am trying to run a test against my rest API endpoint using request hooks, but when I run the test from the command line, the browser opens the API endpoint and loads it and hangs. The test doesn't pass or fail and hangs. The rest API endpoint just returns a JSON response.
const logger = RequestLogger('https://example.com/search/suggestions?search=testkeyword');
fixture `test`
.page('https://example.com/search/suggestions?search=testkeyword');
test
.requestHooks(logger)
('test', async t => {
// Ensure that the response has been received and that its status code is 200.
await t.expect(logger.contains(record => record.response.statusCode === 200)).ok();
const logRecord = logger.requests[0];
console.log(logRecord.userAgent);
console.log(logRecord.request.url);
console.log(logRecord.request.method);
console.log(logRecord.response.statusCode);
});
I expect the test to pass checking for 200 status code, but the test hangs without showing pass/fail. Does testcafe support testing of rest API endpoints? I have checked this issue - https://github.com/DevExpress/testcafe/issues/1471 where it says testcafe doesn't support non-html pages. Please confirm.
You are right, TestCafe is intended to work with html pages, but it will use the "about:blank" page if you don't define any url. You can use the regular node.js HTTP API without request hooks for this case. Look at the following example:
import http from 'http';
const getResponseData = (url) => new Promise((resolve, reject) => {
http.get(url, res => {
const { statusCode } = res;
const contentType = res.headers['content-type'];
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => { rawData += chunk; });
res.on('end', () => resolve({ statusCode, contentType, rawData }));
}).on('error', e => reject(e));
});
fixture `Test REST API`;
test('Simple Test', async t => {
const response = await getResponseData('http://example.com/api/1');
await t
.expect(response.statusCode).eql(200);
});
TestCafe 1.20.0+ offers the t.request method. You can use it for REST API testing. In other words, you can incorporate API testing right into your existing functional TestCafe tests. You no longer need to use any third-party libraries.
You can read about the API testing feature in the corresponding guide.

socket.io-client Jest testing inconsistent results

I am writing some end-to-end test cases to test socket connections in my app. I expect receiving socket events after specific rest API requests. For instance, after hitting: /api/v1/[createTag], I expect receiving createTag event to be captured by socket.io-client. The issue is that, it is very inconsistently passing, and sometimes failing, with good rest API requests. The reason to fail is that done() event inside socket.on('createTag' ... is never called, so it gets timeout. On browser, currently all the API endpoints and sockets seem to be working fine. Is there a specific configuration that I might be missing in order to test socket.io-client within Node.js environment and Jest?
Below is my test cases, and thanks a lot in advance:
describe('Socket integration tests: ', () => {
beforeAll(async done => {
await apiInit();
const result = await requests.userSignIn(TEST_MAIL, TEST_PASSWORD);
TEST_USER = result.user;
SESSION = result.user.session;
console.log('Test user authenticated succesfully.');
done();
});
beforeEach(done => {
socket = io(config.socket_host, { forceNew: true })
socket.on('connect', () => {
console.log('Socket connection succesful.');
socket.emit('session', { data: SESSION }, (r) => {
console.log('Socket session successful.');
done();
});
});
})
test('Receiving createTag socket event?', async(done) => {
console.log('API request on createTag');
const response = await Requester.post(...);
console.log('API response on createTag', response);
socket.on('createTag', result => {
console.log('createTag socket event succesful.');
createdTagXid = result.data.xid;
done();
})
});
afterEach(done => {
if(socket.connected) {
console.log('disconnecting.');
socket.disconnect();
} else {
console.log('no connection to break');
}
done();
})
}
Basically, setting event handles after async API calls seems to be the issue. So I should have first set the socket.on( ... and then call rest API.