PayPal Plus Sandbox - Pay upon Invoice - paypal

I'm integrating PayPal Plus, successfully on my site, except "Pay upon Invoice".
Here's my JavaScript code for integrating the payment wall:
<script src="https://www.paypalobjects.com/webstatic/ppplus/ppplus.min.js"
type="text/javascript"></script>
<script type="application/javascript">
var ppp = PAYPAL.apps.PPP({
"approvalUrl": "<?= $createPaymentArr['links'][1]['href']; ?>",
"placeholder": "ppplus",
"language": "de_DE",
"mode": "sandbox",
"showPuiOnSandbox": "true",
"country": "DE"
});
</script>
When I try to use "Pay upon Invoice" I get this error message:
"Unfortunately we can not process your purchase."
My API call:
$fields = '{
"intent":"sale",
"redirect_urls":{
"return_url":"http://XYZ.info/ABC/paypal/index.php",
"cancel_url":"http://XYZ.info/ABC/paypal/index.php"
},
"payer":{
"payment_method":"paypal"
},
"transactions":[
{
"amount":{
"total":"7.47",
"currency":"EUR",
"details":{
"subtotal":"7.41",
"tax":"0.03",
"shipping":"0.03"
}
},
"item_list":{
"items":[
{
"quantity":"1",
"name":"XYZ",
"price":"7.41",
"currency":"EUR"
}
],
"shipping_address":{
"line1":"XYZ Straße 587",
"city":"OPA",
"postal_code":"12345",
"country_code":"DE"
}
},
"description":"XYZ.info Warenkorb"
}
]
}';
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://api".$mode.".paypal.com/v1/payments/payment",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => $fields,
CURLOPT_HTTPHEADER => array(
"Authorization: Bearer ".$arr['access_token'],
"Content-Type: application/json"
),
));

You need to patch the payment before showing the iframe.
During the patch, simply supply the shipping address.
Then payment upon invoice works, even in the sandbox.

Related

TYPO3 8.7.27: Segment was not a keyword for a postVarSet

