Payment failed but order is Placed in Laravel with Stripe - laravel

I have integrated stripe payment in flutter app but After payment got failed even then order placed in Laravel database so please check, what I have done wrong.
Please check at save method, May be I am wrong and can't validate purchase response.
payment controller
public function makePayment(Request $request)
{
try{
$data = $request->input('cartItems');
$cartItems = json_decode($data, true);
$orderData = $request->input('order');
$selectPaymentOption = json_decode($orderData, true);
$totalAmount = 0.0;
foreach ($cartItems as $cartItem){
$order = new Order();
$order->order_date = Carbon::now()->toDateString();
$order->product_id = $cartItem['productId'];
$order->payment_type = $selectPaymentOption['paymentType'];
$order->user_id = $request->input('userId');
$order->quantity = $cartItem['productQuantity'];
$order->amount = ($cartItem['productPrice'] - $cartItem['productDiscount']);
$totalAmount+= $order->amount * $order->quantity;
$order->save();
}
if($selectPaymentOption['paymentType'] == 'Card'){
\Stripe\Stripe::setApiKey('sk_test_hJUgYYzeXtitxxxx71lK8nE00MELJJS8c');
$token = \Stripe\Token::create([
'card' => [
'number' => $request->input('cardNumber'),
'exp_month' => $request->input('expiryMonth'),
'exp_year' => $request->input('expiryYear'),
'cvc' => $request->input('cvcNumber')
]
]);
$charge = \Stripe\Charge::create([
'amount' => $totalAmount * 100,
'currency' => 'inr',
'source' => $token,
'receipt_email' => $request->input('email'),
]);
}
return response(['result' => true]);
} catch (\Exception $exception){
return response(['result' => $exception]);
}
}
and my Flutter's Post request is here.
I want to POST _makePayment method after complete payment successful.
void _makePayment(BuildContext context, Payment payment) async {
PaymentService _paymentService = PaymentService();
var paymentData = await _paymentService.makePayment(payment);
var result = json.decode(paymentData.body);
print(paymentData);
CartService _cartService = CartService();
this.widget.cartItems!.forEach((cartItem) {
_cartService.makeTheCartEmpty();
});
if (result['result'] == true) {
_showPaymentSuccessMessage(context);
Timer(Duration(seconds: 4), () {
Navigator.pop(context);
Navigator.push(
context, MaterialPageRoute(builder: (context) => HomeScreen()));
});
}
}

Referring to my comment above, this is the rough solution I suggested in your controller you have to switch the logic
public function makePayment(Request $request)
{
try{
$data = $request->input('cartItems');
$cartItems = json_decode($data, true);
$orderData = $request->input('order');
$selectPaymentOption = json_decode($orderData, true);
##Change your frontend logic to pass total amount as variable
$totalAmount = $request->totalAmount;
if($selectPaymentOption['paymentType'] == 'Card'){
##Never have any sk or pk in your controller, switch this to config('common.sk_test')
\Stripe\Stripe::setApiKey(config('common.sk_test'));
$token = \Stripe\Token::create([
'card' => [
'number' => $request->input('cardNumber'),
'exp_month' => $request->input('expiryMonth'),
'exp_year' => $request->input('expiryYear'),
'cvc' => $request->input('cvcNumber')
]
]);
$charge = \Stripe\Charge::create([
'amount' => $totalAmount * 100,
'currency' => 'inr',
'source' => $token,
'receipt_email' => $request->input('email'),
]);
}
##After the stripe transaction is finished you can foreach your cart and do what you need to your database
foreach ($cartItems as $cartItem){
$order = new Order();
$order->order_date = Carbon::now()->toDateString();
$order->product_id = $cartItem['productId'];
$order->payment_type = $selectPaymentOption['paymentType'];
$order->user_id = $request->input('userId');
$order->quantity = $cartItem['productQuantity'];
$order->amount = ($cartItem['productPrice'] - $cartItem['productDiscount']);
$order->save();
}
return response(['result' => true]);
} catch (\Exception $exception){
return response(['result' => $exception]);
}
}
For the config('common.sk_test') part of my answer, in you config folder you can create a new file where you have you custom app variables, so create a file for instance common.php and 'sk_test' that takes its value from you .env file

