Displaying Transaction Id to the customers view - javascript

I've been making an eCommerce laravel system and I've been struggling with showing the customers their transactions Id after they've completed all their payment. I'm using an API to carry out the transaction. After the user has successfully carried out the payment, the transaction Id is then saved to the database. Now, I want to take the transaction id, and display it on the customers view so that they can print an invoice. Here's the controller that's supposed to be handling all the transaction Id:
public function confirmPayment(Request $request){
$request->validate(['transactionId'=>'required']);
$transId = $request->transactionId;
$exists = Payment::where('mpesa_trans_id',$transId)->latest()->first();
if(!$exists){
$error= ["success"=>false, "error"=>"Unable to confirm your transaction code. Please contact admin.. :)"];
session($error);
return back();
}
$message = ["success"=>true, "message"=>"Payment successful!"];
session($message);
return back();
}
Here's how I've tried to display the transaction id on the customers view
<div class="frm-grp">
<label>#lang('Transaction Id')</label>
<input type="text" name="transactionId" placeholder="#lang('Example: OIB9FQP9H7')">
<span class="text-box">Your Transaction Id Is</span>
<span>{{$transId->transactionId}}</span>
</div>
Which also gives me an error 'Undefined variable: transId'. I didn't put the #foreach yet.
Can someone please assist me on figuring out the solution to this problem? This is where the transaction id is supposed to be displayed after the customer makes a payment.

The variables declared in the controller are not automatically available to the view especially as you're doing a redirect.
To pass variables to a view in laravel you need to include them in the second parameter of the view function:
return view('transaction.show', ['transId' => $transId]);
You're redirecting to the previous route however so you can't do that.
Instead you need to make that variable available in some other way.
The previous request data should be available using the old method which I think would work in your case:
<span>{{ old('transId') }}</span>

Related

Setting up flask csrf protection and stripe

I'm following this tutorial from stripe documentation to integrate stripe with flask, but there's some simplicity when it comes to security probably because it's a quickstart.
This following code creates the checkout, and after the user subscribes, the user goes directly to the /success.html and here goes also the CHECKOUT_SESSION_ID which is also the customer id, as you can see below.
checkout_session = stripe.checkout.Session.create(line_items=[{'price': prices.data[0].id,'quantity': 1,},],mode='subscription',success_url=YOUR_DOMAIN +'/success.html?session_id={CHECKOUT_SESSION_ID}',cancel_url=YOUR_DOMAIN + '/cancel.html',)
After that, there is a script inside this article called client.js, with this code:
// In production, this should check CSRF, and not pass the session ID.
// The customer ID for the portal should be pulled from the
// authenticated user on the server.
document.addEventListener('DOMContentLoaded', async () => {
let searchParams = new URLSearchParams(window.location.search);
if (searchParams.has('session_id')) {
const session_id = searchParams.get('session_id');
document.getElementById('session-id').setAttribute('value', session_id);
} });
This code, captures the CHECKOUT_SESSION_ID (also customer id) from /success.html?session_id=CHECKOUT_SESSION_ID so the billing portal can be created.
My question is related to the JS comment, I don't really understand how to pass the csrf instead of the session ID. I already pull the customer ID from the server, but now what should I pass instead? the csrf token? isnĀ“t that supposed to be secret?
Hope anyone can help me. If I missed something please let me know so I can add it up.
I integrated the CSRFProtect library and initiated it with csrf = CSRFProtect() csrf.init_app(app)
I add the <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"> element inside my forms. Then I pulled out the {{ csrf_token() }} when the form got submitted. I store it to pass this token in the /success.html?session_id= instead of the customer id, like this /success.html?session_id={csrf_token}. But I know something is wrong.

Webhooks in Bitcoin Transactions - How to Apply Business Logics?

