Recurring payment with Express Checkout - paypal

TL;DR: I'm trying to implement subscription to my store, but the "paypalobjects.com/api/checkout.js" redirects to "sandbox.paypal.com/webapps/hermes/error". Regular payments work as intended. I'm using Express Checkout advanced server integrations.
My Paypal.Button:
paypal.Button.render({
env: 'sandbox', // Optional: specify 'sandbox' environment
payment: function(resolve, reject) {
const token = localStorage.getItem('_token').split(' ')[1];
if(!subscribe){
var CREATE_PAYMENT_URL = `/store/${store}/paypal/create-payment/${orderId}?token=${token}`;
}else{
var CREATE_PAYMENT_URL = `/store/${store}/subscribe/paypal/create-payment/${orderId}?token=${token}`;
}
paypal.request.post(CREATE_PAYMENT_URL)
.then(function(data) { resolve(data.id); })
.catch(function(err) { console.log(err); });
},
onAuthorize: function(data) {
const token = localStorage.getItem('_token').split(' ')[1];
if(!subscribe){
var EXECUTE_PAYMENT_URL = `/store/${store}/paypal/execute-payment?token=${token}`;
}else{
var EXECUTE_PAYMENT_URL = `/store/${store}/subscribe/paypal/execute-payment?token=${token}`;
}
paypal.request.post(EXECUTE_PAYMENT_URL,
{ paymentID: data.paymentID, payerID: data.payerID })
.then(function(data) {
})
.catch(function(err) { console.log("error " + err);});
},
onCancel: function(data){
cancel();
this.destroy();
},
onError: function (err) {
console.log("ERROR OCCURRED!");
console.log(err);
}
}, '#paypal-button');
Not really relevant, but my backend looks like this(with testdata):
public function createPaypalOrder(Request $request, $store, $orderId){
$order = Order::with(['user', 'whitelabel'])->where('id', $orderId)->first();
$amout = array(
'value' => (string) $order->price/100,
'currency' => 'NOK',
);
$shippingandtax = array(
'value' => '0',
'currency' => 'NOK',
);
$charge_models = array([
'type'=> 'SHIPPING',
'amount'=> $shippingandtax,
],
[
'type'=> 'TAX',
'amount'=> $shippingandtax,
]);
$payment_definitions_creation = array();
array_push($payment_definitions_creation,[
'name' => 'Regular Payment Definition',
'type' => 'REGULAR',
'frequency' => 'MONTH',
'frequency_interval'=> '2',
'amount' => $amout,
'cycles' => '12',
'charge_models' => $charge_models
]);
$format = Config::get('constants.FRONTEND_URL')[env('APP_ENV')];
$redirectBase = sprintf($format, $order->whitelabel->subdomain, 'orders/?order=' . $order->id);
$merchant_preferences_temp = array(
'value' => '0',
'currency' => 'NOK'
);
$merchant_preferences = array(
"setup_fee" => $merchant_preferences_temp,
'return_url' => "http://www.vg.no",
'cancel_url' => "http://www.yahoo.no",
'auto_bill_amount' => 'YES',
'initial_fail_amount_action' => 'CONTINUE',
'max_fail_attempts' => '0'
);
$payment_definitions = array();
array_push($payment_definitions, $payment_definitions_creation);
$name = 'Monthly subscription to ' . (string)$order->whitelabel->title;
$body = array(
'name' => $name,
'description' => 'Subscribtion.',
'type' => 'fixed',
'payment_definitions' => $payment_definitions_creation,
"merchant_preferences"=> $merchant_preferences,
);
$token = $this->getPaypalToken($order);
$client = new \GuzzleHttp\Client();
$response = $client->post('https://api.sandbox.paypal.com/v1/payments/billing-plans', [
'headers' => ['Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $token],
'json' => $body,
]);
$paypalOrderCreation = json_decode($response->getBody());
// add stuff to db
$order->setTransactionId($paypalOrderCreation->id);
return json_encode($paypalOrderCreation);
}
My backend returns a valid response from paypal with the id of the order and the state "CREATED". (And lots of other data..)
{"id":"P-0SE01606VF925501Y2UAKG3Y","state":"CREATED","name":"Monthly subscription to Paypal","description":"Subscribtion.","type":"FIXED","payment_definitions":[{"id":"PD-35U317461H38251442UAKG4A","name":"Regular Payment Definition","type":"REGULAR","frequency":"Month","amount":{"currency":"NOK","value":"500"},"cycles":"12","charge_models":[{"id":"CHM-7T021625H451740052UAKG4A","type":"SHIPPING","amount":{"currency":"NOK","value":"0"}},{"id":"CHM-313690493W320615U2UAKG4A","type":"TAX","amount":{"currency":"NOK","value":"0"}}],"frequency_interval":"2"}],"merchant_preferences":{"setup_fee":{"currency":"NOK","value":"0"},"max_fail_attempts":"0","return_url":"http:\/\/www.vg.no","cancel_url":"http:\/\/www.yahoo.no","auto_bill_amount":"YES","initial_fail_amount_action":"CONTINUE"},"create_time":"2017-01-25T09:41:45.967Z","update_time":"2017-01-25T09:41:45.967Z","links":[{"href":"https:\/\/api.sandbox.paypal.com\/v1\/payments\/billing-plans\/P-0SE01606VF925501Y2UAKG3Y","rel":"self","method":"GET"}]}
Now my problem is that when my paypal.button receives this response it processes the information and redirects me to "sandbox.paypal.com/webapps/hermes/error", which is somewhat hard to debug.
Thanks :)

