Can you please help me to integrate paynow zimbabwe gateway with my localhost system.I have tried to follow their documentation https://developers.paynow.co.zw/docs/quickstart.html but I failed. I want the user to be redirected to the paynow page to pay penalties.Also the result or status must be obtained in order to update the system database. Is it possible to link a localhost system to the paynow api or my system have to be live?. Thank you in advance
<?php
include "./includes/tables_header.php";
include "./includes/db.php";
require_once "./paynow/autoloader.php";
use Paynow\Payments\Paynow;
if(isset($_POST['Paynow']))
{
class Payow{
public function paynows($amount)
{
$siteurl="http://localhost/online_offenceTracking_system/payment1.php?";//substitute with your own return url
define('ps_error', 'Error');
define('ps_ok','Ok');
define('ps_created_but_not_paid','created but not paid');
define('ps_cancelled','cancelled');
define('ps_failed','failed');
define('ps_paid','paid');
define('ps_awaiting_delivery','awaiting delivery');
define('ps_delivered','delivered');
define('ps_awaiting_redirect','awaiting redirect');
define('site_url', $siteurl);
$int_key="###########";//get from paynow.co.zw
$int_id=#######;//get from paynow.co.zw, it should be an intenger
$paymentid="testID1234hs";
$url="https://www.paynow.co.zw/interface/initiatetransaction/?";
$reference=sha1(Paynow\Payments\Paynow::$app->user->identity->email);
$amount=6.25;
$returnurl="http://localhost/online_offenceTracking_system/payment1.php?r=credit/index"; //substitute with your own return urls
$resulturl="http://localhost/online_offenceTracking_system/payment1.php?r=credit/index"; //substitute with your own return urls
$authemail="acmwamuka#gmail.com";//This is the buyer's email address
$additionalinfo="Paying for canteen meals.";
$concat=$int_key.$int_id.$paymentid.$url.$reference.$returnurl.$resulturl.$authemail.$additionalinfo;
$concat=$concat.$int_key;
$values = array('resulturl' => $resulturl,
'returnurl' => $returnurl,
'reference' => $reference,
'amount' => $amount,
'id' => $int_id,
'additionalinfo' => $additionalinfo,
'authemail' => $authemail,
'authphone' => "07777777777",
'status' => 'Message'); //just a simple message
$fields_string = $this->CreateMsg($values,$int_key);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); //need fixing
$result = curl_exec($ch);
if($result)
{
$msg = $this->ParseMsg($result);
if ($msg["status"] == ps_error){
header("Location: $checkout_url");
exit;
}
else if ($msg["status"] == "Ok"){
$validateHash = $this->CreateHash($msg, $int_key);
if($validateHash != $msg["hash"]){
$error = "Paynow reply hashes do not match : " . $validateHash . " - " . $msg["hash"];
echo $error;
}
else
{
$theProcessUrl = $msg["browserurl"];
//echo $theProcessUrl;
//header("Location: ".$theProcessUrl);
Paynow\Payments\Paynow::$app->response->redirect($theProcessUrl);
$orders_array = array();
}
}
else {
//unknown status or one you dont want to handle locally
$error = "Invalid status from Paynow, cannot continue.";
}
}
else
{
$error = curl_error($ch);
echo $error;
}
//print_r($result);
//close connection
curl_close($ch);
}
public function ParseMsg($msg) {
$parts = explode("&",$msg);
$result = array();
foreach($parts as $i => $value) {
$bits = explode("=", $value, 2);
$result[$bits[0]] = urldecode($bits[1]);
}
return $result;
}
function CreateMsg($values, $MerchantKey){
$fields = array();
foreach($values as $key=>$value) {
$fields[$key] = urlencode($value);
}
$fields["hash"] = urlencode($this->CreateHash($values, $MerchantKey));
$fields_string = $this->UrlIfy($fields);
return $fields_string;
}
public function UrlIfy($fields) {
$delim = "";
$fields_string = "";
foreach($fields as $key=>$value) {
$fields_string .= $delim . $key . '=' . $value;
$delim = "&";
}
return $fields_string;
}
public function CreateHash($values, $MerchantKey){
$string = "";
foreach($values as $key=>$value) {
if( strtoupper($key) != "HASH" ){
$string .= $value;
}
}
$string .= $MerchantKey;
$hash = hash("sha512", $string);
return strtoupper($hash);
}
}}
?>
You can use a free service like ngrok to expose your localhost environment to the world wide web. Just make sure your returnurl and resulturl are using your ngrok address so that Paynow can callback your application.
Related
I'm trying to implement Paypal's checkout to my Laravel Api (connected to an Ionic app) and it gets stuck when in the app I press the button to checkout and it goes to Paypal (so far so good) in the login screen. I found it weird because it wouldn't let me login with my sandbox account or even my real account, the error is the same: "Some of your info isn't correct. Please try again." By opening developer tools, those are the errors I get (see screenshots). I really couldn't find where I'm making a mistake here. Maybe you can help me. Below are the screenshots and the code that makes takes the checkout to Paypal. Let me know if I should add any extra info here! Thanks a lot!
error 1: ,
investigating one of the console errors:
Route::middleware('auth:api')->post('/paypal', function (Request $request) {
$user = $request->user();
$data = $request->all();
$list_products_id = $data;
$products = [];
$total = 0;
$titles = '';
foreach($list_products_id as $key => $value) {
$product = Product::find($value);
if($product){
$products[$key] = $product;
$total += $product->price;
$titles .= $product->title." ";
}
}
if($total){
$paypal = config('app.paypal', "sandbox");
if($paypal == "sandbox"){
$userProvider = 'In my app I have the sandbox business credentials here';
$pwdProvider = 'In my app I have the sandbox business credentials here';
$signProvider = 'In my app I have the sandbox business credentials here';
$url = 'https://api-3t.sandbox.paypal.com/nvp';
$url2 = 'https://www.sandbox.paypal.com/cgi-bin/webscr?%s';
} else {
$userProvider = '';
$pwdProvider = '';
$signProvider = '';
$url = 'https://api-3t.paypal.com/nvp';
$url2 = 'https://www.paypal.com/cgi-bin/webscr?%s';
}
$data = [];
$data['USER'] = $userProvider;
$data['PWD'] = $pwdProvider;
$data['SIGNATURE'] = $signProvider;
$data['METHOD'] = 'SetExpressCheckout';
$data['VERSION'] = '108';
$data['LOCALECODE'] = 'en_US';
$data['L_PAYMENTREQUEST_0_NAME0'] = "Products Orders";
$data['L_PAYMENTREQUEST_0_DESC0'] = $titles;
$data['PAYMENTREQUEST_0_AMT'] = number_format($total, 2).'';
$data['PAYMENTREQUEST_0_CURRENCYCODE'] = 'EUR';
$data['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Sale';
$data['L_PAYMENTREQUEST_0_QTY0'] = '1'; //number of the same product the user is ordering
$data['L_PAYMENTREQUEST_0_AMT0'] = number_format($total, 2).'';
$data['L_BILLINGAGREEMENTDESCRIPTION0'] = $titles;
$data['CANCELURL'] = url('/');
$data['RETURNURL'] = url('/');
// curl
$data = http_build_query($data);
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($curl);
curl_close($curl);
$nvp = array();
if (preg_match_all('/(?<name>[^\=]+)\=(?<value>[^&]+)&?/', $response, $matches)) {
foreach ($matches['name'] as $offset => $name) {
$nvp[$name] = urldecode($matches['value'][$offset]);
}
}
if(isset($nvp['ACK']) && $nvp['ACK'] == "Success" ){
$query = array(
'cmd' => '_express-checkout',
'token' => $nvp['TOKEN']
);
$redirectURL = sprintf($url2, http_build_query($query));
return ['date'=>$redirectURL];
}else{
return ['status'=>'error purchasing! - 1'];
}
}
echo "total: " . $total;
return ['status'=>'error purchasing! - 2'];
});
so I did a password reset on my sandboxes account and it worked!
I'm new to php oop and I wanted to send the variable value from one function to another in a different page. So, currently I have this one function in one page that I want to send the data to the other function in a different page. Is that even possible perhaps?
Here's the first function in sendData.php
public function main($data) {
$settings = new Settings();
$hash_code = md5('standard' . '10068' . '08f94110d5697a2497511594c31704d0' .'3.00');
$std_post = array(
'apitype'=>'standard', //fix value
'apiid'=>'10068', //your api id from ibill
'apiorderid'=>'OPC0001#00000282', //your order id
'apihashcode'=>$hash_code, //generate hash code as above
'apiamount'=>'3.00', //your customer transaction amount
'apiemail'=>'alif4arsenal97#gmail.com'); //your customer email
$callbackJSON = json_encode($std_post);
$url = 'https://ibill.my/merchant/?ng=callback_api'; //link need to send data
$ch = curl_init($url); // where to post
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $callbackJSON);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$headers = array();
$headers[] = "Cache-Control: no-cache";
$headers[] = "Content-Type: application/json";
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$results = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
//echo $results;
$objJSON = json_decode($results); //decode json result
//should return 'SUCCESS'
$callback_status = $objJSON->{'callback_status'}; //callback Status
$message = $objJSON->{'message'}; //callback Message
//Refer on statuspage.php
$std_status_code = $objJSON->{'std_status_code'}; //payment status code
$std_status = $objJSON->{'std_status'}; //payment status
$std_order_id = $objJSON->{'std_order_id'}; //your order id
$std_purchase_code = $objJSON->{'std_purchase_code'}; //ibill transaction id
$std_amount = $objJSON->{'std_amount'}; //transaction amount
$std_datepaid = $objJSON->{'std_datepaid'}; //transaction date time
//Hash code for security
$std_hash_code = $objJSON->{'std_hash_code'}; //Hash code
$hash_code = md5('08f94110d5697a2497511594c31704d0'.'10068'.$std_order_id.$std_amount); //hash code format
$data = [
'callback_status' => $callback_status,
'message' => $message,
'std_status_code' => $std_status_code,
'std_status' => $std_status,
'std_order_id' => $std_order_id,
'std_purchase_code' => $std_purchase_code,
'std_amount' => $std_amount,
'std_datepaid' => $std_datepaid,
'std_hash_code' => $std_hash_code,
'hash_code' => $hash_code
];
processPayment($data);
}
Here's the second function in a different that I wanted the data in the first page to be send to which is test.php
public function processPayment($data)
{
if (!isset($data['std_status_code'])) return false;
if (!isset($data['std_hash_code'])) return false;
$settings = new Settings();
$sale_id = (int) substr($data['std_order_id'], 8);
$sale = Sales::get($sale_id);
if (empty($sale)) return false;
if ($sale['status'] == 1) return $sale;
if ($sale['payment_method'] !== 'ibill' || $sale['status'] != 0) return false;
$sale_uid = $sale['uid'];
$sale_method = $sale['method'];
$paid_amount = bcadd($sale['total_amount'], $sale['handling_charge'], 2);
// Verify the data integrity sent by iBill
$hash = md5($settings->ibill_secret_key . $settings->ibill_merchant_id . $data['std_order_id'] . $data['std_amount']);
$payment_processor_status = -1;
$sale_status = 0;
// Check provided hash and status
if ($hash === $data['std_hash_code'] && $data['std_status_code'] == 00) {
$payment_processor_status = 1;
$sale_status = 1;
}
if ($sale_status === 0) {
if ($data['std_status_code'] != 00) {
$data['std_status'] = '<span style="color: red">' . $data['std_status'] . '</span>';
}
if ($data['std_hash_code'] !== $hash) {
$data['std_hash_code'] = '<span style="color: red">' . $data['std_hash_code'] . '</span>';
}
}
// Prepare updated sale data
$now = new DateTime();
$sale = [
'payment_processor_status' => $payment_processor_status,
'payment_processor_data' => $data,
'payment_time' => $now->format('g:i:s A'),
'payment_date' => $now->format('d-m-Y')
];
Sales::update($sale_id, $sale);
if ($sale_status === 1) {
Sales::confirmSale($sale_id, false);
}
return ['uid' => $sale_uid, 'method' => $sale_method];
}
Those functions are class methods, not only functions.
you can use them (or pass data from one to another) by creating instances of their classes. for example something like this:
class one {
public function f1($data) {
// do something
$instance = new two();
$instance->f2($data);
}
}
class two {
public function f2($data) {
// do something else
}
}
I hope it would work for you.
I am up and running my E-Commerce website on a server. I use Paypal IPN notifications to send customers with notifications about payments made by them.
I am currently using Paypal sandbox for testing.
I proceed to checkout => paypal developer account => make payment => i receive message in my paypal account as ipn request is sent but i don't get the values of ipn request in my orders table in the database.
What could be the reason for this ?
I have set my IPN details as in the screenshot below.
and
I also have the screenshot of IPN history of my Paypal developer account.
Can anyone please help me and tell me the reason why the values in my database are not updated ?
Following is my code:
classes/Paypal.php
<?php
class PayPal {
private $_environment = 'sandbox';
private $_url_production = 'https://www.paypal.com/cgi-bin/webscr';
private $_url_sandbox = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
private $_url;
private $_cmd;
private $_products = array();
private $_fields = array();
private $_business = 'xxx-xxx#gmail.com';
private $_page_style = 'null';
private $_return;
private $_cancel_payment;
private $_notify_url;
private $_currency_code = 'GBP';
public $_tax_cart = 0;
public $_tax = 0;
public $_populate = array();
private $_ipn_data = array();
private $_log_file = null;
private $_ipn_result;
public function __construct($cmd = '_cart') {
$this->_url = $this->_environment == 'sandbox' ?
$this->_url_sandbox :
$this->_url_production;
$this->_cmd = $cmd;
$this->_return = SITE_URL."/?page=return";
$this->_cancel_payment = SITE_URL."/?page=cancel";
$this->_notify_url = SITE_URL."/?page=ipn";
$this->_log_file = ROOT_PATH.DS."log".DS."ipn.log";
}
public function addProduct($number, $name, $price = 0, $qty = 1) {
switch($this->_cmd) {
case '_cart':
$id = count($this->_products) + 1;
$this->_products[$id]['item_number_'.$id] = $number;
$this->_products[$id]['item_name_'.$id] = $name;
$this->_products[$id]['amount_'.$id] = $price;
$this->_products[$id]['quantity_'.$id] = $qty;
break;
case '_xclick':
if (empty($this->_products)) {
$this->_products[0]['item_number'] = $number;
$this->_products[0]['item_name'] = $name;
$this->_products[0]['amount'] = $price;
$this->_products[0]['quantity'] = $qty;
}
break;
}
}
private function addField($name = null, $value = null) {
if (!empty($name) && !empty($value)) {
$field = '<input type="hidden" name="'.$name.'" ';
$field .= 'value="'.$value.'" />';
$this->_fields[] = $field;
}
}
private function standardFields() {
$this->addField('cmd', $this->_cmd);
$this->addField('business', $this->_business);
if ($this->_page_style != null) {
$this->addField('page_style', $this->_page_style);
}
$this->addField('return', $this->_return);
$this->addField('notify_url', $this->_notify_url);
$this->addField('cancel_payment', $this->_cancel_payment);
$this->addField('currency_code', $this->_currency_code);
$this->addField('rm', 2);
switch($this->_cmd) {
case '_cart':
if ($this->_tax_cart != 0) {
$this->addField('tax_cart', $this->_tax_cart);
}
$this->addField('upload', 1);
break;
case '_xclick':
if ($this->_tax != 0) {
$this->addField('tax', $this->_tax);
}
break;
}
}
private function prePopulate() {
if (!empty($this->_populate)) {
foreach($this->_populate as $key => $value) {
$this->addField($key, $value);
}
}
}
private function processFields() {
$this->standardFields();
if (!empty($this->_products)) {
foreach($this->_products as $product) {
foreach($product as $key => $value) {
$this->addField($key, $value);
}
}
}
$this->prePopulate();
}
private function getFields() {
$this->processFields();
if (!empty($this->_fields)) {
return implode("", $this->_fields);
}
}
private function render() {
$out = '<form action="'.$this->_url.'" method="post" id="frm_paypal">';
$out .= $this->getFields();
$out .= '<input type="submit" value="Submit" />';
$out .= '</form>';
return $out;
}
public function run($transaction_id = null) {
if (!empty($transaction_id)) {
$this->addField('custom', $transaction_id);
}
return $this->render();
}
private function validateIpn() {
$hostname = gethostbyaddr($_SERVER['REMOTE_ADDR']);
if (!preg_match('/paypal\.com$/', $hostname)) {
return false;
}
$objForm = new Form();
$this->_ipn_data = $objForm->getPostArray();
if (
!empty($this->_ipn_data) &&
array_key_exists('receiver_email', $this->_ipn_data) &&
strtolower($this->_ipn_data['receiver_email']) !=
strtolower($this->_business)
) {
return false;
}
return true;
}
private function getReturnParams() {
$out = array('cmd=_notify-validate');
if (!empty($this->_ipn_data)) {
foreach($this->_ipn_data as $key => $value) {
$value = function_exists('get_magic_quotes_gpc') ?
urlencode(stripslashes($value)) :
urlencode($value);
$out[] = "{$key}={$value}";
}
}
return implode("&", $out);
}
private function sendCurl() {
$response = $this->getReturnParams();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $response);
curl_setopt($ch, T_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Content-Type: application/x-www-form-urlencoded",
"Content-Length: " . strlen($response)
));
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$this->_ipn_result = curl_exec($ch);
curl_close($ch);
}
public function ipn() {
if ($this->validateIpn()) {
$this->sendCurl();
if (strcmp($this->_ipn_result, "VERIFIED") == 0) {
$objOrder = new Order();
if (!empty($this->_ipn_data)) {
$objOrder->approve(
$this->_ipn_data,
$this->_ipn_result
);
}
}
}
}
}
mod/paypal.php
<?php
require_once('../inc/autoload.php');
$token2 = Session::getSession('token2');
$objForm = new Form();
$token1 = $objForm->getPost('token');
if ($token2 == Login::string2hash($token1)) {
// create order
$objOrder = new Order();
if ($objOrder->createOrder()) {
// populate order details
$order = $objOrder->getOrder();
$items = $objOrder->getOrderItems();
if (!empty($order) && !empty($items)) {
$objBasket = new Basket();
$objCatalogue = new Catalogue();
$objPayPal = new PayPal();
foreach($items as $item) {
$product = $objCatalogue->getProduct($item['product']);
$objPayPal->addProduct(
$item['product'],
$product['name'],
$item['price'],
$item['qty']
);
}
$objPayPal->_tax_cart = $objBasket->_vat;
// populate client's details
$objUser = new User();
$user = $objUser->getUser($order['client']);
if (!empty($user)) {
$objCountry = new Country();
$country = $objCountry->getCountry($user['country']);
$objPayPal->_populate = array(
'address1' => $user['address_1'],
'address2' => $user['address_2'],
'city' => $user['town'],
'state' => $user['county'],
'zip' => $user['post_code'],
'country' => $country['code'],
'email' => $user['email'],
'first_name' => $user['first_name'],
'last_name' => $user['last_name']
);
// redirect client to PayPal
echo $objPayPal->run($order['id']);
}
}
}
}
IPN settings
IPN Details
Please help me with this .
IPN is not related to your return URL. If you're adding your code that you expect to run when IPNs are triggered to your return URL you will not get the expected result.
To get data to your return URL you would need to use PDT which is very similar to IPN but is intended to be sent to the return URL. IPN goes to your notify URL, which should not match your return URL.
how to log on localhost mark must be changed at the server login below to log in the server , and ENVIRONMENT == "development " is not called server and ENVIRONMENT == " test " called Server , without change of ENVIRONMENT == " test "?
if($email == NULL || $pass == NULL) return array("success"=>0,"msg"=>"Email dan password harus diisi");
else
{
if (ENVIRONMENT == "development")
{
$data['result'] =Array
(
'message' => 'Success',
'code' => 00,
'obj' => Array ('loginTried' => 0,
'email' => 'maheswara#gmail.com',
'phoneNumber' => 089615378878,
'name' => 'Dika',
'point' => 10, ));
return array("success"=>1,"msg"=>"Logged in");
}
else
{
$pass = md5($pass);
$url = "http://tooz.co.";
$post = json_encode(array('email' => $email, 'userPassword' => $pass));
$fields_string = "";
$fields = array(
'logintikiid' => $post
);
//url-ify the data for the POST
foreach($fields as $key=>$value)
{
$fields_string .= $key.'='.$value.'&';
}
rtrim($fields_string, '&');
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT, 30);
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);
$data = json_decode($result,TRUE);
if($data['code']=="00")
{
$this->CI->session->user_email = $data['obj']['email'];
$this->CI->session->user_phone = $data['obj']['phoneNumber'];
$this->CI->session->user_name = $data['obj']['name'];
$this->CI->session->tooz_point = $data['obj']['point'];
return array("success"=>1,"msg"=>"Logged in");
}
else
{
return array("success"=>0,"msg"=>"Email dan password salah");
}
}
}
}
this is controler
public function index($from=NULL)
{
$data = array();
switch ($from) {
case 'pickup':
$redirect = base_url("pickup");
set_top_msg("Untuk mengakses fitur pickup, silahkan login terlebih dahulu");
break;
case 'book':
$redirect = base_url("book");
set_top_msg("Untuk mengakses fitur booking, silahkan login terlebih dahulu");
break;
default:
$redirect = base_url();
break;
}
if ($this->session->user_email)
{
header("location:". base_url("tooz"));
die();
}
else if($this->input->post())
{
$this->load->library("login_library");
$email = $this->input->post("email");
$pass = $this->input->post("pass");
$return = $this->login_library->login($email,$pass);
if($return['success']==1)header('Location:'. $redirect);
else set_top_msg($return["msg"],"warning");
}
load_page($data);
}
Dear Stackoverflow users,
I am running into a problem. It is as follows:
Currently i am programming a management tool for pfsense, which needs to send a multipart form that the server needs to validate and process. It should enable the voucher based acces control on the interface. However, i am getting the error that my headers are already sent. I did not sent them.
my code is as follows:
protected function doCurl($resourceID=null, $post=null)
{
//volledige url
$url = Yii::app()->params->pfsense['host'].$resourceID;
$ch = curl_init();
if($post != null)
{
$post_string = "";
foreach($post as $key=>$value)
{
if($key != 'enctype')
{
$post_string .= $key.'='.$value.'&';
}
else
{
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: multipart/form-data'
));
}
}
rtrim($post_string, '&');
//var_dump($post);
/**/
curl_setopt($ch,CURLOPT_POST, count($post));
curl_setopt($ch,CURLOPT_POSTFIELDS, $post_string);
//var_dump($post_string);
}
else
{
curl_setopt($ch, CURLOPT_HEADER, true);
}
curl_setopt($ch, CURLOPT_URL, $url);
//omdat het certificaat niet klopt zetten we de verificatie uit.
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
//we setten de useragent en de timeout. Useragent omdat sommige websites iets anders voorschotelen per browser.
//timeout voor als er iets gebeurd wat niet moet
curl_setopt($ch,CURLOPT_USERAGENT,Yii::app()->params->pfsense['useragent']);
curl_setopt($ch,CURLOPT_COOKIEJAR, Yii::app()->params->pfsense['cookiepath']);
curl_setopt($ch,CURLOPT_COOKIEFILE, Yii::app()->params->pfsense['cookiepath']);
curl_setopt($ch, CURLOPT_AUTOREFERER, true );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
$result = array( 'header' => '',
'body' => '',
'http_code' => '',
'last_url' => '');
$header_size = curl_getinfo($ch,CURLINFO_HEADER_SIZE);
$result['header'] = substr($response, 0, $header_size);
$result['body'] = substr( $response, $header_size );
$result['http_code'] = curl_getinfo($ch,CURLINFO_HTTP_CODE);
$result['last_url'] = curl_getinfo($ch,CURLINFO_EFFECTIVE_URL);
//curl_close($ch);
return $result;
}
public function curl($resourceID=null, $post=null)
{
$result = $this->doCurl($resourceID, $post);
if(strpos($result['body'], 'Login') == false && $result['http_code'] != 403)
{
//echo $result['body'];
return $result;
}
else
{
$loginpost = array(
'__csrf_magic' => substr($result['body'], strpos($result['body'],'sid:') , 55),
'login' => urlencode('Login'),
'usernamefld' => urlencode(Yii::app()->params->pfsense['pfuser']),
'passwordfld' => urlencode(Yii::app()->params->pfsense['pfpass'])
);
$result = $this->doCurl('',$loginpost);
$result = $this->doCurl($resourceID, $post);
return $result;
}
}
This is the code that allows a curl request to be sent to the server. If the page that is returned is the login page, the login info needs to be sent and the original post request needs to be sent again.
the code that follows is the code to insert a zone:
public function insertZone($post)
{
$description = $post['description'];
$interface = $post['interfaces'];
$name = $post['name'];
$post=null;
$post['zone'] = $name;
$post['descr'] = $description;
$post['Submit'] = 'Continue';
$result = $this->curl(Yii::app()->params->pfsense['pfpathtoinsertzone']);
$post['__csrf_magic'] = substr($result['body'], strpos($result['body'],'sid:') , 55);
var_dump($post);
$result = $this->curl(Yii::app()->params->pfsense['pfpathtoinsertzone'], $post);
var_dump($result['body']);
//exit;
if(strpos($result['body'], 'The following input errors were detected') == false)
{
$post = null;
$post['enable'] = 'yes';
$post['interfaces'] = $interface;
$post['Submit'] = 'Save';
$post['name'] = $name;
$result = $this->editZone($post);
if($result != false)
{
$post = null;
$post['zone'] = $name;
$post['enable'] = 'yes';
$post['Submit'] = 'Save';
$result = $this->curl(Yii::app()->params->pfsense['pfpathtovoucherroll'].$name);
$post['__csrf_magic'] = substr($result['body'], strpos($result['body'],'sid:') , 55);
$doc = new DOMDocument();
$doc->loadHTML($result['body']);
$doc->preserveWhiteSpace = false;
if($childs = $doc->getElementsByTagName("textarea"))
{
foreach($childs as $child)
{
if($child->nodeType == XML_TEXT_NODE)
{
continue;
}
if(strpos(trim($child->nodeValue),'BEGIN RSA PRIVATE KEY'))
{
$post['privatekey'] = trim($child->nodeValue);
}
elseif(strpos(trim($child->nodeValue),'BEGIN PUBLIC KEY'))
{
$post['publickey'] = trim($child->nodeValue);
}
}
}
$post['charset'] = $doc->getElementById('charset')->attributes->getNamedItem('value')->nodeValue;
$post['rollbits'] = $doc->getElementById('rollbits')->attributes->getNamedItem('value')->nodeValue;
$post['ticketbits'] = $doc->getElementById('ticketbits')->attributes->getNamedItem('value')->nodeValue;
$post['checksumbits'] = $doc->getElementById('checksumbits')->attributes->getNamedItem('value')->nodeValue;
$post['magic'] = $doc->getElementById('magic')->attributes->getNamedItem('value')->nodeValue;
$result = $this->curl(Yii::app()->params->pfsense['pfpathtovoucherroll'].$name, $post);
if($result['http_code'] >= 100 && $result['http_code'] <= 299)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
public function editZone($post)
{
$zone = $post['name'];
$interfaces = $post['interfaces'];
$post = null;
//$post['localauth_priv'] = 'yes';
//$post['radiussrcip_attribute'] = strtolower($interfaces);
if(is_array($interfaces))
{
$post['cinterface[]'] = array_map('strtolower', $interfaces);
}
else
{
$post['cinterface[]'] = strtolower($interfaces);
}
$post['auth_method'] = 'local';
$post['radiussrcip_attribute'] = 'wan';
$post['radiusvendor'] = 'default';
$post['radmac_format'] = 'default';
$post['enable'] = 'yes';
$post['Submit'] = 'Save';
$post["maxprocperip"] = '';
$post["idletimeout"] = '';
$post["timeout"] = '';
$post["freelogins_count"] = '';
$post["freelogins_resettimeout"] = '';
$post["preauthurl"] = '';
$post["redirurl"] = '';
$post["blockedmacsurl"] = '';
$post["bwdefaultdn"] = '';
$post["bwdefaultup"] = '';
$post["radiusip"] = '';
$post["radiusport"] = '';
$post["radiuskey"] = '';
$post["radiusip2"] = '';
$post["radiusport2"] = '';
$post["radiuskey2"] = '';
$post["radiusip3"] = '';
$post["radiusport3"] = '';
$post["radiuskey3"] = '';
$post["radiusip4"] = '';
$post["radiusport4"] = '';
$post["reauthenticateacct"] = '';
$post["radmac_secret"] = '';
$post["radiusvendor"] = 'default';
$post["radiusnasid"] = '';
$post["radmac_format"] = 'default';
$post["httpsname"] = '';
$post['certref'] = '';
$post['enctype'] = true;
$post['zone'] = $zone;
$post['enable'] = 'yes';
$post['Submit'] = 'Save';
$result = $this->curl(Yii::app()->params->pfsense['pfpathtoupdatezone'].$zone);
//echo $result['last_url'];
$post['__csrf_magic'] = substr($result['body'], strpos($result['body'],'sid:') , 55);
//var_dump($post);
$result = $this->curl(Yii::app()->params->pfsense['pfpathtoupdatezone'].$zone, $post);
ini_set('xdebug.var_display_max_depth', -1);
ini_set('xdebug.var_display_max_children', -1);
ini_set('xdebug.var_display_max_data', -1);
var_dump($result['body']);
exit;
if($result['http_code'] >= 100 && $result['http_code'] <= 299)
{
return true;
}
else
{
//var_dump($result);
///exit;
return $result;
}
}
This code works by first inserting a zone with the name and description and then updating it to set the interface active and enabling the captive portal page to be displayed. However, if i sent the page without the multipart form(it seems to be that this is the issue) then the authentication is not set correctly. It is set, but it does not work. If i then manually change the authentication setting (it is a radio button, if i choose another radio button and then choose my original radio button it suddenly works)
has anyone have a clue about what i am doing wrong? because with the following code i get the result that my headers are already sent:
$result = $this->curl(Yii::app()->params->pfsense['pfpathtoupdatezone'].$zone, $post);
ini_set('xdebug.var_display_max_depth', -1);
ini_set('xdebug.var_display_max_children', -1);
ini_set('xdebug.var_display_max_data', -1);
var_dump($result['body']);
exit;
i would appreciate all the help i can get.
thanks in advance!
What got my request to work:
it turned out that there was no enctype needed in the request. It was however, needed that the update request was sent a 3th time. Do'nt ask me why.
If anything, anything at all, is output, e.g. echo, var_dump, you will get this error.
curl sets the headers to application/x-www-form-urlencoded. If the post data is sent as a string.
If it is sent as an array, it uses a Content-Type: multipart/form-data
If that is not it, add this to see the Request header:
Now I am not sure exactly how you fixed it, but you may have a problem.
It appears your data is in an array and then sent as a sting for some unknown reason.
It should have stayed in the array. This code is off.
The else will be executed for every foreach loop. Probably will not hurt anything it is just a mistake
foreach($post as $key=>$value)
{
if($key != 'enctype')
{
$post_string .= $key.'='.$value.'&';
}
else
{
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data'));
}
}
Should have been:
if($key == 'enctype'){
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data'));
}
else{
foreach($post as $key=>$value){
$post_string .= $key.'='.$value.'&';
}
}
I think you sent the data as a string, or not at all.
This is the big question: if($key != 'enctype') Why? Is this open source?
The above loop would be used only if the post data had to be sent encoded.
And this part:
if($key == 'enctype'){
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data'));
}
Should just be:
if($key == 'enctype'){
$post_string = $post;
}
This way, because the post data is in an array curl will automatically use Content-Type: multipart/form-data
The problem is if it is sent as a string curl will use application/x-www-form-urlencoded, then you have to add this after the loop:
$post_string = urlencode($post_string);
Like this:
else{
foreach($post as $key=>$value){
$post_string .= $key.'='.$value.'&';
}
$post_string = urlencode($post_string);
}