GET url varible in Slim v3.2 PHP Stripe checkout - php

I cannot get a URL varible in my stripe checkout PHP slim app.
I need to be able to get a price varible from the URL to echo out into the session for the price of stripe payment. However it is just not working, I can use $_GET['price']; to echo out before it becomes a SLIM APP however when it becomes a SLIM APP it just wont work...
use Slim\Http\Request;
use Slim\Http\Response;
use Stripe\Stripe;
require 'vendor/autoload.php';
$dotenv = Dotenv\Dotenv::create(realpath('../../'));
$dotenv->load();
Stripe::setApiKey(getenv('STRIPE_SECRET_KEY'));
$db = new SQLite3('./store.db');
$db->exec("CREATE TABLE IF NOT EXISTS sessions(id INTEGER PRIMARY KEY, stripe_id TEXT, status TEXT)");
// createSession
function createSession($sessionId) {
global $db;
$stmt = $db->prepare("INSERT INTO sessions(stripe_id, status) VALUES (:id, 'pending')");
$stmt->bindValue(':id', $sessionId, SQLITE3_TEXT);
return $stmt->execute();
}
// markSessionPaid
function markSessionPaid($sessionId) {
global $db;
$stmt = $db->prepare("UPDATE sessions SET status='paid' WHERE :id = stripe_id");
$stmt->bindValue(':id', $sessionId, SQLITE3_TEXT);
return $stmt->execute();
}
// getSessionStatus
function getSessionStatus($sessionId) {
global $db;
$stmt = $db->prepare("SELECT status FROM sessions WHERE :id = stripe_id");
$stmt->bindValue(':id', $sessionId, SQLITE3_TEXT);
$result = $stmt->execute();
return $result->fetchArray()[0];
}
$app = new Slim\App;
$app->get('/', function (Request $request, Response $response, $args) {
$response->getBody()->write(file_get_contents("../../client/index.html"));
return $response;
});
$app->get('/success', function (Request $request, Response $response, $args) {
$response->getBody()->write(file_get_contents("../../client/success.html"));
return $response;
});
$app->get('/cancel', function (Request $request, Response $response, $args) {
$response->getBody()->write(file_get_contents("../../client/cancel.html"));
return $response;
});
function middleware1() {
$price = $app->request()->get('price');
};
$app->post('/create-session', 'middleware1', function(Request $request, Response $response) use ($app) {
try {
// One time payments
$session = \Stripe\Checkout\Session::create([
'payment_method_types' => ['card'],
'line_items' => [[
'name' => 'Order',
'description' => 'ORDER ID: 123456789A',
'images' => ['testimage'],
'amount' => $price,
'currency' => 'aud',
'quantity' => 1,
]],
'success_url' => 'http://localhost:4242/success?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => 'http://localhost:4242/cancel',
]);
// Subscription recurring payments
// $session = \Stripe\Checkout\Session::create([
// // 'customer' => 'cus_123',
// 'payment_method_types' => ['card'],
// 'subscription_data' => [
// 'items' => [[
// 'plan' => 'starter',
// 'quantity' => 1,
// ]],
// ],
// 'success_url' => 'http://localhost:4242/success?session_id={CHECKOUT_SESSION_ID}',
// 'cancel_url' => 'http://localhost:4242/cancel',
// ]);
createSession($session->id);
} catch (Exception $e) {
return $response->withJson($e->getJsonBody(), 400);
}
return $response->withJson($session);
});
$app->post('/webhook', function(Request $request, Response $response) use ($app) {
// You can find your endpoint's secret in your webhook settings
$endpoint_secret = getenv('STRIPE_WEBHOOK_SECRET');
$payload = $request->getBody();
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;
try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}
// Handle the checkout.session.completed event
if ($event->type == 'checkout.session.completed') {
$session = $event->data->object;
// Fulfill the purchase...
handle_checkout_session($session);
}
return $response->withJson(['message' => 'success']);
});
$app->get('/session-status', function (Request $request, Response $response, array $args) {
$status = getSessionStatus($request->getQueryParam('session_id'));
return $response->withJson($status);
});
function handle_checkout_session($session) {
// Call out to inventory management system
// Ding in Slack
// send an email
markSessionPaid($session->id);
}
$app->run();
I've tried everything
$app->request()->get('price');
And more!
The URL looks like this www.example.com/server/php/?price=5770&orderid=y2INOqCUrEzrua1XwBMg
Any help would be greatly appreciated!

