I'm looking into taking payments through the Square connect API on a website, but I can't figure out how to allow the user to key in any payment amount they wish (like a PayPal pay me button). Is this possible to do, or can you only take payments in pre-set fixed amounts via Square?
It looks like in Square's examples the amount is being set in the backend code and there's no way to send the amount for the transaction through from the frontend.
I am following Square's walkthrough using Node here: https://developer.squareup.com/docs/payment-form/payment-form-walkthrough
Apologies if this has been asked before, but I couldn't find anything recent that addressed the issue.
If you want to send the amount from the frontend, you would need to submit it via a field in a form (like the nonce in the example you provided). Ie if you wanted the customer to fill out the amount you would have something like:
<form>
...
<input type="text" id="amount" name="amount">
...
</form>
as a field in your form, and then in your backend retrieve it from the amount name (which depends on what backend language you're using, but as an example PHP would be something like $_POST['amount'].
I ended up solving this by coding the fetch to /process-payment explicitly in the frontend .js code instead of having it in the form submit so it looks like this:
function submitPaymentRequest(event) {
let nonce = document.getElementById("card-nonce").value;
fetch("process-payment", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
nonce: nonce,
amount: document.querySelector('input[name="amount"]').value
})
})
.then(response => {
console.log(response);
response.json().then(data => {
console.log(data);
alert(JSON.stringify(data));
});
})
.catch(function(error) {
console.log("the error was", error);
});
}
I posted a full working example of this here.
Yes i face the same issue but i made the solution.
Firstly You make a hidden type field and give them some value e.g 100
**> <input type="hidden" id="amount" name="amount" value="1000" />**
add this line in below your form.Then go to payment-processing page,
**
> string am = Request.Form["amount"];
**
get that input value i am doing in c# so its a c# code.
then pass this am string type variable to Amountmoney section. like below.
var amountMoney = new Money.Builder()
**.Amount(Convert.ToInt64(am))**
.Currency("USD")
.Build();
Here is the full code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Square;
using Square.Models;
using Square.Exceptions;
using Square.Apis;
public partial class process_payment : System.Web.UI.Page
{
private SquareClient client;
public string ResultMessage
{
get;
set;
}
protected void Page_Load(object sender, EventArgs e)
{
client = new SquareClient.Builder()
.Environment(Square.Environment.Sandbox)
.AccessToken("YOUR ACCESS TOKEN")
.Build();
string nonce = Request.Form["nonce"];
string am = Request.Form["amount"];
IPaymentsApi PaymentsApi = client.PaymentsApi;
var amountMoney = new Money.Builder()
.Amount(Convert.ToInt64(am))
.Currency("USD")
.Build();
string idempotencyKey = NewIdempotencyKey();
var body = new CreatePaymentRequest.Builder(
sourceId: nonce,
idempotencyKey: idempotencyKey,
amountMoney: amountMoney)
.Build();
CreatePaymentRequest createPaymentRequest = new CreatePaymentRequest.Builder(nonce, idempotencyKey, amountMoney)
.Note("From Square Sample Csharp App")
.Build();
try
{
CreatePaymentResponse response = PaymentsApi.CreatePayment(createPaymentRequest);
this.ResultMessage = "Payment complete! " + response.Payment.Note;
}
catch (ApiException es)
{
this.ResultMessage = es.Message;
}
}
private static string NewIdempotencyKey()
{
return Guid.NewGuid().ToString();
}
}
Related
I would like to "authorize" via the .NET framework using my own API keys, secret and Refresh Token, and then pass the Access Token to JavaScript so I can upload a video directly to YouTube with a progress indicator.
I have working code via the .NET API that will accomplish the upload directly to my channel [without authorization], but you get no progress indication (and it can take quite some time) and the file must be uploaded to my server first, then to YouTube server.
Is a server side access code different from a client side access code? If not:
How can I obtain the access code server side? (get the string)
***How can I pass it to Google APIs via JavaScript? (not how to write <%= access code %> but where to pass it in?)
I am well aware of the security risk in exposing the access token, but these do expire right? (as a bonus, how can I shorten the expire time). This is also being done inside a password protected web page, and you don't get the 'client secret' or 'refresh token'
***update - I think I found where to pass in the token, in the MediaUploader object.
var uploader = new MediaUploader({
baseUrl: 'https://www.googleapis.com/upload/youtube/v3/videos',
file: selectedFile,
token: token, // ***RIGHT HERE***
metadata: metadata,
params: params,
onError: function(data) {
Okay, so after weeks of smashing my way through the APIs, .NET, and JavaScript documentation I have built the following solution....
As per the YouTube V3 Developer documentation get your Keys all set up. (choose OAuth, Web Application, and enter URIs for both your Javascript and Redirect code)
Next use the OAuth Playground to obtain your Refresh Code
Once you have your client_id, client_secret, and refresh_token you are ready to rock!
This code makes a simple HTTP/REST call via the code behind to obtain an access_token which is good for 3600 seconds (the default). It then passes this string to the JavaScript code for use ****WARNING****
This does not use any of the .NET or JavaScript Libraries with the exception of one file, the cors_upload.js available on GitHub
Allas, the code
Default.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ApisCallTest.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta charset="utf-8" />
<title>YouTube API Uploads via CORS</title>
<style>
#disclaimer {
font-size: 0.75em;
color: #aeaeae;
max-width: 350px;
}
.during-upload { display: none; }
label { display: block; }
input[type="text"],
textarea,
progress {
font-size: 16px;
width: 15em;
margin-bottom: 1em;
padding: 0.5em;
font-family: "Open Sans", sans-serif;
}
</style>
</head>
<body>
<div>
<input input type="file" id="file" class="button" accept="video/*" />
<button id="button">Upload Video</button>
</div>
<div class="during-upload">
<p><span id="percent-transferred"></span>% done (<span id="bytes-transferred"></span>/<span id="total-bytes"></span> bytes)</p>
<progress id="upload-progress" max="1" value="0"></progress>
</div>
<p id="disclaimer">By uploading a video, you certify that you own all rights to the content or that you are authorized by the owner to make the content publicly available on YouTube, and that it otherwise complies with the YouTube Terms of Service located at http://www.youtube.com/t/terms</p>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="cors_upload.js"></script>
<script>
$('#button').on("click", goForUpload);
function goForUpload() {
if ($('#file').get(0).files[0]) {
$('#button').attr('disabled', true);
var uploadStartTime = 0;
var metadata = {
snippet: {
title: 'PUT YOU TITLE HERE',
description: 'THIS IS YOUR VIDEO DESCRIPTION',
categoryId: '22'
},
status: {
privacyStatus: 'unlisted'
}
};
var uploader = new MediaUploader({
baseUrl: 'https://www.googleapis.com/upload/youtube/v3/videos',
file: $('#file').get(0).files[0],
token: '<%= access_token %>',
metadata: metadata,
params: {
part: Object.keys(metadata).join(',')
},
onError: function (data) {
var message = data;
// Assuming the error is raised by the YouTube API, data will be
// a JSON string with error.message set. That may not be the
// only time onError will be raised, though.
try {
var errorResponse = JSON.parse(data);
message = errorResponse.error.message;
} finally {
alert(message);
}
},
onProgress: function (data) {
var currentTime = Date.now();
var bytesUploaded = data.loaded;
var totalBytes = data.total;
// The times are in millis, so we need to divide by 1000 to get seconds.
var bytesPerSecond = bytesUploaded / ((currentTime - this.uploadStartTime) / 1000);
var estimatedSecondsRemaining = (totalBytes - bytesUploaded) / bytesPerSecond;
var percentageComplete = (bytesUploaded * 100) / totalBytes;
$('#upload-progress').attr({
value: bytesUploaded,
max: totalBytes
});
$('#percent-transferred').text(percentageComplete);
$('#bytes-transferred').text(bytesUploaded);
$('#total-bytes').text(totalBytes);
$('.during-upload').show();
},
onComplete: function (data) {
var uploadResponse = JSON.parse(data);
alert('all done, you can store this id: ' + uploadResponse.id)
}
});
uploadStartTime = Date.now();
uploader.upload();
}
}
</script>
</body>
</html>
and Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace ApisCallTest
{
public partial class WebForm1 : System.Web.UI.Page
{
private static readonly HttpClient client = new HttpClient();
public string access_token;
protected void Page_Load(object sender, EventArgs e)
{
var values = new Dictionary<string, string>
{
{ "client_id", "REPLACE_ME" },
{ "client_secret", "REPLACE_ME" },
{ "refresh_token", "REPLACE_ME" },
{ "grant_type", "refresh_token" }
};
var content = new FormUrlEncodedContent(values);
var response = client.PostAsync("https://www.googleapis.com/oauth2/v4/token", content);
string json = response.Result.Content.ReadAsStringAsync().Result;
dynamic obj = JObject.Parse(json);
access_token = obj.access_token;
}
}
}
The result... From a password protected web page I can have a user upload a video to MY channel, unlisted, and store the video ID to later embed that video back on my website.
as for the ****WARNING****, this is somewhat of a security concern as you are exposing (very directly) your PERSONAL access key to the "public". It only lasts for 1 hour, but gives whatever "scope" of access you are using to "anyone" It would be a good idea to try and obstuficate the key somewhat, and at the very least, don't do this on a publicly available page.
I am using STS 3.9.0 Tool, my project based on Spring Boot, Thymeleaf,
Mysql, Html-Bootstrap and JQuery.
I am showing a dropdown component as apartment list which is taken from thymeleaf,which holds entity values, so I am showing apartment name, But passing entity of particular(selected) apartment only.
But I am posting the data using JQUERY via Ajax call..
I have done the code like below
HTML code..
<div class="form-group">
<label for="societyname">Society Name</label>
<select id="societyname" class="form-control">
<option th:each="propertydetails:${propertydetails}" th:value="${propertydetails}" th:text="${propertydetails.propertyname}">
</option>
</select>
</div>
Jquery
var formData = {
entPropertyMaster : $("#societyname").val(),
}
alert(JSON.stringify(formData));
// DO POST
$.ajax({
type : "POST",
contentType : "application/json",
url : url+"/saveflat",
data :JSON.stringify(formData),
dataType : 'json',
success : function(result) {
if(result.status == "saved") {
$("#resultid").html("<strong>" +result.dataObj.flatname+ " Registered Successfully!" );
} else {
$("#resultid").html("<strong>Error</strong>");
}
alert(result.status);
console.log(result);
},
error : function(e) {
alert("Error!");
alert(url);
console.log("ERROR: ", e);
}
});
#controller
//To save the flat registration details
#PostMapping("/saveflat")
public ResponseMsg doSaveFlatDetails(#ModelAttribute EntFlatMaster flatDetails) {
ResponseMsg responsemsg = new ResponseMsg();
EntFlatMaster flatMaster = new EntFlatMaster();
try {
String logResponse = null;
/*for Master*/
if(flatDetails!=null) {
flatMaster = serflatDetails.doSaveFlatDetails(flatDetails);
/*for Log*/
if(flatMaster!=null) {
logResponse = doSaveLogFlatDetails(flatDetails,flatMaster.getPkflatid());
}
/*for response message to web for master and Log both are saved checking process*/
if(logResponse.equals("saved")) {
responsemsg = new ResponseMsg("saved",flatMaster);
} else {
responsemsg = new ResponseMsg("failed",flatMaster);
}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
responsemsg = new ResponseMsg("failed",flatMaster);
}
return responsemsg;
}
#Entity
#Entity
#Table(name="flatdetails")
public class EntFlatMaster implements Serializable {
private static final long serialVersionUID = 7066060644146063944L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="pkflatid")
private int pkflatid;
#OneToOne
#JoinColumn(name="fkpropertymasterid")
private EntPropertyMaster entPropertyMaster = new EntPropertyMaster();
}
Please Help to solve this...Thank You
Can you please be more specific with errors you are facing? Stacktrace and so on?
Firstly your Thymeleaf code is wrong, use the below:
<div class="form-group">
<label for="societyname">Society Name</label>
<select id="societyname" class="form-control">
<option th:each="pd :${propertydetails}" th:value="${pd.id}"
th:text="${pd.propertyname}"></option>
</select>
</div>
Look at the th:value="${pd.id}" this will hold the identifier for your property.
While building the form data you need to use pkflatid and not entPropertyMaster
I have a script that renders a partial view after its data is loaded, but I want at least one other partial view to load using the same data. It's a long-running query (30sec - 1min), so I don't want to load it for each partial view. Or am I going down the wrong path? It should be noted I'm still pretty new to ASP.Net and very new to Javascript/Jquery, so I'm not totally aware of best practices, so if you spot something that's "against convention", please let me know that, too.
EDIT: It dawned on me I should note what I'm trying to eventually get to. In my current non-ASP app (C#/XAML), it loads the data (with an equivalent of LoadMonitorData method, below) when the app loads, then refreshes every 15 minutes. Or the refresh can be triggered by a Refresh button.
Here's what I've got so far...any help or guidance would be greatly appreciated.
Index.cshtml
#{
ViewBag.Title = "MMCView";
}
#section scripts {
<script type="text/javascript">
$(document).on('click', '[name^=project]', function () {
if ($(this).hasClass('selected')) {
$('.mig-project').removeClass('selected').removeClass('low-opacity').addClass('full-opacity');
$('#data-area').removeClass('show-data-view');
}
else {
$(this).addClass("selected").addClass('full-opacity').removeClass('low-opacity');
$('.mig-project').not(this).removeClass("full-opacity").removeClass('selected').addClass("low-opacity");
$('#data-area').load($(this).data("url"));
$('#data-area').addClass('show-data-view');
}
})
</script>
<script type="text/javascript">
$(document).ready(function(e) {
$("#list-container").each(function(index, item) {
var url = $(item).data("url");
if (url && url.length > 0) {
$(item).load(url);
}
})
})
</script>
}
<div class="project-list slow-load" id="list-container" data-url="/mmc/projectpanes">
<img src="loading.gif" />
</div>
<div class="hide-data-view slow-load" id="data-area" data-url="/mmc/projectdata"></div>
MMCController.cs
using MMC_ASP.Models;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.Script.Serialization;
namespace MMC_ASP.Controllers
{
public class MMCController : AsyncController
{
MonitorData downloadedInfo = new MonitorData();
//GET: MMC
public ActionResult Index()
{
return View();
}
public ActionResult ProjectPanes()
{
downloadedInfo = LoadMonitorData();
return PartialView("_ProjectPanes", downloadedInfo.MainPanel.OrderBy(o => o.Client).ToList());
}
public ActionResult ProjectData(string server)
{
return PartialView("_ProjectData", downloadedInfo.Information.Where(x => x.ServerName == server).ToList());
}
public ActionResult MainWindowMonitor()
{
return PartialView("_MainWindowMonitor", downloadedInfo.MonitorText);
}
public MonitorData LoadMonitorData()
{
MonitorData deserializedData = null;
using (WebClient wc = new WebClient())
{
wc.Encoding = Encoding.Unicode;
string location = "http://MYWEBAPI-RETURNS-JSON";
string data = wc.DownloadString(new System.Uri(location));
var deserializer = new JavaScriptSerializer();
deserializedData = deserializer.Deserialize<MonitorData>(data);
}
return deserializedData;
}
}
}
In this situation, the Cache object might be useful to you. You can store your data in the Cache, set it to expire after a reasonable amount of time, write a helper function to re-pull the data on the fly if the cached data has expired, and have your partial views pull their data from the helper function. This way, the new data will only be pulled as needed, regardless how many views are using it, and as a bonus you have easy control over how often to re-execute that expensive query.
Note that this works well in your situation because your data is global in nature. If you were passing user-specific parameters into your query, then Cache wouldn't be a good fit.
using System.Web.Caching;
private MonitorData getCachedData()
{
var cache = this.HttpContext.Cache;
if (cache["MonitorData"] == null)
cache.Add("MonitorData", LoadMonitorData(), null, DateTime.Now.AddMinutes(15), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); // 15 minute cache expiration, as example
return (MonitorData)cache["MonitorData"];
}
public ActionResult ProjectPanes()
{
downloadedInfo = getCachedData();
return PartialView("_ProjectPanes", downloadedInfo.MainPanel.OrderBy(o => o.Client).ToList());
}
public ActionResult ProjectData(string server)
{
downloadedInfo = getCachedData();
return PartialView("_ProjectData", downloadedInfo.Information.Where(x => x.ServerName == server).ToList());
}
public ActionResult MainWindowMonitor()
{
downloadedInfo = getCachedData();
return PartialView("_MainWindowMonitor", downloadedInfo.MonitorText);
}
The solution that Joe_Irby proposed works great! However, while communicating with him I found another approach that works as well. I figured I'd include it here so anyone else looking for a solution can decide which one will be best for their situation.
https://code.msdn.microsoft.com/Caching-In-Web-API-cb40be30
I have a Winforms form with a WebBrowser control on it.
I've already figured out how to connect the C# code to the Javascript in the Web Browser control by attaching an instance of a C# class to the ObjectForScripting property, like this:
public partial class Browser : Form
{
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
webBrowser1.ObjectForScripting = new ScriptInterface();
}
}
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[ComVisible(true)]
public class ScriptInterface
{
public void DoSomething(string data)
{
// Do something interesting with data here
}
}
... and then call it from the Javascript like this:
<button onclick=window.external.DoSomething('with this')/>
What I haven't figured out yet is how to capture the result of a POST operation from a form in the WebBrowser control, and use it in my C# code.
You could perhaps use jQuery post instead of a form post.
Assuming your form has an id of myForm:
$( "#myForm" ).submit(function( event ) {
// Stop form from submitting normally
event.preventDefault();
// Get some values from elements on the page:
var $form = $(this),
var term = $form.find("input[name='s']").val(),
var url = $form.attr("action");
// Send the data using post
var posting = $.post( url, { s: term } )
.done(function(data) {
//Pass the response back to your code
window.external.DoSomething(data);
});
});
I have a registration form where I am validating the "preferred login id" using AJAX so it searches the users table and shows if it's available or not, and it displays next to the text box "username available" or "username not available".
My requirement is when it's not available I want to pass the text "username not available" back to the javascript in the JSP from the Servlet so that I can stop the user from proceeding the form. I believe I can do it using AJAX. But I dont know how to do it. Could someone help me on this with the code?
I would use JQuery, and the get() method in particular as an example
Here is a pseudo solution (didn't test it, but it's the basic approach I would use)
JavaScript
var userIsAvailable = false;
function checkUsernameAvailability(userIdToCheck){
$.get("pathToServlet",{userId: userIdToCheck},function(resultMessage){
userIsAvailable = resultMessage=="username available" //this is bad practice, just an example, pass true/false
$("#userAvailabilityMessage").text(resultMessage);
}
});
HTML
<form onsubmit="if(!userIsAvailable){alert('user is not available')}; return userIsAvailable">
<label for="userId">preferred login id<label>
<input id="userId" ... type="text" onblur="checkUsernameAvailability(this.value)">
<div id="userAvailabilityMessage" />
...
</form>
Servlet (partial)
#WebServlet("/pathToServlet")
public class MyServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String result;
if(isUserNameAvailable(request.getParameter("userId"))){
result = "username available";
}else{
result = "username not available";
}
response.setContentType("text/plain");
response.getWriter().print(result);
}
}
You need to send object with some flag in message. You can use json for this.
On servlet side:
// This object we will transfere from java to javascript
public class Message {
private boolean error;
private String errorMessage;
// Getters and setters ommited
}
// Servlet code - return content
Message message = new Message();
message.setError(true);
message.setErrorMessage("Your error message");
Gson gson = new Gson(); // GSON - java json library from Google. I prefer it
String content = gson.toJson(message);
response.setContentType("text/json");
response.getWriter().print(content);
And finally javascript code:
function processRequest() {
var result = jQuery.ajax ({
url: "your.url",
method: "post",
async: false,
data: "your=data&andsomedate=somedata"
});
// Creating object from json
var message = jQuery.parseJSON(result.responseText);
// Now we can access all object fields:
if(message.error) {
alert("Error message: " + message.errorMessage);
}
}