The problem was an internal issue at Paypal. Works now.

Related

MOODLE ROLES AND CAPABILITIES

I had developed a block in 2.5. I installed the block successfully..and gave permissions settings on front end to view this block only for one role users say 'Manager'. So, Manager/Admin can only view this block and no one else.
But this block is still visible for all. Could you please judge me.. where I went wrong.. Here is my leisure block code
Blocks/block_leisure/block_leisure.php
<?php
class block_leisure extends block_base
{
public function init()
{
global $CFG;
$this->title = get_string('leisure', 'block_leisure');
}
public function get_content()
{
global $COURSE, $DB, $PAGE, $CFG, $USER, $CFG, $SESSION, $OUTPUT;
if ($this->content !== null)
{
return $this->content;
}
$this->content = new stdClass;
$context = $PAGE->context;
$this->content->text = 'This is a leisure block content';
$this->content->footer = 'Footer here...';
return $this->content;
} // Function - get_content().
public function getmodules()
{
return true;
}
}
Blocks/block_leisure/db/access.php
<?php
defined('MOODLE_INTERNAL') || die;
$capabilities = array(
'block/leisure:myaddinstance' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_SYSTEM,
'archetypes' => array(
'user' => CAP_ALLOW
),
'clonepermissionsfrom' => 'moodle/my:manageblocks'
),
'block/leisure:addinstance' => array(
'riskbitmask' => RISK_SPAM | RISK_XSS,
'captype' => 'write',
'contextlevel' => CONTEXT_BLOCK,
'archetypes' => array(
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
),
'clonepermissionsfrom' => 'moodle/site:manageblocks'
),
'block/leisure:viewpages' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_COURSE,
'legacy' => array(
'guest' => CAP_PREVENT,
'student' => CAP_ALLOW,
'teacher' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'coursecreator' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
),
'block/leisure:managepages' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_COURSE,
'legacy' => array(
'guest' => CAP_PREVENT,
'student' => CAP_PREVENT,
'teacher' => CAP_PREVENT,
'editingteacher' => CAP_ALLOW,
'coursecreator' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
)
);
and as usual I have lang folder, version.php and read me file.
You need to do something with the capability you have defined, otherwise it will have no effect.
Check the capability within get_content, then return null if nothing should be displayed.

My ajax Drupal form shows up old values

