XERO PHP SDK createPayment Validation Exception - xero-api

Using the new SDK using this code in the sandbox:
$payment = new \XeroAPI\XeroPHP\Models\Accounting\Payment([
'code' => '001',
'invoice_number' => $inv_num,
'amount' => $amount
]);
$this->accounting_api->createPayment($this->getSingleTenant(), $payment);
I get the following exception
"ErrorNumber": 10,
"Type": "ValidationException",
"Message": "A validation exception occurred",
"Elements": [
{
"Date": "\/Date(1604880000000+0000)\/",
"Amount": 1.74,
"Status": "AUTHORISED",
"HasAccount": false,
"HasValidationErrors": true,
"ValidationErrors": [
{
"Message": "You must specify either an Invoice ID or Invoice Number or CreditNote ID or CreditNote Number or Prepayment ID or Overpayment ID for the payment"
},
{
"Message": "You must specify and Account code or Account ID for the payment"
},
{
"Message": "You must specify an Overpayment ID for the payment"
}
]
}
]
Do I really have a problem with my inputs, am I missing something required that is triggering this or is the API tanking on this?

In the end the answer was to ignore the account_number and code properties and their getters and setters instead using empty Invoice and Account objects with just the code and invoice_number properties set:
public function RegisterPayment($amount, $inv_num, $account_code){
$payment = new \XeroAPI\XeroPHP\Models\Accounting\Payment([
'account' => new \XeroAPI\XeroPHP\Models\Accounting\Account(['code' => $account_code]),
'invoice' => new \XeroAPI\XeroPHP\Models\Accounting\Invoice(['invoice_number' => $inv_num]),
'amount' => $amount,
'date' => date('Y-m-d')
]);
try{
$this->accounting_api->createPayment($this->getSingleTenant(), $payment);
} catch (\XeroAPI\XeroPHP\ApiException $ex) {
//var_dump($ex->getResponseBody());
}
}

Related

approve an order through paypal Using Saved Card Vault v2 api

The reason why we would want to use the vault is so that we don’t have to store sensitive credit card information on our own servers. We simply reference the payment method via a provided vault ID, meaning that we don’t have to deal with many PCI compliance regulations with storing the credit cards ourselves.
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api-m.sandbox.paypal.com/v2/checkout/orders',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"intent": "CAPTURE",
"purchase_units": [
{
"items": [
{
"name": "T-Shirt",
"description": "Green XL",
"quantity": "1",
"unit_amount": {
"currency_code": "USD",
"value": "100.00"
}
}
],
"amount": {
"currency_code": "USD",
"value": "100.00",
"breakdown": {
"item_total": {
"currency_code": "USD",
"value": "100.00"
}
}
}
}
],
"application_context": {
"return_url": "https://example.com/return",
"cancel_url": "https://example.com/cancel"
}
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Prefer: return=representation',
'PayPal-Request-Id: 232b4c61-b6f7-4c1b-b39c-43e82a1c6daa',
'Authorization: Bearer '
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
A successful request returns the HTTP 201 Created status code and a JSON response body that includes by default a minimal response with the ID, status, and HATEOAS links. If you require the complete order resource representation, you must pass the Prefer: return=representation request header. This header value is not the default.
Example:
{
"id": "1SX99239FX399905E",
"intent": "CAPTURE",
"status": "CREATED",
"purchase_units": [
{
"reference_id": "default",
"amount": {
"currency_code": "USD",
"value": "100.00",
"breakdown": {
"item_total": {
"currency_code": "USD",
"value": "100.00"
}
}
},
"payee": {
"email_address": "john_merchant#example.com",
"merchant_id": "C7CYMKZDG8D6E"
},
"items": [
{
"name": "T-Shirt",
"unit_amount": {
"currency_code": "USD",
"value": "100.00"
},
"quantity": "1",
"description": "Green XL"
}
]
}
],
"create_time": "2022-07-20T00:20:41Z",
"links": [
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/1SX99239FX399905E",
"rel": "self",
"method": "GET"
},
{
"href": "https://www.sandbox.paypal.com/checkoutnow?token=1SX99239FX399905E",
"rel": "approve",
"method": "GET"
},
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/1SX99239FX399905E",
"rel": "update",
"method": "PATCH"
},
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/1SX99239FX399905E/capture",
"rel": "capture",
"method": "POST"
}
]
}
What I need is to be able to integrate from the paypal vault the cards returned in v1 with the credit card id CARD-1YE76616JL1119629MCSXFCY
In the documentation I don't see a way to make a payment through the vault in version v1 it could be done but in this one I still don't know how
The sample code was as it was previously done before v2
public function CreatePaymentUsingSavedCardVault($requestData, $credit_card_id) {
try {
///$card = new CreditCard();
//$card->setId($credit_card_id);
// ### Credit card token
// Saved credit card id from CreateCreditCard.
$creditCardToken = new CreditCardToken();
$creditCardToken->setCreditCardId($credit_card_id);
// ### FundingInstrument
// A resource representing a Payer's funding instrument.
// For stored credit card payments, set the CreditCardToken
// field on this object.
$fi = new FundingInstrument();
$fi->setCreditCardToken($creditCardToken);
// ### Payer
// A resource representing a Payer that funds a payment
// For stored credit card payments, set payment method
// to 'credit_card'.
$payer = new Payer();
$payer->setPaymentMethod("credit_card");
$payer->setFundingInstruments(array($fi));
// ### Itemized information
// (Optional) Lets you specify item wise information
$itemListArray = array();
if(isset($requestData['orderItems'])){
foreach ($this->checkEmptyObject($requestData['orderItems']) as $value) {
$item = new Item();
$array = array_filter($value);
if (count($array) > 0) {
$this->setArrayToMethods($array, $item);
array_push($itemListArray, $item);
}
}
}
$itemList = new ItemList();
if(!empty($itemListArray)){
$itemList->setItems($itemListArray);
}
// ### Additional payment details
// Use this optional field to set additional payment information such as tax, shipping charges etc.
if (isset($requestData['paymentDetails'])) {
$details = new Details();
$this->setArrayToMethods($this->checkEmptyObject($requestData['paymentDetails']), $details);
}
// ### Amount
// Lets you specify a payment amount. You can also specify additional details such as shipping, tax.
$amount = new Amount();
if (isset($requestData['amount'])) {
$this->setArrayToMethods($this->checkEmptyObject($requestData['amount']), $amount);
}
$detailsArray = $this->checkEmptyObject((array)$details);
if (!empty($detailsArray)) {
$amount->setDetails($details);
}
// ### Transaction
// A transaction defines the contract of a payment - what is the payment for and who is fulfilling it.
$transaction = new Transaction();
$amountArray = $this->checkEmptyObject((array)$amount);
if(!empty($amountArray)){
$transaction->setAmount($amount);
}
$itemListArray = $this->checkEmptyObject((array)$itemList);
if (!empty($itemListArray)) {
$transaction->setItemList($itemList);
}
if (isset($requestData['transaction'])){
$this->setArrayToMethods($this->checkEmptyObject($requestData['transaction']), $transaction);
}
// ### Payment
// A Payment Resource; create one using the above types and intent set to sale 'sale'
$payment = new Payment();
$payment->setIntent($requestData['intent']);
$payerArray = $this->checkEmptyObject((array)$payer);
if(!empty($payerArray)){
$payment->setPayer($payer);
}
$transactionArray = $this->checkEmptyObject((array)$transaction);
if(!empty($transactionArray)){
$payment->setTransactions(array($transaction));
}
$requestArray = clone $payment;
$payment->create($this->_api_context);
$returnArray['RESULT'] = 'Success';
$returnArray['PAYMENT'] = $payment->toArray();
$returnArray['RAWREQUEST']=$requestArray->toJSON();
$returnArray['RAWRESPONSE']=$payment->toJSON();
$paypal = new PayPal(array());
$paypal->TPV_Parse_Request($payment->toArray(), array(), 24, true, false, 'PayPal_Rest');
return $returnArray;
} catch (\PayPal\Exception\PayPalConnectionException $ex) {
return $this->createErrorResponse($ex);
}
}

