I am using the BrainTree.js for PCI compliance, and the tutorial I am using here:
https://www.braintreepayments.com/docs/javascript
There recommendation is to call the form by the ID like so:
var braintree = Braintree.create("YourClientSideEncryptionKey");
braintree.onSubmitEncryptForm('braintree-payment-form');
I'm using AngularJS with the form being inside a controller. So inputs such as name, card, etc are tied to a scope using ng-model:
<div class="form-group">
<label>Card Number</label>
<input type="text" class="form-control" name="number" ng-model="card.number" />
</div>
My question is how can I submit a form using AngularJS and BrainTree.js in a manner that uses the data collected using ng-model?
Example:
braintree.onSubmitEncryptForm({name: $scope.card.name, card: $scope.card.number});
In Braintree, the braintree.onSubmitEncryptForm function wraps a small amount of functionality. Basically it just grabs the jQuery form representing the input data, transforms the form fields, and then scrubs them from the DOM, before allowing the request to be submitted to the server.
Since angular includes jQuery, you could call the braintree.encryptForm($('#braintree-payment-form')); which would return the encrypted data in the DOM. You should be able to access the 'ccv' and 'number' input elements like normal (the expire doesn't need to be encrypted).
month=55&year=5555&number=%24bt4%7Cjavascript_1_3_10%24ne0ib
vLjzzck52xzNiY2C8grXaZgpwfVpGrsR9TbHLPaW983e3y7R6tClw8YxYe5w
MA9%2BNHLjPBb%2FEsJQBSiCARJK7Wlxu53GO6mHMr0QMglQEiy9%2B9Dla8
DkY0XBpyfomqniwsDEuudiX7l%2FIb%2FsS4BRFu1BS8MpNpYWSghdj%2FTR
28jhRxlBNZVLjlG9cJd%2FNwDIRUv80qX4Di38bjrvywZR3nP%2BsEcUDSZj
DYQb08LDtN6Vhg5%2FTt1ketZqQH83XheDAFeTuGnb6iE1n8cZbePio8%2FC
m071d2zDZiSc57m%2BEnMJERc%2F2NYrWERl32o4L6DlltB9veZH30mKsPkB
Q%3D%3D%24qpTMCwpQQ5aEk3QO60yu8dQ1SBh3ezit564s1gK604tyIHh%2F
XqipKWgPCli2ZtFW%24AUph2EeuSMh2e8CxNRGVfsIRLvegNAulBDdDY3kwl
GA%3D&cvv=%24bt4%7Cjavascript_1_3_10%24e%2FWsFiRYkHsV%2B6RD5
j26KwII3ErBklZjXB2o1SKGtg1GvemW9J5cSQNBu3K%2BAy0uymAu5awICVR
pIB7%2FiIPBkC8vHBhX57oJabKkCyqkm6YWKio5Pce%2BasD1q4RzGFT1y1Q
iqw%2Fmt12ovQz6G%2B6yZbqQ0wUtFPt4vMSnmQIBogNtgiXeHbirSDHrY9N
V7hoBIaQ%2FV4up87AXs%2FL36FKuBF1rtTyhh%2BEEDgvqkKuRfr6Sim2zc
JNEvcsi7mJp4y6F1%2BNUiLao3w8RfTKt%2BUJUU1XHz3sWLeb2A1chamnFY
UjdVyEgrRFpGH9%2BLdrNYghpmibM6xRsO9p%2Bi1a8yYOMsg%3D%3D%24sd
IGDgI6Jo3zru4YEXtvYI37Oesw09HBISdpcCh6dho%3D%24s8SaRheCM6kWV
OQQ3Ae%2FJjVQQpw6Hht0BWrVIGpV1u4%3D
And then POST to your create_transaction method (if you're running from the tutorial).
Related
I am using Spring Boot and Thymeleaf with some vanilla JavaScript. In my JavaScript, I have an array of strings as below:
var tags = ["ramen", "japanese"];
I want to use JavaScript to dynamically add/remove items in this array before it gets submitted to the backend. The user can add 0..* tags.
Data gets submitted to the backend only via HTML <form> submits. There is also a model attribute which captures these details from the HTML form into Spring called VenueForm.
<form id="tag-form" class="form" method="POST" th:object="${venueForm} th:action="/venue/tag">
VenueForm.java
public class VenueForm {
private List<String> tags;
private Object otherStuff;
...
// Getters and Setters
}
VenueController.java
#Controller
#RequestMapping("/venue/tag")
public class VenueController {
#PostMapping
public String createVenue(#ModelAttribute VenueForm venueForm){
List<String> tags = venueForm.getTags();
System.out.printLn(tag);
return "tags"
}
}
How do I assign the JavaScript array tags to the Thymeleaf form List field tags?
Usually the input comes from th:field="*{tags}" in an input field but because its an array I am not sure how to achieve this. Any help would be much appreciated. Please note jQuery is not an option, only vanilla JS.
I have tried to stop the HTML form submit using JS, then assigning the input field using JS but that did not work.
<input type="submit" value="Submit" th:onsubmit="submitForm(event)">
main.js
function submitForm(event){
event.preventDefault();
venueTagInput.value = JSON.stringify(tags);
console.log("sumitting...");
}
This existing post has helped me figure this out (Send Array using HTML)! Thymeleaf is just a templating engine on the server side, it renders into basic HTML. There is no need to do anything Thymeleaf specific to send an array of elements in the form. You have to follow the basic HTML way using the name attribute on an input field. You can use Javascript to create new DOM elements and making sure that for each element the index is incremented. No changes are needed on the controller side. Spring can work out that name="tags[0]" is tags.get(0);
<input type="text" class="form-control tag" id="1" name="tags[0]" value="">
I'm trying to figure out the best way to submit a form with a complex structure that is dynamically generated in Javascript to a PHP script via the POST method.
The form has this kind of hierarchical structure:
<div class="item">
<textarea class="subitem_textarea"></textarea>
<input type="text"/>
<input type="text"/>
</div>
<div class="item">
<textarea></textarea>
<input type="text"/>
<input type="text"/>
<input type="text"/>
</div>
The number of items is variable and can't be known in advance since items are created by the user. Each item has one <textarea> field, but a variable number of <input type="text"/> fields, since those are also created by the user.
I need to save the content of the form into a database, in a way that preserves this structure, so the PHP script must be able to know which field belong to which item.
I guess that one way to do this is, on the client side (Javascript + jQuery), to arrange for the fields to be given names in such a way that, on the server side (PHP), I can figure that out. For instance, using Javascript + jQuery, I could arrange for the HTML of the form that is dynamically generated on the client side to be:
<div class="item">
<textarea name="textareas[0]"></textarea>
<input type="text" name="texts[0][0]"/>
<input type="text" name="texts[0][1]"/>
</div>
<div class="item">
<textarea name="textareas[1]"></textarea>
<input type="text" name="texts[1][0]"/>
<input type="text" name="texts[1][1]"/>
<input type="text" name="texts[1][2]"/>
</div>
Then, on the server side, I can just recover the structure in PHP by inspecting the $_POST array. However, I can't help but think that I shouldn't have to bother with naming fields in a particular way, that it should be possible to recover the content and structure of the form in a simpler way.
For instance, in order to make various Ajax calls, I already need to store the content and structure of that dynamically created form in a Javascript object as it's being filled, which I send to the server using JSON.stringify when I make the Ajax call and recover in PHP with json_decode
For instance, if I store the content and structure of the dynamically created form in a Javascript object as it's being filled (which I already have to do anyway in order to make various Ajax calls that require that information), perhaps I can somehow use JSON.stringify to send that object to the PHP script that processes the form and use json_decode to get the correct data structure on the server side without the hassle. In fact, I guess I could even do that with another Ajax call that is made when the user clicks on the submit button, instead of doing it through a regular form submission. But I don't suppose it's the best practice and, since I don't have much experience in web development, I want to know what's the best practice to a form with a complex structure dynamically generated in Javascript to a PHP script via the POST method.
EDIT: Just to clarify, since Bilel pointed out I didn't say what I'm planning to do with the data in the form, the PHP script on the server side is going to store the data in the database in a way that preserves the structure.
That's a detailed Question but you didn't told us How are you going to use these collected Data ?
If it's meant to be stored and displayed, then yes you already found the easiest solution by encoding $_POST data with json.
If for example, you could later need relational functionalities like querying User Ages (those being posted through input fields), then you should think about pre-structuring your data. With jQuery/Javascript functions first into a well formatted Json and later Parse the json on the server side to Insert each input field in it's appropriate Database field.
Even, it's against design conventions and space consuming, I do sometimes store the whole json in a separate field near other structured database records. New DBMS can handle json types...
Just to show you an example, I made this function to store a pre-structured json containing Room Information in a booking system, where we can dynamically add extra rooms:
function jss(){
var json = {};
json.rooms = $('.camera').map(function() {
return {
max : $(this).find(".max").val()
, arrange : $(this).find(".arrang").val()
,kids: $('[name^=enf]', this).map(function() {
return {
age: $(this).val()
};
}).get()
, adults: $('[name^=pers]', this).map(function() {
return {
name: $(this).val()
};
}).get()
};
}).get();
return JSON.stringify(json, null, "\t");
}
I wanted to know if it is possible to use a custom form for braintree payment integration. By custom i mean something like this:
<form id="payment-form" method="post" action="/checkout.php">
<div id="customField>{$customField;}</div>
<div id="customField2>{$customField2;}</div>
<input type="submit" value="PAY">
</form>
<script src="https://js.braintreegateway.com/js/braintree-2.31.0.min.js"></script>
<script>
var clientToken = "";
braintree.setup("clientToken", "dropin", {
container: "payment-form"
});
</script>
I want to post my custom fields to checkout.php but it seems the form only returns payment method nonce. I don't want to store any of these custom values in braintree's vault either. Checkout.php just adds all values together (including received payment method nonce) from previous forms in an array and passes these values to .NET server. So is there a way to pass these values to checkout.php?
It looks like this is certainly possible using Braintree's Custom Fields
It looks like, though, you are not properly formatting your form to populate the Drop-In, per your Braintree.setup. The container you are specifying in the braintree.setup will correlate to a div element that will in turn be the drop in, not the ID of the complete payment form.
So, if you have a form that looks like;
<form>
<div id="dropin-container"></div>
</form>
, you'd want your braintree.setup to look like;
braintree.setup('CLIENT-TOKEN-FROM-SERVER', 'dropin', {container: 'dropin-container'});
in order to convert the DIV "dropin-container" into the Drop In.
Custom Fields, though, can be included in the form, but you'll want to make them simply HTML Input elements, as opposed to div elements, that will be returned to your server alongside the nonce.
Hope this helps!
I have a complex form with client and server side validations. lets assume the form is as simple as:
<input type="text" name="name" ng-model="object.name"/>
<div ng-repeat="order in object.Orders">
<input type="text" name="value{{$index}}" ng-model="order.Value"/>
<input type="text" name="descr{{$index}}" ng-model="order.Descr"/>
</div>
The actual form is much more complex than this and all the client side validation is working, my problem is when the user submits the form via an http ajax request then server returns validation errors in json format, like:
{ errors: [ { desc: "Invalid value", path: "object.Orders[0].Value" } ] }
I can easily get the object reference for the path returned by the server but, how can i get the form element so i can mark it invalid within angular?
I particular i wan't to set the form element $invalid. because the form is complex and i have many of thouse forms i wan't to make an automatic way of finding the form element from the object path object.Orders[0].Value.
Can anyone help me with this
Create the new ErrorObjetct and when you get the response assign that error response to that object and use that object like bellow.
<input type="text" name="name" ng-model="object.name"/>
<div ng-repeat="order in object.Orders">
<div>{{ErrorObject.value}}</div>
<input type="text" name="value{{$index}}" ng-model="order.Value"/>
<div>{{ErrorObject.descr}}</div>>
<input type="text" name="descr{{$index}}" ng-model="order.Descr"/>
</div>
if you want to show errors on form level and not field level, then just have some status bar where you can show these errors. It will be quick and a global solution. read here - at very bottom
if you want to show errors on field level and not on form level then you will have to change the format of error message, they should include the name of the property which caused the error + error description
then loop thru the form and each model attached to form and push error to $form.$model.$error array, to have tight integration with server side validation. But this solution would be difficult to make global, given that you might have multiple forms being validated same time. so you might need just one line of code for every form where on error of $http you synchronize errors from server with $form. READ HERE
Its too vast topic to provide a working sample, the links should get you going
I'm trying to setup CSRF protection in asp.net mvc but I'm having problems with the Ajax. It's mind boggling as to why.
I'm using the built in mvc token, which looks like this on the page:
<input name="__RequestVerificationToken" type="hidden" value="gnAeuskcQCq+bjF5bSKg/wyed65M2XNedTPmvKu/+tzCe1GEmIhyeUnurdMgg0ORjfkCBjyOYe78WS6TdJaPSeECTl7w5yjzgwb6TSLjR74cYE4Bd4lJ9YgBGCTyYXur+39inD60jtQh7VciTlM2ap9/YLim/RSCNMxbrs+KMZM=" />
The problem is that when I get the value using jquery it's different to whats on the page. So when I do this:
requestVerifStr = $(document.getElementsByName("__RequestVerificationToken")).val();
I get this value:
X1WV+xrlkKXYjmLZS+OpPfjgeEPGjM/CjOSk0nKwV6iu3rCpHAo2XIDlJcX2ef4hBnK/BYrZw6xICQWqd8a7yJOjngDn1Yf7AKEl2uwLAtMXQQuRJkCzpq+lOWVv1Jyuud6dEIRiaXT0koGDxycps9wQoXvvnMlF1/4G5LDp9Y0=
I'm assuming there's some type of conversion jquery is doing.
It would seem that there are multiple inputs with name="__RequestVerificationToken" and .val() only returns the first result.
Here is an example of how that would happen: http://jsfiddle.net/4qA9V/