Related

Failed asserting that a row in the table student.sections matches the attributes

Hello im new to PHPUnit with minimum knowledge in laravel.
Im trying to test this method that mass create student section
public function setStudentsSection(Request $request)
{
$enrollments = Enrollment::whereIn('student_id', $request->students)->where('session_id', $request->session_id)->get();
$program_section = ProgramSection::withCount('students')->find($request->program_section_id);
if(($program_section->students_count + count($enrollments)) <= $program_section->max_students) {
foreach($enrollments as $enrollment) {
$response = StudentSection::create([
'student_id' => $enrollment->student_id,
'enrollment_id' => $enrollment->id,
'section_id' => $request->program_section_id,
'created_at' => Carbon::now()
]);
return $response;
}
}
return response()->json(['errors' => ['message' => 'Selected Section is full.']], 405);
}
UPDATE
Here's the test case. Im trying to match the method that i've modified with my test, but im failing to do so.
public function testCanMassAssignSection()
{
$sectioning_data = $this->setMassSectioning(10);
$this->json('POST', 'api/enrollments/set-students-section', $sectioning_data['data'])
->assertStatus(201);
$student_section_data = ['student_id' => $sectioning_data['student_ids'], 'section_id' => $sectioning_data['program_section']->id];
$this->assertDatabaseHas('student.sections', $student_section_data);
}
private function setMassSectioning($max_students)
{
$session = Session::factory()->create();
$program_section = ProgramSection::factory()->create(['session_id' => $session->id, 'max_students' => $max_students]);
$enrollments = Enrollment::factory(['session_id' => $session->id])->count(3)->create();
$student_ids = array();
foreach($enrollments as $enrollment) {
array_push($student_ids, $enrollment->student_id);
}
return [
'data' => ['program_section_id' => $program_section->id, 'session_id' => $session->id, 'students' => $student_ids],
'student_ids' => $enrollment->student_id,
'program_section' => $program_section
];
}
UPDATE
Here's the error the i get.
1) Test\Feature\EnrollmentTest::testCanMassAssignSection
Failed asserting that a row in the table [student.sections] matches the attributes {
"student_id": 2765,
"section_id": 1649
}.
Found: [
{
"id": 262,
"student_id": 2763,
"section_id": 1649,
"created_at": "2022-08-24 09:32:05",
"updated_at": "2022-08-24 09:32:05",
"enrollment_id": 1740
}
].
Still can't make it to match. I do not know what im doing wrong.
Solve! I just create $student data and added to $enrollments now assert in database match. Although don't know what exactly is happening on the background.
I think when i added to enrollments variable the 'student_id' => $student->id it creates those 3 records.
private function setMassSectioning($max_students)
{
$session = Session::factory()->create();
$student = Student::factory()->create();
$program_section = ProgramSection::factory()->create(['session_id' => $session->id, 'max_students' => $max_students]);
$enrollments = Enrollment::factory(['session_id' => $session->id, 'student_id' => $student->id])->count(3)->create();
$student_ids = array();
foreach($enrollments as $enrollment) {
array_push($student_ids, $enrollment->student_id);
}
return [
'data' => ['program_section_id' => $program_section->id, 'session_id' => $session->id, 'students' => $student_ids],
'student_ids' => $enrollment->student_id,
'program_section' => $program_section
];
}

Extend Laravel package

