How do I cancel/void an order using Paypal API V2? - paypal

What is the equivalent to https://developer.paypal.com/docs/api/orders/v1/#orders_cancel in the V2 of Paypal API?
After an order has been Authorised (using API v2 authorize request with 'CREATED' response), I want the user to be able to cancel it after the click of a button. That button runs a cancel() method.
So my question is, what request should I put in the cancel method to cancel/void the existing order using the orderID? I know I could just leave the order be in V2, but I specifically want to void/cancel it.
(Also, I can only use post, put and patch requests with the implementation I've been given)
Would really appreciate it if you could provide the curl command or nodeJS fetch implementation for it.
Thank you in advance!

If the v2 order was intent:'authorize' and you 'COMPLETED' it to get back an authorization object, you can void the authorization using the v2/payments API.
If, however, the order was merely 'CREATED' or 'APPROVED', there is no way to cancel or void it. Simply have your system forget about it.

You can't using V2 but V1 API is still available so you can use that API.
Python 3.x sample:
import requests
from requests.auth import HTTPBasicAuth
def get_access_token(client_id, client_secret):
res = requests.post(
'https://api-m.sandbox.paypal.com/v1/oauth2/token',
headers={
'Accept': 'application/json',
'Accept-Language': 'en_US',
},
auth=HTTPBasicAuth(client_id, client_secret),
data={'grant_type': 'client_credentials'},
).json()
return res['access_token']
def cancel_order(access_token, order_id) -> bool:
uri = f'https://api-m.sandbox.paypal.com/v1/checkout/orders/{order_id}'
res = requests.delete(
uri,
headers={
'Content-Type': 'application/json',
'Authorization': f'Bearer {access_token}'
}
)
if not res.ok:
raise Exception(f"\n\nPayPal API Call failed for url {uri}: {res.reason} ({res.text}).\nFull Response:\n{res}\n\n")
return
acc_token = get_access_token('<<client_id>>', '<<client_secret>>')
cancel_order(acc_token, '<<order_id>>')

Related

http api call via proxy for flutter

Currently my server has already setup the proxy, when i wanted to call external api it will be block, so right now i want to call the api https://www.google.com/recaptcha/api/siteverify to implement captcha to my project
final response = await http.post(
Config.verificationURL,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': '*'
},
body: 'secret=${Config.secretKey}&response=$_token',
);
any idea on how to convert this api call via proxy for flutter?

Flutter REST api call with Basic auth returns 401, despite correct credentials

I'm trying to call an api from flutter but i keep getting 401 Unauthorized. According to the api documentation it uses basic authentiocation and is UTF-8 encoded. The username and password is provided by the docs and if try the api in a web browser and enter those credentials it goes through and i recieve the data. This is the code i'm using in flutter:
Future<void> requestData() async {
String username = 'abc';
String password = '123';
String basicAuth = 'Basic ' + base64Encode(utf8.encode('$username:$password'));
Response r = await get(
Uri.parse('http://api.example.com'),
headers: {
HttpHeaders.authorizationHeader: basicAuth,
});
print(r.body);
print(r.statusCode);
}
I've also tried this variation which gave the same result:
headers: <String, String>{
'authorization': basicAuth
}
Seeing as the username and password are correct there must be something wrong with how i make the call, but i've tried to do it a bunch of different ways and nothing works. Any help would be greatly appreciated!
As per my experience, there is no need of token or basic auth while doing login. And login is post method not get.
Turns out the documentation i read was outdated/incorrect. The api uses "Digest authentication" which i looked up and was able to implement. This is the code if anyone is interested:
import 'package:http/http.dart';
import 'package:http_auth/http_auth.dart';
...
Response res = await DigestAuthClient("USERNAME", "PASSWORD")
.get(Uri.parse("API_URL")).timeout(const Duration(seconds: 20));

Paypal UNSUPPORTED_MEDIA_TYPE

