How do I list cards for a specified customer using Balanced API? - rest

I am using PHP to try to get the card from Balanced.
I can get all the cards using
$marketplace = Balanced\Marketplace::mine();
$cards = $marketplace->cards->query()->all();
I can look though the $cards array and in each card object I find a values like this
uri : /v1/marketplaces/TEST-MP4K6K0PWGyPtXL4LZ42sQSb/cards/CC5N3HHUDrAyvhNwQOoUd3UX
this appears to be formatted as
"/v1/marketplaces/MARKETPLACE ID/cards/CARD ID"
However I only want the cards for a specific customer so I tried
$customer = Balanced\Customer::get("/v1/customers/CU6vs1tjxBtifgTuzKjCGtVS");
$cards = $customer->cards->query()->all();
Now when I look thought the card object the format of the uri has changed
uri : /v1/customers/CU6vs1tjxBtifgTuzKjCGtVS/cards/CC5N3HHUDrAyvhNwQOoUd3UX
So it gives the uri as
"/v1/customers/CUSTOMER ID/cards/CARD ID"
Question, can I use this customer based uri for all card functions such as charging and deleting?
Or, if I have to use the marketplaces format do I rebuild the URI (which balanced warns against) or is there some why I can get the uri in it's proper format?

You can use either of those uri's. They are just using different endpoints, but will result in the same successful transactions.

Related

Generate unpredictable/unforgeable URL from predictable ID