I've searched around and couldn't find a definitive answer for this...
I have a package DevDojo Chatter and would like to extend it using my application. I understand I'd have to override the functions so that a composer update doesn't overwrite my changes.
How do I go about doing this?
UPDATE
public function store(Request $request)
{
$request->request->add(['body_content' => strip_tags($request->body)]);
$validator = Validator::make($request->all(), [
'title' => 'required|min:5|max:255',
'body_content' => 'required|min:10',
'chatter_category_id' => 'required',
]);
Event::fire(new ChatterBeforeNewDiscussion($request, $validator));
if (function_exists('chatter_before_new_discussion')) {
chatter_before_new_discussion($request, $validator);
}
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
$user_id = Auth::user()->id;
if (config('chatter.security.limit_time_between_posts')) {
if ($this->notEnoughTimeBetweenDiscussion()) {
$minute_copy = (config('chatter.security.time_between_posts') == 1) ? ' minute' : ' minutes';
$chatter_alert = [
'chatter_alert_type' => 'danger',
'chatter_alert' => 'In order to prevent spam, please allow at least '.config('chatter.security.time_between_posts').$minute_copy.' in between submitting content.',
];
return redirect('/'.config('chatter.routes.home'))->with($chatter_alert)->withInput();
}
}
// *** Let's gaurantee that we always have a generic slug *** //
$slug = str_slug($request->title, '-');
$discussion_exists = Models::discussion()->where('slug', '=', $slug)->first();
$incrementer = 1;
$new_slug = $slug;
while (isset($discussion_exists->id)) {
$new_slug = $slug.'-'.$incrementer;
$discussion_exists = Models::discussion()->where('slug', '=', $new_slug)->first();
$incrementer += 1;
}
if ($slug != $new_slug) {
$slug = $new_slug;
}
$new_discussion = [
'title' => $request->title,
'chatter_category_id' => $request->chatter_category_id,
'user_id' => $user_id,
'slug' => $slug,
'color' => $request->color,
];
$category = Models::category()->find($request->chatter_category_id);
if (!isset($category->slug)) {
$category = Models::category()->first();
}
$discussion = Models::discussion()->create($new_discussion);
$new_post = [
'chatter_discussion_id' => $discussion->id,
'user_id' => $user_id,
'body' => $request->body,
];
if (config('chatter.editor') == 'simplemde'):
$new_post['markdown'] = 1;
endif;
// add the user to automatically be notified when new posts are submitted
$discussion->users()->attach($user_id);
$post = Models::post()->create($new_post);
if ($post->id) {
Event::fire(new ChatterAfterNewDiscussion($request));
if (function_exists('chatter_after_new_discussion')) {
chatter_after_new_discussion($request);
}
if($discussion->status === 1) {
$chatter_alert = [
'chatter_alert_type' => 'success',
'chatter_alert' => 'Successfully created a new '.config('chatter.titles.discussion').'.',
];
return redirect('/'.config('chatter.routes.home').'/'.config('chatter.routes.discussion').'/'.$category->slug.'/'.$slug)->with($chatter_alert);
} else {
$chatter_alert = [
'chatter_alert_type' => 'info',
'chatter_alert' => 'You post has been submitted for approval.',
];
return redirect()->back()->with($chatter_alert);
}
} else {
$chatter_alert = [
'chatter_alert_type' => 'danger',
'chatter_alert' => 'Whoops :( There seems to be a problem creating your '.config('chatter.titles.discussion').'.',
];
return redirect('/'.config('chatter.routes.home').'/'.config('chatter.routes.discussion').'/'.$category->slug.'/'.$slug)->with($chatter_alert);
}
}
There's a store function within the vendor package that i'd like to modify/override. I want to be able to modify some of the function or perhaps part of it if needed. Please someone point me in the right direction.
If you mean modify class implementation in your application you can change the way class is resolved:
app()->bind(PackageClass:class, YourCustomClass::class);
and now you can create this custom class like so:
class YourCustomClass extends PackageClass
{
public function packageClassYouWantToChange()
{
// here you can modify behavior
}
}
I would advise you to read more about binding.
Of course a lot depends on how class is created, if it is created using new operator you might need to change multiple classes but if it's injected it should be enough to change this single class.

How to make the field reuired in Yii2 recaptcha google extension himiklab