I am trying to get an access token from paypal's authorization api.
When I make post request to the api I get UNSUPPORTED_MEDIA_TYPE i.e. 415 response.
Below is the snippet that I used.
const auth = await fetch(PAYPAL_OAUTH_API, {
method: 'post',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${ basicAuth }`
},
body: JSON.stringify({"grant_type": "client_credentials"})
});
I have fixed my issue by setting Content-Type to application/x-www-form-urlencoded.
My guess is paypal accepts only application/x-www-form-urlencoded for authorization api.
I ran into same issue, and the solution is following (using Postman):
Select POST
Add Token into Authorization, type is Bearer-Token
Select Content-Type: application/json in headers
Use RAW as body, and in TEXT dropdown, select JSON (application/JSON)
Copy body as raw object and change info accordingly.
Step 4 and 5 are what solved the error, you must send raw json object.

Error while generating access_token using Ebay 's REST API - Python requests

I'm trying to use the ebay REST-API for the first. I am simply trying to generate an access_token using the client credentials grant-request. I followed the instructions here https://developer.ebay.com/api-docs/static/oauth-client-credentials-grant.html
HTTP method: POST
URL (Sandbox): https://api.sandbox.ebay.com/identity/v1/oauth2/token
HTTP headers:
Content-Type = application/x-www-form-urlencoded
Authorization = Basic <B64-encoded_oauth_credentials>
Request body (wrapped for readability):
grant_type=client_credentials&
redirect_uri=<RuName-value>&
scope=https://api.ebay.com/oauth/api_scope
I'm getting this error: {'error': 'invalid_client', 'error_description': 'client authentication failed'} and my code looks like this:
path = 'https://api.sandbox.ebay.com/'
app_json = 'application/json'
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': base64.b64encode(b'Basic CLIENT_ID:CLIENT_SECRET')
}
payload = 'grant_type=client_credentials&redirect_uri=Searchez&scope=https://api.ebay.com/oauth/api_scope'
def get_oath_token():
url = 'https://api.sandbox.ebay.com/identity/v1/oauth2/token'
r = requests.post(url, headers=headers, data=payload)
print(r.json())
get_oath_token()
What do I have configured incorrectly? Thanks.
You're base64encoding "Basic " and shouldn't be.
The doc says just encode your Client ID + ":" + Client Secret, and leave the word "Basic" and the space that follows it alone.
In your code, i can see sandbox endpoint URI but in the request body scope, you have used production URL, instead of sandbox

Jhipster + REST client + authentication

I need to understand how to authenticate a REST client (could be Paw, could be an android app, an iOs app using AFNetworking with jHipster and I think, more in general, with spring-boot of which I am no expert).
While I am able to obtain a token when logged in a browser, and subsequently use this token in the following requests, I do not understand how I can authenticate in the first place using RESTful best practices.
For example, in Paw.app, I can pass a Basic authentication, or Oauth2, but I don't understand how to get the session token simply authenticating as I do on a web browser.
Similarly, in AFNetworking I am able to pass basic authentication, e.g.
NSString*auth=[NSString stringWithFormat:#"%#:%#", #"admin", #"admin"];
NSString *authValue = [NSString stringWithFormat:#"Basic %#", [auth base64EncodedString]];
[manager.requestSerializer setValue:authValue forHTTPHeaderField:#"Authorization"];
But I struggle to understand how to authenticate with the session security which is bundled in jHipster/spring boot.
First of all, do not use HTTP session authentication for mobile apps.
On the other hand, Oauth2 or JWT works fine with mobile apps. The basic idea behind them is to get a token from Jhipster to mobile the token has an expiry time. In that time you can use the token to access any REST API of Jhipster to access data.
Below I am showing the code snippet of how I was using the Jhipster rest API in my angularjs based ionic app. I hope it gives the idea of what you need to do.
uncomment cors in application.yml inside jhipster
cors: #By default CORS are not enabled. Uncomment to enable.
allowed-origins: "*"
allowed-methods: GET, PUT, POST, DELETE, OPTIONS
allowed-headers: "*"
exposed-headers:
allow-credentials: true
max-age: 1800
To access REST API with Oauth2 authentication in ionic you must first get the token in the ionic app by
$http({
method: "post",
url: "http://192.168.0.4:8085/[Your app name]/oauth/token",
data: "username=admin&password=admin&grant_type=password&scope=read write&client_secret=my-secret-token-to-change-in-production&client_id=auth2Sconnectapp",
withCredentials: true,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'Authorization': 'Basic ' + 'YXV0aDJTY29ubmVjdGFwcDpteS1zZWNyZXQtdG9rZW4tdG8tY2hhbmdlLWluLXByb2R1Y3Rpb24='
}
})
.success(function(data) {
alert("success: " + data);
})
.error(function(data, status) {
alert("ERROR: " + data);
});
Here "YXV0aDJTY29ubmVjdGFwcDpteS1zZWNyZXQtdG9rZW4tdG8tY2hhbmdlLWluLXByb2R1Y3Rpb24=" is equal to (clientId + ":" + clientSecret)--all base64-encoded
The above $http if successful will give you this JSON which contains token and it's expiry time
{
"access_token": "2ce14f67-e91b-411e-89fa-8169e11a1c04",
"token_type": "bearer",
"refresh_token": "37baee3c-f4fe-4340-8997-8d7849821d00",
"expires_in": 525,
"scope": "read write"
}
Take notice of "access_token" and "token_type" if you want to access any API this is what you have to use. We send the token with API to access data until the token expires then we either refresh it or access for a new one.
For example
$http({
method: "get",
url: "http://192.168.0.4:8085/auth-2-sconnect/api/countries",
withCredentials: true,
headers: {
'Authorization':' [token_type] + [space] + [access_token] '
}
})
.success(function(data) {
alert("success: " + data);
})
.error(function(data, status) {
alert("ERROR: " + data);
});
Here a summarisation of how I implemented the solution. It’s real swift code, but please take it as pseudocode, as it might be incorrect.
make a call to whatever method you need to call, passing in such method a callback (block, or equivalent) for the success and one for the failure
func action(
URLString:String,
method:Method,
encoding:Encoding = .JSON,
parameters:[String : AnyObject]?,
success:(statusCode:Int, responseObject:AnyObject)->Void,
failure:(statusCode:Int, error:NSError)->Void
)
Inside the method es. /events you handle a particular case of failure, which is when the status code is 401.
if(r!.statusCode==ResponseCodes.HTTP_UNAUTHORIZED.rawValue){
loginAndAction(URLString, method: method, encoding: encoding, parameters: parameters, success: success, failure: failure)
}else{
failure(statusCode: response.response!.statusCode, error:response.result.error!)
}
In this particular case, instead of returning back the result and calling the failure callback, you call a login() method which, after the necessary parameters, accept the original success() callback
func loginAndAction(
URLString:String,
method:Method,
encoding: Encoding,
parameters:[String:AnyObject]?,
success:(statusCode:Int, responseObject:AnyObject)->Void,
failure:(statusCode:Int, error:NSError)->Void
)->Void
if the authentication succeeds
var d:[String:AnyObject] = response.result.value as! [String:AnyObject]
self.authToken = d["access_token"] as! String
action(URLString, method: method,encoding:encoding, parameters: parameters, success: success, failure: failure)
at this point the method action could use a proper working token.
This should happen only once a day (based on the token expiration), and it is a mechanism appliable to the oauth2 refresh_token call.