I want to start accepting Bitcoin on my website.
In order to do that, I wrote the following piece of code, but I truly struggle to understand how I can implement proper business logic after that the transaction is completed.
Here is the code:
<html>
<head>
<title>Pay with Bitcoin</title>
<script>
//Gets the URL of the Webpage and gets the price value of this transaction in USD.
//For simplicity Here the Value is passed in the URL.
//However in production you wanna use POST instead of GET.
const myUrl = window.location.href;
const url = new URL(myUrl);
const usdPrice = url.searchParams.get("price");
//This is the function where all the magin happens
const showQR = () => {
//URL of the api which will provide us with current BTC exchange rate
const apiUrl = "https://blockchain.info/ticker";
const hr = new XMLHttpRequest();
hr.open('GET', apiUrl, true);
hr.onreadystatechange = function(){
//Make sure the API sent a valid response
if(hr.readyState == 4){
let ticker = JSON.parse(hr.responseText);
//Get last BTC/USD exchange value from the API , then convert Price from USD to BTC
let BTCprice = ticker.USD.last;
let btcToPay = usdPrice / BTCprice;
//Make sure you have just 8 decimal points in your BTC price!!
btcToPay = btcToPay.toFixed(8);
//Use google API (or other...) to create the QR code. Pass on your btc public address and
//the amount (btc price) dynamically created. Message and label parameters can be dynamic too.
let qrurl = "https://chart.googleapis.com/chart?chs=250x250&cht=qr&chl=bitcoin:1BAnkZn1qW42uRTyG2sCRN9F5kgtfb5Bci?amount="+btcToPay+"%26label=CarRental%26message=BookingID123456";
//Populate the 'btc' DIV with QR code and other info...
document.getElementById('btc').innerHTML = "<img src=" +qrurl+"><br> <span class = 'greenMoney'>" + usdPrice + " usd / " + btcToPay + " BTC </span>";
}
}
hr.send();
};
</script>
</head>
<body onload = "showQR()">
<h1>Pay with BitCoin</h1>
<div id = "btc">
</div>
</body>
</html>
This code does the following:
Gets current USD/BTC exchange rate using the blockchain API.
takes the price in USD for the URL and converts it into BTC
generates a QR code using google API.
Embeds the price, label and message into the QR code
Renders the QR code in a DIV
I ve also set up a web hook service which will be listening to new transactions happening in the specified wallet address. Then a callback to my server is made, by mean of a POST request.
The problem is: the label and message parameters passed to the QR code will not be written in the blockchain.
They are just a handy reference for the customer to remind him what that specific transaction paid for.
As a result the callback to my server is practically useless.
In fact, the callback doesn't return any Booking Id or any other piece of information which could help me to understand who paid for what. Needless to say, in this scenario no business logic is possible: I can't update the order status on my DB, I can't send a confirmation email to the right customer.
How can I embed relevant information (e.g. Booking ID) into the BTC payment, ideally through the QR code?
If this is possible, how can I retrieve this information later on when my server receives the callback informing me that a new payment was made to my BTC wallet?
In short, you can't.
When accepting payments, you are supposed to give each invoice a new BTC address. This way, when you receive notification of an incoming transaction, you can check the receiving address to see which invoice is being paid, and compare the received amount against the expected amount.
Note
Technically, you could embed stuff like a order ID into an OP_RETURN. However, most wallets don't support transactions like that, and any users who want to pay you from an exchange account would be unable to comply.
#Raghav Sood thank you for your input which routed me to the right direction.
Using NodeJS/Express/MongoDB in the backend, I managed to implement a solution which I would like to share here.
Before starting, I wanna make a big disclaimer: this solution is not the only one, it is not the best one, it is not the fastest and probably it is not the most elegant.
Anyway, this solution has the advantage of not relying on packaged third parties solutions. This is in line with the spirit of the whole "no intermediation" philosophy of the bitcoin community. Most imortantly, your XPub always stay in your server and is NOT shared with any external service, which is probably the wisest approach.
Having said that, here is how one can show dynamic unique BTC addresses to customers:
First of all , I put in place a counter which keeps track of how many btc addresses were created for customers from a my HD wallet.
This is important to make sure than you never present the same address twice to customers, which is good for privacy of all parties and also for the sake of implementing business logic in your app.
In order to do this, I store a "counter value" into my DB. Everytime someone visits the BTC payment page, this value is retrived from mongo using a "dealCount" function and is assigned to a "serialPay" variable, which is equal to the value gotten from Mongo + 1. In the backend, the code would be something like this:
`function dealCount(){`
return new Promise(function(resolve, reject){
Deal.find({_id: "ID_OF_OBJ_WHERE_YOU_STORE_COUNTER"}, function(err, data){
if(err){
console.log(err);
}
resolve(data[0].serialDeal + 1);
})
})
};
The new value obtained (which later on will be saved again into Mongo in order to keep track of addresses created) is used to generate the new BTC public address for the customer at hand. If you keep reading you will see how.
To create new public addresses dynamically, one needs the xPub Key of his or her HD Wallet. If one is coding in NodeJS there are a couple of libraries (which can be imported into the server) that will enable this operation rather easily: bitcoinjs-lib and/or bitcore-lib. Personally I opted for Bitcore-lib, because there are less dependencies to deal with and I found the supporting material easier to digest.
Codewise, address generation goes as follows:
const bitcore = require('bitcore-lib');
app.post("/pay.html", urlencodedParser, function(req, res){
let serialPay = dealCount();
serialPay.then(function(serialPay){
const pub = new bitcore.HDPublicKey('INSERT_HERE_YOUR_XPUB_KEY');
let derivedHdPk = pub.derive('m/0/'+serialPay);
let derivedPk = derivedHdPk.publicKey;
let myDynAddress = new bitcore.Address(derivedPk);
res.render('pay', {myDynAddress: myDynAddress});
});
});
Then, using EJS as a templating engine, I could easily make the receiving bitcoin address dynamic in the front-end (/pay.ejs):
let myDynAddress = "<%=myDynAddress%>";
let qrurl = "https://chart.googleapis.com/chart?chs=250x250&cht=qr&chl=bitcoin:"+myDynAddress+"?amount="+btcToPay+"%26label=CarRental";
This will generate the QR Code Dynamically. In the original question, one can see how to render that into the webpage. In the meantime one should also put in place a function to store the updated "serialPay" counter back to the DB.
At this point one should only start monitoring incoming (non-confirmed) payments to the dynamic BTC address generated. A simple way to do it, is using the blockchain.info websocket API. When the payment arrives, things go forward as suggested by #Raghav Sood: one checks the incoming transaction making sure the customer paid the right amount to the right address.
Now you know who paid for what and all sorts of business logics can be triggered.

