Callback URL not receiving JSON data - json

I have a PHP page that receives JSON responses located at https://example.ac.ke/op/api/mypesa/index.php
I have success posting responses using Postman when I post to either
https://example.com/op/api/mypesa/
or
https://example.com/op/api/mypesa/index.php
but not when I post to
https://example.com/op/api/mypesa
I have tried redirecting and adding trailing / in htaccess in vain.
I need to make https://example.com/op/api/mypesa to be my callback URL. When I post the receiving page is called but it seems like the data is not redirected.
NEED HELP REDIRECTING BOTH PAGE AND POST DATA
Since I have success redirecting page but not the data
My .htaccess has the following content
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,QSA]
</IfModule>
Posting using postman
database table receiving the json data from page
Posting using postman to the page
Content of my index file located in mypesa folder
<?php
require 'config.php';
header("Content-Type: application/json");
$response = '{
"ResultCode": 0,
"ResultDesc": "Confirmation Received Successfully"
}';
$mpesaResponse = file_get_contents('php://input');
$logFile = "M_PESAConfirmationResponse.txt";
$jsonMpesaResponse = json_decode($mpesaResponse, true);
$transaction = array(
':TransactionType' => $jsonMpesaResponse['TransactionType'],
':TransID' => $jsonMpesaResponse['TransID'],
':TransTime' => $jsonMpesaResponse['TransTime'],
':TransAmount' => $jsonMpesaResponse['TransAmount'],
':BusinessShortCode' => $jsonMpesaResponse['BusinessShortCode'],
':BillRefNumber' => $jsonMpesaResponse['BillRefNumber'],
':InvoiceNumber' => $jsonMpesaResponse['InvoiceNumber'],
':OrgAccountBalance' => $jsonMpesaResponse['OrgAccountBalance'],
':ThirdPartyTransID' => $jsonMpesaResponse['ThirdPartyTransID'],
':MSISDN' => $jsonMpesaResponse['MSISDN'],
':FirstName' => $jsonMpesaResponse['FirstName'],
':MiddleName' => $jsonMpesaResponse['MiddleName'],
':LastName' => $jsonMpesaResponse['LastName']
);
$log = fopen($logFile, "a");
fwrite($log, $mpesaResponse);
fclose($log);
echo $response;
insert_response($transaction);
?>

Related

How can I prevent direct access to files using the .htaccess file?