I am using extension himiklab for yii2 recaptcha, which is similar to the google one. I want to set this field as required field in my rules. When I set it as below it is not validating even If I don't click the checkbox.
[['reCaptcha'], 'required'],
['reCaptcha', \himiklab\yii2\recaptcha\ReCaptchaValidator::className(), 'secret' => '***','skipOnEmpty' => false],
view
<?= $form->field($model, 'reCaptcha')->widget(
\himiklab\yii2\recaptcha\ReCaptcha::className(),
['siteKey' => '6LeY1BAUAAAAALThRhBQ-sJaXbP0Z5i9XFuaz_VW']
)->label(false); ?>
action
public function actionSignup()
{
$browser = new Browser;
if( $browser->getBrowser() == Browser::BROWSER_IE && $browser->getVersion() < 11 )
{
return $this->render('browser');
}
$company = new Company();
$model = new SimUser(['scenario' => SimUser::SCENARIO_REGISTER]);
if ($model->load(Yii::$app->request->post())&& $model->validate() && $company->load(Yii::$app->request->post())&& $company->validate()) {
$model->scenario = SimUser::SCENARIO_REGISTER;
$model->setPassword($model->user_password_hash);
// $model->setCaptcha($model->captcha);
$model->generateAuthKey();
$token = Yii::$app->security->generateRandomString();
$model->user_access_token = $token;
$model->user_verify = 1;
// $company->save();
$model->company_id = 3;
// $model->save();
$model->user_id = 44;
var_dump($model->validate());exit();
if ($model->validate()){
// $auth = Yii::$app->authManager;
// $authorRole = $auth->getRole('Company Admin');
// $auth->assign($authorRole, $model->user_id);
$path = 'C:/wamp/www/test.qsims.com/web/gentelella-1.2.0/production/images/DCMLogo.png';
Yii::$app->mailer->compose('#app/mail/layouts/verify',['model' => $model, 'path' => $path,'token' => $model->user_access_token])
->setTo($model->user_email)
->setFrom('test.qsims#gmail.com')
->setSubject('Welcome to Qsims'.$model->user_fname." ".$model->user_lname.'. Verify your account to continue')
->setTextBody('Verify Account')
->send();
}
// \Yii::$app->user->login($model);
return $this->redirect(['site/verify-new']);
}
return $this->render('signup', [
'model' => $model,
'company' => $company,
]);
}
Where am I going wrong?
Add this to the model
Public $reCaptcha;
add this to rules
['reCaptcha', 'reCaptchaValidator']
call the custom validation
public function reCaptchaValidator($attribute)
{
$validator = new ReCaptchaValidator;
if (!$validator->validate($this->reCaptcha, $error)) {
$this->addError($attribute, $error);
}
}

Laravel 4 code organization

