I am using this packet:
https://github.com/barryvdh/laravel-omnipay
In my controller I added:
$params = [
'amount' => '10',
'issuer' => 22,
'description' => 'desc',
'returnUrl' => URL::action('PurchaseController#returnApi', [43]),
];
$response = Omnipay::purchase($params)->send();
if ($response->isSuccessful()) {
// payment was successful: update database
print_r($response);
} elseif ($response->isRedirect()) {
// redirect to offsite payment gateway
return $response->getRedirectResponse();
} else {
// payment failed: display message to customer
echo $response->getMessage();
}
Here is my omnipay.php conf file:
<?php
return array(
/** The default gateway name */
'gateway' => 'PayPal_Express',
/** The default settings, applied to all gateways */
'defaults' => array(
'testMode' => true,
),
/** Gateway specific parameters */
'gateways' => array(
'PayPal_Express' => array(
'username' => '',
'landingPage' => array('billing', 'login'),
),
),
);
But get this error:
call_user_func_array() expects parameter 1 to be a valid callback,
class 'Omnipay\Common\GatewayFactory' does not have a method
'purchase'
Anyone can help me set this?
I created app on paypal and have details about it but don't know how to set it with this API...
I recommend that you switch from PayPal Express to PayPal REST. It is newer and has better documentation.
I have looked through the laravel-omnipay package and I can't see a use case for it. I would just code to the omnipay package directly.
I recommend that you create a unique transaction ID for each transaction and provide that as part of the URLs for returnUrl and cancelUrl so that you can identify which transaction you are dealing with in the return and cancel handlers.
I think that you are taking the examples in the laravel-omnipay package too literally. You don't need or want those echo statements there. You should be capturing the response from purchase() even if it is a redirectResponse and doing a getTransactionReference() check on it, because you will need that transaction reference later, e.g. for transaction lookup. You should store it in the transaction record that you created before calling purchase().
You may use
use Omnipay\Omnipay;
in your controller, change it to
use Omnipay;
Related
I need to Add Credit Card details in to Vault Programmatically (BrainTree) in Magento 2.1.5
Basically what i want is After LoginIn there will be a separate section for Saved Cards . In that Customer is used to Add/edit/delete All his Credit card details.
the Below Code is used to list all the Credit Card saved by the Customer
use Magento\Vault\Api\PaymentTokenManagementInterface;
use Magento\Customer\Model\Session;
...
// Get the customer id (currently logged in user)
$customerId = $this->session->getCustomer()->getId();
// Card list
$cardList = $this->paymentTokenManagement->getListByCustomerId($customerId);
Now what i want is how to Add the Card Details to the Vault ?
Below is the Code to Add card in core php
$result = Braintree_Customer::create(array(
'firstName' => 'first name',
'lastName' => 'last name',
'company' => 'company',
'email' => 'xxxx#gmail.com',
'phone' => '1234567890',
'creditCard' => array(
'cardholderName' => 'xxx xxx',
'number' => '4000 0000 0000 0002 ',
'expirationMonth' => '10',
'expirationYear' => 2020,
'cvv' => '123',
'billingAddress' => array(
'firstName' => 'My First name',
'lastName' => 'My Last name'
)
)
));
But how can i do this same process in magento 2.
Thanks for the help
First, you have to create a payment token from the card data:
use Magento\Vault\Model\CreditCardTokenFactory;
...
$paymentToken = $this->creditCardTokenFactory->create();
$paymentToken->setExpiresAt('Y-m-d 00:00:00');
$paymentToken->setGatewayToken('card_112371K7-28BB-4O3X-CCG9-1034JHK27D88');
$paymentToken->setTokenDetails([
'type' => 'Visa',
'maskedCC' => '1111',
'expirationDate' => '06/2019'
]);
$paymentToken->setIsActive(true);
$paymentToken->setIsVisible(true);
$paymentToken->setPaymentMethodCode('your_payment_method_code');
$paymentToken->setCustomerId($customerId);
$paymentToken->setPublicHash($this->generatePublicHash($paymentToken));
Then you can save the payment token:
use Magento\Vault\Api\PaymentTokenRepositoryInterface;
...
$this->paymentTokenRepository->save($paymentToken);
This is just an example you can start with. In a real world situation, you would also want to check that the token doesn't already exist, an also try a payment authorisation on the card to make sure it's actually usable and valid.
In order to check if a payment token exists or not, you can use this:
use Magento\Vault\Api\PaymentTokenManagementInterface;
...
$this->paymentTokenManagement->getByPublicHash( $paymentToken->getPublicHash(), $paymentToken->getCustomerId() );
You can have a look at the core Magento 2 classes mentioned here to know more about the functions available for payment token handling.
Good luck!
Replace objectManager when use in projects
<?php
use Magento\Framework\Encryption\EncryptorInterface;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\Vault\Model\AccountPaymentTokenFactory;
use Magento\Vault\Model\PaymentToken;
use Magento\Vault\Model\PaymentTokenRepository;
/** #var EncryptorInterface $encryptor */
$encryptor = $objectManager->get(EncryptorInterface::class);
/** #var PaymentToken $paymentToken */
$paymentToken = $objectManager->create(PaymentToken::class);
$paymentToken
->setCustomerId($customer->getId())
->setPaymentMethodCode('payflowpro')
->setType(AccountPaymentTokenFactory::TOKEN_TYPE_ACCOUNT)
->setGatewayToken('mx29vk')
->setPublicHash($encryptor->hash($customer->getId()))
->setTokenDetails(json_encode(['payerEmail' => 'john.doe#example.com']))
->setIsActive(true)
->setIsVisible(true)
->setExpiresAt(date('Y-m-d H:i:s', strtotime('+1 year')));
/** #var PaymentTokenRepository $tokenRepository */
$tokenRepository = $objectManager->create(PaymentTokenRepository::class);
$tokenRepository->save($paymentToken);
Can someone provide a sample code chunk of php using the sugarcrm API/nusoap for adding creating an acct. and then linking a lead to the acct?
I've got a sample function that adds a lead, and I can see how to create an acct, but I can't see how to tie a lead to the acct, to simulate the subpanel process in the sugarcrm acct/subpanel process.
thanks
// Create a new Lead, return the SOAP result
function createLead($data)
{
// Parse the data and store it into a name/value list
// which will then pe passed on to Sugar via SOAP
$name_value_list = array();
foreach($data as $key => $value)
array_push($name_value_list, array('name' => $key, 'value' => $value));
// Fire the set_entry call to the Leads module
$result = $this->soap->call('set_entry', array(
'session' => $this->session,
'module_name' => 'Leads',
'name_value_list' => $name_value_list
));
return $result;
}
$result = $sugar->createLead(array(
'lead_source' => 'Web Site',
'lead_source_description' => 'Inquiry form on the website',
'lead_status' => 'New',
'first_name' => $_POST['first_name'],
'last_name' => $_POST['last_name'],
'email1' => $_POST['email'],
'description' => $_POST['message']
));
You need to find the ID for the account and assign that ID to whatever the account_id field name is in the Lead Module. I have run into a couple things like this before and I have found it easier to go straight to the Sugar database. So, write a statement that will return the account is, for example: SELECT id WHERE something_in_the_account_table = something else;
Then you can assign that id in your $result array. I hope it helps. I didn't have any code or documentation in front of me or I would have helped more.
I've been asked to add some Google event tracking to a link on a site I'm 'fixing'.
This relies on the 'onclick' attribute and the ZEND framework (1.11.11) application seems to generate those links as described below.
I can't find out how to add custom attributes to this function, specifically, 'onclick'.
Is this even possible? I've never got along with Zend and any gurus out there will probably know far better than I if it's even possible.
/**
* #return Zend_Navigation_Page_Uri
*/
public function getBrochurePageUri()
{
return new Zend_Navigation_Page_Uri(array(
'label' => 'Brochure request',
'uri' => 'http://www.website.com/brochure/'
)
);
}
try adding the following:
'attribs' => array('onclick'=>'somefunction(params)')
resulting in the following:
return new Zend_Navigation_Page_Uri(array(
'label' => 'Brochure request',
'uri' => 'http://www.website.com/brochure/',
'attribs' => array('onclick'=>'somefunction(params)')
)
);
I made a restful controller that if I send the id the get method receives it. But when I update a form I expect the update method to process but I cant get to the right config for this and after 1 day with this issue I decided to right it down here.
Here the code involved
route in module config:
'activities' => array(
'type' => 'segment',
'options' => array(
'route' => '/activities[/:id][/:action][.:formatter]',
'defaults' => array(
'controller' => 'activities'
),
'constraints' => array(
'formatter' => '[a-zA-Z0-9_-]*',
'id' => '[0-9_-]*'
),
),
),
Head of controller:
namespace Clock\Controller;
use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\Mvc\MvcEvent;
use Zend\View\Model\ViewModel;
use Zend\Form\Annotation\AnnotationBuilder;
use Zend\Form;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Clock\Entity\Activity;
use \Clock\Entity\Project;
Wich contains the get method:
public function get($id)
{
$entity = $this->getRepository()->find($id);
$form = $this->buildForm(new Activity());
#$form->setAttribute('action', $this->url()->fromRoute("activities", array('action' => 'update')));
$form->setAttribute('action', "/activities/$id/update");
$form->bind($entity);
return array(
"activities" => $entity,
"form" => $form
);
}
That feeds this view:
<h3>Edit activity</h3>
<div>
<?php echo $this->form()->openTag($form);?>
<?php echo $this->formSelect($form->get("project"));?><br>
<?php echo $this->formInput($form->get("duration"));?><br>
<?php echo $this->formInput($form->get("description"));?><br>
<input type="submit" value="save changes" />
<?php echo $this->form()->closeTag($form);?>
</div>
After sending it, I expect update method in activities to take control, but I get:
A 404 error occurred
Page not found.
The requested controller was unable to dispatch the request.
Controller:
activities
EDIT:#DrBeza
This is what i get, that i think (not a master in routes) is right:
Zend\Mvc\Router\Http\RouteMatch Object
(
[length:protected] => 21
[params:protected] => Array
(
[controller] => activities
[id] => 30
[action] => update
)
[matchedRouteName:protected] => activities
)
--
That's it.
Any help?
Quick Fix
The RouteMatch object tries to dispatch ActivitiesController::updateAction but you have defined ActivitiesController::update
That's due to you using a Restful Controller. the Controller::update-Method is specifically tied to PUT-Requests. You need to define an extra method to handle updates via POST-Requests.
I suggest you define ActivitiesController::updateAction, make clear in the docblock it is meant to handle POST-Update requests and refactor both ::updateAction and ::update to share as much common helper-methods as possible for a fast solution.
Common URI Structur information
As a nice information to have when you start developing RESTful applications/APIs:
The ruby community suggests the following url-structure for your resources:
# These are restful
/resource GET (lists) | POST (creates)
/resource/:id PUT (updates) | DELETE (deletes)
# these are just helpers, not restful, and may accept POST too.
/resource/new GET (shows the create-form), POST
/resource/:id/edit GET (shows the update-form), POST
Detailed Problem Analysis
A restful update will be sent by an consumer via PUT, but browsers sending HTML-forms may only send GET or POST requests. You should never use GET to create something. So you have to use POST in a forms-context.
Looking at the problem from an architectural perspective a multitude of possibilities emerge, depending on how big your application is.
For a small application, tight integration (formhandling and API handling in the controller) apply best.
Getting bigger you may want to split up API-Controllers (only restful actions) from Helper-Controllers (form, website handling) which talk to your API-Controllers
Being big (multitude of API-Users) you will want to have dedicated API Servers and dedicated Website Servers (independent applications!). In this case your website will consume the API serverside (thats what twitter is doing). API Servers and Website Servers still may share libraries (for filtering, utilities).
Code Sample
As an educational example I made an gist to show how such a controller could look like in principle. This controller is a) untested b) not production ready and c) only marginally configurable.
For your special interest here two excerpts about updating:
/* the restful method, defined in AbstractRestfulController */
public function update($id, $data)
{
$response = $this->getResponse();
if ( ! $this->getService()->has($id) )
{
return $this->notFoundAction();
}
$form = $this->getEditForm();
$form->setData($data);
if ( ! $form->isValid() )
{
$response->setStatusCode(self::FORM_INVALID_STATUSCODE);
return [ 'errors' => $form->getMessages() ];
}
$data = $form->getData(); // you want the filtered & validated data from the form, not the raw data from the request.
$status = $this->getService()->update($id, $data);
if ( ! $status )
{
$response->setStatusCode(self::SERVERSIDE_ERROR_STATUSCODE);
return [ 'errors' => [self::SERVERSIDE_ERROR_MESSAGE] ];
}
// if everything went smooth, we just return the new representation of the entity.
return $this->get($id);
}
and the editAction which satisfies browser-requests:
public function editAction()
{
/*
* basically the same as the newAction
* differences:
* - first fetch the data from the service
* - prepopulate the form
*/
$id = $this->params('id', false);
$dataExists = $this->getService()->has($id);
if ( ! $dataExists )
{
$this->flashMessenger()->addErrorMessage("No entity with {$id} is known");
return $this->notFoundAction();
}
$request = $this->getRequest();
$form = $this->getEditForm();
$data = $this->getService()->get($id);
if ( ! $request->isPost() )
{
$form->populateValues($data);
return ['form' => $form];
}
$this->update($id, $request->getPost()->toArray());
$response = $this->getResponse();
if ( ! $response->isSuccess() )
{
return [ 'form' => $form ];
}
$this->flashMessenger()->addSuccessMessage('Entity changed successfully');
return $this->redirect()->toRoute($this->routeIdentifiers['entity-changed']);
}
That error message suggests the dispatch process is unable to find the requested controller action and therefore using notFoundAction().
I would check the route matched and make sure the values are as expected. You can do this by adding the following into your module's onBootstrap() method:
$e->getApplication()->getEventManager()->attach('route', function($event) {
var_dump($event->getRouteMatch());
exit;
});
I am using woocommerce (free plugin).. I am trying to add one custom field to the billing fields..
here it is:
// ADDED HOW YOU GOT TO KNOW ABOUT OUR SERVICE FIELD
add_filter( 'woocommerce_checkout_fields' , 'About_Our_Service' );
// Our hooked in function - $fields is passed via the filter!
function About_Our_Service( $fields ) {
$fields['billing']['billing_meat'] = array(
'label' => __('How you Got to Know About Our Service?', 'woocommerce'),
'placeholder' => _x('', 'placeholder', 'woocommerce'),
'required' => false,
'clear' => false,
'type' => 'select',
'options' => array(
'google-ads' => __('Google', 'woocommerce' ),
'google-search' => __('Yahoo', 'woocommerce' ),
'warrior-forum' => __('Bing', 'woocommerce' ),
'facebook' => __('Facebook', 'woocommerce' ),
'other' => __('Other', 'woocommerce' ),
)
);
return $fields;
}
The problem is: I am not getting the value in my mail for the custom field which was added to the billing fields.. Anyone who already used woocommerce can help me on this... ?
I already created some more custom fields which was added to the checkout (BUT these're not added along with the core fields), for these fields i'm able to get values in my mail..
By the ay, i checked this thread: but didn't much info related to mail..
please kindly someone look into this..
For future readers, custom billing/shipping fields are saved as post meta for the order post. So in general, you can retrieve them with the typical WordPress get_post_meta() function.
But in WooCommerce 2.2, you don't need to as you can pass the field name directly to an array of fields that WC will show as a list in the email:
// pre-WooCommerce 2.3
function kia_email_order_meta_keys( $keys ) {
$keys['Some field'] = '_some_field';
return $keys;
}
add_filter('woocommerce_email_order_meta_keys', 'kia_email_order_meta_keys');
This method has been deprecated in version 2.3, probably so translation can be better. As of 2.3 you will need to target a different filter and send slightly different data.
// WooCommerce 2.3+
function kia_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
$fields['some_field'] = array(
'label' => __( 'Some field', 'my-plugin-textdomain' ),
'value' => get_post_meta( $order->id, '_some_field', true );
);
return $fields;
}
add_filter('woocommerce_email_order_meta_fields', 'kia_email_order_meta_keys', 10, 3 );
I wrote a tutorial on Customizing WooCommerce Checkout Fields
I believe this answer, in the codex is specifically meant for this purpose:
http://wcdocs.woothemes.com/snippets/add-a-custom-field-in-an-order-to-the-emails
I haven't implemented this myself but it's probably your best shot.