You cannot use $_GET in Slim since it wont work. One way to do it is since the parameters are passed in query I think you mean it like this checkout/?price=200. If so, then you can access it using this:
$queryParams = $app->request()->getQueryParams();
$price = $queryParams["price"];
This would probably work

Related

How to add my function and use it properly in controller?

I have 'sendsms' function which i used it in one of my controllers and worked fine. now what i need to know how i can make class reference of this code to use it in other controllers, instead of copy/paste whole code in all controllers.
In other Q/A they mentioned about only creating reference but i wanted to do it properly like using constructor or etc, not just doing things work, i want to do it like real-world project.
Here's the code in controller :
public function store(Request $request)
{
$this->validate($request,[
'title' => 'required|string|min:6',
'gametype' => 'required|string|min:3',
'description' => 'required|string|min:1|max:180',
'price' => 'required|numeric|min:4',
'buyyer_id' => 'required|numeric|min:1'
// 'seller_id' => 'required|numeric|min:1'
]);
// return RequestModel::create([
// 'title' => $request['title'],
// 'description' => $request['description'],
// 'gametype' => $request['gametype'],
// 'price' => $request['price'],
// 'buyyer_id' => $request['buyyer_id'],
// 'seller_id' => Auth::user()->id,
// ]);
//
$requestModel = new RequestModel;
// store
$requestModel->title = $request['title'];
$requestModel->description = $request['description'];
$requestModel->gametype = $request['gametype'];
$requestModel->price = $request['price'];
$requestModel->buyyer_id = $request['buyyer_id'];
$requestModel->seller_id = Auth::user()->id;
$requestModel->save();
return $this->sendSms($request['title'], $request['gametype']);
}
// I want to use this code in another class to use it in all controllers without copy/paste it.
function sendSms($reqid, $recgametype) {
//Send sms to getway
//implement later.
$otp_prefix = ':';
$response_type = 'json';
$textMSGATLAS = iconv("UTF-8", 'UTF-8//TRANSLIT',"req : ( " .$reqid. " ) for ( " .$recgametype. " ) submitted ");
ini_set("soap.wsdl_cache_enabled", "0");
try {
$client = new SoapClient("http://xxxx");
$user = "user";
$pass = "pass";
$fromNum = "+xxx";
$toNum = "+xxxx";
$messageContent = $textMSGATLAS;
$op = "send";
$client->SendSMS($fromNum,$toNum,$messageContent,$user,$pass,$op);
} catch (SoapFault $ex) {
echo $ex->faultstring;
}
}
I'm right now learning and I'm beginner at this so help to understand how to make it work properly. Thanks.
You can create a separate SMS class like :
<?php
namespace App;
class SMS {
private $reqid;
private $recgametype;
public function __construct($reqid, $recgametype)
{
$this->reqid = $reqid;
$this->recgametype = $recgametype;
}
public function send()
{
$otp_prefix = ':';
$response_type = 'json';
$textMSGATLAS = iconv("UTF-8", 'UTF-8//TRANSLIT',"req : ( " .$this->reqid. " ) for ( " .$this->recgametype. " ) submitted ");
ini_set("soap.wsdl_cache_enabled", "0");
try {
$client = new SoapClient("http://xxxx");
$user = "user";
$pass = "pass";
$fromNum = "+xxx";
$toNum = "+xxxx";
$messageContent = $textMSGATLAS;
$op = "send";
return $client->SendSMS($fromNum,$toNum,$messageContent,$user,$pass,$op);
} catch (SoapFault $ex) {
throw new \Exception('SMS sending failed')
}
}
}
And then inside controller or wherever you would need :
public function sendSms($reqid, $recgametype) {
$sms = new \App\SMS($reqid, $recgametype);
$sms->send();
}
You can also create custom exception like SMSSendingFailedException and throw it instead of standard \Exception inside send() function.
That will help you to send appropriate response in controller like :
public function sendSms($reqid, $recgametype) {
try{
$sms = new \App\SMS($reqid, $recgametype);
$sms->send();
return response()->json('message' => 'SMS sent successfully', 200);
}
catch(SMSSendingFailedException $e){
return response()->json('message' => 'SMS sending failed', 500);
}
}
Then to go one step further, you can use concept of laravel facade if you need it all over the project with a quick class alias.