Express-session: first user session overwritten by second user session

This is a get request where the user is passed to the view
app.get('/blog/:id', function(req, res) {
// Define which page
res.render('blog', {
user: req.user,
});
});
This is a textarea where all of the users on this page should have their names stored.
<textarea readonly id="usersInRoom" placeholder="<%= user.username %>"></textarea>
This successfully sets the correct username as the placeholder. If a second user renders the same view and visits this page at the same time as the first user, the second user's username will be the only placeholder. How would one store the first username so that when the second user opens the page, the placeholder can be a concatenation of the first username + the second username? The data stored in any embedded javascript arrays etc. by the first user are not available to the second user.
If you are using SignalR, then you could broadcast the current list of users to each connection and update the view like in the sample chat application.
If you are using regular ajax server polling, set a client method on an interval that gets a list of current page users from a database store. Because of http's lack of state, you would have to 'retire' users from the list if they haven't posted in awhile.
Client code:
setInterval(checkServer,5000);
function checkServer(){
//some ajax call to the server here
//that returns your user list
...
success:function(result){
$('#usersInRoom').val(result);
}
}
Server code (assuming you are saving all your current page users in a table
with a field called LastModified):
CurrentPageUser class (store this in your DbContext as the CurrentPageUsers table):
public class CurrentPageUser{
public int Id {get;set;}
public DateTime LastModified {get;set;}
public string Name {get;set;}
}
Controller method:
public string GetCurrentUsers(int selfid){
using (var db=new DbContext()){
var now=DateTime.Now;
//update your requesting user so other users can see him/her
db.CurrentPageUsers.Find(selfid).LastModified=now;
db.SaveChanges();
DateTime timelimit = now.AddMinutes-5);
return string.Join(", ",
db.CurrentPageUsers.Where(u=>
u.LastModified<timelimit).Select(u=>u.Name).ToList());
}
}
Note that the SignalR implementation has much better performance and is less clumsy to implement on the server side with no need for a database table to store the current page users. It was made for this type of scenario.
I found a solution. I did in fact have express-sessions persisting my login sessions. The first session was overwritten by a second user who logged in while the first user was online, which replaced the first user's credentials with the second users, and now I had user 2 online in two different browsers.
Although I tried this on different browsers, from different devices, the problem was that the node app was hosted locally at localhost. When I uploaded the app to heroku and accessed it from there, the user session was not overwritten.

Paypal integration to Flask application

