When I create a Drupal form with the API and construct the form as necessary, Braintree returns an authentication exception. When I take that same rendered HTML and output it on the page (skip the api), then it works. I can't figure out why!
Below is the code that does not work.
function my_module_menu() {
$items['user/payment/add'] = array(
'title' => t('Add Card'),
'type' => MENU_LOCAL_TASK,
'page callback' => 'drupal_get_form',
'page arguments' => array('my_module_add_form'),
'access arguments' => array('access content'),
'weight' => 2,
);
}
function my_module_add_form() {
global $user;
require_once 'sites/all/libraries/braintree/lib/Braintree.php';
Braintree_Configuration::environment('sandbox');
Braintree_Configuration::merchantId('xxx');
Braintree_Configuration::publicKey('xxx');
Braintree_Configuration::privateKey('xxx');
$customer = Braintree_Customer::find($user->uid);
$trData = Braintree_TransparentRedirect::updateCustomerData(
array(
'redirectUrl' => 'http://www.xxx.com/user/payment',
'customerId' => $user->uid
)
);
$form['#action'] = url(Braintree_TransparentRedirect::url(), array('external' => true));
$form['customer[first_name]'] = array(
'#type' => 'textfield',
'#title' => t('First Name'),
);
$form['customer[last_name]'] = array(
'#type' => 'textfield',
'#title' => t('Last Name'),
);
$form['tr_data'] = array(
'#type' => 'hidden',
'#value' => htmlentities($trData),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save')
);
return $form;
}
if instead I take that exact HTML output and do this with a normal_menu_item and the same credentials as above...
function my_module_menu() {
$items['user/payment/add'] = array(
'title' => t('Add Card'),
'type' => MENU_NORMAL_ITEM,
'page callback' => 'my_module_add_page',
'access arguments' => array('access content'),
'weight' => 2,
);
}
function my_module_add_page() {
global $user;
require_once 'sites/all/libraries/braintree/lib/Braintree.php';
Braintree_Configuration::environment('sandbox');
Braintree_Configuration::merchantId('xxx');
Braintree_Configuration::publicKey('xxx');
Braintree_Configuration::privateKey('xxx');
$customer = Braintree_Customer::find($user->uid);
$trData = Braintree_TransparentRedirect::updateCustomerData(
array(
'redirectUrl' => 'http://www.xxx.com/user/payment',
'customerId' => $user->uid
)
);
$output="
<form accept-charset='UTF-8' id='tqcustom-billing' method='post' action='".Braintree_TransparentRedirect::url()."'>
<div>
<div class='form-item form-type-textfield form-item-customer-first-name'>
<label for='edit-customer-first-name'>First Name </label>
<input type='text' class='form-text' maxlength='128' size='60' value='' name='customer[first_name]' id='edit-customer-first-name'>
</div>
<div class='form-item form-type-textfield form-item-customer-last-name'>
<label for='edit-customer-last-name'>Last Name </label>
<input type='text' class='form-text' maxlength='128' size='60' value='' name='customer[last_name]' id='edit-customer-last-name'>
</div>
<input type='hidden' value='".$trData."' name='tr_data'>
<input type='submit' class='form-submit' value='Save' name='op' id='edit-submit'>
</div>
</form>
";
return $output;
}
it returns fine with a status code of 200. something about drupal_get_form or drupal_render kills the environment that braintree needs to authenticate the form post. What in the world could be causing this? The browser HTML output is 100% exactly the same both ways, but the first way won't authenticate.
Please ask me for details and I'll supply them - desperate to figure this out.
In your first example you are passing the output of Braintree_TransparentRedirect::updateCustomerData through htmlentities before displaying the form. This will cause ampersands to appear as & instead of &. Since the tr_data field is signed with your API key, it must be exactly what is returned from Braintree_TransparentRedirect::updateCustomerData.
Disclaimer: I work for Braintree
Related
I have created a site using CakePHP 3. I have static page which has contact us form something like this:
inside contactus.ctp:
<?=$this->Form->create(); ?>
<?=$this->Form->hidden('form_type',['value' => 'contact']) ?>
<?=$this->Form->input('name',[
'label' => false,
'placeholder' => 'Your Full Name',
'required' => true
]); ?>
<?=$this->Form->input('email',[
'label' => false,
'placeholder' => 'Your Email',
'type' => 'email',
'require' => true
]); ?>
<?=$this->Form->textarea('message',[
'placeholder' => 'Your message...'
]) ?>
<?= $this->Recaptcha->display()?>
<button>Submit Query!</button>
<?=$this->Form->end(); ?>
Using the following link I created Recaptcha:
https://github.com/agiletechvn/Recaptcha
Just beside the Submit button I have Recaptcha.
In the pageController I have the submit check happening:
if($this->request->is(['post']) && $this->request->data('form_type') == 'contact'){
$name = $this->request->data('name');
$email = $this->request->data('email');
$message = $this->request->data('message');
if(!$name){
$this->Flash->set('Please enter a name' . $name,['element' => 'error']);
} elseif (!$email || filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
$this->Flash->set('The email you entered is invalid',['element' => 'error']);
} elseif(!$message){
$this->Flash->set('Message cannot be blank',['element' => 'error']);
} else {
if($this->Recaptcha->verify()) {
$emailObj = new Email();
$emailObj
->from(['contactus#mydomain.com' => 'Developer'])
->replyTo([$email => $name])
->to(['contactus#contactus.com'])
->template('pages/contactus')
->viewVars([
'quickAction' => [
'description' => 'Contact form',
'action' => "from: $name"
],
'name' => 'contactus#mydomain.com',
'senderName' => $name,
'email' => $email,
'message' => $message
])
->subject('Contact email from ' . $name)
->send();
$this->Flash->set('Your message has been sent', ['element' => 'success']);
}
$this->Flash->error(__('Please pass Google Recaptcha first'));
}
If I click submit button I get:
Unexpected field 'g-recaptcha-response' in POST data
I moved the reCaptcha code outside the form. Everything works correctly but the captcha but is sitting outside some random location like this:
How do I solve this issue?
This message can show if you are using CakePHP Security Component, and this component does not recognize one of your form fields. You should unlock this field using:
$this->Form->unlockField('g-recaptcha-response');
More info: CakePHP 3.x Security Component
I would like to make this in my add.ctp.
when user choose the department, on the file form field, only shows the file with the same department that they choose
in my add.ctp
<div class="form-group">
<?php echo $this->Form->input('department', array('class' => 'form-control', 'placeholder' => 'Department', 'options' => array(
'Administrator' => 'Administrator',
'Multimedia' => 'Multimedia',
'Treasurer' => 'Treasurer',
'Marketing' => 'Marketing',
),
'empty' => '(Choose Department)',));?>
</div>
<div class="form-group">
<?php echo $this->Form->input('fail_id', array('class' => 'form-control', 'label' => 'File','placeholder' => 'File Id', 'empty' => '(Choose File)'));?>
</div>
in my controller
public function add() {
if ($this->request->is('post')) {
$this->Borrow->create();
$this->request->data['Borrow']['user_id']= $this->Auth->user('id');
if ($this->Borrow->save($this->request->data)) {
$this->Session->setFlash(__('The borrow has been saved.'), 'default', array('class' => 'alert alert-success'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The borrow could not be saved. Please, try again.'), 'default', array('class' => 'alert alert-danger'));
}
}
$users = $this->Borrow->User->find('list');
$fails = $this->Borrow->Fail->find('list');
$fails = $this->Borrow->Fail->find('list');
$this->set(compact('users', 'fails', 'fails'));
}
thanks for the kindness help.
You have to use ajax post. after user select a department you should send an ajax post with the value of department and get the related files and update second combobox.
I'd like to add a select box for searching with the CakeDC Search Plugin. IE:
<select name="field">
<option value="email">Search By Email</option>
<option value="first_name">Search By First Name</option>
</select>
Currently what I have in my VIEW is:
echo $this->Form->create('User', array(
'url' => array_merge(array('action' => 'index'), $this->params['pass'])
));
echo $this->Form->input('email', array('div' => false, 'empty' => true));
echo $this->Form->input('first_name', array('div' => false, 'empty' => true));
This works just fine this way, but I'd like to avoid the multiple input boxes and simplify it with a select box. I could hard it (take the value from the select box and combine it with the value from the input box), but there has to be another way to do it...
Here is my User Module:
public $filterArgs = array(
'email' => array('type' => 'like'),
'first_name' => array('type' => 'like')
);
And this is my Controller:
public function index() {
$this->Prg->commonProcess();
$this->paginate['conditions'] = $this->User->parseCriteria($this->passedArgs);
$this->set('users', $this->paginate());
}
i think you are looking for
echo $this->Form->input('search', array('div' => false, 'empty' => true));
and
public $filterArgs = array(
'search' => array('type' => 'like', 'field'=>array('email', 'first_name')),
);
and
public $presetVars = true;
but you would lose the "AND" of the two inputs in favor of an OR (this is less powerful).
if thats ok for you, this would be the way.
Working on a Wordpress site and was wondering if anyone could point me in the right direction.
I have the following query_post which filters posts on my template and its working great.
query_posts( array( 'category_name' => 'galoretv', 'post_type' => 'post', 'paged'=>$paged, 'showposts'=>0, ) );
How would I append this to include a check for a specific value from Advanced Custom Fields?
Posts in this category have a radio button with three options 'primary' 'secondary' 'standard'
I want to be able to check against each value i.e if you belong in 'galoretv' and 'standard' do this.
I have the page executing and sorting with the parameters above, just not sure how to add the ACF value. I was able to get it to work using the sticky option but thats gonna work cause i need to have primary and secondar optionality. This is show i had it working with the sticky.
query_posts( array( 'category_name' => 'galoretv', 'post_type' => 'post', 'paged'=>$paged, 'showposts'=>0, 'post__in'=>get_option('sticky_posts')) );
The radio buttons field is called 'landing-grid-placement'
Any thoughts? Been checking the documentation, can't figure it out.
http://www.advancedcustomfields.com/docs/field-types/checkbox/
Thought this would work but it didn't
query_posts( array( 'category_name' => 'galoretv', 'post_type' => 'post', 'paged'=>$paged, 'showposts'=>0, 'landing-grid-placement' => 'primary') );
Any help would be greatly appreciated. This is probably a simple syntax issue but its eluding me and causing me a lot of issues. Been searching for an answer but haven't got it right yet. Thank you advance to whoever reads this and a double thank you to anyone who contributes a solution.
APPENDED CODE PER NOTE BELOW
<?php
$args = array(
'post_type' => 'post',
'category-slug' => 'models-galore',
'showposts'=>1,
'meta_query' => array(
array(
'key' => 'grid_location',
'value' => 'primary',
'compare' => '=',
'type' => 'CHAR'
)
)
);
$query = new WP_Query($args);
if($query->have_posts()) {
while($query->have_posts()) {
$query->the_post();
?>
<li class="span8">
<div class="thumbnail">
<?php echo get_the_post_thumbnail( get_the_ID(), 'media-large-thumb' ); ?>
<h3>
<?php the_title(); ?>
</h3>
</div>
</li>
<?php
}
}
?>
You can do this with a meta_query
Here's the doc
And here's an example:
$args = array(
//...
'post_type' => 'post',
'paged'=>$paged,
//...
'meta_query' => array(
array(
'key' => 'landing-grid-placement',
'value' => 'primary',
'compare' => '=', //default
'type' => 'CHAR' //default
)
)
);
//This is the shoposts option (deprecated since 2.1, now use posts_per_page)
$args['posts_per_page'] = -1; //-1 = infinite
//to add taxonomy
$args['tax_query'] = array(
array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => 'galoretv'
)
);
$query = new WP_Query($args);
if($query->have_posts()) {
while($query->have_posts()) {
$query->the_post();
?>
<li class="span8">
<div class="thumbnail">
<?php echo get_the_post_thumbnail( get_the_ID(), 'media-large-thumb' ); ?>
<h2>
<?php the_title(); ?>
</h2>
</div>
</li>
<?php
}
}
Maybe there is a simpler solution for you :
$args = array(
//...
'post_type' => 'post',
'paged'=>$paged,
//...
'meta_key' => 'landing-grid-placement',
'meta_value' => 'primary',
'meta_compare' => '=' //default
)
);
$query = new WP_Query($args);
if($query->have_posts()) {
while($query->have_posts()) {
$query->the_post();
//do what you would normally do in your loop
}
}
Hi being a newbie to drupal , kindly guide how to add a new user , i know user module with user_save can be used but how and where to implement it ?
Do i have to write this function in submit handler of my custom form below-
function registerme_newform($form, &$form_state)
{
$form = array();
$form['account details'] = array(
'#type' => 'fieldset',
'#title' => t('Account Details'),
'#description' => t('Enter Personal Credentials'),
);
$form['account details']['first name'] = array(
'#type' => 'textfield',
'#title' => t('First Name'),
'#default_value' => t('Be sure of your first name'),
'#attributes' => array(
'onblur' => "if (this.value == '') {this.value = 'Be sure of your first name'}",
'onfocus' => "if (this.value == 'Be sure of your first name') {this.value = ''}"
, ),
);
$form['account details']['last name'] = array(
'#type' => 'textfield',
'#title' => t('Last Name'),
'#default_value' => t('Be sure of your last name'),
'#attributes' => array(
'onblur' => "if (this.value == '') {this.value = 'Be sure of your last name'}",
'onfocus' => "if (this.value == 'Be sure of your last name') {this.value = ''}"
, ), );
$form['account details']['email'] = array(
'#type' => 'textfield',
'#title' => t('E-Mail'),
'#required' => TRUE,
'#default_value' => t('Email acts as username.Dont forget it!'),
'#attributes' => array(
'onblur' => "if (this.value == '') {this.value = 'Email acts as username.Dont forget
it!'}",
'onfocus' => "if (this.value == 'Email acts as username.Dont forget it!')
{this.value = ''}"
, ),
);
$form['account details']['password'] = array(
'#type' => 'password',
'#title' => t('Password'),
'#maxlength' => 60,
'#size' => 60,
'#required' => TRUE,
'#description' => t('Password should be atleast 6 characters long.'),
);
$form['home'] = array(
'#type' => 'fieldset',
'#title' => 'Home Address',
'#description' => t('Enter Personal Residential Credentials')
);
$form['home']['street'] = array(
'#type' => 'textfield',
'#title' => 'Street Address',
);
$form['home']['city'] = array(
'#type' => 'textfield',
'#title' => 'City',
);
$form['work'] = array(
'#type' => 'fieldset',
'#title' => 'Work Address',
'#description' => t('Enter Official Address')
);
$form['work']['street'] = array(
'#type' => 'textfield',
'#title' => 'Street Address',
);
$form['work']['city'] = array(
'#type' => 'textfield',
'#title' => 'City',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Register Me'),
);
return $form;
}
function registerme_newform_validate(&$form, &$form_state)
{
if($form_state['values']['account details']['first name']=='Be sure of your first
name')
{
form_set_error('first name',t('Please enter your first name'));
}
}
function registerme_newform_submit(&$form, &$form_state)
{
dsm($form_state);
}
Also would like to know how will values be entered in database , i mean how will these custom fields be added to database? Kindly guide thanks.
First of all please check if the first name is allowed user name. I recommend you providing another field to enter username as its not uncommon that username is already used by somebody else. Then also check that there are no users registered with the given email address.
function registerme_newform_validate(&$form, &$form_state) {
if($form_state['values']['account details']['first name']=='Be sure of your first
name') {
form_set_error('first name',t('Please enter your first name'));
}
// TODO: Provide user with a chance to enter a name ( drupal user name )
// Also do the following two checks and report an error.
// check using user_load_by_name($form_state['values']['account details']['first anme'])
// check using user_load_by_mail($form_state['values']['account details']['email'])
}
Next in your submit function map the form values to an array that could be passed to user_save as shown bellow. If you want to know exactly how other fields map, use the devel module to inspect the structure by vising an already existing user profile.
function registerme_newform_submit(&$form, &$form_state){
$new_user = array(
// The below name field must be unique.
'name' => $form_state['values']['account details']['name'],
'pass' => $form_state['values']['account details']['password'],
'mail' => $form_state['values']['account details']['email'],
'init' => $form_state['values']['account details']['email'],
'field_first_name' => array(LANGUAGE_NONE => array(array('value' => $form_state['values']['account details']['first name']))),
'field_last_name' => array(LANGUAGE_NONE => array(array('value' => $form_state['values']['account details']['last name']))),
// Map all the extra fields to user objects as shown above.
...
'status' => 1,
'access' => REQUEST_TIME,
'roles' => $roles,
);
// $account returns user object
$account = user_save(null, $new_user);
//after user_save you can use the following code to send notification email.
drupal_mail('user', 'register_no_approval_required', $account->mail, NULL, array('account' => $account), variable_get('site_mail', 'noreply#mysite.com'));
}
I have implemented a different approach to this problem. I created an entity form (https://drupal.org/project/entityform)
where I prompt for key user information. I have also installed the profile2 module allowing me to create alternate profiles. When the form is submitted it triggers a rule. That rule allows me to create the user, create a linked profile and then send an email to the administrator with a link to the new user entry allowing them to review and activate.
A nice alternative if you dont want to solve via PHP or want to create additional content on creation.