I have a simple API that return Something for a given ID and it must be used without any kind of authentication, the URL should be permanent and yet I want to avoid as much as possible it to be botted.
The Url is something like this:
https://url/{SomeId}/doSomething
The problem is that this is very predicable and a bot could easily try all the ID and get everything associated to it.
I'm looking for a way to make the URL non predictable like for example:
https://url/{SomeId}/doSomething?Key=SomeVeryLongCryptographicKey
In this way except if you run a supercalculator you shouldn't be able to deduce all the URLs
I know that there is probably a lot of ways to do that, like using a DB which I want to avoid.
I guess I'm looking for a kind a JWT associated to the ID without expiration but maybe there is better solution.
Edit: to give a better example i'm looking to do a bit like did Zoom for permanent invitation Links. They had predictable room Ids and they added a password making it unpredictable lie so:
https://us05web.zoom.us/j/132465789?pwd=SUxIU0pLankyhTRtWmlGbFlNZ21Ndz08
What would be the best/light/"secure" way to achieve that ?
Also I'm using .Net if there is a library doing that, it would be great.
I think your idea of using a JWT makes the most sense. Better to use something standard from a cryptographic point of view, and the JSON format allows for encoding whatever you need to provide to the receiving endpoint (user names, entity names, entity IDs, other things).
There are standard Microsoft libraries for building and validating JWTs, but I prefer the library Jwt.Net (https://www.nuget.org/packages/JWT). It lets you do something like this quite easily:
var token = JwtBuilder()
.WithAlgorithm(new RS256Algorithm(publicKey,privateKey))
.AddClaim("uri", String.Format("https://example.com/api/{0}/{1}", entityName, entityId))
.Encode();
Just add whatever claims you like, and the JWT will then contain what you want to transfer (I've used an example of the URI that you want to give to the entity) and a signature with your private key. You could even just give a URL like https://example.com/from_token/eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1cmkiOiJodHRwczovL2V4YW1wbGUuY29tL2FwaS90ZXN0RW50aXR5LzEyMzQifQ.K2P4wSF6g1Kt-IHMzlklWTV09_MIkoiNHQztSIYOohmOWe7aBfFSQLIKSbdTECj9XPjNNG_AjH9fdjFglkPuYfr2G9rtl2eh5vTjwdM-Uc0X6RkBu0Z2j7KyMKjkaI3zfkIwhtL1mH873xEBtNOGOW18fuBpgnm8zhMAj1oD3PlDW8-fYBrfLb6VK97DGh_DyxapbksgUeHst7cAGg3Nz97InDPtYcWDi6lDuVQsj3t4iaJBRL8IM785Q8xjlHHhzdfcX3xU4IhflyNHHXxP56_8ahNNMOZKWdwgbTSIxEEB98b3naY3XknC-ea7Nc1y4_5fszrYdy3LaQWV43jpaA
and have the handler decode the entity name and ID you want to retrieve directly from the URI while verifying the signature. Decoding with the library is just as easy:
var json = JwtBuilder.Create()
.WithAlgorithm(new RS256Algorithm(_key))
.MustVerifySignature()
.Decode(token);

Why does one HTTP GET request retrieve the required data and another retrieve []

I'm currently working on ng-admin.
I'm having a problem retrieving user data from my REST API (connected to a MongoDB) and displaying it.
I have identified the problem as the following:
When I enter http://localhost:3000/users into my browser, I get a list of all users in my database.
When I enter http://localhost:3000/users?_page=1&_perPage=30&_sortDir=DESC&_sortField=id,
I get [] as a result.
I am quite new to this, I used both my browser and the POSTMAN Chrome extension to test this and get the same result.
http://localhost:3000/users_end=30&_order=DESC&_sort=id&_start=0
This (/users_end) is a different request than /users.
It should be:
http://localhost:3000/users?end=30&_order=DESC&_sort=id&_start=0
Or, by looking at the other parameters:
http://localhost:3000/users?_end=30&_order=DESC&_sort=id&_start=0
with end or _end being the first parameter (mark the ?).
Update (it is ? and before the _, I have edited.):
If adding parameters to the request returns an empty list, try adding only one at a time to narrow down the problem (there's probably an error in the usage of those parameters - are you sure you need those underscores?).
Your REST API must have a way to handle pagination, sorting, and filtering. But ng-admin cannot determine exactly how, because REST is a style and not a standard. So ng-admin makes assumptions about how your API does that by default, that's why it adds these _end and _sort query parameters.
In order to transform these parameters into those that your API understands, you'll have to add an interceptor. This is all thoroughly explained in the ng-admin documentation: http://ng-admin-book.marmelab.com/doc/API-mapping.html

Sharepoint URL to reference a lookup

I have two SharePoint lists used for Support case management. The first list contains Case Numbers and information about the case. The second list contains exhibits that support the case itself.
We have a convention that the Case Number is a String supplied by the worker, ex 20150205-001. When the exhibits are joined to the Case it is through a Lookup. I want the Exhibit ID, a String, to be of the form Case Number + _[A-Z] -- and be auto-assigned.
I want to use a Workflow (MS Sharepoint Designer 2013) to assign the Exhibit ID. The problem I face is that I cannot get the actual Case Number from the Lookup. The closest I have gotten so far is to get the ID (1, 2, etc) but not the actual String value represented.
Tried working with the following URL:
http://[mySiteURL]/_api/web/lists/getbytitle([listName])/items?$select=Title,Case/Id&$expand=Case/Id&$filter=Case/Id%20eq%2020150205%45001
substituted ascii: $filter=Case/ID eq 20150205-001
without the filter I get all list items (understandably) but the filter does not work properly because the ID is not the actual lookup value.
This is a SPD 2013 limitation. You have to use a web service call from within Designer to get the specifics of a lookup column from SharePoint. You make a REST call ad then parse the JSON response for the specific data from the lookup column. It gives you access to all of the columns from the list item that you looked up:
Build {...} Dictionary (Output to Variable: requestHeader )
Call [%Workflow Context:Current Site URL%]... HTTP web service with Variable: Request (ResponseContent to Variable: PoleIDData |ResponseHeaders to Variable: dictionary |ResponseStatusCode to Variable: responseCode )
Get d/Pole_x0020_ID from Variable: PoleIDData (Output to Variable: PoleID )
Set Name to Variable: PoleID
Your actual web service call will be formatted like this:
[%Workflow Context:Current Site URL%]/_api/web/lists/GetByTitle('List Name')/Items([%Current Item:ID%])/LookupColumnNameOnOtherList
Sorry for the formatting, I would post a screenshot but I cannot.
This article is good for showing you some of the other specifics about formatting your HTTP Request, especially the Request Headers which must be setup right.
http://www.fiechter.eu/Blog/Post/37/SharePoint-2013--HTTP-Web-Service-Action---Use-Managed-Metadata-as-Text-in-Workflow

Paypal IPN currency & response

I am using a paypal ipn script i found here
http://coderzone.org/library/PHP-PayPal-Instant-Payment-Notification-IPN_1099.htm
I am aware that I can send information to paypal and get a response. It states I can get the information back using $_POST . My query is how do I specify the UK currency?
Also wanted to clarify a minor point. Am I correct that this is how i can confirm it was a success.
if ($_POST['payment_status'] == 'completed')
// Received Payment!
// $_POST['custom'] is order id and has been paid for.
}
This might be a little late for you sorry, but just in case - I currently use "currencyCode" = > "AUD" and it is working in the sandbox.
There's a full list of the currency codes available at PayPal
For yours, I'm guessing it would be:
$p->add_field('currencyCode', 'GBP');
As for your question about the IPN itself, it looks like you're on the right track. It will depend on the data you're getting back and whether you're interested in the individual transactions (if using adaptive payments) or if you're reversing them all on error etc. The easiest way to determine what you'll need to do is to simply display or log all the post data so you can see how it's constructed.
You'll also need to set it up so that the script is accessible by PayPal. You'll then pass the full URL of this script to the "notify_url" parameter and send it off to PayPal. Once the payment has completed PayPal will send a bunch of information to your script so that you can process it.
Unfortunately I'm not from a PHP background so I can't give you the exact code you'll need. Also note that there are a lot of security issues that you'll want to look into before going to a production environment. Not sure if you already intend to do this with that validateIPN function, but you need to ensure that you can tell whether it comes from PayPal and not a malicious user. One way would be to pass a value using the custom attribute and have PayPal pass this back to you, however you'd be much better off using the API certificates etc.
If you haven't already, it may be worth checking out a few of the sample applications PayPal has done up, there seem to be quite a few PHP ones.
Let me know if you need anything else,
Use this, it works for me
$p->add_field('currency_code', 'GBP');
You need to use PayPal Adaptive Payments, IPN wouldn't help.
PayPal Adaptive Payments
Using PayPal PHP library then it could look like this:
// Create an instance, you'll make all the necessary requests through this
// object, if you digged through the code, you'll notice an AdaptivePaymentsProxy class
// wich has in it all of the classes corresponding to every object mentioned on the
// documentation of the API
$ap = new AdaptivePayments();
// Our request envelope
$requestEnvelope = new RequestEnvelope();
$requestEnvelope->detailLevel = 0;
$requestEnvelope->errorLanguage = 'en_GB';
// Our base amount, in other words the currency we want to convert to
// other currency type. It's very straighforward, just have a public
// prop. to hold de amount and the current code.
$baseAmountList = new CurrencyList();
$baseAmountList->currency = array( 'amount' => $this->amount, 'code' => 'GBP' );
// Our target currency type. Given that I'm from Mexico I would like to
// see it in mexican pesos. Again, just need to provide the code of the
// currency. On the docs you'll have access to the complete list of codes
$convertToCurrencyListUSD = new CurrencyCodeList();
$convertToCurrencyListUSD->currencyCode = 'USD';
// Now create a instance of the ConvertCurrencyRequest object, which is
// the one necessary to handle this request.
// This object takes as parameters the ones we previously created, which
// are our base currency, our target currency, and the req. envelop
$ccReq = new ConvertCurrencyRequest();
$ccReq->baseAmountList = $baseAmountList;
$ccReq->convertToCurrencyList = $convertToCurrencyListUSD;
$ccReq->requestEnvelope = $requestEnvelope;
// And finally we call the ConvertCurrency method on our AdaptivePayment object,
// and assign whatever result we get to our variable
$resultUSD = $ap->ConvertCurrency($ccReq);
$convertToCurrencyListUSD->currencyCode = 'EUR';
$resultEUR = $ap->ConvertCurrency($ccReq);
// Given that our result should be a ConvertCurrencyResponse object, we can
// look into its properties for further display/processing purposes
$resultingCurrencyListUSD = $resultUSD->estimatedAmountTable->currencyConversionList;
$resultingCurrencyListEUR = $resultEUR->estimatedAmountTable->currencyConversionList;

Tastypie build_filters access tp request.user

Is there any way to access the user that initiated the request in build_filters override in tastypie.
I want to use the logged in user to give context to one of the filters for example filter contains the word Home and i want to use this as a lookup to the requesting users locations to find their home address.
If build filters took the request as an argument this would be easy as i could simply call
request.user.get_profile().userlocation_set.get(name_iexact=filters['location'])
Is there anyway to force the user into the list of filters or alternatively enrich get parameters before they are passed to build_filters.
There still isn't a great method for this. I'm currently overriding obj_get_list like so, so that I can manually pass the bundle object to build_filters:
def obj_get_list(self, bundle, **kwargs):
filters = {}
if hasattr(bundle.request, 'GET'):
filters = bundle.request.GET.copy()
filters.update(kwargs)
applicable_filters = self.build_filters(filters=filters, bundle=bundle)
try:
objects = self.apply_filters(bundle.request, applicable_filters)
return self.authorized_read_list(objects, bundle)
except ValueError:
raise BadRequest("Invalid resource lookup data provided (mismatched type).")
There is currently an open pull request for this change:
https://github.com/toastdriven/django-tastypie/pull/901
I haven't found a way to do that. I generally 'cheat' by adding the code into apply_authorization_limits where the session is available.