I am slightly misunderstand Paypal flow event after reading https://developer.paypal.com/docs/api/. I'd like to integrate express checkout and credit card payments to my site. I am using Flask and paypalrestsdk without any Flask extensions.
Here is excerpts from my app:
#app.route('/', methods=['GET'])
def index():
# Page with but form, price/quantity/name values
# are stored in hidden fields, "Buy now" acts as submit
return render_template('index.html')
#app.route('/payment/paypal', methods=['POST'])
def payment_paypal():
# Here I am creating dict with required params
payment_template = {
'intent': 'sale',
'payer': {'payment_method': 'paypal'},
'redirect_urls': {
'return_url': url_for('payment_paypal_execute'),
'cancel_url': url_for('payment_paypal_error')
},
......
}
payment = paypalrestsdk.Payment(payment)
if payment.create():
print('Payment "{}" created successfully'.format(payment.id))
for link in payment.links:
if link.method == "REDIRECT":
redirect_url = str(link.href)
print('Redirect for approval: {}'.format(redirect_url))
return redirect(redirect_urls)
#app.route('/payment/paypal/execute', methods=['GET'])
def payment_paypal_execute():
payer_id = request.args.get('payerId')
payment_id = request.args.get('paymentId')
token = request.args.get('token')
pending_payment = PayPalPayment.query.filter_by(token=token).filter_by(state='created').first_or_404()
try:
payment = paypalrestsdk.Payment.find(pending_payment.payment_id)
except paypalrestsdk.exceptions.ResourceNotFound as ex:
print('Paypal resource not found: {}'.format(ex))
abort(404)
if payment.execute({"payer_id": payer_id}):
pending_payment.state = payment.state
pending_payment.updated_at = datetime.strptime(payment.update_time, "%Y-%m-%dT%H:%M:%SZ")
db.session.commit()
return render_template('payment/success.html', payment_id=payment.id, state=payment.state)
return render_template('payment/error.html', payment_error=payment.error, step='Finallizing payment')
It is works fine, after clicking on button payment created succesfully (with state created) user redirected to approval page. There he click "Confirm"... And I never returned to my application, event when I specifying return_url! I.e. application could never be informed that buyer approved payment and it should be updated in my own database and new license should be sent to that person.
Problems:
I cannot find way to define some callback using pyhtonrestsdk. How to do it?
Even if I adding callback (I tried embed Express Checkout using pure Javascript button code) with data-callback my application was not called. I suspect because remote server could not call http://127.0.0.1/payment/paypal/success
User could close window with PayPal confirmation immediately after click "Confirm" so I could not trust browser redirection it it performed somehow later.
Finally, I suspect that I do not understand PayPal workflow clear, but I could not find more information about it event on developers portal.
As usual, devil hides in details. My main issue was following: paypal does not redirects me to my application, but I found that it redirects me (after confirmation) to URL which looks like https://sandbox.paypal.com/ with query string contains desired parameters. I.e. redirect_urls works as expected, just redirects me to wrong host.
After that I remembered that url_for generate relative links. So just added keyword _external=True I've been redirected to my application with all required arguments and payment successfully confirmed and executed.
I.e. correct redirect_urls block will looks like:
'redirect_urls': {
'return_url': url_for('payment_paypal_execute', _external=True),
'cancel_url': url_for('payment_paypal_error', _external=True)
}
Finally I've got following workflow:
Opened / (index) which has button Pay with PayPal It is image button inside form. Beside this button form contains hidden fields with amount, product name and quantity (actually if is not good idea because we cannot trust to user, so I storing only product_license_type_id which stored in DB and contains all required information about product).
Once clicked it POST form to '/payment/paypal' (paypal_create) where create object Payment with filling all fields. If call payment.create finished successfully it also creates record in my own database with payment_id and state (these fields related to paypal workflow, of course actually I am storing couple of other fields related to my app).
Once payment created on PayPal side, application look into response for list payment.links. We want one with rel == 'approval_url' and method == 'REDIRECT' and return flask.redirect(found_link)
On PayPal site buyer should click 'Approve', review shipping address and after that he will be immediately redirected to redirect_urls.return_url with following parameters in query string: PayerID, paymentId, token.
Once redirected back you should get this parameters from query string (keep in mind - it is case-sensitive!), find payment using PayPal API (payment = paypalrestsdk.Payment.find(payment_id)) and finalize it (payment.execute({"payer_id": payer_id}):).
When finalized payment changes status to approved.
....
PROFIT!
UPD: You do not need to turn on "AutoRedirect" in you selling account preferences and this approach suitable for integrating one account into multiple sites.

Multi-Page Order Form with sessions

For my web dev class we have to create a login page, verify it against encrypted records (Id, password) that we have to enter, then step through an order form (while being able to step forward and backward throughout).. so sessions and all that.. I have no idea where to even start aside from coding the html which I've already done.. Any pushes in the right direction would be helpful.. my instructor is abrasive and refuses to help most people without degrading them first.
This is kinda like a longer question.
First at login form you need to check with MYSQL / SQL / DB / etc if the username and password matches.
It's basically like this:
SELECT * from users WHERE username = 'username' AND pass = 'sha1(password)'
Or use the encryption method which you use (md5,sha1,any other for password)
Then you check out if it's returning a row. IF it's return 1 row,then everything is correct.
Then you put all this data to session. I don't know how much you need,but you can put the whole sql result to data. IT doesn't matter here as you said it's a dev class work.
So basically at every of your php you have to start with
session_start();
Then when you verified the user you put the sql result into SESSION like this:
$_SESSION['userdata'] = $sql_row_array;
With this data you can read the current loggedin user's informations. So it's like:
Get username: $_SESSION['userdata']['username']
So you can use this to identify whom bought / ordered the products and insert it into the database.

Categories