I have some questions to Laravel 4 code organization. I am not the best "clean coder" and come from the Java world and sometimes my PHP / Laravel 4 code looks terrible. I post an example here from my controller:
public function postCreate()
{
$input = array(
'title' => Binput::json('title'),
'gender' => Binput::json('gender'),
'first' => Binput::json('first'),
'last' => Binput::json('last'),
'birthdate' => Binput::json('birthdate'),
'birthplace' => Binput::json('birthplace'),
'citizenship' => Binput::json('citizenship'),
'organizationId' => Binput::json('organizationId'),
'typeId' => Binput::json('typeId'),
'email' => Binput::json('email'),
'phone_private' => Binput::json('phone_private'),
'phone_mobile' => Binput::json('phone_mobile'),
'address_street' => Binput::json('address.street'),
'address_postcode' => Binput::json('address.postcode'),
'address_city' => Binput::json('address.city'),
'address_country' => Binput::json('address.country'),
'educations' => Binput::json('educations'),
'selectedLanguages' => Binput::json('selectedLanguages'),
'work' => Binput::json('work'),
);
$rules = array (
'gender' => 'required|max:1',
'first' => 'required|min:2',
'last' => 'required|min:2',
'birthdate' => 'required',
'organizationId' => 'required',
'typeId' => 'required',
'email' => 'required|email',
);
$v = Validator::make($input, $rules);
if ($v->fails() || empty($input['educations']))
{
$data = array("flash" => 'Firstname, Lastname, Birthdate, Email and at least 1 entry in Educations required.');
return Response::json($data, 500);
}
try {
DB::connection()->getPdo()->beginTransaction();
$member = new Member();
$member->title = $input['title'];
$member->gender = $input['gender'];
$member->first = $input['first'];
$member->last = $input['last'];
$member->birthdate = $input['birthdate'];
$member->birthplace = $input['birthplace'];
$member->citizenship = $input['citizenship'];
$work = new Work();
$work->working = $input['work']['working'];
if($input['work']['working'] == 1){
$work->branch = $input['work']['branch'];
$work->company = $input['work']['company'];
}
$work->save();
$member->work()->associate($work);
$member->save();
foreach($input['educations'] as $eduInput){
$edu = new Education();
$edu->degree = $eduInput['degree'];
if(!empty($eduInput['course'])){
$edu->course = $eduInput['course'];
}
$edu->term = $eduInput['term'];
$edu->completion = $eduInput['completion'];
if(!empty($eduInput['faculty'])){
try{
$faculty = Faculty::findOrFail($eduInput['faculty']['id']);
$edu->faculty()->associate($faculty);
}catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e){
}
}
if($eduInput['institutionId'] == 0){
// University
try{
$university = University::findOrFail($eduInput['university']['id']);
$edu->university()->associate($university);
}catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e){
}
}else{
// Freetext
$edu->institution = $eduInput['institution'];
}
$edu->save();
$member->educations()->save($edu);
}
foreach($input['selectedLanguages'] as $languageInput){
try{
$lang = Language::findOrFail($languageInput['id']);
$member->languages()->attach($lang);
}catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e){
}
}
try{
$memberType = MemberType::findOrFail($input['typeId']);
$member->memberType()->associate($memberType);
}catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e){
}
try{
$organization = Organization::findOrFail($input['organizationId']);
$member->organizations()->attach($organization);
}catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e){
}
$email = new Email();
$email->email = $input['email'];
$email->primary = true;
$member->emails()->save($email);
// If input for phone is empty
$phone = new Phone();
$phone->phone = $input['phone_private'];
$phone->phoneType()->associate(PhoneType::find(PhoneType::PRIVATE_PHONE));
$member->phones()->save($phone);
$phone = new Phone();
$phone->phone = $input['phone_mobile'];
$phone->phoneType()->associate(PhoneType::find(PhoneType::MOBILE_PHONE));
$member->phones()->save($phone);
$address = new Address();
$address->street = $input['address_street'];
$address->postcode = $input['address_postcode'];
$address->city = $input['address_city'];
$address->country = $input['address_country'];
$address->member()->associate($member);
$address->save();
DB::connection()->getPdo()->commit();
}catch (\PDOException $e) {
DB::connection()->getPdo()->rollBack();
return Response::json("Error while writing to database.", 500);
}
$member->load('emails');
$data = array("flash" => 'Member created successfully.');
return Response::json($data, 200);
}
This is an example from my controller.
Is it normal to get all parameters in this way. It takes much of space.
Can I move my database transaction elsewhere and not storing in the controller ?
In general where to store the code that manages logic ? In the controller ? In the
model ?
Your controller actions are just a sort of middleware in the sense that in there you should not put any of your business logic. a few pointers I can provide:
you can get all the json input with Input::json()->all() which returns an array so you can operate it.
Validation rules are another responsibility so it should be abstracted in another class that you call from the controller, it also may be well suited in your models(or entities).
To help you understand how can you use another class inside your controllers you should look for dependency injection in the laravel docs.
if you can get access to this book https://leanpub.com/laravel by Laravel's creator it will help your understanding of code organization and class responsibilities even outside laravel

CakePHP login when trying to acces controller

