I've signed up to a paypal business account. I've been trying to create a variable recurring payment using paypal. But with no luck. I could not find any working code that can accomplish this.
Things I've tried:
Subscriptions: I've checkout subscriptions too but subscriptions seem to be having fixed amount.
Paypal-rest-sdk: Paypal rest sdk won't let me change the payment_definitions most probably because it is just creating a standard subscription and not a variable one
(async function() {
const paypal = require("paypal-rest-sdk");
paypal.configure({
'mode': 'sandbox', //sandbox or live
'client_id': process.env.PAYPAL_CLIENT_ID,
'client_secret': process.env.PAYPAL_SECRET_KEY
});
var billingPlanAttributes = {
"description": "Create Plan for Regular",
"merchant_preferences": {
"auto_bill_amount": "yes",
"cancel_url": "http://www.cancel.com",
"initial_fail_amount_action": "continue",
"max_fail_attempts": "1",
"return_url": "http://www.success.com",
"setup_fee": {
"currency": "USD",
"value": "25"
}
},
"name": "Testing1-Regular1",
"payment_definitions": [
{
"amount": {
"currency": "USD",
"value": "100"
},
"charge_models": [
{
"amount": {
"currency": "USD",
"value": "10.60"
},
"type": "SHIPPING"
},
{
"amount": {
"currency": "USD",
"value": "20"
},
"type": "TAX"
}
],
"cycles": "0",
"frequency": "MONTH",
"frequency_interval": "1",
"name": "Regular 1",
"type": "REGULAR"
}
],
"type": "INFINITE"
};
const createdBillingPlan = await new Promise((resolve, reject) => {
paypal.billingPlan.create(billingPlanAttributes, function (error, createdBillingPlan) {
if (error) {
reject(error);
} else {
resolve(createdBillingPlan)
}
});
});
// update
var billing_plan_update_attributes = [
{
"op": "replace",
"path": "/",
"value": {
"payment_definitions": [
{
...createdBillingPlan.payment_definitions[0],
"amount": {
"currency": "INR",
"value": 100
}
}
]
}
}
];
console.log(billing_plan_update_attributes);
paypal.billingPlan.update(createdBillingPlan.id, billing_plan_update_attributes, function (error, response) {
if (error) {
console.log(error.response);
throw error;
} else {
paypal.billingPlan.get(createdBillingPlan.id, function (error, updatedBillingPlan) {
if (error) {
console.log(error.response);
throw error;
} else {
console.log(JSON.stringify(updatedBillingPlan));
}
});
}
});
})();
Above code throws
{ name: 'BUSINESS_VALIDATION_ERROR',
details:
[ { field: 'payment_definitions',
issue: 'patch is not supported for this field.' } ],
message: 'Validation Error.',
information_link:
'https://developer.paypal.com/docs/api/payments.billing-plans#errors',
debug_id: 'someid',
httpStatusCode: 400 }
Some links I've found interesting are:
https://www.paypal-community.com/t5/Merchant-services-Archive/Subscription-with-variable-amount-per-month/td-p/49864
https://developer.paypal.com/docs/classic/express-checkout/integration-guide/ECRecurringPayments/#
If some one could help me with some working code that creates a new recurring payment subscription / plan I'd really appreciate it.
No, you are wrong subscriptions are not fixed price. There is an option like seat-based pricing in subscriptions. All you need to do is modify your JSON when you creating a plan. Here is an example plan JSON for 1 USD base price.
{
"product_id": "PROD-60L70341GH758414Y",
"name": "Basic Plan",
"description": "Basic plan",
"billing_cycles": [
{
"frequency": {
"interval_unit": "MONTH",
"interval_count": 1
},
"tenure_type": "REGULAR",
"sequence": 1,
"total_cycles": 12,
"pricing_scheme": {
"fixed_price": {
"value": "1",
"currency_code": "USD"
}
}
}
],
"payment_preferences": {
"service_type": "PREPAID",
"auto_bill_outstanding": true,
"setup_fee_failure_action": "CONTINUE",
"payment_failure_threshold": 3
},
"quantity_supported": true
}
The most important part in here is quantity_supported": true, it indicates that you can give quantity property when creating a subscription. Lets say you want to create a subscription with 12 USD then all you need to do is give quantity as 12. When creating a subscription your JSON may like this
'plan_id': 'P-6AG14992W7150444HLUYGM5I',
'quantity': "12"
Hope it helps.
Related
I am developing an application that communicates with PayPal's API to create invoices.
This is my Request Body:
{
"detail": {
"currency_code": "USD",
"note": "Thank you for using my services!"
},
"invoicer": {
"name": {
"given_name": "Shreyas",
"surname": "Ayyengar"
},
"email_address": "{email}",
"website": "{website}"
},
"primary_recipients": [
{
"billing_info": {
"email_address": "{client_email}"
}
}
],
"items": [
{
"name": "{invoice_name}",
"description": "{invoice_description}",
"quantity": "1",
"unit_amount": {
"currency_code": "USD",
"value": "{invoice_amount}"
},
"tax": {
"name": "PayPal Service Tax",
"percent": "7.25"
}
}
],
"configuration": {
"partial_payment": {
"allow_partial_payment": false
},
"allow_tip": true
}
}
While there are placeholders like: {client_email}, I can guarantee that they are replacing properly and as expected.
However I'm thrown a VALIDATION_ERROR which I am not able to understand: {"name":"VALIDATION_ERROR","message":"Invalid request - see details.","information_link":"https://developer.paypal.com/docs/api/invoicing/#errors","details":[{"field":"merchant_info","issue":"cannot be null."},{"field":"items[0].unit_price","issue":"null"}]}
From what I can minimally understand, this error says that I have missing information like Items[].unit_price and merchant_info however I have no idea where this is supposed to be in my Request Body. I am following the direct documentationhere but I cannot see anything that mentions unit_price or merchant_info.
Submit your request to the correct API endpoint, https://api-m.sandbox.paypal.com/v2/invoicing/invoices
Note the major version number. See the Invoicing API reference for details.
I have a strange thing going on in my Alexa skill. My skill requires to connect with MongoDB and save data. Whenever I connect to database, Alexa is giving me this response: "There was a problem with the requested skill's response". It is completely weired because few days ago my database and Alexa skill were perfectly working. Now, suddenly, I don't get any response from Alexa even though my database in connected and creats documents.
Below is my JSON INPUT and code from the Launchrequesthandler :
{
"version": "1.0",
"session": {
"new": true,
"sessionId": "amzn1.echo-api.session.b163d6da-ab3d-483c-ba19-60156810739c",
"application": {
"applicationId": "amzn1.ask.skill.bd7f1ea6-53ab-41af-9a59-4853d4906373"
},
"user": {
"userId": "amzn1.ask.account.AFMYVNKRB3REUKGDDLGIFOYXR53ISFLYHQJXHO2YDRYVQCPCRLYQFIVLBE5HDXH6FNMTMN4YLXHR6ZMSJEFQ3Y2BRI76N2FHSHDXAWUPVFB6JKWSRTPA7EWOH6ZOF24KY5DXUBA3UMUY3TNQZ42AOOFESTFWW6VLTU63AHHQMMPKA74M2WX66TN4IYOZUNLMBXMX3LCUBWPO4FY"
}
},
"context": {
"Viewports": [
{
"type": "APL",
"id": "main",
"shape": "RECTANGLE",
"dpi": 213,
"presentationType": "STANDARD",
"canRotate": false,
"configuration": {
"current": {
"mode": "HUB",
"video": {
"codecs": [
"H_264_42",
"H_264_41"
]
},
"size": {
"type": "DISCRETE",
"pixelWidth": 1280,
"pixelHeight": 800
}
}
}
}
],
"Viewport": {
"experiences": [
{
"arcMinuteWidth": 346,
"arcMinuteHeight": 216,
"canRotate": false,
"canResize": false
}
],
"mode": "HUB",
"shape": "RECTANGLE",
"pixelWidth": 1280,
"pixelHeight": 800,
"dpi": 213,
"currentPixelWidth": 1280,
"currentPixelHeight": 800,
"touch": [
"SINGLE"
],
"video": {
"codecs": [
"H_264_42",
"H_264_41"
]
}
},
"Extensions": {
"available": {
"aplext:backstack:10": {}
}
},
"System": {
"application": {
"applicationId": "amzn1.ask.skill.bd7f1ea6-53ab-41af-9a59-4853d4906373"
},
"user": {
"userId": "amzn1.ask.account.AFMYVNKRB3REUKGDDLGIFOYXR53ISFLYHQJXHO2YDRYVQCPCRLYQFIVLBE5HDXH6FNMTMN4YLXHR6ZMSJEFQ3Y2BRI76N2FHSHDXAWUPVFB6JKWSRTPA7EWOH6ZOF24KY5DXUBA3UMUY3TNQZ42AOOFESTFWW6VLTU63AHHQMMPKA74M2WX66TN4IYOZUNLMBXMX3LCUBWPO4FY"
},
"device": {
"deviceId": "amzn1.ask.device.AHVUJSCJ4KXLFF5SOTIFUCLYUXGBZFLUK3QURQHGX5S7N5E53K7O3ZXEO5V7KFPDR6XPPZECKTX5HEWB3BTLGAM34J7DVPKOALFNNDXCYDUIQWHNH327H3LCV3RNS7XFQLMJ6FXZ36JB5SF3YRUAEULDNIQCBSGZPR7J7KPCGCAHLPJXV5YRA",
"supportedInterfaces": {}
},
"apiEndpoint": "https://api.amazonalexa.com",
"apiAccessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJhdWQiOiJodHRwczovL2FwaS5hbWF6b25hbGV4YS5jb20iLCJpc3MiOiJBbGV4YVNraWxsS2l0Iiwic3ViIjoiYW16bjEuYXNrLnNraWxsLmJkN2YxZWE2LTUzYWItNDFhZi05YTU5LTQ4NTNkNDkwNjM3MyIsImV4cCI6MTYyNjY2MDY3NCwiaWF0IjoxNjI2NjYwMzc0LCJuYmYiOjE2MjY2NjAzNzQsInByaXZhdGVDbGFpbXMiOnsiY29udGV4dCI6IkFBQUFBQUFBQUFDWFBEU1FPNldCNURRZG9RaCtXRHZjS2dFQUFBQUFBQUFJVkx0RDV3L1VSTklPK1VEQkVGZWdDUTA2Z3IvZ1dRZHFCUThYSzBjSmZmQUhDRXRsR05QUDNEeXRVVjcyc1VFbWFHMktETjc1MkpMemNPNDhpdm1WYlFjbEMrZ1VrUU9BY09RUEw3R1JEVGd5SUpPVStoVkRNQ1BJdmJhd2F1YUUxM2wzcE95WmFlVDdocnA0dDF6bXJ6MkdyM1BJbXdBbm1WaGNlakpqRCtVUHFZL0VPeGRRNm5OaGs5eXVZdEF3alF1dkpwWFM3ZkQzSmlwbVR5eTkwVHRiSERlckxUN2lmaTV2cnJpdHNBS1FjbksrY2VzRjErRm9zbUZLYmZsbWJpa3lIZVo5LzE4VmJ2d0tBelVreW9BVXI2aUQvakt6VjVUTzlyYjduZmZXdWZVZXNDMEhtM3lzWEhUbFRXSHhVektGR2NySHBzQ1kwSXBGRldWaTV6aEp4S3ovZ0RUbUdnZ09uajVDcnkxWHhrd1c3bXZQa1YxdFJrUUlkSnlBNElZMzJHV3FZMXQyIiwiY29uc2VudFRva2VuIjpudWxsLCJkZXZpY2VJZCI6ImFtem4xLmFzay5kZXZpY2UuQUhWVUpTQ0o0S1hMRkY1U09USUZVQ0xZVVhHQlpGTFVLM1FVUlFIR1g1UzdONUU1M0s3TzNaWEVPNVY3S0ZQRFI2WFBQWkVDS1RYNUhFV0IzQlRMR0FNMzRKN0RWUEtPQUxGTk5EWENZRFVJUVdITkgzMjdIM0xDVjNSTlM3WEZRTE1KNkZYWjM2SkI1U0YzWVJVQUVVTEROSVFDQlNHWlBSN0o3S1BDR0NBSExQSlhWNVlSQSIsInVzZXJJZCI6ImFtem4xLmFzay5hY2NvdW50LkFGTVlWTktSQjNSRVVLR0RETEdJRk9ZWFI1M0lTRkxZSFFKWEhPMllEUllWUUNQQ1JMWVFGSVZMQkU1SERYSDZGTk1UTU40WUxYSFI2Wk1TSkVGUTNZMkJSSTc2TjJGSFNIRFhBV1VQVkZCNkpLV1NSVFBBN0VXT0g2Wk9GMjRLWTVEWFVCQTNVTVVZM1ROUVo0MkFPT0ZFU1RGV1c2VkxUVTYzQUhIUU1NUEtBNzRNMldYNjZUTjRJWU9aVU5MTUJYTVgzTENVQldQTzRGWSJ9fQ.MheHasYZKwNcTzwQLjt42C_yujmQJrGGHQ6tvWXt7uNTRzi73-MzzxXMOrztDYaBBCHmHZQS0Qy0-blTfgBT2Yqj5W5gAmcAc_CKKZhh4awlM1xGSAD87kOW8ZiLY2n68IfiKTsUHf6Bp4YiLOMcWWErSTCq91JeYeau0W7B5TvZGTm04OmfK-qkZBVPq6ME8_ulukdZUNxIpVUItkSEuhppcegUcGkzqYdrPRY0BJrsBe-Pytu5xLRiBM3T78nTysnGM288IJSccGJ4rmW4UdzHA_lnH7543QhgU9t71JRncgEDKEsEcVgxs5biFR9il4W8ASfwuDeJhdy8HpiXZw"
}
},
"request": {
"type": "LaunchRequest",
"requestId": "amzn1.echo-api.request.3e29f996-69b2-4e90-bfef-628d74f57307",
"locale": "en-US",
"timestamp": "2021-07-19T02:06:14Z",
"shouldLinkResultBeReturned": false
}
}
//database connection//
const q="mongodb+srv://sumya:sumya123#mydata.acxs0.mongodb.net/Mydata?retryWrites=true&w=majority";
mongoose.connect(q,{ useNewUrlParser: true, useUnifiedTopology: true,useFindAndModify: false })
.then(() => console.log("Database connected!")
)
.catch(err => console.log(err))
const Alexa = require('ask-sdk-core');
const LaunchRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
},
async handle(handlerInput) {
const speakOutput = 'Hi, I am Nao. I am here to give you counseling on your anxiety issues. Can I have your name, please? Note: We are not professional therapists or counselors. ';
const useri=handlerInput.requestEnvelope.session.user.userID;
const z=handlerInput.requestEnvelope.session.sessionId;
const g=Alexa.getUserId(handlerInput.requestEnvelope);
const curr_session=new post.session({
alexa_sessionid:z
});
let user=await post.findOne({userID:g});
if(!user){
user=new post({
userID:g
});
}
user.session_list.push(curr_session);
user.save();
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
Here is the Log that I got from Cloudwatch.
START RequestId: 6a416b77-5d2c-4ebe-8ac4-dec09f67e9b9 Version: 304
2021-07-19T16:40:00.570Z 6a416b77-5d2c-4ebe-8ac4-dec09f67e9b9 INFO Database connected!
END RequestId: 6a416b77-5d2c-4ebe-8ac4-dec09f67e9b9
REPORT RequestId: 6a416b77-5d2c-4ebe-8ac4-dec09f67e9b9 Duration: 8008.11 ms Billed Duration: 8000 ms Memory Size: 512 MB Max Memory Used: 102 MB Init Duration: 653.49 ms
2021-07-19T16:40:08.023Z 6a416b77-5d2c-4ebe-8ac4-dec09f67e9b9 Task timed out after 8.01 seconds
START RequestId: 4e671447-8207-414e-aaf4-9a807fe3ac01 Version: 304
2021-07-19T16:40:08.894Z 4e671447-8207-414e-aaf4-9a807fe3ac01 INFO ~~~~ Session ended:
{
"version": "1.0",
"session": {
"new": false,
"sessionId": "amzn1.echo-api.session.05ca6843-cdc8-47eb-9a5f-081942cf2674",
"application": {
"applicationId": "amzn1.ask.skill.bd7f1ea6-53ab-41af-9a59-4853d4906373"
},
"user": {
"userId": "amzn1.ask.account.AFMYVNKRB3REUKGDDLGIFOYXR53ISFLYHQJXHO2YDRYVQCPCRLYQFIVLBE5HDXH6FNMTMN4YLXHR6ZMSJEFQ3Y2BRI76N2FHSHDXAWUPVFB6JKWSRTPA7EWOH6ZOF24KY5DXUBA3UMUY3TNQZ42AOOFESTFWW6VLTU63AHHQMMPKA74M2WX66TN4IYOZUNLMBXMX3LCUBWPO4FY"
}
},
"context": {
"Viewports": [
{
"type": "APL",
"id": "main",
"shape": "RECTANGLE",
"dpi": 213,
"presentationType": "STANDARD",
"canRotate": false,
"configuration": {
"current": {
"mode": "HUB",
"video": {
"codecs": [
"H_264_42",
"H_264_41"
]
},
"size": {
"type": "DISCRETE",
"pixelWidth": 1280,
"pixelHeight": 800
}
}
}
}
],
"Viewport": {
"experiences": [
{
"arcMinuteWidth": 346,
"arcMinuteHeight": 216,
"canRotate": false,
"canResize": false
}
],
"mode": "HUB",
"shape": "RECTANGLE",
"pixelWidth": 1280,
"pixelHeight": 800,
"dpi": 213,
"currentPixelWidth": 1280,
"currentPixelHeight": 800,
"touch": [
"SINGLE"
],
"video": {
"codecs": [
"H_264_42",
"H_264_41"
]
}
},
"Extensions": {
"available": {
"aplext:backstack:10": {}
}
},
"System": {
"application": {
"applicationId": "amzn1.ask.skill.bd7f1ea6-53ab-41af-9a59-4853d4906373"
},
"user": {
"userId": "amzn1.ask.account.AFMYVNKRB3REUKGDDLGIFOYXR53ISFLYHQJXHO2YDRYVQCPCRLYQFIVLBE5HDXH6FNMTMN4YLXHR6ZMSJEFQ3Y2BRI76N2FHSHDXAWUPVFB6JKWSRTPA7EWOH6ZOF24KY5DXUBA3UMUY3TNQZ42AOOFESTFWW6VLTU63AHHQMMPKA74M2WX66TN4IYOZUNLMBXMX3LCUBWPO4FY"
},
"device": {
"deviceId": "amzn1.ask.device.AHVUJSCJ4KXLFF5SOTIFUCLYUXGBZFLUK3QURQHGX5S7N5E53K7O3ZXEO5V7KFPDR6XPPZECKTX5HEWB3BTLGAM34J7DVPKOALFNNDXCYDUIQWHNH327H3LCV3RNS7XFQLMJ6FXZ36JB5SF3YRUAEULDNIQCBSGZPR7J7KPCGCAHLPJXV5YRA",
"supportedInterfaces": {}
},
"apiEndpoint": "https://api.amazonalexa.com",
"apiAccessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJhdWQiOiJodHRwczovL2FwaS5hbWF6b25hbGV4YS5jb20iLCJpc3MiOiJBbGV4YVNraWxsS2l0Iiwic3ViIjoiYW16bjEuYXNrLnNraWxsLmJkN2YxZWE2LTUzYWItNDFhZi05YTU5LTQ4NTNkNDkwNjM3MyIsImV4cCI6MTYyNjcxMzA5OCwiaWF0IjoxNjI2NzEyNzk4LCJuYmYiOjE2MjY3MTI3OTgsInByaXZhdGVDbGFpbXMiOnsiY29udGV4dCI6IkFBQUFBQUFBQUFDWFBEU1FPNldCNURRZG9RaCtXRHZjS2dFQUFBQUFBQUE2aVpRZUVXeHoyTG9zdVRVQktXTmIzSXVCUU51cEZnMzgzdzZRUnVTN1U1eU5qQUF3a2puZVk2Si9DWS85TTN1QWFEMVQrZS9ndktVNVFOaWxCT3RpdEV4d3ZYdXVEekZ1WDdhQ1hCc2xlVWdYenNSZWg2Q1RjaGUvR3pwdkk3eEE5NzBydlRCeVlCNll0WVVvZVpyZmZMT2w5Z09iQVpUaHpyKzVOOTBPRWdwNUpXMjdvYUhDSkxHVStxZHFUd3RQVzI3M2RPSEZ5N3Zzc2VSTFdIc0o2WUVjeVFwa2p5QzZyRU1yNlRLdVBHSG1ZemIzVGxmb043cTlGdGI0THFFdGwrSkdXeU1mVTBMeEllNGZ3OWhWa1lFR3BLeEl1c0VPc1FOenh6UVV1UEJiZ3Z1T0dDN2Q1KzM4YnY4UWQyb2twUzlNZ2R1ZTlPamxnSlRvbmFFMS9nNFVxYlBZM0dqZEgzMVV3NFZLR29CekJRaGdXMDlTVDFJRmZELzhwcmF2dFFMYmNGQ0tlcklPIiwiY29uc2VudFRva2VuIjpudWxsLCJkZXZpY2VJZCI6ImFtem4xLmFzay5kZXZpY2UuQUhWVUpTQ0o0S1hMRkY1U09USUZVQ0xZVVhHQlpGTFVLM1FVUlFIR1g1UzdONUU1M0s3TzNaWEVPNVY3S0ZQRFI2WFBQWkVDS1RYNUhFV0IzQlRMR0FNMzRKN0RWUEtPQUxGTk5EWENZRFVJUVdITkgzMjdIM0xDVjNSTlM3WEZRTE1KNkZYWjM2SkI1U0YzWVJVQUVVTEROSVFDQlNHWlBSN0o3S1BDR0NBSExQSlhWNVlSQSIsInVzZXJJZCI6ImFtem4xLmFzay5hY2NvdW50LkFGTVlWTktSQjNSRVVLR0RETEdJRk9ZWFI1M0lTRkxZSFFKWEhPMllEUllWUUNQQ1JMWVFGSVZMQkU1SERYSDZGTk1UTU40WUxYSFI2Wk1TSkVGUTNZMkJSSTc2TjJGSFNIRFhBV1VQVkZCNkpLV1NSVFBBN0VXT0g2Wk9GMjRLWTVEWFVCQTNVTVVZM1ROUVo0MkFPT0ZFU1RGV1c2VkxUVTYzQUhIUU1NUEtBNzRNMldYNjZUTjRJWU9aVU5MTUJYTVgzTENVQldQTzRGWSJ9fQ.d-u2NVM8g_trqjKN_IxpFYy1_Fp-iL6MhTV8uOqScwa-kQF4ax-LzOWKaOE-ZrTW75UGhf6LxNorGxEDDhzNajObdQt9NBGIoM-E-LcLX1rjKvUarDgHvbQFLMt5HzjKNBSJjJ-ZyQodmI-7qDijf5vag3ea6ITEP1jciU5A0iMAtZNhKDNp0hgt7oyfYypRihWklSFrj21KXBjwo0nO0mJyA-Q81jAJU-wjxLDLXm6btsD4z4NWtHYMkjiEcjXfPhE6MyFNEH1_jPU6HbnOl1xRQJkEtTZeb6C44ZmzUkfrKRgWetWqfOr2GnF11vpKGk2_ueoNJZcBoJhzr57DiQ"
}
},
"request": {
"type": "SessionEndedRequest",
"requestId": "amzn1.echo-api.request.bf2b3b37-7260-4813-a43c-b94ae49b45bf",
"timestamp": "2021-07-19T16:40:08Z",
"locale": "en-US",
"reason": "ERROR",
"error": {
"type": "INVALID_RESPONSE",
"message": "An exception occurred while dispatching the request to the skill."
}
}
}
If you are hosting skill in lambda, there may be a chance for timeout. Database operations may take time, meanwhile lambda closed the session.
I think following log line suggests the same.
**2021-07-19T16:40:08.023Z 6a416b77-5d2c-4ebe-8ac4-dec09f67e9b9 Task timed out after 8.01 seconds**
Also, we have to consider maximum time allowed for Alexa to receive the response from end point. It is good to cap the response by 8 secs. For more information : DeferredResponse
{
"data": [
{
"event_name": "ViewContent",
"event_time": 1620216748,
"action_source": "email",
"user_data": {
"em": "7b17fb0bd173f625b58636fb796407c22b3d16fc78302d79f0fd30c2fc2fc068",
"ph": null
},
"custom_data": {
"currency": "USD",
"value": "142.52"
}
}
],
"test_event_code": "TEST1234"
}
I am using the test JSON request, it does not throw error and gives
{
"events_received": 1,
"messages": [
],
"fbtrace_id": "As1JpX8LxeVtLP5XLSfY7Np"
}
But i am unable to get it under Facebook Event manager test events.
Try to insert this Json code:
You need only change the values of <A IP ADDRESS> and <YOUR TEST_CODE> with your data.
{
"data": [
{
"event_name": "Purchase",
"event_time": 1620921176,
"action_source": "website",
"user_data": {
"em": "7b17fb0bd173f625b58636fb796407c22b3d16fc78302d79f0fd30c2fc2fc068",
"client_user_agent": "mozilla",
"client_ip_address": "<A IP ADDRESS>"
},
"custom_data": {
"currency": "USD",
"value": "142.52"
}
}
],
"test_event_code": "<YOUR TEST_CODE>"
}
On my tests, it works after I insert these data:
"client_user_agent": "mozilla",
"client_ip_address": "<A IP ADDRESS>"
I have been trying to figure it out... I have tried quite a few things. Entering the IP did the trick. Not sure if that means there is something wrong, but I do know the conversation api test didn't work until we added the IP.
I am connecting to Dialogflow REST API v2beta1 to the method: projects.agent.sessions.detectIntent. In the first request I send a text and the response is returning the expected result which contains outputContexts; when I made the 2nd request I send the context and it should find the intent which is linked to that context, but instead of that it is returning the Default Fallback Intent.
What may be the problem on the 2nd request?
Here are the URL and requests with their respective responses, and below I added the screenshots of the intents expected to match.
URL
https://dialogflow.googleapis.com/v2beta1/projects/project-name/agent/sessions/12343:detectIntent
1st request
{
"queryInput":{
"text":{
"text":"play a video about love",
"languageCode":"en"
}
}
}
1st response
{
"responseId": "15a3b767-52fe-4fc2-8ffd-9d7bb9c6961a",
"queryResult": {
"queryText": "play a video about love",
"action": "video.play",
"parameters": {
"organization": "",
"tag": "Love",
"item": ""
},
"allRequiredParamsPresent": true,
"fulfillmentText": "Here is a video about Love!",
"fulfillmentMessages": [
{
"platform": "ACTIONS_ON_GOOGLE",
"simpleResponses": {
"simpleResponses": [
{
"textToSpeech": "Here is a video about Love!"
}
]
}
},
{
"text": {
"text": [
"Here is a video about Love!"
]
}
}
],
"outputContexts": [
{
"name": "projects/project-name/agent/sessions/12343/contexts/play-video",
"lifespanCount": 5,
"parameters": {
"tag": "Love",
"organization": "",
"tag.original": "love",
"item": "",
"organization.original": "",
"item.original": ""
}
}
],
"intent": {
"name": "projects/project-name/agent/intents/9e5d2bbc-81f3-4700-8740-01504b05443f",
"displayName": "video-play"
},
"intentDetectionConfidence": 1,
"languageCode": "en"
}
}
2nd request (where the problem should be)
{
"queryParams":{
"contexts":[
{
"name":"projects/project-name/agent/sessions/12342/contexts/play-video"
}
]
},
"queryInput":{
"text":{
"text":"that video matters a lot for me",
"languageCode":"en"
}
}
}
2nd response
{
"responseId": "40d1f94f-4673-4644-aa53-99c854ff2596",
"queryResult": {
"queryText": "that video matters a lot for me",
"action": "input.unknown",
"parameters": {},
"allRequiredParamsPresent": true,
"fulfillmentText": "Can you say that again?",
"fulfillmentMessages": [
{
"text": {
"text": [
"Sorry, what was that?"
]
}
}
],
"intent": {
"name": "projects/project-name/agent/intents/10c88e8d-f16a-4905-b829-f596d3b3c588",
"displayName": "Default Fallback Intent",
"isFallback": true
},
"intentDetectionConfidence": 1,
"languageCode": "en"
}
}
Screenshots of the intents expected to match
1st intent
2nd intent
Useful documentation
Doc of the method: https://dialogflow.com/docs/reference/api-v2/rest/v2beta1/projects.agent.sessions/detectIntent
Doc of the Context object: https://dialogflow.com/docs/reference/api-v2/rest/Shared.Types/Context
Doc of the Params object to be sent: https://dialogflow.com/docs/reference/api-v2/rest/v2beta1/QueryParameters
It looks like your second request has an incomplete context. Although you're specifying the name, you're not including the lifespanCount parameter. Since you're not providing a parameter, it defaults to 0, which means that it has timed out.
You should send back exactly what you received from the outputContext attribute in the previous reply.
{
"queryParams":{
"contexts":[
{
"name": "projects/project-name/agent/sessions/12343/contexts/play-video",
"lifespanCount": 5,
"parameters": {
"tag": "Love",
"organization": "",
"tag.original": "love",
"item": "",
"organization.original": "",
"item.original": ""
}
}
]
},
"queryInput":{
"text":{
"text":"that video matters a lot for me",
"languageCode":"en"
}
}
}
I want to create a chatbot with Dialogflow and Google Assistant along with Google Transactions API for enabling a user to order a chocolate box. For now my agent contains the following four intents:
Default Welcome Intent (text response: Hello, do you want to buy a chocolate box?)
Default Fallback Intent
Int1 (training phrase: Yes, I want, fulfilment: enabled webhook call)
Int2 (event: actions_intent_TRANSACTION_REQUIREMENTS_CHECK )
I am using Dialogflow Json instead of Node.js to connect my agent with Transactions API. I want to test that the user meets the transaction requirements (when ordering the chocolate box) by using the actions.intent.TRANSACTION_REQUIREMENTS_CHECK action of Google actions. For this reason, following Google docs, when Int1 is triggered I am using a webhook which connect Google Assistant to the following python script (back-end):
from flask import Flask, render_template, request, jsonify
from flask_cors import CORS
import requests
app = Flask(__name__)
CORS(app)
#app.route("/", methods=['POST'])
def index():
data = request.get_json()
intent = data["queryResult"]["intent"]["displayName"]
if (intent == 'Int1'):
return jsonify({ "data": {
"google": {
"expectUserResponse": True,
"isSsml": False,
"noInputPrompts": [],
"systemIntent": {
"data": {
"#type": "type.googleapis.com/google.actions.v2.TransactionRequirementsCheckSpec",
"paymentOptions": {
"actionProvidedOptions": {
"displayName": "VISA-1234",
"paymentType": "PAYMENT_CARD"
}
}
},
"intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK"
}
}
}
})
else:
return jsonify({'message': 'HERE'})
if __name__== "__main__":
app.run(debug=True)
The json which I return above when intent = 'Int1' is the one specified at Google docs for "Checking requirements with your own payment method".
According to Google docs, this must be done next:
Receiving the result of a requirements check
After the Assistant fulfills the intent, it sends your fulfillment a
request with the actions.intent.TRANSACTION_REQUIREMENTS_CHECK intent
with the result of the check.
To properly handle this request, declare a Dialogflow intent that's
triggered by the actions_intent_TRANSACTION_REQUIREMENTS_CHECK event.
For this reason, I defined Int2 and as its event the actions_intent_TRANSACTION_REQUIREMENTS_CHECK.
However, I do not receive anything at my back-end like a result of the check and therefore I do not know if the action actions.intent.TRANSACTION_REQUIREMENTS_CHECK is really triggered. Why is this happening?
In general, how can I trigger one actions.intent.INTENT_NAME intent from my webhook/back-end?
When I am using the v2 version of Dialogflow, I am getting the following info/message about the webhook on Dialogflow when Int1 is triggered:
"webhookStatus": {
"code": 3,
"message": "Webhook call failed. Error: Failed to parse webhook JSON response: Cannot find field: data in message google.cloud.dialogflow.v2.WebhookResponse."
}
In the same case, I am getting the following info/message about the webhook on Google Assistant simulator when Int1 is triggered:
"responseMetadata": {
"status": {
"code": 14,
"message": "Webhook error (206)"
}
Finally, let me mention that I am testing all this with Python and ngrok at my local computer so perhaps this poses a problem because at the beginning of Google docs the following is mentioned:
Warning: The Actions Web Simulator should not be used to test an app
with transactions. Please use an Assistant-enabled Android or iOS
device to accurately test your app during development.
I finally solved this problem.
I had to replace the key "data" in the json which I was sending back when Int1 was triggered with the key "payload". In other words, I had to adjust my fulfilment response to the v2 version of Dialogflow.
Therefore, now I do get a second post request at my back-end which is sent because of the trigger of actions.intent.TRANSACTION_REQUIREMENTS_CHECK and of Int2.
Specifically, I get the following:
{
"responseId": "*****************************",
"queryResult": {
"queryText": "actions_intent_TRANSACTION_REQUIREMENTS_CHECK",
"parameters": {},
"allRequiredParamsPresent": true,
"fulfillmentText": "HERE",
"fulfillmentMessages": [
{
"text": {
"text": [
"HERE"
]
}
}
],
"outputContexts": [
{
"name": "*****************************"
},
{
"name": "*****************************"
},
{
"name": "*****************************"
},
{
"name": "*****************************"
},
{
"name": "*****************************"
},
{
"name": "*****************************",
"parameters": {
"TRANSACTION_REQUIREMENTS_CHECK_RESULT": {
"#type": "type.googleapis.com/google.actions.v2.TransactionRequirementsCheckResult",
"resultType": "OK"
}
}
}
],
"intent": {
"name": "*****************************",
"displayName": "Int2"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {},
"languageCode": "en-us"
},
"originalDetectIntentRequest": {
"source": "google",
"version": "2",
"payload": {
"isInSandbox": true,
"surface": {
"capabilities": [
{
"name": "actions.capability.WEB_BROWSER"
},
{
"name": "actions.capability.MEDIA_RESPONSE_AUDIO"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.AUDIO_OUTPUT"
}
]
},
"inputs": [
{
"rawInputs": [
{
"inputType": "KEYBOARD"
}
],
"arguments": [
{
"extension": {
"#type": "type.googleapis.com/google.actions.v2.TransactionRequirementsCheckResult",
"resultType": "OK"
},
"name": "TRANSACTION_REQUIREMENTS_CHECK_RESULT"
}
],
"intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK"
}
],
"user": {
"lastSeen": "2018-05-16T11:15:14Z",
"locale": "en-US",
"userId": "*****************************"
},
"conversation": {
"conversationId": "1526470000479",
"type": "ACTIVE",
"conversationToken": "[]"
},
"availableSurfaces": [
{
"capabilities": [
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.AUDIO_OUTPUT"
}
]
}
]
}
},
"session": "*****************************"
}
I think your response object is incorrect. the intent attribute should be inside the systemIntent object
"data": {
"google": {
"expectUserResponse": true,
"isSsml": false,
"noInputPrompts": [],
"systemIntent": {
"intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK",
"data": {
"#type": "type.googleapis.com/google.actions.v2.TransactionRequirementsCheckSpec",
"paymentOptions": {
"actionProvidedOptions": {
"displayName": "VISA-1234",
"paymentType": "PAYMENT_CARD"
}
}
}
}
}
}