INVALID DATA RECEIVED in flightOffers.pricing

I'm getting an "INVALID DATA RECEIVED"/"Flight segment not found" error when making a POST request to /shopping/flight-offers/pricing. I am using data from the flightOffersSearch GET request. I'm just getting started and following the amadeus tutorial, but as far as I can tell my data and code look correct. Since I am just getting started I am running this in the test env.
Here's my data:
{"data":{"type":"flight-offers-pricing","flightOffers":[{"type":"flight-offer","id":"1","source":"GDS","instantTicketingRequired":false,"nonHomogeneous":false,"oneWay":false,"lastTicketingDate":"2022-07-27","numberOfBookableSeats":3,"itineraries":[{"duration":"PT2H27M","segments":[{"departure":{"iataCode":"LGA","terminal":"0","at":"2022-11-22T08:05:00"},"arrival":{"iataCode":"ORD","terminal":"2","at":"2022-11-22T09:32:00"},"carrierCode":"DL","number":"1189","aircraft":{"code":"223"},"operating":{"carrierCode":"DL"},"duration":"PT2H27M","id":"1","numberOfStops":0,"blacklistedInEU":false}]}],"price":{"currency":"EUR","total":"103.82","base":"83.00","fees":[{"amount":"0.00","type":"SUPPLIER"},{"amount":"0.00","type":"TICKETING"}],"grandTotal":"103.82"},"pricingOptions":{"fareType":["PUBLISHED"],"includedCheckedBagsOnly":false},"validatingAirlineCodes":["DL"],"travelerPricings":[{"travelerId":"1","fareOption":"STANDARD","travelerType":"ADULT","price":{"currency":"EUR","total":"103.82","base":"83.00"},"fareDetailsBySegment":[{"segmentId":"1","cabin":"ECONOMY","fareBasis":"XAVNA0BQ","brandedFare":"BASICECON","class":"E","includedCheckedBags":{"quantity":0}}]}]}]}}
Here's the code:
exports.confirmFlight = (req, res, next) => {
//implement the amadeus confirm flight logic
const flight = req.body.flight;
amadeus.shopping.flightOffers.pricing
.post(
JSON.stringify({
data: { type: 'flight-offers-pricing', flightOffers: [flight] },
})
)
.then((response) => {
res.send(response.result);
//console.log(response);
})
.catch((response) => res.send(response));
};
Here's the error:
"result": {
"errors": [
{
"code": 4926,
"title": "INVALID DATA RECEIVED",
"detail": "Flight segment not found",
"status": 400
}
]
},
"parsed": true

