Zend Framework: Paypal - zend-framework

I have been attempting to implement a paypal functionality into my application by following the example here: http://www.alexventure.com/2011/04/02/zend-framework-and-paypal-api-part-2-of-2/
This is my paymentAction in my controller.
public function paymentAction()
{
$auth= Zend_Auth::getInstance();
$user= $auth->getIdentity();
$username = $user->username;
$cart = new Application_Model_DbTable_Cart();
$select = $cart->select()
->from(array('c' => 'cart'))
->join(array('p' => 'product'), 'p.productid = c.productid')
->where('username = ?', $username)
->setIntegrityCheck(false);
$fetch = $cart->fetchAll($select)->toArray();
$paypal = new My_Paypal_Client;
$amount = 0.0;
foreach($fetch as $item) {
$amount = $amount + ($item['price']*$item['quantity']);
}
$returnURL = 'http://www.google.com';
$cancelURL = 'http://www.yahoo.com';
$currency_code = 'USD';
$reply = $paypal->ecSetExpressCheckout(
$amount,
$returnURL,
$cancelURL,
$currency_code
);
if ($reply->isSuccessfull())
{
$replyData = $paypal->parse($reply->getBody());
if ($replyData->ACK == 'SUCCESS' || $replyData->ACK == 'SUCCESSWITHWARNING')
{
$token = $replyData->TOKEN;
$_SESSION['CHECKOUT_AMOUNT'] = $amount;
header(
'Location: ' .
$paypal->api_expresscheckout_uri .
'?&cmd=_express-checkout&token=' . $token
);
}
}
else
{
throw new Exception('ECSetExpressCheckout: We failed to get a successfull response from PayPal.');
}
}
However, this is the error that returns.
Message: No valid URI has been passed to the client
Where did i go wrong? I would be happy to provide code from other areas of my application if needed. Thanks.

