I have a problem with a POST to add the informations of a credit card.
I'm using MangoPay's API to implement the payment method.
I've installed mangopay/php-sdk-v2 et http-client pour gérer les API.
To add a credit card, I have to create a token.
The resulted token is an object with these keys:
{
"Id": "136943412",
"Tag": null,
"CreationDate": 1649425095,
"UserId": "135643537",
"AccessKey": "1X0m87dmM2LiwFgxPLBJ",
"PreregistrationData": "Qi7oou23Q8d9B3xUpjdMucwiSczJqPyOPNZWThaZUKnrBt3dR9IXdzkIKyiibnTP2ddFLVXdicolcUIkv_kKEA",
"RegistrationData": null,
"CardId": null,
"CardType": "CB_VISA_MASTERCARD",
"CardRegistrationURL": "https://homologation-webpayment.payline.com/webpayment/getToken",
"ResultCode": null,
"ResultMessage": null,
"Currency": "EUR",
"Status": "CREATED"
}
After that, I have to do a POST with the URL give by the CardRegistrationURL.
Its body will have five keys to enter:
data (its value => PreregistrationData), accessKeyRef, cardNumber, cardExpirationDate and cardCvx.
// ApiUser.php
public function Registration($id, $form)
{
$CardRegistration = new \MangoPay\CardRegistration();
$CardRegistration->UserId = $id;
$CardRegistration->Currency = "EUR";
$CardRegistration->CardType = "CB_VISA_MASTERCARD";
$Result = $this->mangoPayApi->CardRegistrations->Create($CardRegistration);
$this->registration = $Result;
$respose = $this->client->request(
'POST',
$Result->CardRegistrationURL,
[
'headers' => [
'Content-Type' => [
'application/x-www-form-urlencoded',
'application/json',
],
'Connection' => 'keep-alive'
],
'json' => [
'data' => $Result->PreregistrationData,
'accessKeyRef' => $Result->AccessKey,
'cardNumber' => $form['cardnumber']->getData(),
'cardExpirationDate ' => $form['cardexpdate']->getData(),
'cardCvx' => $form['cardcvx']->getData(),
]
]
);
return [
$response,
$Result
];
}
If it worked, I should have as a result a string that start by data=.
But an error occurs:
All query attempts failed for homologation-webpayment.payline.com: No response for 'homologation-webpayment.payline.com' (A) from any nameserver within 3000 ms after 2 attempts, tried udp://192.168.1.254:53, udp://192.168.1.254:53, No response for 'homologation-webpayment.payline.com' (AAAA) from any nameserver within 3000 ms after 2 attempts, tried udp://192.168.1.254:53, udp://192.168.1.254:53
Related
I'm using the Merchant Fulfillment portion of the Amazon Selling Partner API found at https://github.com/jlevers/selling-partner-api/
I have other portions working... namely orders coming down and reports going up. But I am using the same techniques and the Merchant Fulfillment API is not working. The response I get back indicates that it's not received the data I am sending it.
What am I doing wrong?
// North America Live
$NA = [
'url' => 'https://sellingpartnerapi-na.amazon.com',
'region' => 'us-east-1',
];
// North America Sandbox
// $NA = [
// 'url' => 'https://sandbox.sellingpartnerapi-na.amazon.com',
// 'region' => 'us-east-1',
// ];
$config = new SellingPartnerApi\Configuration([
"lwaClientId" => $lwaClientId,
"lwaClientSecret" => $lwaClientSecret,
"lwaRefreshToken" => $lwaRefreshToken,
"awsAccessKeyId" => $awsAccessKeyId,
"awsSecretAccessKey" => $awsSecretAccessKey,
"endpoint" => $NA // or another endpoint from lib/Endpoint.php
]);
$apiInstance = new SellingPartnerApi\Api\MerchantFulfillmentApi($config);
$body = new \SellingPartnerApi\Model\MerchantFulfillment\GetEligibleShipmentServicesRequest(
[
"shipment_request_details" =>
[
"amazon_order_id" => "XXX-XXXXXXXX-XXXXXXXX",
"item_list" =>
[
"order_item_id" => "XXXXXXXXXXXXXXX",
"quantity" => 1,
],
"ship_from_address" =>
[
"name" => "XXXXXXX",
"address_line1" => "XXXXXXXXXX",
"email" => "XXXXX#XXXXX.COM",
"city" => "XXXXXXXXX",
"postal_code" => "XXXXXX",
"country_code" => "US",
"phone" => "XXXXXXXXXXXX",
],
"weight" =>
[
"value" => 7,
"unit" => "oz",
],
"shipping_service_options" =>
[
"delivery_experience" => "DeliveryConfirmationWithSignature",
"carrier_will_pick_up" => true,
]
]
]
);
try {
$result = $apiInstance->getEligibleShipmentServices($body);
d($result);
} catch (Exception $e) {
echo "<PRE>";
echo 'Exception when calling MerchantFulfillmentV0Api->getEligibleShipmentServices: <BR>', wordwrap($e->getMessage(),80,"<br>\n",TRUE), PHP_EOL;
echo "</PRE>";
}
The $response I get back is:
Exception when calling MerchantFulfillmentV0Api->getEligibleShipmentServices:
[400] {
"errors": [
{
"code": "InvalidInput",
"message": "5
validation errors detected: Value \u0027\u0027 at
\u0027shipmentRequestDetails.shipFromAddress.email\u0027 failed to satisfy
constraint: Member must satisfy regular expression pattern: .+#.+; Value
\u0027\u0027 at \u0027shipmentRequestDetails.amazonOrderId\u0027 failed to
satisfy constraint: Member must satisfy regular expression pattern:
[0-9A-Z]{3}-[0-9]{7}-[0-9]{7}; Value \u0027\u0027 at
\u0027shipmentRequestDetails.weight.unit\u0027 failed to satisfy constraint:
Member must satisfy enum value set: [g, ounces, oz, grams]; Value null at
\u0027shipmentRequestDetails.weight.value\u0027 failed to satisfy constraint:
Member must not be null; Value \u0027[]\u0027 at
\u0027shipmentRequestDetails.itemList\u0027 failed to satisfy constraint: Member
must have length greater than or equal to 1",
"details": ""
}
]
}
In the Shipping Service options.... this needs to be set false.
"carrier_will_pick_up" => true,
If its set to true then it will not work. I think it has something to do with sending a request for pickup to the carrier.... and it seems counter-intuitive to set it to false... but thats what made it work!
Description
I am trying to integrate Amadeus Self-Service API within the Laravel Environment. I am successfully able to get content by GET request, but I am not able to get content by the POST request. I have set the exceptions to display the errors thrown by the guzzle in specific.
Here is the api reference, which has the data and the endpoint which I want to post to.
https://developers.amadeus.com/self-service/category/air/api-doc/flight-offers-search/api-reference
How to reproduce
This is the method which I call from my Client.php and pass the data through by calling the POST method.
public function __construct() {
throw_if(static::$instance, 'There should be only one instance of this class');
static::$instance = $this;
$this->client = new Client([
'base_uri' => 'https://test.api.amadeus.com/',
]);
}
public function get($uri, array $options = []) {
$this->authenticate();
return $this->client->request('GET', $uri, [
$options,
'headers' => [
'Authorization' => 'Bearer '.$this->access_token,
],
]);
}
public function post($uri, array $options = []) {
$this->authenticate();
return $this->client->request('POST', $uri, [
$options,
'headers' => [
'Authorization' => 'Bearer '.$this->access_token,
],
]);
}
After calling the POST method, I pass the 'X-HTTP-Method-Override' as 'GET', and pass the data as body.
$requests_response = $client->post('v2/shopping/flight-offers', [
'headers' => [
'X-HTTP-Method-Override' => 'GET',
],
'body' => [
[
"currencyCode" => "USD",
"originDestinations" => [
[
"id" => "1",
"originLocationCode" => "RIO",
"destinationLocationCode" => "MAD",
"departureDateTimeRange" => [
"date" => "2022-11-01",
"time" => "10:00:00",
],
],
[
"id" => "2",
"originLocationCode" => "MAD",
"destinationLocationCode" => "RIO",
"departureDateTimeRange" => [
"date" => "2022-11-05",
"time" => "17:00:00",
],
],
],
"travelers" => [
["id" => "1", "travelerType" => "ADULT"],
["id" => "2", "travelerType" => "CHILD"],
],
"sources" => ["GDS"],
"searchCriteria" => [
"maxFlightOffers" => 2,
"flightFilters" => [
"cabinRestrictions" => [
[
"cabin" => "BUSINESS",
"coverage" => "MOST_SEGMENTS",
"originDestinationIds" => ["1"],
],
],
"carrierRestrictions" => [
"excludedCarrierCodes" => ["AA", "TP", "AZ"],
],
],
],
],
],
]);
Additional context
Here is the error, which I caught in the log.
local.ERROR: Guzzle error {"response":{"GuzzleHttp\\Psr7\\Stream":"
{
\"errors\": [
{
\"code\": 38189,
\"title\": \"Internal error\",
\"detail\": \"An internal error occurred, please contact your administrator\",
\"status\": 500
}
]
}
"}}
local.ERROR: Server error: POST https://test.api.amadeus.com/v2/shopping/flight-offers resulted in a 500 Internal Server Error response:
{
"errors": [
"code": 38189,
(truncated...)
"exception":"[object] (GuzzleHttp\\Exception\\ServerException(code: 500): Server error: POST https://test.api.amadeus.com/v2/shopping/flight-offers resulted in a 500 Internal Server Error response:
"errors": [
"code": 38189,
(truncated...)
at C:\\xampp\\htdocs\\Application\\vendor\\guzzlehttp\\guzzle\\src\\Exception\\RequestException.php:113)
Please spare some time to have a look, help is really appreciated.
Do the POST calls actually work using a HTTP client such as Postman or Insomnia ?
I am noticing is that you are passing an array of $options and are nesting it inside the Guzzle options. The resulting call will look something like this:
$this->client->request('POST', $uri, [
['headers' => '...', 'body' => ['...']],
'headers' => ['...']
]);
That won't work, you are going to need to unpack them this way:
public function post($uri, array $options = []) {
$this->authenticate();
return $this->client->request('POST', $uri, [
...$options,
'headers' => [
'Authorization' => 'Bearer '.$this->access_token,
],
]);
}
Notice the dots ... to unpack the options array. Also notice that you are setting the headers key twice (once in your post method definition and once in the options parameter), so only one will actually be used (by the way why exactly are you using the X-HTTP-Method-Override header ?).
Another solution if you want to pass all header and body in the POST function parameters is this:
public function post($uri, array $options = []) {
$this->authenticate();
return $this->client->request('POST', $uri, [
'json' => $options['json'], // I would suggest 'json' because it looks like the API is looking for a JSON body, if that doesn't work go with 'body'
'headers' => [
'Authorization' => 'Bearer '.$this->access_token,
...$options['headers']
],
]);
}
Another thing you might try if this doesn't do it is using the Guzzle json option instead of body for the POST request.
when you are exploring any Amadeus Self Service API, I recommend to review the portal, because it will help you with one idea about how to make the http calls.
In your case:
https://developers.amadeus.com/self-service/category/air/api-doc/flight-offers-search/api-reference
Another help could be to review the coding examples:
https://github.com/amadeus4dev/amadeus-code-examples/blob/master/flight_offers_search/v2/post/curl/
https://github.com/amadeus4dev/amadeus-code-examples/tree/master/flight_offers_search/v2/get/curl
Maybe it's a little late but this example work for me:
$options = [
'headers' => [
'Authorization' => sprintf('Bearer %s', $this->getApiToken()),
'content-type' => 'application/vnd.amadeus+json',
'X-HTTP-Method-Override' => 'GET',
],
'body' => '{
"currencyCode": "XPF",
"originDestinations": [
{
"id": 1,
"originLocationCode": "PPT",
"originRadius": null,
"alternativeOriginsCodes": [],
"destinationLocationCode": "CDG",
"alternativeDestinationsCodes": [],
"departureDateTimeRange": {
"date": "2022-12-22",
"dateWindow": "I2D"
},
"includedConnectionPoints": [],
"excludedConnectionPoints": []
}
],
"travelers": [
{
"id": "1",
"travelerType": "ADULT",
"associatedAdultId": null
}
],
"sources": [
"GDS"
]
}'
];
try {
...
$response = $this->httpClient->post(self::AMADEUS_API_URL_FLIGHT_OFFER, $options);
$body = $response->getBody();
...
Note: don't forget the content-type, it's not very obvious at first sight in the documentation but without it doesnt work with Guzzle for me (but with insomnia no problem)
consts of the class:
private const AMADEUS_API_CLIENT_GRANT_TYPE = 'client_credentials';
private const AMADEUS_API_URL_AUTH = '/v1/security/oauth2/token';
private const AMADEUS_API_URL_FLIGHT_OFFER = '/v2/shopping/flight-offers';
Authentication:
/**
*
*/
public function authenticate()
{
if (!is_null($this->getApiToken())) {
return $this->getApiToken();
}
$options = [
'form_params' => [
'client_id' => $this->apiId, //setted in the parent construct
'client_secret' => $this->apiKey, //setted in the parent construct
'grant_type' => self::AMADEUS_API_CLIENT_GRANT_TYPE,
]
];
try {
$response = $this->httpClient->post(self::AMADEUS_API_URL_AUTH, $options);
} catch (ClientExceptionInterface $exception) {
...
}
if ($response->getStatusCode() != Response::HTTP_OK) {
throw new ApiException($errorMessage, [$response->getReasonPhrase()], $response->getStatusCode());
}
$body = $response->getBody();
//custom serializer, AmadeusAuthenticationResponse is a mapping based on Amadeus authentication response
$authenticationResponse = $this->serializer->convertSerializationToData($body->getContents(), AmadeusAuthenticationResponse::class);
$this->setApiToken($authenticationResponse->getAccessToken());
return $this->getApiToken();
}';
I am trying to hit a POST API Endpoint with Guzzle in PHP (Wordpress CLI) to calculate shipping cost. The route expects a RAW JSON data in the following format:
{
"startCountryCode": "CH"
"endCountryCode": "US",
"products": {
"quantity": 1,
"vid": x //Variable ID
}
}
Link to the API I am consuming: https://developers.cjdropshipping.com/api2.0/v1/logistic/freightCalculate
$body = [
"endCountryCode" => "US",
"startCountryCode" => "CN",
"products" => [
'vid' => $vid,
'quantity' => 1
],
];
$request = $this->client->request(
'POST', 'https://developers.cjdropshipping.com/api2.0/v1/logistic/freightCalculate',
[
'headers' => [
'CJ-Access-Token' => $this->auth_via_cj(), // unnecessary, no auth required. Ignore this header
],
'body' => json_encode( $body )
],
);
I've also tried using 'json' => $body instead of the 'body' parameter.
I am getting 400 Bad Request error.
Any ideas?
Try to give body like this.
"json" => json_encode($body)
I spent so many hours on this to just realise that products is actually expecting array of objects. I've been sending just a one-dimensional array and that was causing the 'Bad Request' error.
In order to fix this, just encapsulate 'vid' and 'quantity' into an array and voila!
You don't need to convert data in json format, Guzzle take care of that.
Also you can use post() method of Guzzle library to achieve same result of request. Here is exaple...
$client = new Client();
$params['headers'] = ['Content-Type' => 'application/json'];
$params['json'] = array("endCountryCode" => "US", "startCountryCode" => "CN", "products" => array("vid" => $vid, "quantity" => 1));
$response = $client->post('https://developers.cjdropshipping.com/api2.0/v1/logistic/freightCalculate', $params);
I've managed to go through creating webhook using Shopify API, but I can create only one webhook per request. I've already tried to customize the request so it could possibly create a few webhooks at once, but it doesn't seem to work.
I'm using GuzzleHttp\Client for my requests and this is what my working request look like:
$client = new Client();
$response = $client->request(
'POST',
"https://{$store}/admin/webhooks.json",
[
'headers' => [
'X-Shopify-Access-Token' => $access_token,
'X-Shopify-Shop-Domain' => $store
],
'form_params' => [
'webhook' => [
"topic" => "orders/create",
"address" => $appAddress,
"format" => "json"
],
]
]);
But when I try something like this:
$client = new Client();
$response = $client->request(
'POST',
"https://{$store}/admin/webhooks.json",
[
'headers' => [
'X-Shopify-Access-Token' => $access_token,
'X-Shopify-Shop-Domain' => $store
],
'form_params' => [
'webhook' => [
[
"topic" => "orders/create",
"address" => $appAddress,
"format" => "json"
],
[
"topic" => "orders/delete",
"address" => $appAddress,
"format" => "json"
]
]
]
]);
Im getting this:
POST https://smshopify.myshopify.com/admin/webhooks.json resulted in
a 422 Unprocessable Entity response: {"errors":{"topic":["can't be blank","Invalid topic specified. Topics allowed: app/uninstalled,
carts/create, carts/u (truncated...)
Is there a way to create couple webhooks in one request, I couldn't find a word about it in Shopify documentation, and my attempts to modify request body are not very successful. What I've managed to do is just foreach topics array and to the single request for every webhook.
No, there is no way to create a batch of webhooks in one request. This is true for most Shopify resources - e.g. products must also be created one-by-one.
I try to send http request to track eCommerce.
I got response http_code=200 but, I can't see any event or transaction.
Code:
$fields_string = '';
$fields = array(
'v' => 1,
'tid' => "UA-xxxxxx-1",
'cid' => $userid,
't' => 'transaction',
'ti' => $transaction_id,
'tr' => $Transaction_revenue,
'ts' => $Transaction_shipping,
'tt' => $tax,
'cu' =>'EUR'
);
Hit:
v=1&t=event&tid=UA-xxxxxx-1&cid=555&uid=123&ti=21&tr=20&tt=5&ts=2&pa=purchase&ec=Checkout&ea=Purchase
what could be the problem?
Thanks a lot.
What makes you think its not working. I ran your hit against debug collect to verify it. Looks good to me.
https://www.google-analytics.com/debug/collect?v=1&t=event&tid=UA-3731463-1&cid=555&uid=123&ti=21&tr=20&tt=5&ts=2&pa=purchase&ec=Checkout&ea=Purchase
{
"hitParsingResult": [ {
"valid": true,
"parserMessage": [ ],
"hit": "/debug/collect?v=1\u0026t=event\u0026tid=UA-3731463-1\u0026cid=555\u0026uid=123\u0026ti=21\u0026tr=20\u0026tt=5\u0026ts=2\u0026pa=purchase\u0026ec=Checkout\u0026ea=Purchase"
} ],
"parserMessage": [ {
"messageType": "INFO",
"description": "Found 1 hit in the request."
} ]
}
Did you check the real time reports have you double checked your Tid?
https://www.google-analytics.com/debug/collect?v=1&tid=UA-3731463-1&cid=123&t=transaction&ti=124&tr=1&ts=1&tt=1&cu=EUR
{
"hitParsingResult": [ {
"valid": true,
"parserMessage": [ ],
"hit": "/debug/collect?v=1\u0026tid=UA-3731463-1\u0026cid=123\u0026t=transaction\u0026ti=124\u0026tr=1\u0026ts=1\u0026tt=1\u0026cu=EUR"
} ],
"parserMessage": [ {
"messageType": "INFO",
"description": "Found 1 hit in the request."
} ]
}
Could also be something with the values you are sending in the second one.
Apparently I cloud not send transaction because my IP was blocked.