Loopback 4 auto generated model with required id failing validation

I'm using an automated script that runs an auto-generation model using lb4 cli.
Looks like validation expects id to be provided, but swagger missing it in its schema. Why I can't see the id property in swagger?
PLEASE NOTE! I don't want to modify manually my models
lb4 model activity --dataSource DS --table activity
Created model:
export class Activity extends Entity {
#property({
type: 'string',
required: true,
id: 1,
postgresql: {
columnName: 'id',
dataType: 'uuid',
dataLength: null,
dataPrecision: null,
dataScale: null,
nullable: 'NO',
},
})
id: string;
...
}
When I run the swagger tool and try to POST new activity, it missing the id field and returns the following error:
{
"error": {
"statusCode": 422,
"name": "ValidationError",
"message": "The `Activity` instance is not valid. Details: `id` can't be blank (value: undefined).",
"details": {
"context": "Activity",
"codes": {
"id": [
"presence"
]
},
"messages": {
"id": [
"can't be blank"
]
}
}
}
}
If I add a property id manually, then it throws a validation error:
{
"error": {
"statusCode": 422,
"name": "UnprocessableEntityError",
"message": "The request body is invalid. See error object `details` property for more info.",
"code": "VALIDATION_FAILED",
"details": [
{
"path": "",
"code": "additionalProperties",
"message": "must NOT have additional properties",
"info": {
"additionalProperty": "id"
}
}
]
}
}
Change your #model() by #model({settings: {strict: false}}) and add this line [prop: string]: any; into your model
#model({settings: {strict: false}})
[prop: string]: any;

Customizing Laravel validation JSON message format - Laravel

I'm trying to figure out how to customize the Form requests to validate
By default Laravel gives a good enough JSON format for validation errors but what if we want to customize it?
{
"message": "The given data was invalid.",
"errors": {
"email": [
"Please enter email address."
],
"password": [
"Please enter password."
]
}
}
for a particular project, we decided to change the format to this.
{
"success": false,
"errors": [
{
"email": "Please enter an email address."
},
{
"password": "Please enter a password."
}
]
}
Any help would be great.
Regards.
Please try the following.
public function render($request, Throwable $e)
{
if ($e instanceof ValidationException) {
// Custom response
$response = [
'success' => false,
'error' => $e->errors()
];
return response()->json($response, 422);
}
return parent::render($request, $e);
}

How to update the state of store when we add new data by api

I am new in React-native and Redux, I am trying to do CRUD operation. How to update the state of store when we add data by api. I am calling Get Business Api in may action. and I store it into Store.
business action:
export const getBusinessByAliases = (aliases) => {
return (dispatch) => {
dispatch(getBusinessByAliasesData(aliases))
//API CALL
getBusiness(aliases)
.then(response=>{
//HERE I GET WHOLE BUSINESS DATA
dispatch(getBusinessByAliasesSuccess(response.data.business))
})
.catch(err => {
console.log("err",err)
dispatch(getBusinessByAliasesFailure(err))
})
}
}
business data is:
business:[
"id": "17bfdde3-bc04-4a9c-87e7-7530ded1b929",
"inserted_at": "2019-07-10T09:47:41",
"name": "Business2",
"employees": [
{
"nickname": "xyz",
"settings": null,
"user": {
"email": null,
"first_name": null,
"id": "582f5d07-146e-4a81-a6c0-7dd5208b43b2",
"image_id": null,
"inserted_at": "2019-07-02T13:41:06",
"last_name": null,
"phone": "+911234567890"
}
}
],
"services": [
{
"id": "34bd8c80-41e1-459a-bc09-d88a6894bd42",
"name": "Gsgsha",
"settings": {
"color": "#039BE5",
"duration": 4,
"price": 6
}
}
],
]
Now i am adding customer by calling create employee api in another action
employee action :
export const createNewEmployee = (businessName,data) => {
//console.log("whole data", data)
return (dispatch) => {
dispatch(createEmployee(businessName,data))
// API CALL
createEmployees(businessName,data)
.then(response=>{
//IN RESPONSE I GET SUCCESS MESSAGE WITH TRANSACTION ID
dispatch(createEmployeeSuccess(response.data.transaction_id))
})
.catch(err => {
console.log("errEmp",err)
dispatch(createEmployeeFailure(err))
})
}
}
Now, How do I update by the business state which contains all data with my new added employee entry?
I think the best solution is that your endpoint should response the new business object with all employes or only the new list of employes.
Keep in mind that your server can be modified by a lot of app clients, if you need to keep the information updated, you need to implement a Firebase protocol to update your store every time.