I have developed ajax drupal and add a form (textfield and button) in it using #ajax key and callback function where I do my process and return my form new element.
So when I starts adding my data form, it works fine for me and form_state['values'] are updated fine.
The problem here is when I reload my form and I add some data, form_state['values'] are not the same in my form fields.
Here is my code:
function my_horoscope_menu() {
$items = array();
$items['admin/horoscopes'] = array(
'title' => 'Horoscopes',
'page callback' => 'drupal_get_form',
'page arguments' => array('my_horoscope_admin_form'),
'access arguments' => array('Administer site configuration '),
//'type' => MENU_LOCAL_TASK,
);
return $items;
}
function my_horoscope_admin_form($form, &$form_state) {
$form['settings']['horoscopes']['add_horoscopes'] = array(
'#type' => 'fieldset',
'#title' => t('Add horoscopes'),
'#collapsible' => TRUE,
'#collaspsed' => TRUE,
);
$form['settings']['horoscopes']['add_horoscopes']['name'] = array(
'#type' => 'textfield',
'#title' => t('Horoscope name'),
'#default_value' => t('Horoscope name'),
'#size' => 20,
'#maxlength' => 60,
'#required' => FALSE,
);
$form['settings']['horoscopes']['add_horoscopes']['beginning_date_rang'] = array(
'#type' => 'date',
'#title' => t('Horoscope beginning date rang'),
'#description' => t('Set the beginning date rang of this horoscope.'),
'#required' => FALSE,
);
$form['settings']['horoscopes']['add_horoscopes']['ending_date_rang'] = array(
'#type' => 'date',
'#title' => t('Horoscope ending date rang'),
'#description' => t('Set the ending date rang of this horoscope.'),
'#required' => FALSE,
);
$form['settings']['horoscopes']['add_horoscopes']['add_button'] = array(
'#type' => 'button',
'#value' => t('Add this horoscope'),
'#submit' => array(''),
'#ajax' => array(
'event' => 'click',
'callback' => 'add_horoscope_ajax_process',
'wrapper' => 'add_horoscope_wrapper',
),
);
$form['settings']['horoscopes']['add_horoscopes']['adding_horoscope_wrapper'] = array(
'#type' => 'markup',
'#prefix' => '<div id="add_horoscope_wrapper">',
'#suffix' => '</div>',
);
return $form;
}
function add_horoscope_ajax_process ($form, &$form_state) {
if (isset($form_state['values'])) {
if (isset($form_state['values']['name']) AND $form_state['values']['name'] != '') {
$name = $form_state['values']['name'];
}
if (isset($form_state['values']['beginning_date_rang']) AND $form_state['values']['beginning_date_rang'] != '') {
$beginning_date_rang = $form_state['values']['beginning_date_rang'];
$beginning_date_rang1 = sprintf("%04d-%02d-%02d", $beginning_date_rang['year'], $beginning_date_rang['month'], $beginning_date_rang['day']);
}
if (isset($form_state['values']['ending_date_rang']) AND $form_state['values']['ending_date_rang'] != '') {
$ending_date_rang = $form_state['values']['ending_date_rang'];
$ending_date_rang1 = sprintf("%04d-%02d-%02d", $ending_date_rang['year'], $ending_date_rang['month'], $ending_date_rang['day']);
}
// Prepare record to add
$record = array(
'h_name' => $name,
'h_date_begin' => $beginning_date_rang1,
'h_date_end' => $ending_date_rang1,
);
// Add the record
$res = drupal_write_record('my_horoscope_structure', $record);
if($res != FALSE) {
drupal_set_message(t('Horoscope #name is inserted successfully!', array('#name' => $name)));
}
}
// return $form
return $form['settings']['horoscopes']['add_horoscopes']['adding_horoscope_wrapper'];
}

Zend_Form not valid but no error messages

