Below is my code.
define('SHOPIFY_APP_SECRET', 'xxxxxxxxxx');
function verify_webhook($data, $hmac_header)
{
$calculated_hmac = base64_encode(hash_hmac('sha256', $data, SHOPIFY_APP_SECRET, true));
return hash_equals($hmac_header, $calculated_hmac);
}
$hmac_header = $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header);
echo "<pre>";
print_r($data);
exit;
?>
I've registered the app/uninstalled webhook.
So this is my code but not receiving any response
I know it is a late answer. But might helpful for the future user who will land here. You forgot to save the response you are getting from uninstall webhook to somewhere. Considered saving response to file. here is php code to save. After saving the response you can read or do processing after that.
file_put_contents($newFileName, $data);
Also, save the response only when HMAC hash matched you got from api. You can get domain name and for which topic api is fired. below is code. Do the necessary work.
$domain = $_SERVER['X-Shopify-Shop-Domain'];
$topic = $_SERVER['X-Shopify-Topic'];
Let me know if you are looking for more detail. thanks
Related
I created a website and I integrated payment using PayStack and it is fully functional, but something unusual came up sometime when a customer wanted to make a payment. After the successful payment processing, maybe something went wrong with the customer's Network provider but the customer was not redirected to a success page where to give values to database.
So I implemented webhooks to get values from paystack and PUT THE CONTENTS in a .txt (webhookApi.txt) file but it seems something is wrong with the code and I can't figure it out.
`
<?php
// only a post with paystack signature header gets our attention
if ((strtoupper($_SERVER['REQUEST_METHOD']) != 'POST' ) || !array_key_exists('x-paystack-signature', $_SERVER) )
exit();
// Retrieve the request's body
$input = #file_get_contents("php://input");
define('PAYSTACK_SECRET_KEY','sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxx');
// validate event do all at once to avoid timing attack
if($_SERVER['HTTP_X_PAYSTACK_SIGNATURE'] !== hash_hmac('HMAC SHA512', $input, PAYSTACK_SECRET_KEY))
exit();
http_response_code(200);
// parse event (which is json string) as object
// Do something - that will not take long - with $event
$event = json_decode($input);
$reference = $event->data->reference;
$email = $event->data->customer->email;
$eventMessage = $event->event;
file_put_contents("webhookApi.txt", PHP_EOL.$input, FILE_APPEND);
exit();
?>
`
I have implemented webhook for revenuecat in .net core C#. But for some reason I am getting 400 badrequest with empty response. I am mostly sure that I am not getting the json response in webook through revenuecat for any of the event occurring.
I have also added endpoint on revenue cat webhook with authentication. I have tried several time and as I have not way to test this on local machine. I need help from revenue cat team to provide some reference doc with sample implementation just to get proper json response. Below is the code snippet that I am using to get json response from the webhook endpoint added in revenuecat.
var webHookSecret = _configuration[Constants.RevenueCatWebHookSecret]; var headerAuthorization = HttpContext.Request.Headers["Authorization"].ToString(); #region Check authorization if (webHookSecret == headerAuthorization) { json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); } else { _logger.Information($"Un-Authorized token access in revenuecat webhook. Returning BadRequest response."); throw new APIException(HttpStatusCode.Unauthorized, new APIError(_configuration, "InternalServerError")); }
If my bot asks different questions and if the user answers each of them, how do I find out which answer relates to which question. There is a field called metadata that you can attach to the sendTextMessage API but when the user responds, this metadata comes in as undefined. Do you guys use any node-cache for tracking state or an FSM such as machina.js? How can I best figure out at what of the conversation we are currently stuck in?
When your app receives a message, there's no payload or metadata associated with it. This is as opposed to a quick-reply or post-back which can have a payload. The only way to associate a response with a question this is to manually track the conversation state in your app as suggested by #anshuman-dhamoon
To do this, it's best to maintain a state for each user, as well as the next state for each state.
// optionally store this in a database
const users = {}
// an object of state constants
const states = {
question1: 'question1',
question2: 'question2',
closing: 'closing',
}
// mapping of each to state to the message associated with each state
const messages = {
[states.question1]: 'How are you today?',
[states.question2]: 'Where are you from?',
[states.closing]: 'That\'s cool. It\'s nice to meet you!',
}
// mapping of each state to the next state
const nextStates = {
[states.question1]: states.question2,
[states.question2]: states.closing,
}
const receivedMessage = (event) => {
// keep track of each user by their senderId
const senderId = event.sender.id
if (!users[senderId].currentState){
// set the initial state
users[senderId].currentState = states.question1
} else {
// store the answer and update the state
users[senderId][users[senderId].currentState] = event.message.text
users[senderId].currentState = nextStates[users[senderId.currentState]]
}
// send a message to the user via the Messenger API
sendTextMessage(senderId, messages[users[senderId].currentState])
}
Note If you wanted, you can even make the values of nextStates into callable functions that take the answer of the current state and branch off into different conversation flows by passing the user to a different state depending on his/her response.
As per my knowledge,in Facebook chatbot you can send data from user to chatbot just by setting payload from postback buttons as they have given in API reference.
And chatbot won't store your session or any states/flags.you can set status or flags or arrays but all will be lost when you update your application or restart your server.
so,if you really want to set status you should use database for that.and senderID will remain same everytime so you can handle data from database by that particular id for particular user.
For more details checkout technical referance here.
I hope this will help you.if so,kindly mark it as an answer.
You can have a status code in your code, to keep track of where the user conversation with the bot is.
For eg. if you have 10 questions, keep statuscode = 0 initially, and ask the first question. When you receive a message to your webhook, check if statuscode==0, and store that user message as a response to your first question. Then increment statusCode=1 and ask the next question.
You can have multiple flags and statusCodes to deal with different conversation flows.
I'm running into this issue myself. Though it hasn't been mentioned at all in their documentation, I don't think attaching an in-memory database is out of the question. It seems that the user_id is the same regardless of when the conversation is initiated.
Making an API call every time the user rejoins the session would probably slow down the performance of the bot. Also, I noticed that you can't really construct a "pseudo-distributed database" by using the metadata key in the API if that is what you were suggesting. The metadata tag can be sent from Server -> Client (Messenger) but not from Client -> Server from what the documentation says.
I've spent some time working with this. The best solution is to use a database to track the user's conversation flow. The POST object contains the senders ID. You can use this ID to make a row in the database in which you'd definitely need to store this ID, any answers to the questions, and a field to keep track of of which step in the conversation.
Then you can use if statements in your code to return the proper responses. Some example code below:
if( $currentStep == '1' ){
// Ask Next Question
$message_to_reply = "Thank you! What's your name?";
$message_to_reply = '"text":"'.$message_to_reply.'"';
} elseif( $currentStep == '2' ){
// Ask Next Question
$message_to_reply = "Thank you! What's your email address?";
$message_to_reply = '"text":"'.$message_to_reply.'"';
} elseif( $currentStep == '3' ){
// Ask Next Question
$message_to_reply = "Thank you! What's your address?";
$message_to_reply = '"text":"'.$message_to_reply.'"';
}
I am working on a project to retrieve the gmail inbox messages through GMAIL REST API and populate them into a new user interface that is going to be used for other purpose. This project is in PHP. I am currently using PHP version. This is the code snippet that I am using to retrieve the message body.
$service = new Google_Service_Gmail($client);
$user = 'me';
function get_Message_Body($messageId,$service)
{
$optParamsGet = [];
$optParamsGet['format'] = 'full';
echo "this is optParamsGet";
var_dump($optParamsGet);
$message = $service->users_messages->get('me',$messageId,$optParamsGet);
echo "this is message";
var_dump($message);
echo "<pre>".$message->snippet."</pre>";
$messagePayload = $message->getPayload();
$headers = $message->getPayload()->getHeaders();
$parts = $message->getPayload()->getParts();
$body = $parts[0]['body'];
echo "this is body";
var_dump($body);
$rawData = $body->data;
$sanitizedData = strtr($rawData,'-_', '+/');
$decodedMessage = base64_decode($sanitizedData);
echo $decodedMessage;
}
get_Message_Body($_REQUEST["id"], $service);
However, I see that this code works only for messages with mime/type of multipart/alternative. However, I need to retrieve the message body and attachments for any kind of gmail message. How do I do that. This is the output that I see for a different mime type on the new user interface
The code snippet for retrieving the messages
Here the message body in the snippet, does not pass into the data parameter in the MessagePartBody. Unlike this code which is mime type mulipart/alternative, where the code passes into the message body->parts and rendered on ui.enter image description here
For security purposes, I try to allow only Mandrill's IP(s) to access these urls.
Does anyone know them?
Mandrill's signature is located in the HTTP response header: Authenticating-webhook-requests
In the request header find: X-Mandrill-Signature. This is a base64 of the hashcode, signed using web-hook key. This key is secret to your webhook only.
We have a range of IPs used for webhooks, but they can (and likely will) change or have new ones added as we scale. An alternative would be to add a query string to the webhook URL you add in Mandrill, and then check for that query string when a POST comes in so you can verify it's coming from Mandrill.
Just replace the constants and use this function:
<?php
function generateSignature($post)
{
$signed_data = WEB_HOOK_URL;
ksort($post);
foreach ($post as $key => $value) {
$signed_data .= $key;
$signed_data .= $value;
}
return base64_encode(hash_hmac('sha1', $signed_data, WEB_HOOK_AUTH_KEY, true));
}
//---
if (generateSignature($_POST) != $_SERVER['HTTP_X_MANDRILL_SIGNATURE']) {
//Invalid
}
?>
As described in mandrill's docs, they provide a signature to check if the request really came from them. to build the request there's a few steps:
start with the exact url of your webhook (mind slashes and params)
sort the post variables by key (in case of mandrill, you'll only have one post parameter: mandrill_events)
add key and value to the url, without any delimiter
hmac the url with your secret key (you can get the key from the web-interface) and base64 it.
compare the result with the X-Mandrill-Signature header
here's a sample implementation in python:
import hmac, hashlib
def check_mailchimp_signature(params, url, key):
signature = hmac.new(key, url, hashlib.sha1)
for key in sorted(params):
signature.update(key)
signature.update(params[key])
return signature.digest().encode("base64").rstrip("\n")
205.201.136.0/16
I have just whitelisted them in my server's firewall.
We don't need to white list the Ip they are using. Instead of that they have provided their own way to authenticate the webhook request.
When you are creating the mandrill webhook it will generate the key. It will come under the response we are getting to our post URL which is provided in the webhook.
public async Task<IHttpActionResult> MandrillEmailWebhookResponse()
{
string mandrillEvents = HttpContext.Current.Request.Form["mandrill_events"].Replace("mandrill_events=", "");
// validate the request is coming from mandrill API
string url = ConfigurationManager.AppSettings["mandrillWebhookUrl"];
string MandrillKey = ConfigurationManager.AppSettings["mandrillWebHookKey"];
url += "mandrill_events";
url += mandrillEvents;
byte[] byteKey = System.Text.Encoding.ASCII.GetBytes(MandrillKey);
byte[] byteValue = System.Text.Encoding.ASCII.GetBytes(url);
HMACSHA1 myhmacsha1 = new HMACSHA1(byteKey);
byte[] hashValue = myhmacsha1.ComputeHash(byteValue);
string generatedSignature = Convert.ToBase64String(hashValue);
string mandrillSignature = HttpContext.Current.Request.Headers["X-Mandrill-Signature"].ToString();
if (generatedSignature == mandrillSignature)
{
// validation = "Validation successful";
// do the updating using the response data
}
}