This is my first time attempting to use paypal ipn. I am an amateur coder for sure. I have developed a user/subscriber site and I am wanting to finalize the paypal subscriber payments.
I have a number of questions but I know I should narrow it down to 1.
I understand ipn as sending a message to a page on my site. (I may be wrong). I am going to assume that would be the IPN handler URL. (?)
Does the IPN actually hit the page and create an action?
I would like that message (or loading of the page) to call a function which inserts in my database.
Here is my Listener...ipnverify.php
<?php require(Config::get('URL').'/paypalipn/PaypalIPN.php');
use PaypalIPN;
$ipn = new PayPalIPN();
$ipn->useSandbox();$verified = $ipn->verifyIPN();$name = $_POST['custom'];
if ($name==1) {
function updatePaypalTest()
{
$database = DatabaseFactory::getFactory()->getConnection();
$sql = "INSERT INTO paypal_test (name) VALUES('1')";
$query = $database->prepare($sql);
$query->execute();
}
updatePaypalTest();
header("HTTP/1.1 200 OK");
?>
And then the other file from github...PaypalIPN.php
<?php
class PaypalIPN
{
private $use_sandbox = true;
private $use_local_certs = false;
/*
* PayPal IPN postback endpoints
*/
const VERIFY_URI = 'https://ipnpb.paypal.com/cgi-bin/webscr';
const SANDBOX_VERIFY_URI = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr';
/*
* Possible responses from PayPal after the request is issued.
*/
const VALID = 'VERIFIED';
const INVALID = 'INVALID';
/**
* Sets the IPN verification to sandbox mode (for use when testing,
* should not be enabled in production).
* #return void
*/
public function useSandbox()
{
$this->use_sandbox = true;
}
/**
* Determine endpoint to post the verification data to.
* #return string
*/
public function getPaypalUri()
{
if ($this->use_sandbox) {
return self::SANDBOX_VERIFY_URI;
} else {
return self::VERIFY_URI;
}
}
/**
* Verification Function
* Sends the incoming post data back to paypal using the cURL library.
*
* #return bool
* #throws Exception
*/
public function verifyIPN()
{
if ( ! count($_POST)) {
throw new Exception("Missing POST Data");
}
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = [];
foreach ($raw_post_array as $keyval) {
$keyval = explode('=', $keyval);
if (count($keyval) == 2) {
// Since we do not want the plus in the datetime string to be encoded to a space, we manually encode it.
if ($keyval[0] === 'payment_date') {
if (substr_count($keyval[1], '+') === 1) {
$keyval[1] = str_replace('+', '%2B', $keyval[1]);
}
}
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
}
// Build the body of the verification post request, adding the _notify-validate command.
$req = 'cmd=_notify-validate';
$get_magic_quotes_exists = false;
if (function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
// Post the data back to paypal, using curl. Throw exceptions if errors occur.
$ch = curl_init($this->getPaypalUri());
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
// This is often required if the server is missing a global cert bundle, or is using an outdated one.
if ($this->use_local_certs) {
curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . "/cert/cacert.pem");
}
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Connection: Close']);
$res = curl_exec($ch);
$info = curl_getinfo($ch);
$http_code = $info['http_code'];
if ($http_code != 200) {
throw new Exception("PayPal responded with http code $http_code");
}
if ( ! ($res)) {
$errno = curl_errno($ch);
$errstr = curl_error($ch);
curl_close($ch);
throw new Exception("cURL error: [$errno] $errstr");
}
curl_close($ch);
// Check if paypal verfifes the IPN data, and if so, return true.
if ($res == self::VALID) {
return true;
} else {
return false;
}
}
}
Please help me understand what I am missing. Is there a way that I can call my function from the ipn message?
Related
I am writing a custom PrimaryAuthenticationProvider using MediaWiki for authorizing against my API instead of a MediaWiki database. But when I turn off the autocreation in LocalSettings.php the following way:
$wgGroupPermissions['*']['createaccount'] = false;
$wgGroupPermissions['*']['edit'] = false;
$wgGroupPermissions['*']['read'] = false;
when I try to login against my API with the correct credentials, the request fails with the error: Auto-creation of a local account failed: Automatic account creation is not allowed.
I suppose that I didn't stub one of my functions that should return the correct value that MediaWiki shouldn't create the user, but I can't find which one. When I enable $wgGroupPermissions['*']['createaccount'] = false;, it starts working, but I want to disable creating accounts at all. How can I achieve this?
Here's my core for my authentication provider:
<?php
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* #file
* #ingroup Auth
*/
use \MediaWiki\Auth\AuthenticationRequest;
use \MediaWiki\Auth\ButtonAuthenticationRequest;
use \MediaWiki\Auth\AbstractPrimaryAuthenticationProvider;
use \MediaWiki\Auth\AbstractPasswordPrimaryAuthenticationProvider;
use \MediaWiki\Auth\AuthManager;
use \MediaWiki\Auth\AuthenticationResponse;
/**
* A primary authentication provider that uses the password field in the 'user' table.
* #ingroup Auth
* #since 1.27
*/
class MyAEGEEApiPrimaryAuthenticationProvider
extends AbstractPasswordPrimaryAuthenticationProvider
{
/**
* #param array $params Settings
* the local password will be invalidated when authentication is changed
* and new users will not have a valid local password set.
*/
public function __construct( $params = [] ) {
parent::__construct( $params );
$this->baseHost = 'https://my.aegee.eu';
$this->loginUrl = $this->baseHost.'/services/oms-core-elixir/api/login';
$this->getUserUrl = $this->baseHost.'/services/oms-core-elixir/api/members/me';
}
/**
* Check if the password has expired and needs a reset
*
* #param string $username
* #param \stdClass $row A row from the user table
* #return \stdClass|null
*/
protected function getPasswordResetData( $username, $row ) {
return null;
}
/**
* Makes a /login request to core.
* #param{string} $username
* #param{string} $password
* #return $access_token
*/
private function tryLogin($username, $password) {
$ch = curl_init($this->loginUrl);
$body = json_encode(array(
'username'=>$username,
'password'=>$password
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Accept: application/json',
'Content-Type: application/json'
));
$response = curl_exec($ch);
$error = curl_error($ch);
$errno = curl_errno($ch);
if (is_resource($ch)) {
curl_close($ch);
}
if (0 !== $errno) {
wfDebugLog( 'MyAEGEEApi', 'Auth request returned error, failing.' );
return null;
}
$response_parsed = json_decode($response);
if (!$response_parsed->success) {
wfDebugLog( 'MyAEGEEApi', 'Auth request not successful, failing.' );
return null;
}
return $response_parsed->access_token;
}
/**
* Fetches user from core.
* #param{string} $access_token
* #return $user
*/
private function tryGetUser($access_token) {
$ch = curl_init($this->getUserUrl);
$body = json_encode(array(
'username'=>$username,
'password'=>$password
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Accept: application/json',
'Content-Type: application/json',
'X-Auth-Token: '.$access_token
));
$response = curl_exec($ch);
$error = curl_error($ch);
$errno = curl_errno($ch);
if (is_resource($ch)) {
curl_close($ch);
}
if (0 !== $errno) {
wfDebugLog( 'MyAEGEEApi', 'User request returned error, failing.' );
return null;
}
$response_parsed = json_decode($response);
if (!$response_parsed->success) {
wfDebugLog( 'MyAEGEEApi', 'User request not successful, failing.' );
return null;
}
return $response_parsed->data;
}
/**
* All fun starts here.
*/
public function beginPrimaryAuthentication( array $reqs ) {
if ( !$reqs[0] ) {
wfDebugLog( 'MyAEGEEApi', 'No req, failing' );
return AuthenticationResponse::newAbstain();
}
$username = $reqs[0]->username;
$password = $reqs[0]->password;
if ( $username === null || $password === null ) {
wfDebugLog( 'MyAEGEEApi', 'Empty password or username, failing' );
return AuthenticationResponse::newAbstain();
}
$username = User::getCanonicalName( $username, 'usable' );
if ( $username === false ) {
wfDebugLog( 'MyAEGEEApi', 'Username not usable, failing' );
return AuthenticationResponse::newAbstain();
}
$access_token = $this->tryLogin($username, $password);
wfDebugLog( 'MyAEGEEApi', 'Got access token');
if (!$access_token) {
wfDebugLog( 'MyAEGEEApi', 'Access token failed, failing.');
return AuthenticationResponse::newAbstain();
}
wfDebugLog( 'MyAEGEEApi', 'Auth succeeded.');
$user = $this->tryGetUser($access_token);
if (!$user) {
wfDebugLog( 'MyAEGEEApi', 'User failed, failing.');
return AuthenticationResponse::newAbstain();
}
$username = $user->first_name.' '.$user->last_name;
wfDebugLog( 'MyAEGEEApi', 'User succeeded: '.$username);
return AuthenticationResponse::newPass( $username );
}
public function testUserCanAuthenticate( $username ) {
wfDebugLog( 'MyAEGEEApi', 'testUserCanAuthenticate start');
return true;
}
public function testUserExists( $username, $flags = User::READ_NORMAL ) {
wfDebugLog( 'MyAEGEEApi', 'testUserExists called');
return false;
}
/**
* A stub to just implement something.
*/
public function providerAllowsAuthenticationDataChange(
AuthenticationRequest $req, $checkData = true
) {
wfDebugLog( 'MyAEGEEApi', 'providerAllowsAuthenticationDataChange called');
return \StatusValue::newGood( 'ignored' );
}
/**
* A stub to just implement something.
*/
public function providerChangeAuthenticationData( AuthenticationRequest $req ) {
wfDebugLog( 'MyAEGEEApi', 'providerChangeAuthenticationData start');
}
/**
* A stub to just implement something.
*/
public function accountCreationType() {
wfDebugLog( 'MyAEGEEApi', 'accountCreationType called start');
return self::TYPE_NONE;
}
/**
* A stub to just implement something.
*/
public function testForAccountCreation( $user, $creator, array $reqs ) {
wfDebugLog( 'MyAEGEEApi', 'testForAccountCreation called');
}
/**
* A stub to just implement something.
*/
public function beginPrimaryAccountCreation( $user, $creator, array $reqs ) {
wfDebugLog( 'MyAEGEEApi', 'beginPrimaryAccountCreation called');
return AuthenticationResponse::newAbstain();
}
/**
* A stub to just implement something.
*/
public function finishAccountCreation( $user, $creator, AuthenticationResponse $res ) {
wfDebugLog( 'MyAEGEEApi', 'finishAccountCreation called');
return null;
}
}
And I get the following log in my debug console:
IP: 172.18.0.2
Start request POST /index.php/Special:UserLogin
HTTP HEADERS:
HOST: localhost
USER-AGENT: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:70.0) Gecko/20100101 Firefox/70.0
CONTENT-LENGTH: 208
ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
ACCEPT-ENCODING: gzip, deflate
ACCEPT-LANGUAGE: en-US,en;q=0.5
CONTENT-TYPE: application/x-www-form-urlencoded
COOKIE: __test=1; Webstorm-87597fa=870153af-a572-4e74-a5d9-c7709900917d; sails.sid=s%3ASAu438xerbZoNUyYmK9AIxJCEBE_KkV0.%2FEydN2aTQPEaxd%2BhxAq3dkfHy1YDlnv2joc82HyQ%2Bi8; mediawiki_session=s0i4jb61ka5ckdhnfqoids1mjb9rl520
DNT: 1
ORIGIN: http://localhost
REFERER: http://localhost/index.php/Special:UserLogin
UPGRADE-INSECURE-REQUESTS: 1
X-FORWARDED-FOR: <IP>
X-FORWARDED-HOST: localhost
X-FORWARDED-PORT: 80
X-FORWARDED-PROTO: http
X-FORWARDED-SERVER: 28ef83ab1502
X-REAL-IP: <IP>
[caches] cluster: APCUBagOStuff, WAN: mediawiki-main-default, stash: db-replicated, message: APCUBagOStuff, session: APCUBagOStuff
[caches] LocalisationCache: using store LCStoreDB
[DBConnection] Wikimedia\Rdbms\LoadBalancer::openConnection: calling initLB() before first connection.
[DBReplication] Cannot use ChronologyProtector with EmptyBagOStuff.
[DBReplication] Wikimedia\Rdbms\LBFactory::getChronologyProtector: using request info {
"IPAddress": "172.18.0.2",
"UserAgent": "Mozilla\/5.0 (Macintosh; Intel Mac OS X 10.15; rv:70.0) Gecko\/20100101 Firefox\/70.0",
"ChronologyProtection": false,
"ChronologyPositionIndex": 0,
"ChronologyClientId": null
}
[DBConnection] Wikimedia\Rdbms\LoadBalancer::openLocalConnection: connected to database 0 at 'maria-mediawiki'.
[session] Session "s0i4jb61ka5ckdhnfqoids1mjb9rl520" requested without UserID cookie
[MessageCache] MessageCache::load: Loading en-gb... local cache is empty, global cache is expired/volatile, loading from database
Unstubbing $wgParser on call of $wgParser::firstCallInit from MessageCache->transform
Parser: using preprocessor: Preprocessor_DOM
Unstubbing $wgLang on call of $wgLang::_unstub from ParserOptions->__construct
[MyAEGEEApi] providerAllowsAuthenticationDataChange called
User::getBlockedStatus: checking...
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" data dirty due to dirty(): MediaWiki\Auth\AuthManager->setAuthenticationSessionData/MediaWiki\Session\Session->setSecret/MediaWiki\Session\Session->getSecretKeys/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" data dirty due to dirty(): MediaWiki\Auth\AuthManager->setAuthenticationSessionData/MediaWiki\Session\Session->setSecret/MediaWiki\Session\Session->getSecretKeys/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" data dirty due to dirty(): MediaWiki\Auth\ThrottlePreAuthenticationProvider->testForAuthentication/MediaWiki\Auth\AuthManager->setAuthenticationSessionData/MediaWiki\Session\Session->setSecret/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" save: dataDirty=1 metaDirty=0 forcePersist=0
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" data dirty due to dirty(): AuthManagerSpecialPage->performAuthenticationStep/MediaWiki\Auth\AuthManager->beginAuthentication/MediaWiki\Session\Session->setSecret/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" save: dataDirty=1 metaDirty=0 forcePersist=0
[MyAEGEEApi] Got access token
[MyAEGEEApi] Auth succeeded.
[MyAEGEEApi] User succeeded: <user name>
[authentication] Primary login with MyAEGEEApiPrimaryAuthenticationProvider succeeded
[authentication] Auto-creating <user name> on login
[authentication] MediaWiki\Auth\AuthManager::autoCreateUser: IP lacks the ability to create or autocreate accounts
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" data dirty due to dirty(): MediaWiki\Auth\AuthManager->beginAuthentication/MediaWiki\Auth\AuthManager->continueAuthentication/MediaWiki\Auth\AuthManager->autoCreateUser/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" save: dataDirty=1 metaDirty=0 forcePersist=0
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" data dirty due to dirty(): AuthManagerSpecialPage->performAuthenticationStep/MediaWiki\Auth\AuthManager->beginAuthentication/MediaWiki\Auth\AuthManager->continueAuthentication/MediaWiki\Session\Session->remove/MediaWiki\Session\SessionBackend->dirty
[session] SessionBackend "s0i4jb61ka5ckdhnfqoids1mjb9rl520" save: dataDirty=1 metaDirty=0 forcePersist=0
[authevents] Login attempt
[MyAEGEEApi] providerAllowsAuthenticationDataChange called
MediaWiki::preOutputCommit: primary transaction round committed
MediaWiki::preOutputCommit: pre-send deferred updates completed
MediaWiki::preOutputCommit: LBFactory shutdown completed
Thanks for your answer in advance.
You should probably disable the login providers you don't want instead of removing account creation permissions. That said, $wgGroupPermissions['*']['autocreateaccount'] = true; should be enough to make your provider work while still disallowing normal account creation.
I'm creating an Wordpress nonce on an user api login (domain1) and then send this nonce back to the domain (domain2) where the request came from. From domain2 there is another call made to domain1 for retrieving data, again through api, with the nonce created on login. This nonce is used for verifying this action.
Is this the right thing to do, if correct; Why is the result of wp_verify_nonce false?
My code:
function login() {
$creds = array();
$creds['user_login'] = $_GET["username"];
$creds['user_password'] = $_GET["password"];
$user = wp_signon($creds, false);
if (!is_wp_error($user))
{
$nonce = wp_create_nonce('wp_rest');
$url = "http://hongarijestek2/view/login.html?nonce=" . $nonce;
wp_redirect( $url );
exit;
}
}
function get_visitors( $data ) {
global $wpdb;
$nonce = $_GET['nonce'];
if( wp_verify_nonce( $_GET['nonce'], 'wp-rest' ) ) {
echo "Nonce is ok!";
} else {
echo "Nonce is not ok!";
die();
}
$visitors = $wpdb->get_results("SELECT * FROM cp_visitors_present");
if ( empty( $visitors ) ) {
return null;
}
return $visitors;
}
How to get the product details in JSON format using REST API in Magento2? When I search I found the following code.
$url = 'magentohost url';
$callbackUrl = $url . "oauth_admin.php";
$temporaryCredentialsRequestUrl = $url . "oauth/initiate?oauth_callback=" . urlencode($callbackUrl);
$adminAuthorizationUrl = $url . 'admin/oauth_authorize';
$accessTokenRequestUrl = $url . 'oauth/token';
$apiUrl = $url . 'api/rest';
$consumerKey = 'consumer_key';
$consumerSecret = 'consumer_secret';
$token = 'token';
$secret = 'token_secret';
try {
$oauthClient = new OAuth($consumerKey, $consumerSecret, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_AUTHORIZATION);
$oauthClient->setToken($token, $secret);
$resourceUrl = "$apiUrl/products";
$oauthClient->fetch($resourceUrl, array(), 'GET', array('Content-Type' => 'application/json', 'Accept' => 'application/json'));
$productsList = json_decode($oauthClient->getLastResponse());
echo '<pre>';
print_r($productsList);
}
catch(Exception $e) {
echo '<pre>';
print_r($e);
}
But where I need to put this query... And also I am confusing with the URL...
And also it returns error Class OAuth not found
First, we need to create Web Service Role and Web Service User in Magento 2
Create Web Service Role:
Login Admin Panel> System> User Roles> Add New Role
Add the Role Name and your current password of Admin in Your Password field
Tap Role Resources
Choose what are required for service of your web in Resource Access
Tap Save Role
Create Web Service User in Magento 2
This user is used for the role you’ve created
Go to System> All Users> Add New User
Fill in all the necessary information
Tap User Role then choose which you’ve created
Tap Save User
The user above will used to REST API web service in Magento 2.
Next, we will get starting with Magento 2 REST API. Create a php file called my_magento2_rest_apt.php or whatever you want to make it. and place it in the magneto root directory.
Add this code into the file.
define('BASEURL','http://yourdomin.com/magento2location/');
$apiUser = 'username';
$apiPass = 'password';
$apiUrl = BASEURL.'index.php/rest/V1/integration/admin/token';
/*
Magento 2 REST API Authentication
*/
$data = array("username" => $apiUser, "password" => $apiPass);
$data_string = json_encode($data);
try{
$ch = curl_init($apiUrl);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data_string))
);
$token = curl_exec($ch);
$token = json_decode($token);
if(isset($token->message)){
echo $token->message;
}else{
$key = $token;
}
}catch(Exception $e){
echo 'Error: '.$e->getMessage();
}
/*
Get Product By SKU REST API Magento 2
Use above key into header
*/
$headers = array("Authorization: Bearer $key");
//$requestUrl = BASEURL.'index.php/rest/V1/products/24-MB01';//24-MB01 is the sku.
//$requestUrl = BASEURL.'index.php/rest/V1/products?searchCriteria[page_size]=10';// get total 10 products
//$requestUrl = BASEURL.'index.php/rest/V1/categories/24/products';// 24 category id
//$requestUrl = BASEURL.'index.php/rest/V1/products?searchCriteria=';//get all products
$requestUrl = BASEURL.'index.php/rest/V1/products?searchCriteria[filter_groups][0][filters][0][field]=category_id&searchCriteria[filter_groups][0][filters][0][value]=24&searchCriteria[filter_groups][0][filters][0][condition_type]=eq';
$ch = curl_init();
try{
$ch = curl_init($requestUrl);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$result = json_decode($result);
if(isset($result->message)){
echo $result->message;
}else{
print_r($result);
}
}catch(Exception $e){
echo 'Error: '.$e->getMessage();
}
now to get to your API just type. http://yourdomin.com/magento2location/my_magento2_rest_apt.php
I'm building a module that will help seller put their products catalogue in the Amazon Product Ads service. For that, I need to make a mapping between the client's category and the Amazon Product Ads categories.
Problem is, I can't find an API that will help me search for Categories, or a file containing all the existing categories for Amazon Product Ads.
I found that link http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BrowseNodeIDs.html, that may be a start, but based on their API, it's not possible to search by text (like "Apparel") but by NodeId, which is not what I'm looking for :/
Can anyone of you help me please?
Thank you for your help :)
You have to use Browse Node Id of parent categories and bases on that you can search for sub categories.
Create a file named amazon_api_class.php
<?php
require_once 'aws_signed_request.php';
class AmazonProductAPI
{
/**
* Your Amazon Access Key Id
* #access private
* #var string
*/
private $public_key = "";
/**
* Your Amazon Secret Access Key
* #access private
* #var string
*/
private $private_key = "";
private $media_type = "";
private $region = "";
private $out_file_fp = "";
public function __construct($public, $private, $region) {
$this->public_key = $public;
$this->private_key = $private;
$this->region = $region;
}
public function getNode($node)
{
$parameters = array("Operation" => "BrowseNodeLookup",
"BrowseNodeId" => $node,
"ResponseGroup" => "BrowseNodeInfo");
$xml_response = aws_signed_request($parameters,
$this->public_key,
$this->private_key,
$this->region);
return ($xml_response);
}
public function setMedia($media, $file = "") {
$media_type = array("display", "csv");
if(!in_array($media,$media_type)) {
throw new Exception("Invalid Media Type");
exit();
}
$this->media_type = $media;
if($media == "csv") {
$this->out_file_fp = fopen($file,'a+');
}
}
private function writeOut($level, $name, $id, $parent) {
if($this->media_type == "display") {
$spaces = str_repeat( ' ', ( $level * 6 ) );
echo $spaces . $parent . ' : ' . $name . ' : ' . $id . "\n";
} elseif ($this->media_type == "csv") {
$csv_line = '"' . $parent . '","' . $name . '","' . $id . '"' . "\n";
fputs($this->out_file_fp, $csv_line);
} else {
throw new Exception("Invalid Media Type");
exit();
}
}
public function getBrowseNodes($nodeValue, $level = 0)
{
try {
$result = $this->getNode($nodeValue);
}
catch(Exception $e) {
echo $e->getMessage();
}
if(!isset($result->BrowseNodes->BrowseNode->Children->BrowseNode)) return;
if(count($result->BrowseNodes->BrowseNode->Children->BrowseNode) > 0) {
foreach($result->BrowseNodes->BrowseNode->Children->BrowseNode as $node) {
$this->writeOut($level, $node->Name,
$node->BrowseNodeId,
$result->BrowseNodes->BrowseNode->Name);
$this->getBrowseNodes($node->BrowseNodeId, $level+1);
}
} else {
return;
}
}
public function getNodeName($nodeValue)
{
try {
$result = $this->getNode($nodeValue);
}
catch(Exception $e) {
echo $e->getMessage();
}
if(!isset($result->BrowseNodes->BrowseNode->Name)) return;
return (string)$result->BrowseNodes->BrowseNode->Name;
}
public function getParentNode($nodeValue)
{
try {
$result = $this->getNode($nodeValue);
}
catch(Exception $e) {
echo $e->getMessage();
}
if(!isset($result->BrowseNodes->BrowseNode->Ancestors->BrowseNode->BrowseNodeId)) return;
$parent_node = array("id" => (string)$result->BrowseNodes->BrowseNode->Ancestors->BrowseNode->BrowseNodeId,
"name" => (string)$result->BrowseNodes->BrowseNode->Ancestors->BrowseNode->Name);
return $parent_node;
}}?>
Create file named as aws_signed_request.php
<?php
function aws_signed_request($params,$public_key,$private_key,$region)
{
$method = "GET";
$host = "ecs.amazonaws.".$region; // must be in small case
$uri = "/onca/xml";
$params["Service"] = "AWSECommerceService";
$params["AWSAccessKeyId"] = $public_key;
$params["AssociateTag"] = 'YOUR-ASSOCIATES-ID-HERE';
$params["Timestamp"] = gmdate("Y-m-d\TH:i:s\Z");
$params["Version"] = "2009-03-31";
/* The params need to be sorted by the key, as Amazon does this at
their end and then generates the hash of the same. If the params
are not in order then the generated hash will be different thus
failing the authetication process.
*/
ksort($params);
$canonicalized_query = array();
foreach ($params as $param=>$value)
{
$param = str_replace("%7E", "~", rawurlencode($param));
$value = str_replace("%7E", "~", rawurlencode($value));
$canonicalized_query[] = $param."=".$value;
}
$canonicalized_query = implode("&", $canonicalized_query);
$string_to_sign = $method."\n".$host."\n".$uri."\n".$canonicalized_query;
/* calculate the signature using HMAC with SHA256 and base64-encoding.
The 'hash_hmac' function is only available from PHP 5 >= 5.1.2.
*/
$signature = base64_encode(hash_hmac("sha256", $string_to_sign, $private_key, True));
/* encode the signature for the request */
$signature = str_replace("%7E", "~", rawurlencode($signature));
/* create request */
$request = "http://".$host.$uri."?".$canonicalized_query."&Signature=".$signature;
/* I prefer using CURL */
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$xml_response = curl_exec($ch);
if ($xml_response === False)
{
return False;
}
else
{
/* parse XML */
$parsed_xml = #simplexml_load_string($xml_response);
return ($parsed_xml === False) ? False : $parsed_xml;
}
}
?>
Create file named as index.php
<?php
/* Example usage of the Amazon Product Advertising API */
include("amazon_api_class.php");
$public_key = "YOUR-AMAZON-PUBLIC-KEY";
$private_key = "YOUR-AMAZON-SECRET-KEY";
$region = "com"; // or "CA" or "DE" etc.
$obj = new AmazonProductAPI($public_key, $private_key, $region);
$obj->setMedia("display");
$obj->getBrowseNodes("1036592"); //Apparel US store
?>
Dont forget to update your public and private key in index.php
im trying to use the google places service with php curl
in my for loop (2 laps) , i send my url,
at the 1 lap, i can get json informations but the 2nd lap give me "REQUEST_DENIED" status. Here is my code :
<?php
//header("content-type: application/json");
//header("content-type: Access-Control-Allow-Origin: *");
//header("content-type: Access-Control-Allow-Methods: GET");
set_time_limit(0);
ini_set("memory_limit","12000M");
error_reporting(E_ALL);
ini_set('display_errors', True);
$cumulResults = array();
$pagenext="";
for($i=0;$i<2;$i++)
{
try{
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=48.859294,2.347589&radius=50000&sensor=false&keyword=doctor&key=myapikeysecret'.$pagenext,
));
if(!curl_exec($curl)){
die('Error: "' . curl_error($curl) . '" - Code: ' . curl_errno($curl));
}
$resp = curl_exec($curl);
$result = json_decode($resp, true) ;
if(array_key_exists( 'status', $result ) )
{
switch ($result['status'])
{
case "OK":
break;
case "OVER_QUERY_LIMIT":
case "INVALID_REQUEST":
case "REQUEST_DENIED":
//echo $result['status'];
//exit;
break;
}
}
print_r($result );
if (array_key_exists('next_page_token', $result ) )
{
$pagenext = "&pagenex="+$result['next_page_token'];
}else{
$pagenext = "";
}
if($curl){curl_close($curl);}
sleep(5);
} catch (Exception $e) {
if($curl){curl_close($curl);}
}
}
?>
thanks
I would suggest using sleep to wait the thread between calls? Perhaps they are executing too quickly and hitting the request speed limit. Most Google maps services have them but they're not very well documented.
Hope this helps.