I'm installing an existing TYPO3 project. After a lot of trying, we managed to get the typo3 backend ready. However, when I go to the website I always get this error message. This probably has something to do with the multilingualism of the website and with the realurl extension.
composer.json (at root /var/www/html/typo3)
{
"repositories": [{
"type": "composer",
"url": "https://composer.typo3.org/"
},
{
"type": "package",
"package": {
"name": "Bm/ah-contentapi",
"version": "0.0.1",
"type": "typo3-cms-extension",
"source": {
"url": "https://user#bitbucket.org/comp/ah_config_typo3.git",
"type": "git",
"reference": "master"
}
}
},
{
"type": "package",
"package": {
"name": "Bm/ah-contentelements",
"version": "0.0.1",
"type": "typo3-cms-extension",
"source": {
"url": "https://user#bitbucket.org/comp/ah_contentelements_typo3.git",
"type": "git",
"reference": "master"
}
}
}
],
"name": "typo3/cms-base-distribution",
"description": "TYPO3 CMS Base Distribution",
"license": "GPL-2.0-or-later",
"require": {
"helhum/typo3-console": "^4.9.3 || ^5.2",
"typo3/cms-about": "^8.7.10",
"typo3/cms-belog": "^8.7.10",
"typo3/cms-beuser": "^8.7.10",
"typo3/cms-context-help": "^8.7.10",
"typo3/cms-documentation": "^8.7.10",
"typo3/cms-felogin": "^8.7.10",
"typo3/cms-fluid-styled-content": "^8.7.10",
"typo3/cms-form": "^8.7.10",
"typo3/cms-func": "^8.7.10",
"typo3/cms-impexp": "^8.7.10",
"typo3/cms-info": "^8.7.10",
"typo3/cms-info-pagetsconfig": "^8.7.10",
"typo3/cms-rte-ckeditor": "^8.7.10",
"typo3/cms-setup": "^8.7.10",
"typo3/cms-sys-note": "^8.7.10",
"typo3/cms-t3editor": "^8.7.10",
"typo3/cms-tstemplate": "^8.7.10",
"typo3/cms-viewpage": "^8.7.10",
"typo3/cms-wizard-crpages": "^8.7.10",
"typo3/cms-wizard-sortpages": "^8.7.10",
"typo3/cms": "^8.7",
"dmitryd/typo3-realurl": "2.*",
"GridElementsTeam/Gridelements": "8.2.*",
"clickstorm/cs_seo": "3.*",
"Bm/ah-contentapi": "0.0.1",
"Bm/ah-contentelements": "0.0.1"
},
"scripts": {
"typo3-cms-scripts": [
"typo3cms install:fixfolderstructure",
"typo3cms install:generatepackagestates"
],
"post-autoload-dump": [
"#typo3-cms-scripts"
]
},
"extra": {
"typo3/cms": {
"web-dir": "public"
},
"helhum/typo3-console": {
"comment": "This option is not needed ay more for helhum/typo3-console 5.x",
"install-extension-dummy": false
}
},
"autoload": {
"psr-4": {
"Bm\\AhContentelements\\": "public/typo3conf/ext/ah_contentelements/Classes",
"Bm\\AhContentapi\\": "public/typo3conf/ext/ah_contentapi/Classes"
}
}
}
realurl_autoconf.php at location:
/var/www/html/typo3/public/typo3conf/ext/ah_contentapi
<?php
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl'] = array(
'_DEFAULT' => array(
'init' =>
array(
'appendMissingSlash' => 'ifNotFile,redirect',
'emptyUrlReturnValue' => '/',
),
'pagePath' =>
array(
'rootpage_id' => '1',
),
'fileName' =>
array(
'defaultToHTMLsuffixOnPrev' => 0,
'acceptHTMLsuffix' => 0,
'index' =>
array(
'print' =>
array(
'keyValues' =>
array(
'type' => 98,
),
),
),
),
'postVarSets' => array(
'_DEFAULT' => array(
'api' => array(
array(
'GETvar' => 'tx_ahcontentapi_api[type]',
'valueMap' => array(
'json' => 'json',
),
),
array(
'GETvar' => 'tx_ahcontentapi_api[controller]',
'valueMap' => array(
'pages' => 'Pages',
),
),
array(
'GETvar' => 'tx_ahcontentapi_api[action]',
),
array(
'GETvar' => 'tx_ahcontentapi_api[uid]'
),
),
),
),
),
);
realurl extension conf:
as you have multiple realurl files it is important to know which one is used.
in the TYPO3 BackEnd go to the extension manager module, (1)
filter for 'realurl' (2)
and enter the configuration for the extension (3).
then have a view to the configuration:
in the first field (Path to configuration file / basic.configFile (string)) you find the active file.
for a better readability you should select "PHP source (slow)" in the field Automatic configuration file format/ basic.autoConfFormat (options) (it is not noticable slower).
Please show that active realurl config file.

how to create bundle product in Magento 2 by REST API?