Getting "Undefined variable: emails" in Laravel 5.4

Why am I getting "Undefined variable: emails" in Laravel 5.4, but the same code is working fine in Laravel 5.2? Below is a code snipped. Don't think this matters but I'm using PHP 7.1.3.
public function send(Request $request) {
$emails = "";
try {
$emails = [$request->input('to'), "john.doe#gmail.com"];
Mail::send('email.contact', ['request' => $request], function($message) use ($request) {
$message->from($request->input('email'), $request->input('email'));
$message->to($emails[0], $emails[0])
->cc($emails[1], $emails[1])
->subject("Contact Us");
});
$response = array (
'success' => true,
'message' => 'Message sent.',
$request
);
}
catch(Exception $e) {
$response = array (
'success' => false,
'message' => $e->getMessage(),
$request
);
}
// return Response::json( $response );
return $response;
}
The issue is here:
use ($request) {
to use $emails inside the anonymous function you have to pass it here like:
use ($request, $emails) {
Now you can use it.
Anonymous function reference
Just simply use the $emails variable in the anonymous function along with $request variable.
Full code to give this it a try.
public function send(Request $request) {
$emails = "";
try {
$emails = [$request->input('to'), "john.doe#gmail.com"];
Mail::send('email.contact', ['request' => $request], function($message) use ($request, $emails) {
# Here add $emails variable in use list.
$message->from($request->input('email'), $request->input('email'));
$message->to($emails[0], $emails[0])
->cc($emails[1], $emails[1])
->subject("Contact Us");
});
$response = array (
'success' => true,
'message' => 'Message sent.',
$request
);
}
catch(Exception $e) {
$response = array (
'success' => false,
'message' => $e->getMessage(),
$request
);
}
// return Response::json( $response );
return $response;
}
Hope this helps.

angular2 with Slim framework jwt authentication

I am trying to create a survice to authenticate user name and password in angular2.
Here is the code for authentication.service.ts
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { Observable } from 'rxjs';
import {Md5} from 'ts-md5/dist/md5';
export interface User {
userName: string;
password: string; }
#Injectable()
export class AuthenticationService {
public token: string;
constructor(private http: Http) {
// set token if saved in local storage
var currentUser = JSON.parse(localStorage.getItem('currentUser'));
this.token = currentUser && currentUser.token;
}
login(user:User): Observable {
return this.http.post('http://localhost/hj1/api/authenticate',
JSON.stringify({ 'user': user.userName, 'password': Md5.hashStr(user.password) }))
.map((response: Response) => {
// login successful if there's a jwt token in the response
console.log(response);
let token = response.json() && response.json().token;
if (token) {
// set token property
this.token = token;
// store username and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify({ user: user, token: token }));
// return true to indicate successful login
return true;
} else {
// return false to indicate failed login
return false;
}
}
);
}
logout() {
localStorage.removeItem("currentUser");
this.token = null;
}
}
and this is my index.php using slim framework
getContainer();
$container["jwt"] = function ($container) {
return new StdClass;
};
$app->add(new \Slim\Middleware\JwtAuthentication([
"path" => "/",
"passthrough" => "/authenticate",
"secret" => getenv("HJ_ENV"),
"error" => function ($request, $response, $arguments) {
$data["status"] = "error";
$data["message"] = $arguments["message"];
return $response
->withHeader("Content-Type", "application/json")
->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
},
"callback" => function ($request, $response, $arguments) use ($container) {
$body = $response->getBody();
$body->write($arguments["decoded"]);
$container["jwt"] = $arguments["decoded"];
}
]));
$app->post('/authenticate', 'authenticate');
$app->run();
function authenticate(Request $request, Response $response)
{
$params = json_decode($request->getBody());
$sql = "select * from users where userName = :userName";
$result = json_decode( runQuery($sql, [ ':userName', $params->user ]) );
$body = $response->getBody();
if ( $result && $result[0]->password == $params->password )
{
$decoded = $request->getAttribute("jwt");
$body->write( json_encode([ 'token' => $decoded ]) );
}
else
{
$body->write( json_encode(['token' => null]) );
}
}
function runQuery($sql, ...$params)
{
try
{
$db = getConnection();
$stmt = $db->prepare($sql);
foreach ( $params as $param )
{
$stmt->bindParam( $param[0], $param[1] );
}
$stmt->execute();
$rows = [];
while($row=$stmt->fetch(PDO::FETCH_OBJ))
{
/*its getting data in line.And its an object*/
array_push($rows, $row );
}
$db = null;
return json_encode($rows);
}
catch(PDOException $e)
{
$db = null;
return $e->getMessage() ;
}
}
?>
my question is
I am not able to get token from container['jwt'].
If i give incorrect user name and password then token remain null.
But if i give correct user name and password. the $result variable give me data from my database. i can verify password. but $request->getAttribute("jwt") this method gives me null.
also i have checked $decoded = $container["jwt"]
but this also gives me null.
SO i could not know how to get the token created by jwt.
Thank you.
add(new \Slim\Middleware\JwtAuthentication([
"path" => "/",
"passthrough" => "/authenticate",
"error" => function ($request, $response, $arguments) {
$data["status"] = "error";
$data["message"] = $arguments["message"] ;
return $response
->withHeader("Content-Type", "application/json")
->write(json_encode($data, JSON_UNESCAPED_SLASHES |
JSON_PRETTY_PRINT));
}
]));
$app->post('/authenticate', function (Request $request, Response $response )
{
$params = json_decode($request->getBody());
/* $params will contain user and password posted by angular for
verification in data base */
/* here you retrieve user name and password from database */
if ( /* check here user name and password */ )
{
$now = new DateTime();
$future = new DateTime("now +2 hours");
$payload = [
"iat" => $now->getTimeStamp(),
"exp" => $future->getTimeStamp()
];
$secret = getenv("HJ_ENV"); /* put your secret key here */
$token = JWT::encode($payload, $secret, "HS256");
$data["status"] = "ok";
$data["token"] = $token;
return $response->withStatus(201)
->withHeader("Content-Type", "application/json")
->write(json_encode($data, JSON_UNESCAPED_SLASHES |
JSON_PRETTY_PRINT));
}
else
{
$data["status"] = "error";
$data["message"] = "Invalid Token" ;
return $response
->withHeader("Content-Type", "application/json")
->write(json_encode($data, JSON_UNESCAPED_SLASHES |
JSON_PRETTY_PRINT));
}
});

Slim Payment controller

I followed a serie on creating a shopping cart on codecourse - and it was just what I was looking for.
In the series the payment happens on creating the order - but now my client says that they don't want the payment on creating order - first when they have processed the order - they want to send an email with payment or an link to a payment site.
I thought no big deal - just move the BraintreePayment par out of the create class - create a new class called payment and thats that - but no - so now I am stuck.
I am using swiftmailer to send the mail with the link and that works fine - but the payment part fails.
I am new to this MVC / Slim thing - so please can someone help me in the right direction.
The error it throws say:
Type: TypeError Message: Argument 1 passed to
Cart\Events\OrderWasCreated::__construct() must be an instance of
Cart\Models\Order, integer given, called in
/Applications/AMPPS/www/testshop.dev/cart/app/Controllers/OrderController.php
on line 160 File:
/Applications/AMPPS/www/testshop.dev/cart/app/Events/OrderWasCreated.php
Line: 17
My ordercontroller with the payment class - looks like this:
<?php
namespace Cart\Controllers;
use Slim\Router;
use Slim\Views\Twig;
use Cart\Basket\Basket;
use Cart\Models\Order;
use Cart\Models\Product;
use Cart\Models\Address;
use Cart\Models\Delivery;
use Cart\Models\Customer;
use Cart\Controllers\MailController;
use Cart\Validation\Contracts\ValidatorInterface;
use Cart\Validation\Forms\OrderForm;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Braintree_transaction;
class OrderController
{
protected $basket;
protected $mailcontroller;
protected $router;
protected $validator;
public function __construct(Basket $basket, Mailcontroller $mailcontroller, Router $router, ValidatorInterface $validator)
{
$this->basket = $basket;
$this->mailcontroller = $mailcontroller;
$this->router = $router;
$this->validator = $validator;
}
public function index(Request $request, Response $response, Twig $view)
{
$this->basket->refresh();
if (!$this->basket->subTotal()) {
return $response->withRedirect($this->router->pathFor('cart.index'));
}
return $view->render($response, 'order/index.twig');
}
public function show($hash, Request $request, Response $response, twig $view, Order $order)
{
$order = $order->with('address', 'products')->where('hash', $hash)->first();
$this->mailcontroller->mailLisbeth($hash);
if (!$order) {
return $response->withRedirect($this->router->pathFor('home'));
}
return $view->render($response, 'order/show.twig', [
'order' => $order,
]);
}
public function create(Request $request, Response $response, Customer $customer, Address $address, Delivery $delivery, Order $order)
{
$this->basket->refresh();
$validation = $this->validator->validate($request, OrderForm::rules());
if (!$this->basket->subTotal()) {
return $response->withRedirect($this->router->pathFor('cart.index'));
}
if ($validation->fails()) {
return $response->withRedirect($this->router->pathFor('order.index'));
}
$hash = bin2hex(random_bytes(32));
$customer = $customer->firstOrCreate([
'email' => $request->getParam('email'),
'name' => $request->getParam('name'),
]);
$delivery = $delivery->firstOrCreate([
'delivery' => $request->getParam('delivery'),
'deliverydate' => $request->getParam('deliverydate'),
'deliverytime' => $request->getParam('deliverytime'),
]);
$address = $address->firstOrCreate([
'address1' => $request->getParam('address1'),
'address2' => $request->getParam('address2'),
'city' => $request->getParam('city'),
'postal_code' => $request->getParam('postal_code'),
]);
$order = $customer->orders()->create([
'hash' => $hash,
'accepted' => "2",
'paid' => false,
'total' => $this->basket->subTotal() + 150,
]);
$address->order()->save($order);
$delivery->order()->save($order);
$allItems = $this->basket->all();
$order->products()->saveMany(
$allItems,
$this->getQuantities($allItems)
);
$event = new \Cart\Events\OrderWasCreated($order, $this->basket);
$event->attach([
// new \Cart\Handlers\MarkOrderPaid,
// new \Cart\Handlers\RecordSuccessfulPayment($result->transaction->id),
new \Cart\Handlers\UpdateStock,
new \Cart\Handlers\Emptybasket,
]);
$event->dispatch();
return $view->render($response, 'order/show.twig', [
'order' => $order,
]);
}
//
public function payment($slug, Request $request, Response $response, twig $view, Customer $customer, Address $address, Delivery $delivery, Order $order)
{
$order = $order->with('address', 'products')->where('id', $slug)->first();
// var_dump($order);
// die();
// if (!$request->getParam('payment_method_nonce')) {
// return $response->withRedirect($this->router->pathFor('order.index'));
// }
$order = $customer->orders()->update([
'paid' => true,
]);
$result = Braintree_Transaction::sale([
'amount' => $this->basket->subTotal() + 150,
'paymentMethodNonce' => $request->getParam('payment_method_nonce'),
'options' => [
'submitForSettlement' => true,
]
]);
$event = new \Cart\Events\OrderWasCreated($order, $this->basket);
if (!$result->success) {
$event->attach(new \Cart\Handlers\RecordFailedPayment);
$event->dispatch();
return $response->withRedirect($this->router->pathFor('order.index'));
}
$event->attach([
new \Cart\Handlers\MarkOrderPaid,
new \Cart\Handlers\RecordSuccessfulPayment($result->transaction->id),
// new \Cart\Handlers\UpdateStock,
// new \Cart\Handlers\Emptybasket,
]);
}
protected function getQuantities($items)
{
$quantities = [];
foreach ($items as $item) {
$quantities[] = ['quantity' => $item->quantity];
}
return $quantities;
}
}
The error occures on line 160:
$event = new \Cart\Events\OrderWasCreated($order, $this->basket);
because you invoke Cart\Events\OrderWasCreated constructor, which requires instance of Cart\Models\Order class as first argument. Instead your first argument ($order) is integer.
Now latest assignment of $order is on line 147:
$order = $customer->orders()->update([
'paid' => true,
]);
I'll have a guess and say that this is an operation that returns integer as result (be that a simple 1/0 success/fauilure or the id of the order being updated). Are you sure that you need that? Asking because:
You are assigning $order a value on line 138:
$order = $order->with('address', 'products')->where('id', $slug)->first();
And you're passing $order as an argument to the OrderController::payment.
So, my guess is: you want to remove lines 138 and 147.

paypal success url error laravel

I'm using laravel Omni plugin for transactions. Once payment has been done , I'm getting error for success url.
public function checkOut(Request $request)
{
$params = array(
'cancelUrl' => 'http://localhost/vis/public/cancel_order',
'returnUrl' => 'http://localhost/vis/public/payment_success',
'name' => 'Meal',
'description' => 'Casper',
'amount' => '1.00',
'currency' => 'USD'
);
Session::put('params', $params);
Session::save();
$gateway = Omnipay::create('PayPal_Express');
$gateway->setUsername('un');
$gateway->setPassword('pwd');
$gateway->setSignature('signature');
$gateway->setTestMode(true);
$response = $gateway->purchase($params)->send();
if ($response->isSuccessful()) {
print_r($params);
redirect('payment_success/' . $this->orderNo);
// payment was successful: update database
print_r($response);
} elseif ($response->isRedirect()) {
// redirect to offsite payment gateway
$response->redirect();
} else {
// payment failed: display message to customer
echo $response->getMessage();
}
}
public function getSuccessPayment()
{
$gateway = Omnipay::create('PayPal_Express');
$gateway->setUsername('un');
$gateway->setPassword('pwd');
$gateway->setSignature('signature');
$gateway->setTestMode(true);
$params = Session::get('params');
$response = $gateway->completePurchase($params)->send();
$paypalResponse = $response->getData(); // this is the raw response object
if(isset($paypalResponse['PAYMENTINFO_0_ACK']) && $paypalResponse['PAYMENTINFO_0_ACK'] === 'Success') {
// Response
print_r($params);
// print_r($paypalResponse);
} else {
//Failed transaction
}
// return View('result');
print_r($params);
print_r($paypalResponse);
}
I'm getting following error
Not Found
HTTP Error 404. The requested resource is not found.
http://localhost/vis/public/payment_success?token=EC-1R845179Asss493N&PayerID=swdw3BS9REA4AN
It looks like you may have forgotten to add that route in the routes.php, Make sure you have something like this in routes.php
Route::get('/payment_success', 'StoreController#getSuccessPayment');
Change StoreController to the name of the controller this function is in.

Categories