Zend_Http_Client::request() has not received a valid instance of Zend_Uri_Http.
Here's where the error occurs:
/**
* Send the HTTP request and return an HTTP response object
*
* #param string $method
* #return Zend_Http_Response
* #throws Zend_Http_Client_Exception
*/
public function request($method = null)
{
if (! $this->uri instanceof Zend_Uri_Http) {
/** #see Zend_Http_Client_Exception */
require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception('No valid URI has been passed to the client');//Note the exact message.
}//Truncated
The only obvious error I see in the code you provided is :
$paypal = new My_Paypal_Client;//no () at end of declaration
I hope you implemented part one of the tutorial where the constructor is built. Otherwise you may just need to pass a better uri.
[EDIT]
I think your problem is here:
//needs a uri value for Zend_Http_Client to construct
$paypal = new My_Paypal_Client($url);
ecSetExpressCheckout does not construct the http client so it has no idea of where it's requesting the token from.
Alternatively you could just add this line below $paypal and above $reply:
//pass the uri required to construct Zend_Http_Client
$paypal->setUri($url);
I just hope you know what the url shouild be.
Good Luck.

Related

How to use createUser in Facebook Ads (to replace deprecated addUsers)

Now that I've upgraded to "facebook/php-ads-sdk": "2.8.*" (https://github.com/facebook/facebook-php-ads-sdk), this function of mine doesn't work anymore:
public function addToCustomAudience($entriesArray, $audienceId, $inputType = CustomAudienceTypes::EMAIL) {
$audience = new CustomAudience($audienceId);
$result = $audience->addUsers($entriesArray, $inputType);
return $result;
}
Apparently addUsers is no longer available.
I see a createUser function, but it looks quite different, and there is no documentation online about how to migrate from addUsers to createUser.
What I want to do is simple.
Given an array of email addresses and an ID of an audience, how can I add all of those email addresses to that Facebook Custom Audience?
From what I can see in the code, addUsers is still there, and it's documented on the Developer site.
I just used the latest SDK along with the following code to update an audience:
use FacebookAds\Object\CustomAudience;
use FacebookAds\Object\Values\CustomAudienceTypes;
$emails = array(
'test1#example.com',
'test2#example.com',
'test3#example.com',
);
$audience = new CustomAudience(<CUSTOM_AUDIENCE_ID>);
$audience->addUsers($emails, CustomAudienceTypes::EMAIL);
This seems to work for my purposes.
I copied some code from the facebook-php-ads-sdk as a workaround.
$audience = new CustomAudience($audienceId);
$params = $this->formatParams($entriesArray, $inputType, [], false);
$audience->createUser([], $params, false);
/**
* Copied this from Facebook's https://github.com/facebook/facebook-php-ads-sdk/blob/d51193b19d730ae9274d45540986e1ac311b074d/src/FacebookAds/Object/CustomAudience.php#L363
* Take users and format them correctly for the request
*
* #param array $users
* #param string $type
* #param array $app_ids
* #param bool $is_hashed
* #return array
*/
protected function formatParams(array $users, $type, array $app_ids = array(), $is_hashed = false) {
if ($type == CustomAudienceTypes::EMAIL || $type == CustomAudienceTypes::PHONE) {
$normalizer = new EmailNormalizer();
$hash_normalizer = new HashNormalizer();
foreach ($users as &$user) {
if ($type == CustomAudienceTypes::EMAIL) {
$user = $normalizer->normalize(CustomAudienceTypes::EMAIL, $user);
}
if (!$is_hashed) {
$user = $hash_normalizer->normalize(
CustomAudienceTypes::EMAIL, $user);
}
}
}
$payload = array(
'schema' => $type,
'data' => $users,
);
if ($type === CustomAudienceTypes::ID) {
if (empty($app_ids)) {
throw new \InvalidArgumentException(
"Custom audiences with type " . CustomAudienceTypes::ID . " require"
. "at least one app_id");
}
$payload['app_ids'] = $app_ids;
}
return array('payload' => $payload);
}

Creating an attachment for MailMessage

From my extbase 6.2 extension I want to send different e-mails.
In a controller class I wrote a mail function that looks like this:
(notice no #param for $attachment - see my question at the end)
/**
*
* #param string $to
* #param string $subject
* #param string $email_prefix
* #param string $msg
* #param string $email_suffix
*/
public function mailAction($to, $subject, $email_prefix, $msg, $email_suffix, $attachment = null) {
try {
$from = \TYPO3\CMS\Core\Utility\MailUtility::getSystemFrom();
$body = $email_prefix
. PHP_EOL . PHP_EOL
. $msg
. PHP_EOL . PHP_EOL
. $email_suffix;
$htmlBody = nl2br($body);
$toEmail = $to;
$mail = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
$mail->setFrom($from)
->setTo(array($toEmail))
->setSubject($subject)
->setBody($htmlBody, 'text/html');
$mail->addPart($body, 'text/plain');
if ($attachment) {
$mail->attach($attachment);
}
if (empty($toEmail) || strpos($toEmail, '#') === FALSE) {
$this->addFlashMessage('Die Mail konnte nicht verschickt werden! Keine Email-Adresse des Empfängers', '', \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
);
} else {
if ($mail->send()) {
$this->addFlashMessage('Die Mail für wurde verschickt!', '');
} else {
$this->addFlashMessage('Die Mail konnte nicht verschickt werden!', '', \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
);
}
}
$this->redirect('list');
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
}
In a function that calls the mail function I tried creating an attachment like this but it failed saying: Fatal error: Class 'Swift_Attachment' not found in.../...Controller.php
$attachment = \Swift_Attachment::newInstance()
->setFilename('Termine.html')
->setContentType('text/html')
->setBody($emailView->render());
Then I call the mail function like this:
$this->redirect('mail', null, null, array(
$to,
$subject,
$email_prefix,
$msg,
$email_suffix,
$attachment));
My questions:
How can I successfully create an object of type Swift_Attachment in a controller of my extbase extension (without creating a MailMessage object beforehand and creating the attachment inside of it)?
What should I put after #param as the type of my $attachment variable in my mail function for this to work?
-- EDIT --
Ok, so apparently no one does that because it's not meant to be.
I now used Rene's approach combining it with Dimitri's scalable answer for multiple attachments. My #param is now array because I have to create the actual attachment after instantiating MailMessage - thanks!
In my extension for 6.2.25 ist works without any including:
$email->attach(\Swift_Attachment::newInstance(
$emailView->render(),
'Termine.html',
'text/html'
));
So you should check why your autoload of classes don't work. Have you tried to clear the cache complete?
To your second question: the correct param declaration should be:
#param \Swift_Mime_Attachment $attachment
But I wouldn't make an redirect, but an $this->forward. You don't need an redirection on client side for this. If this action is only called by an other action I also recommend to make it an protected function an call it directly from your action:
$this->sendMail($to, $subject, $email_prefix, $msg, $email_suffix, $attachment)
-- EDIT --
I recommend to use bypass the attachment information to the function to create the attachment object after the SwitftMailer was initialized:
/**
*
* #param string $to
* #param string $subject
* #param string $email_prefix
* #param string $msg
* #param string $email_suffix
* #param array $attachment
*/
public function mailAction($to, $subject, $email_prefix, $msg, $email_suffix, $attachment = null) {
...
if (is_array($attachment) && array_key_exist('content', $attachment) && array_key_exist('filename', $attachment) && array_key_exist('mime', $attachment)) {
$mail->attach(\Swift_Attachment::newInstance($attachment['content'], $attachment['filename'], $attachment['mime']));
}
...
}
In \TYPO3\CMS\Core\Mail\MailMessage there is a require_once for the swiftmailer classes; they don't seem to be autoloaded. Maybe you can pass the attachment as rendered HTML and create the Swift_Attachment object after instantiating the MailMessage object?
If the solution in 1. works it would be a simple string.
As already stated by Jigal van Hemert you can only create the attachment objects after you create the MailMessage object because the class is not autoloaded. I would just pass the attachment as a filepath to your mail function and it should be handled there and not outside.
if ($attachment) {
$email->attach(\Swift_Attachment::fromPath($attachment));
}
In my opinion it makes more sense if you can pass multiple files instead of one, so the $attachment should be an $attachments array
if(count($attachments)) {
foreach ($attachments as $name => $file) {
if(file_exists($file)) {
if(trim($name) && !is_numeric($name)) {
$email->attach(\Swift_Attachment::fromPath($file)->setFilename($name));
} else {
$email->attach(\Swift_Attachment::fromPath($file));
}
}
}
}

Emails are not send to the user

I have a problem with sending emails with raports. I am create some data, and then try to send it as an email to the user. But emails are not deliwered. I am using swiftmailer configured as in the Symfony cookbool. Parameters for the swiftmailer are set properly because emails from FosUserBundle are working without problems. I have write a method to use it in comand line, the code is below
class DailyRaportCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
->setName('raport:daily')
->setDescription('Send daily raports to the Users');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$em = $this->getContainer()->get('doctrine')->getEntityManager();
$users = $em->getRepository('GLUserBundle:User')->findAllByRaport('DAILY');
foreach($users as $user)
{
$date_to = new \DateTime();
$date_to = $date_to->sub(date_interval_create_from_date_string('1 day'));
$date_from = new \DateTime();
$date_from = $date_from->sub(date_interval_create_from_date_string('1 day'));
$format = "Y-m-d";
$raport = array();
foreach($user->getShops() as $shop)
{
$raport[$shop->getName()] = array();
$shop_list = array();
$shop_list[] = $shop->getId();
$groupBy = array();
$all_policies = $em->getRepository('GLPolicyBundle:Policy')
->findAllByOptions($shop_list, $date_from, $date_to, $groupBy);
$raport[$shop->getName()]['all'] = $all_policies;
$groupBy[] = 'typePolicy';
$policies_by_type = $em->getRepository('GLPolicyBundle:Policy')
->findAllByOptions($shop_list, $date_from, $date_to, $groupBy);
$raport[$shop->getName()]['type'] = $policies_by_type;
$groupBy[] = 'bundle';
$policies_by_bundle = $em->getRepository('GLPolicyBundle:Policy')
->findAllByOptions($shop_list, $date_from, $date_to, $groupBy);
$raport[$shop->getName()]['bundle'] = $policies_by_bundle;
}
$message = \Swift_Message::newInstance()
->setSubject('Dzienny raport sprzedaży')
->setFrom('g#######1#gmail.com')
->setTo($user->getEmail())
->setBody(
$this->getContainer()->get('templating')->render(
'GLRaportBundle:Raport:raport.html.twig',
array('raport' => $raport)
));
$this->getContainer()->get('mailer')->send($message);
}
The wiev of the email is rendered in outside twig file. I will be grateful if someone point whots the reason of this problem.
You might need to manually flush the memory spool, see the following answer which helped me with the same problem:
Unable to send e-mail from within custom Symfony2 command but can from elsewhere in app

ZF2 - Show just one error on forms

I can't seem to get ZF2 to show just one error message for failed form validation messages.
For example, an EmailAddress validator can pass back up to 7 messages and typically shows the following if the user has made a typo:
oli.meffff' is not a valid hostname for the email address
The input appears to be a DNS hostname but cannot match TLD against known list
The input appears to be a local network name but local network names are not allowed
How can I override the error to show something a little more friendly, such as "Please enter a valid email address" instead of specifics like the above?
OK, managed to come up with a solution for this. Instead of using the same string as the error for all validator failures as Sam suggested above, I have overridden the error messages in the InputFilter for the elements and then used a custom form error view helper to show only the first message.
Here is the helper:
<?php
namespace Application\Form\View\Helper;
use Traversable;
use \Zend\Form\ElementInterface;
use \Zend\Form\Exception;
class FormElementSingleErrors extends \Zend\Form\View\Helper\FormElementErrors
{
/**
* Render validation errors for the provided $element
*
* #param ElementInterface $element
* #param array $attributes
* #throws Exception\DomainException
* #return string
*/
public function render(ElementInterface $element, array $attributes = array())
{
$messages = $element->getMessages();
if (empty($messages)) {
return '';
}
if (!is_array($messages) && !$messages instanceof Traversable) {
throw new Exception\DomainException(sprintf(
'%s expects that $element->getMessages() will return an array or Traversable; received "%s"',
__METHOD__,
(is_object($messages) ? get_class($messages) : gettype($messages))
));
}
// We only want a single message
$messages = array(current($messages));
// Prepare attributes for opening tag
$attributes = array_merge($this->attributes, $attributes);
$attributes = $this->createAttributesString($attributes);
if (!empty($attributes)) {
$attributes = ' ' . $attributes;
}
// Flatten message array
$escapeHtml = $this->getEscapeHtmlHelper();
$messagesToPrint = array();
array_walk_recursive($messages, function ($item) use (&$messagesToPrint, $escapeHtml) {
$messagesToPrint[] = $escapeHtml($item);
});
if (empty($messagesToPrint)) {
return '';
}
// Generate markup
$markup = sprintf($this->getMessageOpenFormat(), $attributes);
$markup .= implode($this->getMessageSeparatorString(), $messagesToPrint);
$markup .= $this->getMessageCloseString();
return $markup;
}
}
It's just an extension of FormElementErrors with the render function overridden to include this:
// We only want a single message
$messages = array(current($messages));
I then insert the helper into my application using the solution I posted to my issue here.

JSP code for FB credit callback url

i am developing a Facebook iframe app with Facebook credit API. i am using FB JavaScript SDK for that. but i am unable to find out any sample code in java or JSP for FB credit callback URL. all i found is te PHP code and i dont know PHP much.. can anyone convert it for me in JSP or Java?
here is the php sample code
**
* Copyright 2004-Present Facebook. All Rights Reserved.
*
* You should reference https://developers.facebook.com/docs/credits/ as you
* familiarize yourself with callback.php. In particular, read all the steps
* under "Credits Tutorial" and "Credits Callback".
*
* Your application needs the following inputs and outputs
*
* #param int order_id
* #param string status
* #param string method
* #param array order_details (JSON-encoded)
*
* #return array A JSON-encoded array with order_id, next_state
* (optional: error code, comments)
*/
// Enter your app information below
$app_secret = '<app_secret>';
// Prepare the return data array
$data = array('content' => array());
// Parse the signed_request to verify it's from Facebook
$request = parse_signed_request($_REQUEST['signed_request'], $app_secret);
if ($request == null) {
// Handle an unauthenticated request here
}
// Grab the payload
$payload = $request['credits'];
// Retrieve all params passed in
$func = $_REQUEST['method'];
$order_id = $payload['order_id'];
if ($func == 'payments_status_update') {
// Grab the order status
$status = $payload['status'];
// Write your apps logic here for validating and recording a
// purchase here.
//
// Generally you will want to move states from `placed` -> `settled`
// here, then grant the purchasing user's in-game item to them.
if ($status == 'placed') {
$next_state = 'settled';
$data['content']['status'] = $next_state;
}
// Compose returning data array_change_key_case
$data['content']['order_id'] = $order_id;
} else if ($func == 'payments_get_items') {
// remove escape characters
$order_info = stripcslashes($payload['order_info']);
$item_info = json_decode($order_info, true);
if ($item_info == "abc123") {
// Per the credits api documentation, you should pass in an item
// reference and then query your internal DB for the proper
// information. Then set the item information here to be
// returned to facebook then shown to the user for confirmation.
$item['title'] = 'BFF Locket';
$item['price'] = 1;
$item['description'] = 'This is a BFF Locket...';
$item['image_url'] = 'https://www.facebook.com/images/gifts/21.png';
$item['product_url'] = 'https://www.facebook.com/images/gifts/21.png';
} else {
// For the sake of the sample, we will default to this item if
// the `order_info` reference passed from your JS call is not matched
// above.
$item['title'] = 'A Facebook Hat';
$item['price'] = 1;
$item['description'] = 'The coolest hat you\'ve ever seen.';
$item['image_url'] = 'https://www.facebook.com/images/gifts/740.png';
$item['product_url'] = 'https://www.facebook.com/images/gifts/740.png';
}
// Put the associate array of item details in an array, and return in the
// 'content' portion of the callback payload.
$data['content'] = array($item);
}
// Required by api_fetch_response()
$data['method'] = $func;
// Send data back
echo json_encode($data);
// You can find the following functions and more details
// on https://developers.facebook.com/docs/authentication/canvas.
function parse_signed_request($signed_request, $app_secret) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
// Decode the data
$sig = base64_url_decode($encoded_sig);
$data = json_decode(base64_url_decode($payload), true);
if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
error_log('Unknown algorithm. Expected HMAC-SHA256');
return null;
}
// Check signature
$expected_sig = hash_hmac('sha256', $payload, $app_secret, $raw = true);
if ($sig !== $expected_sig) {
error_log('Bad Signed JSON signature!');
return null;
}
return $data;
}
function base64_url_decode($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
One sample, I will link more as I get.
https://github.com/facebook/facebook-android-sdk
http://code.google.com/p/facebook-java-sdk/