I have a problem, I tried to restrict access to files with direct link (etc. www.domen.com/folder/subfolder/file.ext), to can only access to them using HTML code like "< img src ='/folder/subfolder/file.ext' >"...
I create .htaccess file with next lines
# enable mod_rewrite
RewriteEngine On
# RewriteCond = define rule condition
# HTTP_REFERER = check from where the request originated
# ! = exclude
# ^ = start of string
# [NC] = case insensitive search
RewriteCond %{HTTP_REFERER} !^http://domen.com/folder/subfolder [NC]
# \ = match any
# . = any character
# () = pattern, group
# $ = end of string
# [F] = forbidden, 403
# [L] = stop processing further rules
RewriteRule \.(gif|jpg|jpeg|png|mp4|mov|mkv|flv)$ - [F,L]
Permission code of my files is 0644 in folders and subfolders, and permission code of my folders and subfolders is 0755
Problem is next.. When I use this code in .htaccess file I restrict direct access to files but at the same time I cant access them with HTML code..
<Directory platform/courses/*>
Order Allow,Deny
Allow from 1.1.1.1
Deny from All
</Directory>
<Directory>
Order Allow, Deny
Allow from All
</Directory>
I tried something like this (with IP addres taken from my cPanel) but I get this result:
This is a cutdown version of what I use, so may have syntax errors.
The code is laid out to demonstrate the process. It can be made more robust.
The user is shown a url with a filename using download.php.
This can be posted.
Once the page is shown, it saves the filename with an expiry of 1 hour
in the cookie. If it expires, the page has to be refreshed.
When the button is pressed, sendfile.php gets all the information
from the cookie, validates the expiry and filename and sends it.
download.php
This is the landing page that the user can link to.
Show the user a link like /download/document.pdf
Use .htaccess to map it to /download?name=document.pdf
<?php
// Returns the param by name, if not found then get it from the current_url.
// So this works regardless of how the .htaccess redirection has been done.
function Get_Param ($name, $current_url)
{ $par = filter_var ($_GET [$name] ?? '', FILTER_SANITIZE_STRING);
if ($par)
{return $par;}
if ($only)
{return '';}
$pi = pathinfo ($current_url);
$pi = $pi['filename'] ?? '';
if (strpos ($pi, '=') == 0)
{return $pi;}
else
{return '';};
}
//Save Information in session with an expiry of 1hr
function Save_Info ($file)
{ $expiry = time()+3610;
setcookie ('Download',$file, $expiry, '/');
}
//Get the Filename from the param or url
$file = Get_Param ('name', $current_url);
//Save to Session
Save_Info ($file)
// Show page with filename and details
// Show button with link "/sendfile"
?>
sendfile.php
This basically pretends to be the file thats being downloaded and then dies.
<?php
// Sends the file and dies
function Send_File ($file)
{ header ('Content-Description: File Transfer');
header ('Content-Type: application/octet-stream');
header ('Content-Disposition: attachment; filename="'.basename($file).'"');
header ('Expires: 0');
header ('Cache-Control: must-revalidate');
header ('Pragma: public');
header ('Content-Length: ' . filesize($file));
flush ();
if (readfile ($file)) {
//LogIt ($file);
}
die ();
}
//Load Info from session and unset it
function Load_Info ()
{ $file = $_COOKIE ['Download'] ?? '';
unset ($_COOKIE ['Download']);
return $file
}
//Validate FileName
function Is_Valid ($file,$path)
{ if (!$file) {
return 'FileName is Blank';
}
$file = urldecode($file);
if (!preg_match('/^[^.][-a-z0-9_.]+[a-z]$/i', $file)) {
return 'Invalid FileName';
}
if (!file_exists($path.$file)) {
return 'File does not exist';
}
return false;
}
//Your actual path to the file
$path ='';
// Load Info from Session
$file = Load_Info ();
// Die if filename invalid or session expired
$error = Is_Valid ($file,$path);
if (!$error) {
//Show Message and die
}
else
{Send_File ($path.$file);
}
?>

yii2 can not read json file into backend/web folder

I have js file in backend/web/js/my.js
var conf = function() {
return ('../conf.json');
}
But can not read conf.json file. I got 403 error. What is the problem ?
Thanks anyway
you should use
var conf = function() {
return ('../js/conf.json');
}
or build the proper url using urlHelper
<?= 'var url_base = "' . \yii\helpers\Url::base() .'";'; ?>
var conf = function() {
return ( url_base + '/js/conf.json');
}
you need add some row in .htacces file into the root
#if files in the root
RewriteRule conf.php conf.php [L]
#or
RewriteRule conf.json conf.json [L]
#if files in the directory into the root
RewriteRule ^js/(.*)$ js/$1 [L]
#or images directory
RewriteRule ^images/(.*)$ images/$1 [L]

Perl script literally prints http headers instead of understanding them

I couldn't think of better keywords to Google this issue, so I apologize if this is a duplicate.
Here is my logout.pl script that basically erases cookie:
#!/usr/bin/perl -w
use strict;
use warnings;
use CGI;
my $q = new CGI;
print $q->header('text/html');
my $cookie = $q->cookie(
-name => 'CGISESSID',
-value => '',
-expires => '-1d'
);
print $q->header(-cookie=>$cookie);
print $q->redirect('welcome.pl');
exit;
When I run this script in a browser, it prints the following:
Set-Cookie: CGISESSID=; path=/; expires=Mon, 17-Feb-2014 09:05:42 GMT Date: Tue, 18 Feb 2014 09:05:42 GMT Content-Type: text/html; charset=ISO-8859-1 Status: 302 Found Location: welcome.pl
What I want, however, is for the browser to delete the cookie and redirect to welcome.pl.
When you print $q->header, that prints all the headers, including the blank line which signals the end of headers, making anything after it content. You need to only print $q->header once, no more.
There is actually one more problem you might not figure out on your own. The “clear” cookie you’re trying to send to expire the session must be sent with the redirect. The -w switch is not usually what you want, just the use warnings you have too. Also, redirect URLs RFC:MUST be absolute. "welcome.pl" will in most likelihood work but it’s not a good practice and I had relative URIs bite very badly in a modperl app once. So, amended–
#!/usr/bin/env perl
use strict;
use warnings;
use CGI;
use URI;
my $q = CGI->new;
my $cookie = $q->cookie(
-name => 'CGISESSID',
-value => '',
-expires => '-1d'
);
my $welcome = URI->new_abs("welcome.pl", $q->url);
print $q->redirect( -uri => $welcome,
-cookie => $cookie,
-status => 302 );
exit;
You should use $q->header only once in your script and that should be before using anything printable on page

Error response when POSTing JSON with PERL

I wrote a small PERL script to fetch some data from an URL using PERL. Not being an experienced programmer, I used the examples I found here in Stackoverflow. However, I always get the response
{"error":{"code":2,"message":"post parameter request missing"}}
The script looks like this
my $uri = 'URL';
my $json = '{"sourceCountry":"DE","sourceStore":476,"targetCountry":"DE","targetStore":[869],"article":[110101]}';
my $req = HTTP::Request->new( 'POST', $uri );
$req->header( 'Content-Type' => 'application/json' );
$req->content( $json );
my $lwp = LWP::UserAgent->new;
$response = $lwp->request($req);
The complete response is this:
HTTP/1.1 200 OK
Connection: close
Date: Wed, 15 Jan 2014 14:29:06 GMT
Server: Apache
Content-Length: 63
Content-Type: application/json; charset=utf-8
Client-Date: Wed, 15 Jan 2014 14:29:06 GMT
Client-Peer: 10.200.10.74:80
Client-Response-Num: 1
X-Powered-By: PHP/5.3.3
{"error":{"code":2,"message":"post parameter request missing"}}
What did I wrong?
Try:
use HTTP::Request::Common 'POST';
my $lwp = LWP::UserAgent->new;
$lwp->request( POST $uri, 'Content-Type' => 'application/json', 'Content' => $json );
though that should do basically the same thing except also setting Content-Length.
Alternatively, if the error you mention is literally indicating there is supposed to be a POST parameter (aka form data parameter) named request, try:
use HTTP::Request::Common 'POST';
my $lwp = LWP::UserAgent->new;
$lwp->request( POST $uri, [ 'request' => $json ] );
Assuming that it is a JSON RPC 2 service that you are trying to contact, you are missing part of the structure.
my $json = '{
"jsonrpc":"2.0",
"id":1,
"method":"some-method",
"params":{"sourceCountry":"DE","sourceStore":476,"targetCountry":"DE","targetStore":[869],"article":[110101]}
}';
If it is a JSON RPC service you could use JSON::RPC::LWP; which combines LWP::UserAgent and JSON::RPC::Common. It uses Moose so there will be quite a few dependencies to install. ( It uses Moose because JSON::RPC::Common uses Moose. )
use JSON::RPC::LWP;
my $url = ...;
my $rpc = JSON::RPC::LWP->new(
agent => 'Example ',
);
my $response = $rpc->call(
$url, # uri
'some-method', # service
{
sourceCountry => "DE",
sourceStore => 476,
targetCountry => "DE",
targetStore => [869],
article => [110101],
} # JSON container
);
if( my $error = $response->error ){
print 'error: #', $error->code, ' "', $error->message, "\"\n";
}else{
print "success!\n";
use Data::Dumper;
print Dumper( $response->result );
}
Note that you don't give JSON::RPC::LWP a JSON string, you give it a data structure.

Number of times a file (e.g., PDF) was accessed on a server

I have a small website with several PDFs free for download. I use StatCounter to observe the number of page loads. It also shows me the number of my PDF downloads, but it considers only those downloads where a user clicks on the link from my website. But what's with the "external" access to the PDFs (e.g., directly from Google search)? How I can count those? Is there any possibility to use a tool such as StatCounter?
Thanks.
.htaccess (redirect *.pdf requests to download.php):
RewriteEngine On
RewriteRule \.pdf$ /download.php
download.php:
<?php
$url = $_SERVER['REQUEST_URI'];
if (!preg_match('/([a-z0-9_-]+)\.pdf$/', $url, $r) || !file_exists($r[1] . '.pdf')) {
header('HTTP/1.0 404 Not Found');
echo "File not found.";
exit(0);
}
$filename = $r[1] . '.pdf';
// [do you statistics here]
header('Content-type: application/pdf');
header("Content-Disposition: attachment; filename=\"$filename\"");
readfile($filename);
?>
You can use a log analyzer to check how many times a file was accessed. Ask you hosting provider if they provide access to access logs and a log analyzer software.
in php, it would be something like (untested):
$db = mysql_connect(...);
$file = $_GET['file'];
$allowed_files = {...}; // or check in database
if (in_array($file, $allowed_files) && file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
mysql_query('UPDATE files SET count = count + 1 WHERE file="' . $file . '"')
readfile($file);
exit;
} else {
/* issue a 404, or redirect to a not-found page */
}
You would have to create a way to capture the request from the server.
If you are using php, probably the best would be to use mod_rewrite.
If you are using .net, an HttpHandler.
You must handle the request, call statcounter and then send the pdf content to the user.