So problem is I am using inline keyboard in my bot. And when I am trying to push this keyboard it gives me 3-5 callbacks. I don't know where is my mistake.
EDIT
I don't know why but it causes this error when i working with mysqli->fetch_assoc();
There is not full code just peace where I use inline keyboard
if ($callback_data!=Null){
checkJSON(3124,$order_id);
$message_id = $update['callback_query']['message']['message_id'];
$callback_data = json_decode($callback_data,true);
checkJSON(3125,$callback_data["order_id"]);
$order_id = $callback_data["order_id"];
checkJSON(3126,$order_id);
$rs = $mysqli->query("SELECT manager_id FROM orders WHERE id=".$order_id);
$row = $rs->fetch_assoc();
$manager = $row['manager_id'];
if ($manager!=Null){
$rs = $mysqli->query("SELECT telegram_id FROM managers WHERE id=".$manager);
$row = $rs->fetch_assoc();
$manager_telegram_id = $row['telegram_id'];
if ($chatID==$manager_telegram_id){
$callback_data = json_decode($callback_data);
$order_id = $callback_data["order_id"];
$status = $callback_data["status"];
checkJSON(1231234,$callback_data);
if($status == '3'){
editMessage($chatID,$message_id,"Заказ N".$order_id." подтвержден");
}
else{
editMessage($chatID,$message_id,"Заказ N".$order_id." отклонен");
}
$mysqli->query("UPDATE orders SET status=".$status." WHERE id=".$order_id);
}
sendMessage($chatID,$update['callback_query']['message']['message_id']);
editMessage($chatID,$message_id,
"Данный заказ уже в оброботке");
}
else{
$get_manager_query = $mysqli->query("SELECT id FROM managers WHERE telegram_id=".$chatID);
$row = $get_manager_query->fetch_assoc();
$manager = $row['id'];
$data1 = json_encode(array("order_id"=>$order_id,"status"=>3));
$data2 = json_encode(array("order_id"=>$order_id,"status"=>4));
$inline_button1 = array("text"=>"Принять","callback_data"=>$data1);
$inline_button2 = array("text"=>"Отказать","callback_data"=>$data2);
$inline_keyboard = [[$inline_button1,$inline_button2]];
$keyboard=json_encode(array("inline_keyboard"=>$inline_keyboard));
editMessage($chatID,$message_id,
"Вы приняли данный заказ",$keyboard);
$rs = $mysqli->query("UPDATE orders SET status=1, manager_id=".$manager." WHERE id=".$order_id);
}
}
function sendMessage($chatID,$text){
$sendto =API_URL."sendmessage?chat_id=".$chatID."&text=".urlencode($text);
file_get_contents($sendto);
}
function editMessage($chatId, $messageId, $message,$replyMarkup=Null) {
$url = API_URL."editMessageText?chat_id=".$chatId."&message_id=".$messageId.
"&text=".urlencode($message)."&reply_markup=".$replyMarkup;
file_get_contents($url);
}
It's Not your mistake!
Telegram Server is send callbacks for every changes in inline query.
You can setting that to off in BotFatherwith /setinlinefeedback command.
For more information visit this
Set your data by some separator After, get that data by $update['callback_query']['data'] and split by seted separator.
$botToken = "(your token)";
$website = "https://(site_url)/bot" . $botToken;
$order_id = '44423'; //my additional data
$keyboard = ["inline_keyboard" => [
[
[
"text" => "Доставлено",
"callback_data" => "delivered_".$order_id, // set few data by '_' separator Like ("delivered_443423_phone12345667_...)
],
[
"text" => "Затримуюсь",
"callback_data" => "delaying_".$order_id,
]
],
]
];
$params = [
'chat_id' => $chat_id,
'text' => $msg,
'parse_mode' => 'html',
'reply_markup' => json_encode($keyboard),
];
$ch = curl_init($website . '/sendMessage');
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec($ch);
Update processing. For get update you need set webhook on file where bot is placed. https://api.telegram.org/bot(your token)/setWebhook?url=https://example.com/bot_directory/bot.php Site must have SSL (https).
$update = json_decode(file_get_contents('php://input'), TRUE);
$botToken = "(your token)";
$botAPI = "https://api.telegram.org/bot" . $botToken;
$msg = $update['message']['text'];
$user_id = $update['message']['from']['id'];
if (isset($update['callback_query'])) {
$update_multiple = explode('_', $update['callback_query']['data']); //split data
if ($update_multiple[0] == 'delivered') {
$data1 = $update_multiple[1]; // get some data
// ......
}
}
Related
My website's framework is in CodeIgniter. I have integrated instamojo payment gateway in it. The query inserting the payment id but after successful payment not updating the column value of status to 1 from 0,
This is the block code of paymentcontroller.php
public static function userDataUpdate($trx)
{
$general = getGeneral();
$data = Deposit::where('trx', $trx)->first();
if ($data->status == 0) {
$data->status = 1;
$data->save();
$user = User::find($data->user_id);
$wallet = $user->wallet;
$wallet->balance += $data->amount;
$wallet->save();
$transaction = new Transaction();
$transaction->user_id = $data->user_id;
$transaction->amount = $data->amount;
$transaction->post_balance = $wallet->balance;
$transaction->charge = $data->charge;
$transaction->trx_type = '+';
$transaction->details = 'Deposited via ' . $data->gatewayCurrency()->name;
$transaction->trx = $data->trx;
$transaction->save();
$adminNotification = new AdminNotification();
$adminNotification->user_id = $user->id;
$adminNotification->title = 'Deposit succeeded via '.$data->gatewayCurrency()->name;
$adminNotification->click_url = urlPath('admin.deposit.successful');
$adminNotification->save();
notify($user, 'DEPOSIT_COMPLETE', [
'method_name' => $data->gatewayCurrency()->name,
'method_currency' => $data->method_currency,
'method_amount' => showAmount($data->final_amo),
'amount' => showAmount($data->amount),
'charge' => showAmount($data->charge),
'currency' => $general->cur_text,
'rate' => showAmount($data->rate),
'trx' => $data->trx,
'post_balance' => showAmount($wallet->balance)
]);
}
}
This is the code of processcontroller.php
<?php
namespace App\Http\Controllers\Gateway\Instamojo;
use App\Models\Deposit;
use App\Http\Controllers\Gateway\PaymentController;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class ProcessController extends Controller
{
/*
* Instamojo Gateway
*/
public static function process($deposit)
{
$basic = getGeneral();
$instaMojoAcc = json_decode($deposit->gatewayCurrency()->gateway_parameter);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://test.instamojo.com/api/1.1/payment-requests/');
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
"X-Api-Key:$instaMojoAcc->api_key",
"X-Auth-Token:$instaMojoAcc->auth_token"
)
);
$payload = array(
'purpose' => 'Payment to ' . $basic->sitename,
'amount' => round($deposit->final_amo,2),
'buyer_name' => $deposit->user->username,
'redirect_url' => route('user.deposit.history'),
'webhook' => route('ipn.'.$deposit->gateway->alias),
'email' => $deposit->user->email,
'btc_wallet' => $deposit->trx,
'send_email' => true,
'allow_repeated_payments' => false
);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
$response = curl_exec($ch);
curl_close($ch);
$res = json_decode($response);
if (#$res->success) {
if(!#$res->payment_request->id){
$send['error'] = true;
$send['message'] = "Response not given from API. Please re-check the API credentials.";
}else{
$deposit->btc_wallet = $res->payment_request->id;
$deposit->save();
$send['redirect'] = true;
$send['redirect_url'] = $res->payment_request->longurl;
$send['btc_wallet'] = $deposit->trx;
}
} else {
$send['error'] = true;
$send['message'] = "Credentials mismatch. Please contact with admin";
}
return json_encode($send);
}
public function ipn(Request $request)
{
//$this->customLog($request->all(),'Instamojo',true);
$deposit = Deposit::where('btc_wallet', $_POST['payment_request_id'])->orderBy('id', 'DESC')->first();
$instaMojoAcc = json_decode($deposit->gatewayCurrency()->gateway_parameter);
$deposit->detail = $request->all();
$deposit->save();
$imData = $_POST;
$macSent = $imData['mac'];
unset($imData['mac']);
ksort($imData, SORT_STRING | SORT_FLAG_CASE);
$mac = hash_hmac("sha1", implode("|", $imData), $instaMojoAcc->salt);
if ($macSent == $mac && $imData['status'] == "Credit" && $deposit->status == '0') {
PaymentController::userDataUpdate($deposit->trx);
}
}
}
I am unable to find out why the query is not updating the status of the transaction in mysqli.
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 am using usaEpay for my mobile app. I was using my friend's server and there was no problem.
Then I rented a server for my own. switched the backend to the new server. I am using the exact same code. I implemented rapid SSL to my site. But I cannot make a payment.
This is the error;
Error reading from card processing gateway.
Unsupported SSL protocol version
My php api is the same as this; https://github.com/usaepay/usaepay-php/blob/master/usaepay.php
this is my payOrder.php class
require('connector.php');
include ('phpseclib/Crypt/RSA.php');
include ('usaepay/usaepay.php');
$request = json_decode($HTTP_RAW_POST_DATA, true);
$token = $request['token'];
$orderid = $request['orderid'];
$ccInfo = base64_decode($request['ccinfo']);
$address = $request['address'];
if(strlen($out_plain) >= 25) {
$query = "SELECT * FROM xxxx_order WHERE order_id = $orderid";
$result = mysql_query($query);
$order = mysql_fetch_assoc($result);
$total = $order['order_total'];
$creditcard = explode("||", $out_plain);
$ccnumber = $creditcard[0];
$cvvnumber = $creditcard[1];
$cctype = $creditcard[2];
$ccmonth = $creditcard[3];
$ccyear = $creditcard[4];
$ccdate = $ccmonth.$ccyear;
$ccname = $creditcard[5];
$address = explode("||", $address);
$street = $address[0];
$city = $address[1];
$state = $address[2];
$zip = $address[3];
$name = $address[4];
$umcommand = "cc:sale" ;
$umkey = "mykey" ;
$pin = "mypin";
$tran=new umTransaction;
$tran->key = "mytrkey";
$tran->pin = "mypin";
$tran->usesandbox = false;
$tran->testmode = 0;
$tran->command = "cc:sale";
$tran->card = $ccnumber;
$tran->exp = $ccdate;
$tran->amount = $total;
$tran->invoice = $orderid;
$tran->cardholder = $ccname;
$tran->street = $street;
$tran->zip = $zip;
$tran->description = "App sale";
$tran->cvv2 = $cvvnumber;
flush();
if($tran->Process()) {
$auth = $tran->authcode;
$refnum = $tran->refnum;
$response = "$auth---$refnum";
$query = "UPDATE `mydb` SET `order_status`= 2, UMresponse =
$check = false;
$count = 0;
do {
$check = mysql_query($query);
$count++;
} while ($check == false && $count < 50);
array_push($arr, array("status" => "success", "request" => "check", "order_status" => "success"));
} else {
$tranresult = $tran->result;
$tranerror = $tran->error;
$trancurl = "";
if(#$tran->curlerror) $trancurl = $tran->curlerror;
$response = "$tranresult---$tranerror---$trancurl";
$query = "UPDATE `mydb` SET `order_status`= 4, UMresponse = '$response' WHERE order_id = $orderid";
$check = false;
$count = 0;
do {
$check = mysql_query($query);
$count++;
} while ($check == false && $count < 50);
array_push($arr, array("status" => "success", "request" => "check", "order_status" => "declined"));
}
/*
$hashseed = mktime (); // mktime returns the current time in seconds since epoch.
$hashdata = $umcommand . ":" . $pin . ":" . $total . ":" . $orderid . ":" . $hashseed ;
$hash = md5 ( $hashdata );
$umhash = "m/$hashseed/$hash/y";
$fields = array(`enter code here`
"UMkey" => urlencode($umkey),
"UMredir" => urlencode("myurl"),
"UMinvoice" => urlencode($orderid),
"UMamount" => urlencode($total),
"UMname" => urlencode($ccname),
"UMstreet" => urlencode($street),
"city" => urlencode($city),
"City" => urlencode($city),
"state" => urlencode($state),
"State" => urlencode($state),
"UMzip" => urlencode($zip),
"cardtype" => urlencode($cctype),
"UMcard" => urlencode($ccnumber),
"UMexpir" => urlencode($ccdate),
"UMcommand" => urlencode("cc:sale"),
"UMhash" => $umhash,
"UMechofields" => "yes",
"OrderRef" => $orderid
);
$fields_string = "";
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string, '&');
$url = "https://www.usaepay.com/gate.php";
// $fields = "UMkey=".urlencode($umkey)."&UMredir=".urlencode("myurl**strong text**")."&UMinvoice=$orderid&UMamount=".urlencode($total)."&UMname=".urlencode($ccname)."&UMstreet=".urlencode($street)."&city=".urlencode($city)."&state=".urlencode($state)."&UMzip=".urlencode($zip)."&cardtype=".urlencode($cctype)."&UMcard=".urlencode($ccnumber)."&UMexpir=".urlencode($ccdate)."&UMcommand=".urlencode("cc:sale");
// array_push($arr, array("url" => $url, "fields" => $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);
//execute post
$result = curl_exec($ch);
if($result == true) {
array_push($arr, array("status" => "success", "request" => "send", "msg" => "Payment request sent"));
}
else {
array_push($arr, array("status" => "error", "request" => "send", "msg" => "Failed to connect to the payment system"));
}
//close connection
curl_close($ch);
*/
} else {
array_push($arr, array("status" => "error", "request" => "send", "msg" => "Decryption failure, please check fields before submission"));
} else {
array_push($arr, array("status" => "error", "request" => "send", "msg" => "User token not verified"));
}
header('Content-Type: application/json');
echo json_encode($arr);
Any help would be overly appreciated. What is my problem ?
I think the error message said it clearly that your communication with payment gateway is rejected or refused due to unsupported SSL version, you should check your server setting and compare with your friend's server. BTW, looking at your PHP code, do you know that mysql extension has been deprecated since PHP v5.5.0 and total removed from PHP 7? I'd suggest that you read PHP The right way about the Database part and the php.net documentation.
I am new to php. The script succeeds if i send manually changing the start and end values each time. But, it fails when trying to send via a while loop and displays this error:
Request Entity Too Large. Error 413
GCMSendMessage:
<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
include("GCMPushMessage.php");
$new_array= array();
$i = 0; // counter
$mysqli = mysqli_connect("localhost", "root", "xxx", "xxx");
while ($i < n) //n is the (total registration id's)/1000
{
$new_array[] = null;
$start = ($i * 1000);
$end = $start + 1000; //GCM Limit of 1000 users per notification
$queryregid = "SELECT gcm_regid FROM `gcm_users` WHERE id >$start AND id <=$end";
$result_select = $mysqli->query($queryregid);
if ($result_select->num_rows > 0) {
// output data of each row
while ($row = $result_select->fetch_assoc()) {
$new_array[] = $row["gcm_regid"]; // Inside while loop
}
} else {
echo "0 results";
}
$apiKey = "xxx";
$param1 = "XXX";
$param2 = "AAA";
$param3 = '0';
$gcpm = new GCMPushMessage($apiKey);
$gcpm->setDevices($new_array);
$response = $gcpm->send($message, array(
'param1' => $param1,
'param2' => $param2,
'param3' => $param3
));
$i = $i + 1; // counter increment
}
print "Response=$response";
?>
GCMPushMessage.php:
<?php
/*
Class to send push notifications using Google Cloud Messaging for Android
Example usage
-----------------------
$an = new GCMPushMessage($apiKey);
$an->setDevices($devices);
$response = $an->send($message);
-----------------------
$apiKey Your GCM api key
$devices An array or string of registered device tokens
$message The mesasge you want to push out
#author Matt Grundy
Adapted from the code available at:
http://stackoverflow.com/questions/11242743/gcm-with-php-google-cloud-messaging
*/
class GCMPushMessage {
var $url = 'https://android.googleapis.com/gcm/send';
var $serverApiKey = "";
var $devices = array();
/*
Constructor
#param $apiKeyIn the server API key
*/
function GCMPushMessage($apiKeyIn){
$this->serverApiKey = $apiKeyIn;
}
/*
Set the devices to send to
#param $deviceIds array of device tokens to send to
*/
function setDevices($deviceIds){
if(is_array($deviceIds)){
$this->devices = $deviceIds;
} else {
$this->devices = array($deviceIds);
}
}
/*
Send the message to the device
#param $message The message to send
#param $data Array of data to accompany the message
*/
function send($message, $data = false){
if(!is_array($this->devices) || count($this->devices) == 0){
$this->error("No devices set");
}
if(strlen($this->serverApiKey) < 8){
$this->error("Server API Key not set");
}
$fields = array(
'registration_ids' => $this->devices,
'data' => array( "message" => $message ),
);
if(is_array($data)){
foreach ($data as $key => $value) {
$fields['data'][$key] = $value;
}
}
$headers = array(
'Authorization: key=' . $this->serverApiKey,
'Content-Type: application/json'
);
// Open connection
$ch = curl_init();
// Set the url, number of POST vars, POST data
curl_setopt( $ch, CURLOPT_URL, $this->url );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $fields ) );
// Avoids problem with https certificate
curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false);
// Execute post
$result = curl_exec($ch);
// Close connection
curl_close($ch);
return $result;
}
function error($msg){
echo "Android send notification failed with error:";
echo "\t" . $msg;
exit(1);
}
}
?>
I have some issues trying to get this working, I've implemented the checkout express (or seems to be) successfully, but also my system needs subscription option, following this example.
Now, my problem is that in Laravel you cannot simply put some random files, so I'm trying to do it in the correct way, sadly, there is no documentation of the classes and methods including on the library.
I've created some functions within controllers (I don't know if this the right way) the problem I'm facing now is trying to createRecurringPayment() to apply the desired amount of the recurring payment, is the final step I guess.
Thanks for yout help.
app/controllers/PaypalController.php
public function prepareExpressCheckout(){
$storage = $this->getPayum()->getStorage('Payum\Core\Model\ArrayObject');
$details = $storage->createModel();
$details['PAYMENTREQUEST_0_CURRENCYCODE'] = 'USD';
$details['PAYMENTREQUEST_0_AMT'] = 1.23;
$storage->updateModel($details);
$captureToken = $this->getTokenFactory()->createCaptureToken('paypal_es', $details, 'payment_done');
$details['RETURNURL'] = $captureToken->getTargetUrl();
$details['CANCELURL'] = $captureToken->getTargetUrl();
$storage->updateModel($details);
return \Redirect::to($captureToken->getTargetUrl());
}
public function prepareSubscribe(){
$storage = $this->getPayum()->getStorage('Payum\Core\Model\ArrayObject');
$details = $storage->createModel();
$details['PAYMENTREQUEST_0_AMT'] = 0;
$details['L_BILLINGTYPE0'] = Api::BILLINGTYPE_RECURRING_PAYMENTS;
$details['L_BILLINGAGREEMENTDESCRIPTION0'] = "Suscripción por X meses";
$details['NOSHIPPING'] = 1;
$storage->updateModel($details);
$captureToken = $this->getTokenFactory()->createCaptureToken('paypal_es', $details, 'payment_done');
$storage->updateModel($details);
return \Redirect::to($captureToken->getTargetUrl());
}
public function createRecurringPayment(){
$payum_token = Input::get('payum_token');
$request = \App::make('request');
$request->attributes->set('payum_token', $payum_token);
$token = ($request);
//$this->invalidate($token);
$agreementStatus = new GetHumanStatus($token);
$payment->execute($agreementStatus);
if (!$agreementStatus->isSuccess()) {
header('HTTP/1.1 400 Bad Request', true, 400);
exit;
}
$agreementDetails = $agreementStatus->getModel();
$storage = $this->getPayum()->getStorage('Payum\Core\Model\ArrayObject');
$recurringPaymentDetails = $storage->createModel();
$recurringPaymentDetails['TOKEN'] = $agreementDetails['TOKEN'];
$recurringPaymentDetails['DESC'] = 'Subscribe to weather forecast for a week. It is 0.05$ per day.';
$recurringPaymentDetails['EMAIL'] = $agreementDetails['EMAIL'];
$recurringPaymentDetails['AMT'] = 0.05;
$recurringPaymentDetails['CURRENCYCODE'] = 'USD';
$recurringPaymentDetails['BILLINGFREQUENCY'] = 7;
$recurringPaymentDetails['PROFILESTARTDATE'] = date(DATE_ATOM);
$recurringPaymentDetails['BILLINGPERIOD'] = Api::BILLINGPERIOD_DAY;
$payment->execute(new CreateRecurringPaymentProfile($recurringPaymentDetails));
$payment->execute(new Sync($recurringPaymentDetails));
$doneToken = $this->createToken('paypal_es', $recurringPaymentDetails, 'payment_done');
return \Redirect::to($doneToken->getTargetUrl());
}
app/routes.php
Route::get('/payment', array('as' => 'payment', 'uses' => 'PaymentController#payment'));
Route::get('/payment/done', array('as' => 'payment_done', 'uses' => 'PaymentController#done'));
Route::get('/payment/paypal/express-checkout/prepare', array('as' => 'paypal_es_prepare', 'uses' => 'PaypalController#prepareExpressCheckout'));
Route::get('/payment/paypal/subscribe/prepare', array('as' => 'paypal_re_prepare', 'uses' => 'PaypalController#prepareSubscribe'));
Route::get('/payment/paypal/subscribe/create', array('as' => 'payment_create', 'uses' => 'PaypalController#createRecurringPayment'));
I have found the problem. It is with the parameters we pass to the create recurring payment function. Here are functions for agreement and payment creation. It should work fine.
<?php
namespace App\Http\Controllers;
use Payum\Core\Request\GetHumanStatus;
use Payum\LaravelPackage\Controller\PayumController;
use Payum\Paypal\ExpressCheckout\Nvp\Api;
use Payum\Core\Request\Sync;
use Payum\Paypal\ExpressCheckout\Nvp\Request\Api\CreateRecurringPaymentProfile;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class PayPalController extends PayumController {
public function prepareSubscribeAgreement() {
$storage = $this->getPayum()->getStorage('Payum\Core\Model\ArrayObject');
$details = $storage->create();
$details['PAYMENTREQUEST_0_AMT'] = 0;
$details['L_BILLINGTYPE0'] = Api::BILLINGTYPE_RECURRING_PAYMENTS;
$details['L_BILLINGAGREEMENTDESCRIPTION0'] = "Weather subscription";
//$details['NOSHIPPING'] = 1;
$storage->update($details);
$captureToken = $this->getPayum()->getTokenFactory()->createCaptureToken('paypal_ec', $details, 'paypal_subscribe');
return \Redirect::to($captureToken->getTargetUrl());
}
public function createSubscribePayment(Request $request) {
$request->attributes->set('payum_token', $request->input('payum_token'));
$token = $this->getPayum()->getHttpRequestVerifier()->verify($request);
$gateway = $this->getPayum()->getGateway($token->getGatewayName());
$agreementStatus = new GetHumanStatus($token);
$gateway->execute($agreementStatus);
if (!$agreementStatus->isCaptured()) {
header('HTTP/1.1 400 Bad Request', true, 400);
exit;
}
$agreement = $agreementStatus->getModel();
$storage = $this->getPayum()->getStorage('Payum\Core\Model\ArrayObject');
$recurringPayment = $storage->create();
$recurringPayment['TOKEN'] = $agreement['TOKEN'];
$recurringPayment['PAYERID'] = $agreement['PAYERID'];
$recurringPayment['PROFILESTARTDATE'] = date(DATE_ATOM);
$recurringPayment['DESC'] = $agreement['L_BILLINGAGREEMENTDESCRIPTION0'];
$recurringPayment['BILLINGPERIOD'] = Api::BILLINGPERIOD_DAY;
$recurringPayment['BILLINGFREQUENCY'] = 7;
$recurringPayment['AMT'] = 0.05;
$recurringPayment['CURRENCYCODE'] = 'USD';
$recurringPayment['COUNTRYCODE'] = 'US';
$recurringPayment['MAXFAILEDPAYMENTS'] = 3;
$gateway->execute(new CreateRecurringPaymentProfile($recurringPayment));
$gateway->execute(new Sync($recurringPayment));
$captureToken = $this->getPayum()->getTokenFactory()->createCaptureToken('paypal_ec', $recurringPayment, 'payment_done');
return \Redirect::to($captureToken->getTargetUrl());
}
public function done(Request $request) {
/** #var Request $request */
//$request = \App::make('request');
$request->attributes->set('payum_token', $request->input('payum_token'));
$token = $this->getPayum()->getHttpRequestVerifier()->verify($request);
$gateway = $this->getPayum()->getGateway($token->getGatewayName());
$gateway->execute($status = new GetHumanStatus($token));
return \Response::json(array(
'status' => $status->getValue(),
'details' => iterator_to_array($status->getFirstModel())
));
}
}
The routes:
Route::get('paypal/agreement', 'PayPalController#prepareSubscribeAgreement');
Route::get('paypal/subscribe', [
'as' => 'paypal_subscribe',
'uses' => 'PayPalController#createSubscribePayment'
]);
Route::get('paydone', [
'as' => 'payment_done',
'uses' => 'PayPalController#done'
]);
Simply open www.example.com/paypal/agreement and it should take you to PayPal
In my project I used the following library and it helped me alot:
https://github.com/amirduran/duranius-paypal-rest-api-php-library
Here are some features:
Easy to install - Just one file
Library is implemented as PHP class
It supports Recurring Payments It supports ExpressCheckout payments
All available PayPal API methods are wrapped in belonging methods
Well documented
Here is my Pay Pal REST API code.
//Request Perms
$cardtype = $request->cardtype;
$account_number = $request->cardnumber;
$expire_date =$request->expire_date;
$cvv = $request->cvv;
$plan_id =$request->plan_id;
$amount = $request->amount;
$userid = $request->user_id;
$payment_type = $request->plan_type;
//Genrate tokens
$ch = curl_init();
$clientId ='Your Client ID';
$clientSecret= 'Your Secret ID';
//you get Clientid and clientSecret
https://developer.paypal.com/developer/applications
curl_setopt($ch, CURLOPT_URL, "https://api.sandbox.paypal.com/v1/oauth2/token");
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, $clientId.":".$clientSecret);
curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=client_credentials");
$result = curl_exec($ch);
if(empty($result))die("Error: No response.");
else
{
$json = json_decode($result);
}
curl_close($ch);
$product_id = '';
//you can create payment plan this link
https://www.sandbox.paypal.com/billing/plans
if ($plan_id == 1) {
$product_id = 'your plan id';
}elseif ($plan_id == 2) {
$product_id = 'your plan id';
}
$ch = curl_init();
$payment_data = '{
"plan_id":"'.$product_id.'",
"start_time":"'.gmdate("Y-m-d\TH:i:s\Z",strtotime("+1 day")).'",
"shipping_amount":{
"currency_code":"USD",
"value":"'.$amount.'"
},
"subscriber":{
"name":{
"given_name":"",
"surname":""
},
"email_address":"'.$users->email.'",
"shipping_address":{
"name":{
"full_name":""
},
"address":{
"address_line_1":"",
"address_line_2":"",
"admin_area_2":"",
"admin_area_1":"",
"postal_code":"",
"country_code":"US"
}
},
"payment_source":{
"card":{
"number":"'.$account_number.'",
"expiry":"'. $expiry_date.'",
"security_code":"'.$cvv.'",
"name":"",
"billing_address":{
"address_line_1":"",
"address_line_2":"",
"admin_area_1":"",
"admin_area_2":"",
"postal_code":"",
"country_code":"US"
}
}
}
}
}';
curl_setopt($ch, CURLOPT_URL, 'https://api.sandbox.paypal.com/v1/billing/subscriptions');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payment_data);
$headers = array();
$headers[] = 'Accept: application/json';
$headers[] = 'Authorization: Bearer '.$json->access_token.'';
$headers[] = 'Paypal-Request-Id: SUBSCRIPTION-'. rand() .'';
$headers[] = 'Prefer: return=representation';
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
$payment_id = json_decode($result);
$data =$headers[2];
$subid = substr($data, strpos($data, ":") + 2);
//save data in database
$payment = new Subscription();
$payment->userid=$userid;
$payment->plan_id=$plan_id;
$payment->price=$amount;
$payment->sub_id=$subid;
$payment->transaction_id=$payment_id->id;
$payment->payment_type='Paypal';
$payment->charge=$paypal_charge;
$payment->plan_type=$plan_type;
$payment->subscription_startdate= $subscription_startdate;
$payment->subscription_enddate= $subscription_enddate;
$payment->subscription_status= 'active';
$payment->save();
return response()->json(['status' => true,'message'=>'Payment has been successfully Done','data'=>$payment]);
It's working fine for me.