I want to create a bundle product through REST API in postman client, but i can't seem to find the right API to create the same. I can add bundle options through REST API but to add those options i need to have a bundle product.So can someone help me with the issue?
I had some issue trying to create a bundle product with the Magento 2 API but finally figured it out, as this post come up every time I googled I will answer here with the request you need to make through postman in order to create a bundle product. Using the url http://{{host}}/rest/default/V1/products with method POST and the Authorization header with the token received from http://{{host}}/rest/default/V1/integration/admin/token, you will have to send the following body as JSON in order to create a bundle product with associated products:
{
"product": {
"sku": "some-bundle-sku",
"name": null,
"attribute_set_id": 4,
"price": 1000,
"status": 1,
"visibility": 1,
"type_id": "bundle",
"created_at": "2018-01-01 00:00:00",
"updated_at": "2018-01-01 00:00:00",
"extension_attributes": {
"stock_item": {
"qty": 100
},
"website_ids": [
1
],
"category_links": [],
"bundle_product_options": [
{
"option_id": 0,
"position": 1,
"sku": "bundle-option-sku",
"title": "Bundle products",
"type": "select",
"required": true,
"product_links": [
{
"sku": "some prod 1 sku",
"option_id": 1,
"qty": 1,
"position": 1,
"is_default": false,
"price": null,
"price_type": null,
"can_change_quantity": 0
},
{
"sku": "some prod 2 sku",
"option_id": 1,
"qty": 1,
"position": 2,
"is_default": false,
"price": null,
"price_type": null,
"can_change_quantity": 0
}
]
}
]
},
"custom_attributes": [
{
"attribute_code": "price_view",
"value": "0"
}
]
},
"saveOptions": true
}
Make sure that the products you are adding in "product_links" exist otherwise it will not create the bundle product. Pay attention to "bundle_product_options", this needs to be an array of options, my mistake was that I was trying to create a single option and I was not passing it within an array.
To Create Bundle Product in Magento 2 via REST API:
//API URL for authentication
$apiURL="http://{host}/rest/V1/integration/admin/token";
//parameters passing with URL
$data = array("username" => "<username>", "password" => "<password>");
$data_string = json_encode($data);
$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);
//decoding generated token and saving it in a variable
$token = json_decode($token);
print_r($token);
//Using above token into header
$headers = array("Content-Type: application/json", "Authorization: Bearer ".$token);
//API URL to Add Product(s) in Magento
$requestUrl='http://{host}/rest/default/V1/products';
$toBeAdded = '{
"product": {
"sku": "some-bundle-sku",
"name": Demo-Bundle,
"attribute_set_id": 4,
"price": 1000,
"status": 1,
"visibility": 1,
"type_id": "bundle",
"created_at": "2019-04-28 00:00:00",
"updated_at": "2019-04-28 00:00:00",
"extension_attributes": {
"stock_item": {
"qty": 100
},
"website_ids": [
1
],
"category_links": [],
"bundle_product_options": [
{
"option_id": 0,
"position": 1,
"sku": "bundle-option-sku",
"title": "Bundle products",
"type": "select",
"required": true,
"product_links": [
{
"sku": "Sample",
"option_id": 1,
"qty": 1,
"position": 1,
"is_default": false,
"price": 20,
"price_type": null,
"can_change_quantity": 0
},
{
"sku": "Demo",
"option_id": 1,
"qty": 1,
"position": 2,
"is_default": false,
"price": 30,
"price_type": null,
"can_change_quantity": 0
}
]
}
]
},
"custom_attributes": [
{
"attribute_code": "price_view",
"value": "0"
}
]
},
"saveOptions": true
}';
$ch = curl_init();
$ch = curl_init($requestUrl);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
$options = array(
CURLOPT_POSTFIELDS=>$toBeAdded
);
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
$result= json_decode($result);
echo "<pre>";
print_r($result);
This should resolve your issues. Also make sure Assigned User has Access to desired Resources and the product you are adding as bundle options must exit on your Magento environment.
Happy coding ! Cheers !
To create bundle product in Magento 2 by REST API, We will be followed some step's see below:
STEP 1- First let us write the configurations (URL's,username,password)
// configuration Data
$url="http://www.example.com/index.php/";
$token_url=$url."rest/V1/integration/admin/token";
$product_url=$url. "rest/V1/products";
$username="your admin username";
$password="your admin password";
$product_links = array(
array("sku"=>"cpu1","qty"=>1)
);
STEP 2- Then let us get access token
//Authentication rest API magento2, get access token
$ch = curl_init();
$data = array("username" => $username, "password" => $password);
$data_string = json_encode($data);
$ch = curl_init($token_url);
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);
$adminToken= json_decode($token);
STEP 3- No let us prepare the Product data
// Create the Configurable Product
$configProductData = array(
'sku' => 'bundle'. uniqid(),
'name' => 'Bundle' . uniqid(),
'visibility' => 4, /*'catalog',*/
'type_id' => 'bundle',
'price' => 99.95,
'status' => 1,
'attribute_set_id' => 4,
'weight' => 1,
'custom_attributes' => array(
array( 'attribute_code' => 'category_ids', 'value' => ["42","41","32"] ),
array( 'attribute_code' => 'description', 'value' => 'Description' ),
array( 'attribute_code' => 'short_description', 'value' => 'Short Description' ),
array( 'attribute_code' => 'price_view', 'value' => '0' ),
array( 'attribute_code' => 'price_type', 'value' => '0' ),
),
'extension_attributes' => array("bundle_product_options"=>array(
array("title"=>"CPU","type"=>"select","product_links"=>$product_links),
),
)
);
$productData = json_encode(array('product' => $configProductData));
STEP 4- At the end we will send the product data to magento to create the product
$setHaders = array('Content-Type:application/json','Authorization:Bearer '.$adminToken);
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $product_url);
curl_setopt($ch,CURLOPT_POSTFIELDS, $productData);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, $setHaders);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
var_dump($response);