i have a strange Problem with one of my Zend_Forms: isValid() correctly states that my form isn't valid but i do not get any error messages. How could that happen?
Heres the code, nothing special here. $data is an array of post data. The problem occurs when no file is sended.
$form = $this->getForm('Foto');
if(!$form->isValid($data)) {
var_dump( $form->getErrors() ); die;
return false;
}
getForm() initializes the form if not allready done. The form itself is pretty straight forward.
class Media_Forms_Foto extends Zend_Form
{
/**
* Initializer function. Setup forms fields.
*/
public function init()
{
$this->setName('add Image');
$this->setAction('media/gallery/addImage');
$this->addElement('Hidden', 'gallery', array(
'filters' => array(),
'validators' => array('Digits'),
'required' => false,
'label' => '',
));
$this->addElement('File', 'foto', array(
'required' => true,
'destination' => ROOT_PATH .'public/upload/tmp/',
'label' => 'Foto',
'validators' => array(
new Zend_Validate_File_IsImage(array(
'image/jpeg', 'image/gif', 'image/png'
))
),
'maxFileSize' => 2097152,
));
$this->addElement('Submit', 'add', array(
'required' => false,
'ignore' => true,
'label' => 'add Foto',
));
$this->setAttrib('enctype', 'multipart/form-data');
}
}
Output:
array(3) {
["gallery"]=>
array(0) {
}
["foto"]=>
array(0) {
}
["add"]=>
array(0) {
}
}
Are you using the jquery form plugin by any chance? if so, try using the iframe mode to upload files:
var options = {
url: '/test/upload',
success: function(response) {
},
beforeSubmit: disableSubmitButtons,
iframe: true,
dataType : 'json'
};
$('#testForm').ajaxForm(options);

sending email with cakephp2

I'm having problems sending a mail with cakephp2, I know I can send emails because I have my postfix configured, and I can send e-mails with command line or php. So please, can you send me an example of cakephp2 sending emails.
This is the error message
Invalid email: "you#localhost"
Error: An Internal Error Has Occurred.
I've also tried with the ssl via gmail and it doesn't work either, and it's giving me a really hard time.
thanks guys
by the way, I'm trying the exact example of this url http://book.cakephp.org/2.0/en/core-utility-libraries/email.html
Your app/config/Email.
class EmailConfig {
public $gmail = array(
'port' => '465',
'timeout' => '300',
'host' => 'ssl://smtp.gmail.com',
'username' => '<your_email>#gmail.com',
'password' => '<you_password>',
'transport' => 'Smtp'
); }
your file = app/controller/appController.php insert this function
public function sendEmail($type, $options){
try {
$Email = new CakeEmail($type);
$Email->config($options);
$Email->template = "email_confirmation";
$Email->emailFormat('html');
//$this->idCrudRash = $options;
$Email->send();
} catch (SocketException $e) {
die('Erro ao enviar email:'. $e->getMessage());
$this->log(sprintf('Erro ao enviar email: %s', $e->getMessage()));
}
}
for user: app/controller/contato.php
$options = array(
'emailFormat' => 'html',
'from' => array(
$config['email_noanswer'] => $config['site_name']
),
'subject' => 'Confirmação de Cadastro',
'to' => $this->request->data['User']['email'],
//'template' => 'default',
'template' => 'email_confirmation',
'viewVars' => array(
'title_for_layout' => 'Confirmação de Email ' . $config['site_name'],
'name' => $this->request->data['User']['name'],
'email' => $this->request->data['User']['email'],
//'cpf' => base64_encode($this->request->data['User']['cpf']),
'site_name' => $config['site_name'],
),
);
$this->sendEmail('gmail', $options);
In your email.php file, please remove the default 'from' value, it overrides your passed param.
public $default = array(
'transport' => 'Mail',
'from' => 'you#localhost', // remove this line
...
);
In app/config/Email
public $smtp = array(
'transport' => 'Smtp',
'from' => array('no-reply#xyz.com' => 'no-reply#xyz.com'),
'host' => 'ssl://smtp.abc.com',
'port' => 465,
'timeout' => 30,
'username' => 'username',
'password' => 'password',
'client' => null,
'log' => false,
);
In Your Controller
App::uses('AppController', 'Controller');
App::uses('CakeEmail', 'Network/Email');
public function index()
{
$this->layout = 'layout';
$this->set('title', "Title");
if ($this->request->is('Post')) {
if (!empty($this->request->data)) {
if ($this->Modal->Save($this->request->data)) {
$to = 'test#anc.com';
$subject = 'Your_subject';
$message = $this->request->data;
if ($this->sendmail($to, $subject, $message)) {
echo"sent";die;
}
} else {
echo"wrong";die;
}
}
}
}
public function sendmail($to = null, $subject = '', $messages = null, $ccParam = null, $from = null, $reply = null, $path = null, $file_name = null)
{
$this->layout = false;
$this->render(false);
$name = $messages['Modalname']['name'];
$email = $messages['Modalname']['email'];
$Email = new CakeEmail();
$Email->config('smtp');
$Email->viewVars(array('name' => $name, 'email' => $email));
$Email->template('comman_email_template', 'comman_email_template');
return $Email->emailFormat('html')
->from(array('no-reply#xyz.com' => 'no-reply#xyz.com'))
->to($to)
->subject($subject)
->send();
}
Create a layout and view for email template.and add the data value that have been sent.