im having troubles with a web app that a teacher ask me to modify, the problem its that i dont know about cakePHP and i have been having troubles.After reading a lot, i think i have grasped the basics of the framework. My problem now its that i have a link in a view so i call a function in the controller to retrive data from the model, the problem its that each time i try to acces the function , the app makes me log in, and the idea its that it shouldnt.
I dont know exactly how the session handling on cakePhp works so, im requesting some help.
the code for the controller its this:
<?php
class RwController extends AppController {
var $name = 'Rw';
// var $paginate = array(
// 'Tip' => array(
// 'limit' => 1,
// 'order' => array(
// 'tip.created' => 'desc'
// ),
// ),
// 'Evento' => array(
// 'limit' => 1,
// 'order' => array(
// 'evento.fecha' => 'desc'
// ),
// )
// );
function map() {
$this->helpers[]='GoogleMapV3';
}
function pageForPagination($model) {
$page = 1;
// $chars = preg_split('/model:/', $this->params['url']['url'], -1, PREG_SPLIT_OFFSET_CAPTURE);
// #print_r($chars);
// if(sizeof($chars) > 1 && sizeof($chars) < 3) {
// #echo "Belongs to ".$model.": \n";
// #echo var_dump($chars);
// }
// $params = Dispatcher::parseParams(Dispatcher::uri());
// echo "<p>".var_dump($params)."</p><br />";
#echo $this->params['named']['model'].$model;
#echo $this->params['named']['page'];
$sameModel = isset($this->params['named']['model']) && $this->params['named']['model'] == $model;
$pageInUrl = isset($this->params['named']['page']);
if ($sameModel && $pageInUrl) {
$page = $this->params['named']['page'];
} else {
#echo var_dump($this->passedArgs);
}
$this->passedArgs['page'] = $page;
return $page;
}
function index() {
$this->log('indexeando esta chingadera','debug');
$this->loadModel('User');
$this->loadModel('Evento');
$this->loadModel('Tip');
$dataEvento = $this->Evento->find('all');
$dataTip = $this->Tip->find('all');
$page = $this->pageForPagination('Evento');
$this->paginate['Evento'] = array(
'contain' => false,
'order' => array('Evento.fecha' => 'desc'),
'limit' => 1,
'page' => $page
);
$dataEvento = $this->paginate('Evento');
$page = $this->pageForPagination('Tip');
$this->paginate['Tip'] = array(
'contain' => false,
'order' => array('Tip.created' => 'desc'),
'limit' => 1,
'page' => $page
);
$dataTip = $this->paginate('Tip');
$this->set('users', $this->User->find('all'));
$this->set('eventos', $dataEvento);
$this->set('tips', $dataTip);
$this->set('rw');
if(isset($this->params['named']['model'])) {
if (strcmp($this->params['named']['model'], 'Evento') == 0) {
if($this->RequestHandler->isAjax()) {
$this->render('/elements/ajax_rw_evento_paginate');
return;
}
} elseif (strcmp($this->params['named']['model'], 'Tip') == 0) {
if($this->RequestHandler->isAjax()) {
$this->render('/elements/ajax_rw_tip_paginate');
return;
}
}
}
}
function about($id = null) {
$this->Rw->recursive = 0;
$this->set('rw', $this->paginate());
}
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow(array('index', 'about'));
}
function getCentros($id){
$this->loadModel('Centro');
$this->log('getcentros','debug');
if( sizeof($id) > 1){
$this->set('centros', $this->Centro->query("SELECT centros.id, name, latitud ,longitud
FROM `centros`,`centrosmateriales`
WHERE centros.id = centro_id
AND material_id ='".$id[0]."'
OR material_id='".$id[1]."'"));
}elseif( sizeof($id) >0) {
if($id == 0){
$this->set('centros', $this->Centro->find('all'));
}else{
$this->set('centros', $this->Centro->query("SELECT centros.id, name, latitud ,longitud
FROM `centros`,`centrosmateriales`
WHERE centros.id = centro_id
AND material_id ='".$id[0]."'"));
}
}
$this->redirect(array('action' => 'index'));
}
}
?>
Edit:
The function im calling is getCentros().
this is what i have in app_controller.
<?php
class AppController extends Controller {
var $components = array('Session', 'Auth', 'RequestHandler');
var $helpers = array('Html', 'Form', 'Time', 'Session', 'Js', 'Paginator', 'GoogleMapV3');
function beforeFilter() {
$this->Auth->userModel = 'User';
$this->Auth->fields = array('username' => 'email', 'password' => 'password');
$this->Auth->loginAction = array('admin' => false, 'controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'index');
}
}
?>
try this
$this->Auth->allow(array('*'));
it allows you to access all functions inside the controller.
But before that make sure that you have access on the controller with out errors because your controller name is like this
class RwController extends AppController {
}
may be it want like this
class RwsController extends AppController {
}
Don't know which function you are trying to call but if cake tries to log you in and you don'want this add the function to:
$this->Auth->allow(array('index', 'about'));
in your beforefilter

Resources