New Ionic push registering device tokens

I´ve set up all necessary for push notifications described here.
I am registering the device on startup like:
// register for pushio
$ionicPush.register().then(function(t) {
return $ionicPush.saveToken(t, {ignore_user:true});
}).then(function(t) {
console.log('Token saved:', t.token);
});
The device token is logged "Token saved: xxxxthetokenxxxx".
Now I´m sending push from CURL and the Ionic.io dashboard. The status (checked with CURL) of the message is 200 and no errors. So the push notification is sent:
{"meta": {"request_id": "8d9c69ce-b66c-4002-8cb3-f91c57505b0f", "version": "2.0.0-beta.0", "status": 200}, "data": []}
But my device isn´t recieving the notification. I think that this is due to the saveToken() function. Where is saveToken() saving the token?
Does anybody have a clue how to solve this?
UPDATE:
I´m using this code to send the push:
<?php $curl = curl_init();
$token = "mytoken";
curl_setopt_array($curl, array(
CURLOPT_URL => "https://api.ionic.io/push/notifications",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => '
{
"tokens": "bbc654c496abc2dc42a40941ac944f0a8aeb0d5b227d523e335dbd51b71ed646",
"profile": "getto",
"notification": {
"message": "Hello World!"
}
}',
CURLOPT_HTTPHEADER => array(
"Authorization: Bearer $token",
"Content-Type: application/json"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
} ?>
EDIT: The strange thing is, that on Android the device token is not registered.
Initialize the service and register your device in your module's run function. You'll need the device token that is registered by the user for sending notification to the user.
$ionicPush.init({
debug: true,
onNotification: function (notification) {
console.log('token:', notification.payload);
},
onRegister: function (token) {
console.log('Device Token:', token);
$ionicPush.saveToken(token); // persist the token in the Ionic Platform
}
});
$ionicPush.register();
Ionic Push lets you create targeted push notifications through the dashboard (ionic.io). You can also send notifications from the server in the below format.
curl -X POST -H "Authorization: Bearer API_TOKEN" -H "Content-Type: application/json" -d '{
"tokens": ["DEVICE_TOKEN"],
"profile": "PROFILE_TAG",
"notification": {
"message": "Hello World!"
"android": {
"title": "Hi User",
"message": "An update is available for your App",
"payload": {
"update": true
}
}
} }' "https://api.ionic.io/push/notifications"

Paypal adaptive payment error 58001

I am currently developing an adaptive payment system using paypal however a 58001 error keeps occurring
Paypal Response:
{
"responseEnvelope": {
"timestamp": "2013-09-05T23:38:25.762-07:00",
"ack": "Failure",
"correlationId": "a72d1f30e37d4",
"build": "6941298"
},
"error": [
{
"errorId": "580001",
"domain": "PLATFORM",
"subdomain": "Application",
"severity": "Error",
"category": "Application",
"message": "Invalid request: {0}"
}
]
}
Paypal Request:
$createPacket = array(
"actionType" => "PAY",
"currencyCode " => "USD",
"receiverList" => array(
"reveiver" => array(
array(
"amount" => "1.00",
"email" => USER_EMAIL1
),
array(
"amount" => "3.00",
"email" => USER_EMAIL2
)
)
),
"returnUrl" => "http://localhost/",
"errorUrl" => "http://localhost/",
"cancelUrl" => "http://localhost/",
"requestEnvelope" => array(
"errorLanguage" => "en_US",
"detailLevel" => "ReturnAll"
)
);
And I can't figure out what's wrong. I have double checked everything.
I figured it out. I just had and extra space after currencyCode. It was "currencyCode " => "USD" when is should have been "currencyCode" => "USD" :)

Google Calendar API - PATCH returning 200 OK but not actually updating event