jQuery AJAX request with Zend_Form_Captcha ReCaptcha

I am trying to create an AJAX form with Zend_Form. It all works, except when the form is returned invalid, the ReCaptcha scripts are "filtered" out by jQuery. I have tried several different methods, but to no avail.
Zend Form:
<?php
class Application_Form_Login extends Zend_Form
{
public function init()
{
$this->setName('loginfrm')
->setOptions(array('class' => 'niceform', 'action' => 'login/index'));
$username = $this->addElement('text', 'username', array(
'filters' => array(
'StringTrim',
'StringToLower'
),
'validators' => array(
'Alnum',
array('StringLength', false, array(3,20))
),
'required' => true,
'label' => 'Your Username:'
));
$password = $this->addElement('password', 'password', array(
'filters' => array('StringTrim'),
'validators' => array(
'Alnum',
array('StringLength', false, 6, 32)
),
'required' => true,
'label' => 'Your Password:'
));
$config = new Zend_Config_Ini( APPLICATION_PATH . '/configs/config.ini', 'auth' );
$recaptcha = new Zend_Service_ReCaptcha(
$config->keys->recaptcha->public , $config->keys->recaptcha->private , null, array( 'theme' => 'clean' )
);
$captcha = $this->addElement('captcha', 'captcha', array(
'label' => 'Type the characters you see in the picture below',
'captcha' => 'ReCaptcha',
'captchaOptions' => array(
'captcha' => 'ReCaptcha',
'service' => $recaptcha
)
));
$this->addElement('button', 'submit', array(
'label' => 'Login',
'ignore' => true,
'class' => 'submit'
));
$this->setDecorators(array(
'FormElements',
array('HtmlTag', array('tag' => 'dl', 'class' => 'form')),
array('Description', array('placement' => 'prepend', 'class' => 'errors')),
'Form'
));
}
}
Javascript file: (removed some code to save you time)
//
// Namespace - Module Pattern.
//
var first = (function ($, window, document, undefined) {
// Expose innards of first.
return {
go: function () {
for (var i in first.init) {
first.init[i]();
}
},
init: {
partofcode: function() {
var d = $(document);
// support form submits
d.on('click', 'button', function(ev) {
var form = $(this).closest("form");
first.util.ajax(
form.attr("action"),
form.serialize(),
function(data) {
if(window.debug){ alert(data); }
var topDiv = form.closest(".window_main_full");
topDiv.html(data);
},
"html"
);
});
}
},
util: {
ajax: function(location, data, success, dataType) {
$.ajax({
dataType: dataType,
type: 'POST',
url: location,
data: data,
beforeSend: function() {
// show the loading image
var panel = $('#ajax_panel').show();
panel.html('Loading...');
// center the ajax_panel
panel.css({
'width' : (panel.width() + 25) + 'px',
'margin-left' : (($(window).width() / 2) - (panel.width() / 2 )) + 'px'
});
if(window.debug){ alert("before"); }
},
success: function(data){
if(window.debug){ alert("Before function..."); }
success(data);
$('#ajax_panel').html('').hide();
if(window.debug){ alert("after"); }
},
error: function(xhr, status, error) {
$('#ajax_panel').html('<span class="error"><strong>Oops!</strong> Try that again in a few moments.</span>');
if(window.debug){
alert('XHR: ' + xhr.status + '\nStatus:' + status + '\nError: ' + error);
setTimeout(function() {
$('#ajax_panel').slideUp(500, function() {
$('#ajax_panel').hide();
});
}, 2000);
}
}
});
}
}
};
// Pass in jQuery.
})(jQuery, this, this.document);
//
// Kick things off.
//
jQuery(document).ready(function () {
first.go();
});
I know the whole .html() filtering out scripts has been asked lots of times, but I just can't seem to find a solution.