So I need users to upload files. These files can then be bought by customers (who are not users). Once the payment has been processed by stripe, the buyer should receive an email with a link to download the file.What I need is a download link for these files, that is only available to the user who has uploaded the file, and the customers who have bought the file.
Here is my controller for processing a form filled by a user to upload a file. NonUser is the details for the file from a previous form.
$note = new Note;
$note->title = $nonUser->title;
$note->description = $nonUser->description;
$note->mark = $nonUser->mark;
$note->page_count = $nonUser->page_count;
$note->subject_id = $nonUser->subject_id;
$note->year = $nonUser->year;
$note->modules = $nonUser->modules;
$note->price = $nonUser->modules*25;
$note->user_id = $user->id;
$note->exam_id=$user->exam_id;
$note->save();
Storage::put(
'notes/' . $note->id . '.pdf',
file_get_contents($request->file('notes')->getRealPath())
);
My stripe processing.
public function charge()
{
$nid = Session::get('nid');
$note = Note::where('id','=',$nid)->first();
$price = $note->price;
\Stripe\Stripe::setApiKey("sk_test_key");
$token = $_POST['stripeToken'];
try {
$charge = \Stripe\Charge::create(array(
"amount" => $price*100, // amount in cents, again
"currency" => "aud",
"source" => $token,
"description" => "Example charge"
));
} catch(\Stripe\Error\Card $e) {
flashWarning('An error occured');
return back();
}
flash('payment succesful! Check your email for a download link!');
return back();
}
I would use the following steps to service buyers:
Once payment is successful, store in the DB the orderID, fileID (should match the primary key of all files, stored in a different table) a random hash as download_ticket,a DateTime as ticket_expiration, and the # of times the ticket was used as download_count
Email the buyer a download link that points to a php script. The script should expect the download ticket. example:
example.com/download.php?ticket=m54hm4j390534gi2frew0094
In the script download.php, you would do the following:
Grab ticket from the query string: $ticket = $_GET['ticket']
Get the record in the DB: SELECT * from tbl WHERE ticket=m54hm4j390534gi2frew0094
If there is no match, error 404 not found with http_response_code(404) and abort.
If ticket_expiration has passed, delete the record, error 403 forbidden and abort.
If download_count has exceeded a limit, delete the record, error 429 too many requests and abort.
Use the fileID column to find the file that was purchased
If all checks workout, you can send the file to the user. do not redirect the user to the file's true location. Instead, do something like:
$path = '...'; // real path on disk
header('Content-Type: application/pdf');
header('Content-Length: ' . filesize($path));
$pipe = fopen($path, 'rb');
fpassthru($pipe); //sends file to user
fclose($pipe);
//TODO: increment `download_count` in the purchase record
You can do this by the following way
Step 1 : Generate the Link
After you do
Storage::put(
'notes/' . $note->id . '.pdf',
file_get_contents($request->file('notes')->getRealPath())
);
Generate the link with
$data['link'] = URL::to('/notes/'.$note->id.'pdf'); //Modify path according to your need
$message = 'Your Custom HTML';
Step 2 : Send the Email
Trigger mail to the User who uploads it
Mail::send(email.file, function ($message) {
$message->from('youremail#example.com', 'File Received');
$message->to(Auth::user()->email); // Email id of one who uploads it
});
Trigger mail who bought the file
$userlist = User::where('file_id' , $fileid)->get(); //modify the condition according to the tables you have
foreach($userlist as $users)
{
Mail::send(email.file, function ($message) {
$message->from('youremail#example.com', 'File Received');
$message->to($user['email']); // Looped Email id
});
}
Additional Step : (To make sure the file is secure)
Don't Point the file directly, you can do like this
Generate the link like this
yourapp.com/pdf/12/143
Where 12 is the user id and 143 is the pdf file's id
And under your controller you can check whether the user with id 12 is authorized to download the file with id 143, If so, then generate the pdf view or download it to the user.
Hope this helps you
When the payment is processed successfully store the PK of the file upload (from your database) in a new table (let's call it purchased downloads) along with a unique token that can be used to look up the file's PK in that table. This will be the token you'd send along with the email for them to download the file.
Create a new controller that accepts this token and looks up the unique token in the purchased downloads table then you can use something like an X-Sendfile header to have your webserver serve up the file to the client from your file system if the token verifies. You can also set an expiration time on this token if you'd like.
Related
So we have a website where Employers can log in and add new employees they just hired. When you hit 'Submit' on the form asking for the employees info, a unique link is created that if they click on, it will take them to a page to view the handbook (Onboarding) and electronically sign for it. We recently have a new Employer who wanted to see if we could add his current 300 employees into the site and have each one view and sign the handbook. I able to dumb all 300 employees into the database with MySQL but the issue now is that a Unique Link was never created for all of them because the 'Submit' button was never pushed for each one.
What do you guys think would be the best method to tackle this? Im not really sure how the Unique Links are created but I think I found the code that creates it. I was thinking of just creating a button that would create the link but I would have to tell it to do it for each of the 300 employees. I just cant seem to think of a better way.
<?php
ob_start();
//-------------------PAGE SETUP------------------------------------------------------
// Connect to the database
include( "db/connect.php" );
include( "db/dbFunctions.php" );
//-----------------------------------------------------------------------------------
//Restrict Users who do not have the Onboarding service
if (!hasService($USERID,'Onboarding')) {header( 'Location: home.php' ,true,301) ;}
//Check to see if the user has access to this functionality
checkAccessToFunctionality($USERID,$USERTYPE,'ADDEMPLOYEE',true);
$client = getClient($_POST['clientid'],$USERID);
$clientID = $client->id;
$locationID = $_POST['locationid'];
$templateID = $_POST['templateid'];
//Update the data fields
if ($clientID)
{
//Create the account and add data
$newuserID = createOnboardingEmployee();
setData($newuserID,'tblonboardingemployees','locationid',$_POST['locationid']);
setData($newuserID,'tblonboardingemployees','firstname',$_POST['firstname']);
setData($newuserID,'tblonboardingemployees','lastname',$_POST['lastname']);
setData($newuserID,'tblonboardingemployees','middleinitial',$_POST['middleinitial']);
setData($newuserID,'tblonboardingemployees','ssn',$_POST['ssn']);
setData($newuserID,'tblonboardingemployees','phone',$_POST['phone']);
setData($newuserID,'tblonboardingemployees','hiredate',$_POST['dateofhire_year'].'-'.$_POST['dateofhire_month'].'-'.$_POST['dateofhire_day']);
setData($newuserID,'tblonboardingemployees','startdate',$_POST['startdate_year'].'-'.$_POST['startdate_month'].'-'.$_POST['startdate_day']);
setData($newuserID,'tblonboardingemployees','hourlyrate',$_POST['hourlyrate']);
setData($newuserID,'tblonboardingemployees','addedby',$USERID);
setData($newuserID,'tblonboardingemployees','customfield1',$_POST['customfield1']);
setData($newuserID,'tblonboardingemployees','customfield2',$_POST['customfield2']);
setData($newuserID,'tblonboardingemployees','customfield3',$_POST['customfield3']);
setData($newuserID,'tblonboardingemployees','customfield4',$_POST['customfield4']);
setData($newuserID,'tblonboardingemployees','customfield5',$_POST['customfield5']);
if (isset($_POST['noemail']))
{
setData($newuserID,'tblonboardingemployees','noemail','1');
}
else{
setData($newuserID,'tblonboardingemployees','emailaddress',$_POST['email']);
}
//Set the employee's onboarding link
setData($newuserID,'tblonboardingemployees','onboardinglink',$newuserID . '-' . GUID());
//Set the onboarding template to use for the employee
assignOnboardingTemplateToEmployee($templateID,$locationID,$newuserID,$USERID);
//Send the onboarding link to the user
sendOnboardingIntroEmail($USERID,$newuserID,$templateID);
//auditaction($USERID,'USER',$newuserID,'User Added','UserType='.$_POST['usertype'],null);
//Assign permission to all client data and locations
//$permission = createUserPermission($newuserID,4,1,$clientID);
//Assign the master user ID to the client record
//setData($clientID,'tblclients','masteruserid',$newuserID);
}
else
{
echo 'A location ID was not found. Had to stop. Sorry about that!.';
ob_flush();
exit(0);
}
header( 'Location: onboarding_addemployee_complete.php?id='. $newuserID ) ;
ob_flush();
I want to create an account activation where after registering, a link would be sent to an administrator (or one) email whereby the admin just has to click that link to activate that account.
I have the registration and login working. I'm using MySQL Workbench and have a "flag" or rather just a field in my accounts table (named user_login) to tell whether the account is enabled or disabled, which is disabled by default after registration.
I am stuck and sending a link through email, I'm not sure where to begin. That link that I want to send would contain a random string and would be sent to the admin, say abc/123/random?stringis=1234. Then the admin would just have to open his email and click on the string and then that specific user's account would be activated. I found this and this but that's just for how to send a link through email.
I don't have an idea on the logic. Do I create a function whereby the link would go directly to the function and from there, it would change the value in my table to enabled or whatever I call it so that the user's account is counted as activated? Do I need to create a new field to match the random generated string then?
Main idea is I'm trying to do like those typical sites whereby a link would be sent to the user to activate the account once he/she clicks it in the email, but this time just to a specific email which is the admin's.
EDIT:
In controller
public function activate_user($activation_code)
{
$result = $this->home_model->activate($activation_code);
if($result != FALSE)
{
echo "You have activated :".$result[0]->user_id.".";
}
else
{
echo "Activation failed, something went wrong.";
}
}
In Model:
public function activate($activation_link)
{
$this->db->select('*');
$this->db->from('user_login');
$this->db->where('activation_link', $activation_link);
$query = $this->db->get();
if($query->num_rows() == 1)
{
return $query->result();
}
else
{
return FALSE;
}
}
First
Database
add two column
activation_token{varchar|255}
activation_time{datetime}
After registration Success
add some randome has into activation_token(md5 or sha1(up to you))
add time if registration using Current timestamp(now())
Link
link should be
I strongly prefer userid in activation url
because it's remove the link duplication.
http://sitename.com/activation/{user_id}/{hash}
in controller
public function activation($user_id,$hash)
{
$timeOfexpiration = 3600;
$data = $this->model->get_data($id,$hash);
if(!$data)
{
return false
}
//if user found
//check expiration of linke
//like
if($data['activation_time']+$timeOfexpiration < now())
{
return true;
}
else
{
return false;
}
}
for that you need to add one more field in table called activation_linkwhen user register in site then generate random string and store that in activation_link and send link to the user so once user back then check the link and activate that user.
I am trying to make image upload on laravel but at some point it fails to set image destination in database.
When i try and test and echo back final image and link destination everything works fine, when i check the image destination and on my destination folder image is there but only image wont set in database.
I have set this field in database
Name Type Collation Attributes Null Default
avatarfull varchar(500) utf8_unicode_ci No None
i increased varchar to 500 just in case.
and on my usercontroller i have this for storing new user
public function store() {
$validator = Validator::make(Input::all(), [
'photo' => 'mimes:jpeg,bmp,png|max:1000'
]);
if($validator->fails()) {
return Redirect::route('admin.users.create')->withErrors($validator)->withInput();
} else {
if(Input::hasFile('photo')) {
if(Input::file('photo')->isValid()) {
$imagename = str_random(20) . '.' . Input::file('photo')->getClientOriginalExtension();
$imagelocation = Input::file('photo')->move(base_path() . '/img', $imagename );
$avatarfull = 'img/' . $imagename;
} else {
$avatarfull = 'img/profile_default.png';
}
} else {
$avatarfull = 'img/profile_default.png';
}
$create = User::create([
'avatarfull' => $avatarfull,
]);
if($create) {
return Redirect::route('admin.users.index')
->with('success_message', 'New user is successfully created!');
}
}
}
So the validator checks for what it needs to check, if the image is that mime type, and checks if image size doesn't exceed 1mb, that works.
Further on input checks if hasfile set for upload, if file is set for upload, it checks if file is valid, and than it gets image, rename it to random string, copy to proper location and set $avatarfull variable to proper path for setting it in the database.
If i
echo $avatarfull
or
print_r($avatarfull)
or
var_dump(Input::all())
I get all the data correct as it should be
var_dump shows all the data of input fields and there are laravel's usual backend things like checking the file type, file size, storing it in temp path, moved path to new location. Everything works fine.
if i check at the end $avatarfull variable, just before i store a new user $avatarfull variable is as it should, if image is uploaded than it echoes
img/random10characterstring.jpg
Checking against base path image is properly stored and moved to wanted location on my pc
/opt/lampp/htdocs/laravel/img/random10characterstring.jpg
Using in combination to link_to it shows the final results of url linked image
localhost/laravel/img/random10characterstring.jpg
And of course checking in my file browser the image does exists in that path. So laravel done it's work uploaded image, renamed it, and moved to desired location.
Only it won't set the field in the databas. When i add new user (this is image field for user avatar) it adds new user in the database, and i get set all the fields in the database except i don't get set path to image in database. For some reason this field lefts blank.
Please check if avatarfull is in $fillable array in your User model. If not Users model mass assignment protection will not allow to store the data by Users::create(...).
If you don't want to put avatarfull in fillable array, you can always use:
$user = new User;
$user->avatarfull = $avatarfull;
$user->save();
For more information about mass assignment see: http://laravel.com/docs/4.2/eloquent#mass-assignment
I am working of CIM (Customer information manager) and i have created customer profile using CIM function. But i want to get customer profile using customer id instead of customer profile id.
$cim = new AuthnetCIM('***MASKED***', '***MASKED***', AuthnetCIM::USE_DEVELOPMENT_SERVER);
$cim->setParameter('email', 'fakeemail#example.com');
$cim->setParameter('description', 'Profile for Joe Smith'); // Optional
$cim->setParameter('merchantCustomerId', '7789812');
//create profile function
$ss=$cim->createCustomerProfile();
//and get profile by..
$profile_id = $cim->getProfileID();
You can't. You can only get the profile using the profile ID. This means you'll want to store that ID in your database and associate it with the customer's record so whenever you need to get their profile you know what their Profile ID is.
Actually it is possible if you must, however I would still recommend storing it if possible, but this alternative might be of help.
Authorize.Net defines a unique customer profile by the composite key (Merchant Customer Id, Email, and Description), thus you must ensure this is unique. The CreateCustomerProfile(..) API method will enforce uniqueness and return an error if you attempt to create the same composite key again, as it should. However, the message in this response will contain the conflicting customer profile id, and since your composite key is unique, and Authorize.Net enforces uniqueness of this composite key, then this must be the Authorize.Net customer profile id of your customer.
Code sample in C#
private long customerProfileId = 0;
var customerProfile = new AuthorizeNet.CustomerProfileType()
{
merchantCustomerId = "123456789",
email = "user#domain.com",
description = "John Smith",
};
var cpResponse = authorize.CreateCustomerProfile(merchantAuthentication, customerProfile, ValidationModeEnum.none);
if (cpResponse.resultCode == MessageTypeEnum.Ok)
{
customerProfileId = cpResponse.customerProfileId;
}
else
{
var regex = new Regex("^A duplicate record with ID (?<profileId>[0-9]+) already exists.$", RegexOptions.ExplicitCapture);
Match match = regex.Match(cpResponse.messages[0].text);
if (match.Success)
customerProfileId = long.Parse(match.Groups["profileId"].Value);
else
//Raise error.
}
I have this method:
public function activation_code()
{ //activation code sent into db
$activation_code = random_string('alnum', 32);
return $activation_code;
}
What I'm trying to do is provide this with the post data that gets sent to my database but also provide a copy of that same activation code so I can concatenate it with the "click here to confirm email" url that is in my confirmation email that is sent to users upon registration.
How can I do this? I can't provide the method because if I do the database code and the email URL code will be different so user wouldn't be able to match them and confirm their email address.
I've tried many other ways such as providing the method in one place e.g.
public function create()
{ //get post data and insert into db
$dbcolumn->group_id = 2; //group 1 for admin group 2 for member
$dbcolumn->first_name = $this->input->post('first_name');
$dbcolumn->last_name = $this->input->post('last_name');
$dbcolumn->email = $this->input->post('email');
$dbcolumn->password = $this->hashed();
$dbcolumn->birthday = $this->input->post('year') .
'-' . $this->input->post('month') . '-' . $this->input->post('day');
$dbcolumn->sex = $this->input->post('sex');
$dbcolumn->activation_code = $this->activation_code();
// date and time user joined the website
$dbcolumn->created_on = date('Y-m-d H:i:s', now());
$this->db->insert('users', $dbcolumn);
}
If you look at the dbcolumn->activation code line you'll see what I've done. That works and the code is stored in the database. If I provide the same "$this->activation_code() method to the email that's sent the codes will obviously be different.
public function send_confirmation_email()
{ //receives variable from create method
$this->load->library('email');
$this->email->from('wengerarsen#gmail.com', 'my site');
$this->email->to($this->input->post('email'));
$this->email->subject('my site - Activate your account');
//copy of activation code returned from create method
$this->email->message('We\'re back, please click the link to activate your account ' . anchor('http://mysite.com/activation/' . $this->activation_code(), 'Activate my account'));
$this->email->send();
}
As you can see I have the same method $activation_code() pulled into my send confirmation email method. This will just generate a whole new code meaning I won't be able to match the database activation code and the URI segment code in the users email.
I have tried to make the variable in the return public and call it in the send confirmaton email method but it doesn't work. The code ends up missing from he end of the URL in the email.
I've tried so many different ways and nothings working.
Maybe I'm missing something here?
Advice, examples etc will be much appreciated.
Every time you're calling activation_code() you're going to be creating a new code, because you're only storing it in the scope of that function.
A better idea would be to store it as an object property, like follows:
public var $_activation_code = null;
public function activation_code() {
if (is_null($this->_activation_code)) {
$this->_activation_code = random_string('alnum', 32);
}
return $this->_activation_code;
}
This will create the code if it hasn't already been done so for this object, or will simply return the current code if the method has been called more than once, meaning the code will be consistent across the object.