I'm attempting to integrate my webapp's calendar with Google Calendar. I'm successfully authenticating the user, able to read events from Google and delete events from Google. I'm having trouble updating events from my app to Google.
I'm using the PATCH method described here as I only want to modify the fields that I send in the API call (as opposed to the PUT call which requires all fields for the event).
My Perl code create a JSON object representing what I want to change. I then submit a PATCH request to Google, and I receive status 200 OK and the event resource back from Google. What I receive back is supposed to be the modified event resource, but the fields I have modified are not modified in the response. When I check in Google Calendar itself, once again I see the event is not modified.
I'm confused as to why I'm getting the 200 OK response instead of an error, when the event is not updating. Curiously, in the response, the "updated" timestamp property has been updated, but the summary field has not.
my $ua = LWP::UserAgent->new;
my $url = "https://www.googleapis.com/calendar/v3/calendars/primary/events/${id}?access_token=${access_token}";
my $resource{"summary"} = "$g{summary}";
$resource = encode_json(\%resource);
my $headers = HTTP::Headers->new();
$headers->header(If_Match => "$etag");
my $request = HTTP::Request->new('PATCH',$url,$headers,$resource);
my $response = $ua->request($request);
my $status = $response->status_line;
my $result = decode_json($response->decoded_content);
The "etag" value from the result is updated as I expect, which indicates that the calendar event is being (somewhat) modified in Google.
Some Data::Dumper tracing:
The request:
$VAR1 = bless( {
'_content' => '{"summary":"End of season function MODIFIED"}',
'_uri' => bless( do{\(my $o = 'https://www.googleapis.com/calendar/v3/calendars/primary/events/<eventID>?access_token=<access_token>')}, 'URI::https' ),
'_headers' => bless( {
'if-match' => '<etag>'
}, 'HTTP::Headers' ),
'_method' => 'PATCH'
}, 'HTTP::Request' );
The response:
$VAR1 = bless( {
'_protocol' => 'HTTP/1.1',
'_content' => '{
"kind": "calendar#event",
"etag": "<etag>",
"id": "<eventID>",
"status": "confirmed",
"htmlLink": "<suppressed>",
"created": "2012-03-08T05:06:04.000Z",
"updated": "2012-03-25T09:18:49.000Z",
"summary": "End of season function",
"creator": {
"email": "<suppressed>"
},
"organizer": {
"email": "<suppressed>"
},
"start": {
"date": "2012-03-24"
},
"end": {
"date": "2012-03-24"
},
"iCalUID": "<suppressed>",
"sequence": 1,
"reminders": {
"useDefault": true
}
}
',
'_rc' => '200',
'_headers' => bless( {
'connection' => 'close',
'cache-control' => 'no-cache, no-store, max-age=0, must-revalidate',
'date' => 'Sun, 25 Mar 2012 09:18:49 GMT',
'client-ssl-cert-issuer' => '/C=US/O=Google Inc/CN=Google Internet Authority',
'client-ssl-cipher' => 'ECDHE-RSA-RC4-SHA',
'client-peer' => '173.194.72.95:443',
'client-date' => 'Sun, 25 Mar 2012 09:18:49 GMT',
'pragma' => 'no-cache',
'content-type' => 'application/json; charset=UTF-8',
'x-xss-protection' => '1; mode=block',
'server' => 'GSE',
'client-ssl-socket-class' => 'IO::Socket::SSL',
'client-response-num' => 1,
'etag' => '<etag>',
'x-frame-options' => 'SAMEORIGIN',
'x-content-type-options' => 'nosniff',
'client-ssl-cert-subject' => '/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.googleapis.com',
'expires' => 'Fri, 01 Jan 1990 00:00:00 GMT'
}, 'HTTP::Headers' ),
'_msg' => 'OK',
'_request' => bless( {
'_content' => '{"summary":"End of season function MODIFIED"}',
'_uri' => bless( do{\(my $o = 'https://www.googleapis.com/calendar/v3/calendars/primary/events/<eventID>?access_token=<access_token>')}, 'URI::https' ),
'_headers' => bless( {
'user-agent' => 'libwww-perl/6.01',
'if-match' => '<etag>'
}, 'HTTP::Headers' ),
'_method' => 'PATCH',
'_uri_canonical' => $VAR1->{'_request'}{'_uri'}
}, 'HTTP::Request' )
}, 'HTTP::Response' );
Can anyone see what I'm doing wrong? I'm sure that Google is accepting my PATCH request, but for some reason not exactly seeing the field I want to modify. I've tried submitting the exact same JSON object on their testing page and have no problem getting that to work...
I found the solution purely by trial and error - adding the "Content-Type" header to the HTTP header seemed to do the trick:
my $headers = HTTP::Headers->new();
$headers->header(If_Match => "$etag");
$headers->header(Content_Type => "application/json");
Adding the header accept = application/json fixed it for me