I'm trying to use ci-merchant with paypal.
here is my test controller
class Test extends CI_Controller {
function paypal_express(){
$this->load->library('merchant');
$this->merchant->load('paypal_express');
$settings = array(
'username' => '***',
'password' => '***',
'signature' => '***',
'test_mode' => true);
$this->merchant->initialize($settings);
$params = array(
'amount' => 100.00,
'currency' => 'TRY',
'return_url' => site_url('test/paypal_express'),
'cancel_url' => site_url('test/paypal_express'));
$response = $this->merchant->purchase_return($params);
if ($response->success()){
echo 'ok';
}else{
$message = $response->message();
echo('Error processing payment: ' . $message);
exit;
}
}
}
When I run site.dev/test/paypal_express, I get,
Fatal error: Call to a member function set_params() on a non-object in /var/www/ci/application/libraries/merchant.php on line 192
php version: PHP 5.5.9-1ubuntu4.3
ci version : 2.2
Related
I deployed a Laravel-Livewire on Digital Ocean and now I'm having a Mixed content problem when I try to upload a file.
Here is the error:
UploadManager.js:131 Mixed Content: The page at 'https://intake.freejiji.ca/clients/3/extensions' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://intake.freejiji.ca/livewire/upload-file?expires=1625251608&signature=9d98c598db4f6fccc01c009bcfc3051c6a97b56f4058f4d9489a8d30d6d497c2'. This request has been blocked; the content must be served over HTTPS.
The error happens when after I click "Select File" and chose the .csv file I want. Since I'mdoing this on a livewire component I'm not sure how to fix this so that the request goes over HTTPS instead of HTTP.
I was able to fix similar problems on the app by changing "asset()" with "secure_asset()"
and "route()" with "secure_url()" but in this case I'm not sure what to do.
Here is the whole "Import" component:
<?php
namespace App\Http\Livewire\Modals;
use Validator;
use Livewire\Component;
use App\Http\Traits\Csv;
use App\Models\AccountUser;
use Livewire\WithFileUploads;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\Auth;
class ImportExtensions extends Component
{
use WithFileUploads;
public $clientID;
public $showModal = false;
public $upload;
public $columns;
public $fieldColumnMap = [
'first_name' => '',
'last_name' => '',
'email' => '',
'password' => '',
'extension' => '',
'user_type' => '',
];
protected $rules = [
'fieldColumnMap.first_name' => 'required|max:255',
'fieldColumnMap.last_name' => 'required|max:255',
'fieldColumnMap.email' => 'required|max:255',
'fieldColumnMap.password' => 'required|max:255',
'fieldColumnMap.extension' => 'required|max:255',
'fieldColumnMap.user_type' => 'required|max:255',
];
protected $validationAttributes = [
'fieldColumnMap.first_name' => 'First Name',
'fieldColumnMap.last_name' => 'Last Name',
'fieldColumnMap.email' => 'Email',
'fieldColumnMap.password' => 'Password',
'fieldColumnMap.extension' => 'Extension',
'fieldColumnMap.user_type' => 'User Type',
];
public function updatingUpload($value)
{
Validator::make(
['upload' => $value],
['upload' => 'required|mimes:csv'],
)->validate();
}
public function updatedUpload()
{
$this->columns = Csv::from($this->upload)->columns();
$this->guessWhichColumnsMapToWhichFields();
}
public function import()
{
// Validate that you are importing any data
$this->validate();
$importCount = 0;
Csv::from($this->upload)
->eachRow( function ($row) use (&$importCount){
$eachRow = $this->extractFieldsFromRow($row);
// Validate each Row of the csv file
$validatedData = Validator::make([
'first_name' => $eachRow['first_name'],
'last_name' => $eachRow['last_name'],
'email' => $eachRow['email'],
'password' => $eachRow['password'],
'extension' => $eachRow['extension'],
'user_type' => $eachRow['user_type'],
],[
'first_name' => 'required',
'last_name' => 'required',
'password' => 'required|max:255',
'user_type' => 'required|in:user,admin',
'email' => 'required|email|unique:account_users',
'extension' => ['required', 'numeric', Rule::unique('account_users', 'extension')
->where(function($query)
{return $query->where("account_id", $this->clientID);
})],
],);
if($validatedData->fails()){
$this->notify(['error','Oops something went wrong!']);
}else{
AccountUser::create([
'user_id' => Auth::user()->id,
'account_id' => $this->clientID,
'first_name' => $eachRow['first_name'],
'last_name' => $eachRow['last_name'],
'email' => $eachRow['email'],
'password' => $eachRow['password'],
'extension' => $eachRow['extension'],
'user_type' => $eachRow['user_type'],
]);
$importCount++;
}
});
$this->reset();
$this->emit('refreshExtensions');
if($importCount!=0) $this->notify(['success','Successfully Imported '.$importCount.' Extensions']);
}
public function guessWhichColumnsMapToWhichFields()
{
$guesses = [
'first_name' => ['first_name', 'name'],
'last_name' => ['last_name'],
'email' => ['email'],
'password' => ['password', 'pass'],
'extension' => ['extension', 'ext'],
'user_type' => ['user_type', 'user', 'type'],
];
foreach ($this->columns as $column) {
$match = collect($guesses)->search(fn($options) => in_array(strtolower($column), $options));
if ($match) $this->fieldColumnMap[$match] = $column;
}
}
public function extractFieldsFromRow($row)
{
$attributes = collect($this->fieldColumnMap)
->filter()
->mapWithKeys(function($heading, $field) use ($row) {
return [$field => $row[$heading]];
})
->toArray();
return $attributes;
}
public function downloadTemplate()
{
$filename = 'extensions_template.xls';
$path = public_path('files/' . $filename);
return response()->download($path, $filename, [
'Content-Type' => 'application/vnd.ms-excel',
'Content-Disposition' => 'inline; filename="' . $filename . '"'
]);
}
}
If you get mixed content problem it is mostly about you fetching the assets or resources from different http scheme. Here you are using HTTP to fetch data in HTTPS site. Change all the links to have HTTPS link.
If you want to force all the routes to use https you can achieve this by using following code.
if(env('APP_ENV', 'production') == 'production') { // use https only if env is production
\URL::forceScheme('https')
}
The above should solve your problem as all contents now will load from https.
I'm trying to test my login endpoint where a successful response would return the access_token among other things.
I'm using RefreshDatabase, so I changed the login method on the controller to retrieve the client_secret via a DB call. I tested with a dd() and I can confirm that the client_secret changes on each phpunit run in the terminal. The credentials are correct and the API endpoint works - just not when it's run via a test. For example, I have the passport tables set up on my mysql server and I can login successfully when running Postman. It's only when trying to run a test do I get a 401 error.
Here is my AuthTest
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class AuthTest extends TestCase
{
use RefreshDatabase;
/**
* #test
*/
public function a_user_receives_an_access_token()
{
\Artisan::call('passport:install');
$user = factory('App\User')->create();
$response = $this->json('POST', '/api/login', [
'username' => $user->email,
'password' => 'password'
]);
$response
->assertJson([
'access_token' => true
]);
}
}
routes/api.php
Route::post('login', 'AuthController#login');
AuthController#login:
public function login(Request $request) {
$http = new \GuzzleHttp\Client;
try {
$response = $http->post(config('services.passport.login_endpoint'), [
'form_params' => [
'grant_type' => 'password',
'client_id' => '2', //config('services.passport.client_id')
'client_secret' => DB::table('oauth_clients')->where('id', 2)->pluck('secret')[0], //config('services.passport.client_secret'),
'username' => $request->username,
'password' => $request->password
]
]);
return $response->getBody();
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
if ($e->getCode() == 400 || $e->getCode() == 401) {
return response()
->json([
'status' => $e->getCode(),
'message' => 'Your email and/or password are incorrect',
'expanded' => $e->getMessage()
]);
}
return response()
->json([
'status' => $e->getCode(),
'message' => $e->getMessage()
]);
}
}
I took a look at this question and the accepted answer: How to test authentication via API with Laravel Passport?
I am unable to use the following
public function setUp() {
parent::setUp();
\Artisan::call('migrate',['-vvv' => true]);
\Artisan::call('passport:install',['-vvv' => true]);
\Artisan::call('db:seed',['-vvv' => true]);
}
This results in an error:
PHP Fatal error: Declaration of Tests\Feature\AuthTest::setUp() must be compatible with Illuminate\Foundation\Testing\TestCase::setUp()
Edit: I just added
public function setUp() :void {
parent::setUp();
\Artisan::call('migrate',['-vvv' => true]);
\Artisan::call('passport:install',['-vvv' => true]);
\Artisan::call('db:seed',['-vvv' => true]);
}
but the problem still persists
Edit again:
If I test the oauth route directly, it passes.
public function testOauthLogin() {
$oauth_client_id = 2;
$oauth_client = OAuthClient::findOrFail($oauth_client_id);
$user = factory('App\User')->create();
$body = [
'username' => $user->email,
'password' => 'password',
'client_id' => $oauth_client_id,
'client_secret' => $oauth_client->secret,
'grant_type' => 'password',
'scope' => '*'
];
$this->json('POST','/oauth/token',$body,['Accept' => 'application/json'])
->assertStatus(200)
->assertJsonStructure(['token_type','expires_in','access_token','refresh_token']);
}
But my custom endpoint that uses guzzle fails. I do not know why
Edit again:
I think the issue is with Guzzle, but I'm not sure. I found another implementation of what I'm trying to do, which is the following:
public function login(Request $request) {
$request->request->add([
'username' => $request->username,
'password' => $request->password,
'grant_type' => 'password',
'client_id' => $this->client->id,
'client_secret' => $this->client->secret,
'scope' => '*'
]);
$response = Route::dispatch(Request::create(
'oauth/token',
'POST'
));
}
The above works.
I just noticed yesterday, there was a problem with my reCAPTCHA, last year was fine.
Here's my code:
public function message(Request $request) {
$response = $_POST["g-recaptcha-response"];
$url = 'https://www.google.com/recaptcha/api/siteverify';
$data = array(
'secret' => '6LcwXi8UAAAAAE9zNCVfqwDOIWNazNgdK-0wQv9L',
'response' => $_POST["g-recaptcha-response"]
);
//For debug purpose (remove comments)
//dd($request->all());
$options = array(
'http' => array (
'method' => 'POST',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
$verify = file_get_contents($url, false, $context);
$captcha_success=json_decode($verify);
if ($captcha_success->success==false) {
return redirect('/')->with('success', 'You are a bot! Go away!');;
} else if ($captcha_success->success==true) {
$content = array (
'http' => array (
'header' => "Content-Type: application/x-www-form-urlencoded\r\n".
"Content-Length: ".strlen($query)."\r\n".
"User-Agent:MyAgent/1.0\r\n",
'method' => 'POST',
'content' => http_build_query($data)
)
);
When I submitted contact form, it gave me this error:
ErrorException in PagesController.php line 37:
file_get_contents(): Content-type not specified assuming
application/x-www-form-urlencoded
Line 37 is:
$verify = file_get_contents($url, false, $context);
I've fixed this, here's my code:
private function check_recaptcha($key){
$secret = '6LdMgJIUAAAAAOvJPW8MHjumG2xQNNuRyw-WctqQ';
$verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$secret.'&response='.$key);
$responseData = json_decode($verifyResponse);
return ($responseData->success)? true:false;
}
public function message(Request $request) {
//Validate
$validator = Validator::make($request->all(), [
'name' => 'required',
'subject' => 'required',
'message' => 'required',
'email' => 'required|email',
'g-recaptcha-response' => 'required',
]);
//If validator failed
if ($validator->fails()) {
return redirect('/')
->withErrors($validator)
->withInput();
}
//Declare variable
$name = $request->input("name");
$email = $request->input("email");
$subject = $request->input("subject");
$message = $request->input("message");
$captchaKey = $request->input("g-recaptcha-response");
//Test reCAPTCHA
if (!$this->check_recaptcha($captchaKey)) {//captcha gagal
return redirect('/')->with('success', 'You are a bot! Go away!');
} else{//captcha sukses
$content = [
'name' => $name,
'email' => $email,
'subject' => $subject,
'message' => $message
];
In my case this header was missing and worked try this
$options = array('http' => array(
'method' => 'POST',
'content' => http_build_query($data),
'header' => 'Content-Type: application/x-www-form-urlencoded'
)
);
I am trying to add drop down box information:
USERNAME EMAIL ROLE
3 user user#mail.com 12345
How to add role so that it shows administrator or Manager? instead of the codes?
models/Mpages.php
public function add_user()
{
$options = [
'roles' => 'administrator',
];
$hash = password_hash($this->input->post('password'), PASSWORD_BCRYPT, $options);
$data = array(
'username' => $this->input->post('username'),
'email' => $this->input->post('email'),
'password' => $hash,
'role' => form_dropdown('roles', $options, 'administrator')
);
return $this->db->insert('login', $data);
}
controllers/Cpages.php
public function addusers() {
$data['successmessage'] = "";
$data['options'] = array(
'administrator' => 'Administrator',
'manager' => 'Manager',
);
$this->Mpages->add_user();
$this->load->view('addusers', $data);
}
Here is the answer key:
controllers/Cpages.php
public function addusers() {
$data['successmessage'] = "";
$data['options'] = array(
'administrator' => 'Administrator',
'manager' => 'Manager',
);
$this->Mpages->add_user();
$this->load->view('addusers', $data);
}
models/Mpages.php
public function add_user()
{
$options = [
'roles' => 'administrator',
];
$hash = password_hash($this->input->post('password'), PASSWORD_BCRYPT, $options);
$data = array(
'username' => $this->input->post('username'),
'email' => $this->input->post('email'),
'password' => $hash,
'role' => $this->input->post('roles')
);
return $this->db->insert('login', $data);
}
I have this method to store new user
public function register(CreateUserRequest $request){
$file = $request->file('idcard');
$fileName = rand(0, 99999).$file->getClientOriginalName();
if($request->hasFile('idcard') && $request->file('idcard')->isValid()){
$request->file('idcard')->move("images/idcard/", $fileName);
}
User::create([
'role_id' => 1,
'email' => $request->email,
'password' => $request->password,
'full_name' => $request->full_name,
'address' => $request->address,
'phone' => $request->phone,
'family_name' => $request->family_name,
'family_address' => $request->family_address,
'family_phone' => $request->family_phone,
'idcard' => $fileName,
'status' => 'unconfirmed',
'balance' => 0,
]);
Session::flash('success', 'Please check your email to activate your account.');
return redirect('/register');
}
And I have this unit test
public function testNewUserRegistration()
{
$this->visit('/register')
->type('This is full name', 'full_name')
->type('JL. Mulyorejo 226 D', 'address')
->type('085788884877', 'phone')
->type('Rizky Sugiarto', 'family_name')
->type('JL. Kandangan', 'family_address')
->type('085766669999', 'family_phone')
->attach('/var/www/html/autodealer/images/pics/banner_car.jpg', 'idcard')
->type('mail#yahoo.co.id', 'email')
->type('123456789', 'password')
->type('123456789', 'password_confirmation')
->press('Submit')
->seeInDatabase('users', ['email' => 'mail#yahoo.co.id', 'role_id' => 1, 'balance' => 0, 'status' => 'unconfirmed'])
->seePageIs('/register')
->see('Please check your email to activate your account.');
}
If I test my function via browser, it successfuly input database and move file.
But when I test via PHPUnit it pass the test, successfully input database but the image doesn't move.
Is there something wrong with my attach() or something else wrong?
Thanks, any help appreciated.