I am implementing an external wrapper for the Stripe API in Coldfusion.
One of the functions I am calling takes an argument of type "timestamp", as seen below:
public struct function updateSubscription(required string customerid, required string planid, string coupon='', boolean prorate=true, timestamp trial_end, any card)
{
...
}
I am passing a valid date (tested and IsDate() resulted in "YES") to the trial_end argument but it is giving me a "not of type timestamp" error.
What do I need to do to this date to get the function call to work properly?
Thanks
UPDATE: FULL FUNCTION ADDED:
public struct function updateSubscription(required string customerid, required string planid, string coupon='', boolean prorate=true, timestamp trial_end, any card) {
local.HTTPService = createHTTPService('POST');
local.HTTPService.addParam(type='formfield',name='plan',value=arguments.planid);
local.HTTPService.setUrl(getBaseUrl() & 'customers/' & arguments.customerid & '/subscription');
if (Len(Trim(arguments.coupon))) {
local.HTTPService.addParam(type='formfield',name='coupon',value=Trim(arguments.coupon));
}
local.HTTPService.addParam(type='formfield',name='prorate',value=arguments.prorate);
if (StructKeyExists(arguments,'trial_end') AND IsDate(arguments.trial_end)) {
loca.intUTCDate = timeToUTCInt(arguments.trial_end);
local.HTTPService.addParam(type='formfield',name='trial_end',value=local.intUTCDate);
}
if (StructKeyExists(arguments,'card') AND isStruct(arguments.card)) {
local.HTTPService.addParam(type='formfield',name='card[number]',value=arguments.card.number);
local.HTTPService.addParam(type='formfield',name='card[exp_month]',value=arguments.card.exp_month);
local.HTTPService.addParam(type='formfield',name='card[exp_year]',value=arguments.card.exp_year);
if (StructKeyExists(arguments,'card.cvc')) {
local.HTTPService.addParam(type='formfield',name='card[cvc]',value=arguments.card.cvc);
}
if (StructKeyExists(arguments,'card.name') AND Len(Trim(arguments.card.name))) {
local.HTTPService.addParam(type='formfield',name='card[name]',value=arguments.card.name);
}
if (StructKeyExists(arguments,'card.address_line1') AND Len(Trim(arguments.card.address_line1))) {
local.HTTPService.addParam(type='formfield',name='card[address_line1]',value=Trim(arguments.card.address_line1));
}
if (StructKeyExists(arguments,'card.address_line2') AND Len(Trim(arguments.card.address_line2))) {
local.HTTPService.addParam(type='formfield',name='card[address_line2]',value=Trim(arguments.card.address_line2));
}
if (StructKeyExists(arguments,'card.address_zip') AND Len(Trim(arguments.card.address_zip))) {
local.HTTPService.addParam(type='formfield',name='card[address_zip]',value=Trim(arguments.card.address_zip));
}
if (StructKeyExists(arguments,'card.address_state') AND Len(Trim(arguments.card.address_state))) {
local.HTTPService.addParam(type='formfield',name='card[address_state]',value=Trim(arguments.card.address_state));
}
if (StructKeyExists(arguments,'card.address_country') AND Len(Trim(arguments.card.address_country))) {
local.HTTPService.addParam(type='formfield',name='card[address_country]',value=Trim(arguments.card.address_country));
}
} else if (StructKeyExists(arguments,'card')) {
local.HTTPService.addParam(type='formfield',name='card',value=Trim(arguments.card));
}
local.HTTPResult = local.HTTPService.send().getPrefix();
if (NOT isDefined("local.HTTPResult.statusCode")) {
throw(type='Stripe',errorcode="stripe_unresponsive", message="The Stripe server did not respond.", detail="The Stripe server did not respond.");
} else if (left(local.HTTPResult.statusCode,3) NEQ "200") {
throw(type='Stripe',errorcode=local.HTTPResult.statusCode, message=local.HTTPResult.statuscode, detail=local.HTTPResult.filecontent);
}
return deserializeJSON(local.HTTPResult.filecontent);
}
timestamp is not a native CF data type, so CF is trying to find a CFC called timestamp.cfc.
I think you just mean date in this case.
Related
I have a fairly good template (as in snippet of code) I pull out whenever I need a singleton class. I am now trying to apply it within my project to allow me to control a single instance of a web server. I can make a web server without encasing it in my class. When I try to encase it within the class I'm apparently too unskilled to pull it off.
I've tried the obvious Googling and searching here. I've read relevant posts. I am sure this does not mean I have a unique problem, just that I've not figured out the right way to fix it. Here's what I am working with:
webserver.h:
#include <ESP8266WebServer.h>
#include <FS.h>
class WebServer {
private:
// Singleton Declarations
static bool instanceFlag;
static WebServer *single;
WebServer() {}
// Other Declarations
FS *filesystem;
ESP8266WebServer server();
String getContentType(String);
bool handleFileRead(String);
public:
// Singleton Declarations
static WebServer* getInstance();
~WebServer() {instanceFlag = false;}
// Other Declarations
void initialize(int);
void handleLoop();
};
webserver.cpp:
#include "webserver.h"
bool WebServer::instanceFlag = false;
WebServer* WebServer::single = NULL;
WebServer* WebServer::getInstance() {
if(!instanceFlag) {
single = new WebServer();
instanceFlag = true;
return single;
} else {
return single;
}
}
void WebServer::initialize (int port) {
ESP8266WebServer server(port);
FS *filesystem;
filesystem->begin();
Serial.print("Open: http://");
Serial.print(WiFi.hostname().c_str());
Serial.println(".local");
server.onNotFound([]() {
if (!single->handleFileRead(single->server.uri())) {
single->server.send(404, "text/plain", "404: File not found.");
}
});
server.begin();
Serial.print("HTTP server started on port ");
Serial.print(port);
Serial.println(".");
}
String WebServer::getContentType(String filename) {
if (single->server.hasArg("download")) {
return "application/octet-stream";
} else if (filename.endsWith(".htm")) {
return "text/html";
} else if (filename.endsWith(".html")) {
return "text/html";
} else if (filename.endsWith(".css")) {
return "text/css";
} else if (filename.endsWith(".js")) {
return "application/javascript";
} else if (filename.endsWith(".png")) {
return "image/png";
} else if (filename.endsWith(".gif")) {
return "image/gif";
} else if (filename.endsWith(".jpg")) {
return "image/jpeg";
} else if (filename.endsWith(".ico")) {
return "image/x-icon";
} else if (filename.endsWith(".xml")) {
return "text/xml";
} else if (filename.endsWith(".pdf")) {
return "application/x-pdf";
} else if (filename.endsWith(".zip")) {
return "application/x-zip";
} else if (filename.endsWith(".gz")) {
return "application/x-gzip";
} else {
return "text/plain";
}
}
bool WebServer::handleFileRead(String path) {
Serial.println("handleFileRead: " + path);
if (path.endsWith("/")) {
path += "index.htm";
}
String contentType = getContentType(path);
String pathWithGz = path + ".gz";
if (filesystem->exists(pathWithGz) || filesystem->exists(path)) {
if (filesystem->exists(pathWithGz)) {
path += ".gz";
}
File file = filesystem->open(path, "r");
single->server.streamFile(file, contentType);
file.close();
return true;
}
return false;
}
void WebServer::handleLoop() {
single->server.handleClient();
}
The errors I am getting are all similar to the following:
src\webserver.cpp: In member function 'bool WebServer::handleFileRead(String)':
src\webserver.cpp:81:23: error: 'WebServer::single->WebServer::server' does not have class type
single->server.streamFile(file, contentType);
I get the idea of "does not have a class type", I just have no idea what it means here. In my mind, "single" is a pointer to the class so I'm unclear what that reference is not working.
Obviously, there are ample examples out there how to do a web server without encapsulating it. Other things I need to do for this project lend itself to creating that requirement.
There are some mistake in your code.
In webserver.h:
...
private:
// Singleton Declarations
static bool instanceFlag;
static WebServer *single;
WebServer() {}
// Other Declarations
FS *filesystem;
ESP8266WebServer *server; // <--- remove the parentheses and make it a pointer
String getContentType(String);
bool handleFileRead(String);
...
In webserver.cpp:
In WebServer::initialize I am guessing you want to initialize the class server and filesystem not locals, so it should probably look like this:
void WebServer::initialize (int port) {
server = new ESP8266WebServer(port);
filesystem = new FS();
...
}
And now everywhere you use the server you have to use the -> operator.
For example:
void WebServer::handleLoop() {
single->server->handleClient();
}
Please keep in mind that server and filesystem objects have to be deleted to avoid memory leaks.
EDIT:
You get the new error because FS has no constructor without arguments.
FS's constructor looks like this: FS(FSImplPtr impl) : _impl(impl) { }, here you can see that FSImplPtr is a typedef for std::shared_ptr<FileImpl>, so you need to provide this as a parameter.
It works your way, because SPIFFS's existence is declared here and is of type FS.
If you want to use SPIFFS, you have to use it like this: filesystem = &SPIFFS;, not like you mentioned in the comments (FS* filesystem = &SPIFFS;) because your way creates a new temporary variable named filesystem, and probably you expect to initiate the filesystem in the class, not a local one.
I am working on two apps, in one of my app "A" i applied retrofit 2.
This was the method i used to retrieve data.
But here in on Response the data retrieved in response body can be set to activity variables and can be used outside this method without getting null values.
public void fetch_information() {
ApiInterface = ApiClient.getApiClient().create(Api.class);
Call<List<City>> call = ApiInterface.GetCities();
call.enqueue(new Callback<List<City>>() {
#Override
public void onResponse(Call<List<City>> call, Response<List<City>> response) {
citylist = new ArrayList<City>();
citylist = response.body();
cities = new String[citylist.size()];
citiesid = new String[citylist.size()];
for (int i = 0; i < citylist.size(); i++) {
cities[i] = citylist.get(i).getCityName();
citiesid[i] = citylist.get(i).getCityId();
}
city_adapter = new ArrayAdapter<String>(Pay_Payment_X.this, android.R.layout.simple_list_item_1, cities);
city_adapter.setDropDownViewResource(R.layout.spinner_dropdown_layout);
City_Spinner.setAdapter(city_adapter);
}
#Override
public void onFailure(Call<List<City>> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
after applying this method and on debugging this method i will retain values of varaibles "cities" and "citiesid"out side onResponse.
But applying retrofit 2 similarly on another app "B", i did the same thing for retrieving data on different URL.
ApiUtil.getServiceClass().getAllPost().enqueue(new Callback<List<ApiObject>>() {
#Override
public void onResponse(Call<List<ApiObject>> call, Response<List<ApiObject>> response) {
if (response.isSuccessful()) {
List<ApiObject> postList = response.body();
try {
for (int i = 0; i < postList.size(); i++) {
String Name = postList.get(i).getGamesName();
mGamesName.add(Name);
}
} catch (Exception e) {
}
Log.d(TAG, "Returned count " + postList.size());
NewAdapter adapter = new NewAdapter(getApplicationContext(), postList);
recyclerView.setAdapter(adapter);
}
}
#Override
public void onFailure(Call<List<ApiObject>> call, Throwable t) {
//showErrorMessage();
Log.d(TAG, "error loading from API");
}
});
the data is retrievable inside onResponse but outside it shows null.
So here variables are not retaining values.
Why is this happening?
the only thing came to mind is retrieving data can take time while your code lines are being read and finding null values as data has not been received yet.
Also to mention in app "A" the data retrieved is huge but in app "B" only 3 objects with string values.But still in app"A" data is retrievable.
In app 2 did this for resolving my issue.
public void doRequest( final ApiCallback callback){
ApiUtil.getServiceClass().getAllPost().enqueue(new Callback<List<ApiObject>>() {
#Override
public void onResponse(Call<List<ApiObject>> call, Response<List<ApiObject>> response) {
if (response.isSuccessful()) {
List<ApiObject> postList = response.body();
callback.onSuccess(postList);
// apobject =response.body();
if(response.isSuccessful()) {
try {
for (int i = 0; i < postList.size(); i++) {
String Name = postList.get(i).getGamesName().toString();
mGamesName.add(Name);
}
} catch (Exception e) {
}
}
Log.d(TAG, "Returned count " + postList.size());
NewAdapter adapter = new NewAdapter(getApplicationContext(), postList);
recyclerView.setAdapter(adapter);
}
}
#Override
public void onFailure(Call<List<ApiObject>> call, Throwable t) {
//showErrorMessage();
Log.d(TAG, "error loading from API");
}
});
}
pass an interface
public interface ApiCallback{
void onSuccess(List<ApiObject> result);
}
and in on Create view of activity i called this
doRequest(new ApiCallback(){
#Override
public void onSuccess(List<ApiObject> result){
//here i can set variable values
}
});
the only thing came to mind is retrieving data can take time while your code lines are being read and finding null values as data has not been received yet.
That's entirely correct. Your call is finishing after you check the values. I'm going to go on a limb here and say that it's just a coincidence that it works on one app and not in the other (if they are actually doing it the same way)
When you call callback.onSuccess(postList); doesn't seem to be right either, because you haven't checked yet for success. This means that response.body() might be null and response.errorBody() will contain the body of the error.
If you'd move callback.onSuccess inside the if this would be fixed:
if(response.isSuccessful()) {
callback.onSuccess(response.body());
try {
for (int i = 0; i < postList.size(); i++) {
String Name = postList.get(i).getGamesName().toString();
mGamesName.add(Name);
}
} catch (Exception e) {
}
Last but not least, inside the onSuccess method is when you can use your global variables. Maybe it's better to stop using global variables and just use the callback parameters.
I'm creating a function that handles objects from the database. I have two different data structures where the same property has a different name. I can't change that, so I have to handle it in JavaScript.
The objects have other differences, but that's not important to this function.
I want to use the same function for two different types of objects. Here's sample code demonstrating my problem:
interface TypeA {
itemName: string;
}
interface TypeB {
itemTitle: string;
}
function getItemName(item: TypeA | TypeB): string {
let name = '';
if (item.hasOwnProperty('itemName')) {
name = item.itemName;
} else {
name = item.itemTitle;
}
return name;
}
Of course, this code runs. But the IDE marks both the lines name = item.itemName; and name = item.itemTitle; as errors ("Property does not exist on type"), because both types do not have both properties.
So, what's the proper typescript way to do this?
You need to create a User Defined Type Guard, then you can use an if statement and get the correct typing.
function isTypeA(value: TypeA | TypeB): value is TypeA {
return value.hasOwnProperty('itemName');
}
Then you can get the typing much cleaner:
function getItemName(item: TypeA | TypeB): string {
return isTypeA(item) ? item.itemName : item.itemTitle;
}
Check it out here. Item is correctly cast to either TypeA or TypeB.
I might be a little bit late, but you could give this a try inside your function:
if ('itemName' in item) {
name = item.itemName;
} else {
name = item.itemTitle;
}
you can make a type assertion if you don't do this too often :
if (item.hasOwnProperty('itemName')) {
name = (item as TypeA).itemName;
} else {
name = (item as TypeB).itemTitle;
}
or
if (item.hasOwnProperty('itemName')) {
name = (<TypeA>item).itemName;
} else {
name = (<TypeB>item).itemTitle;
}
if you need to make this check more than once or twice, you'd better writing a type guard as #Daryl suggests.
interface TypeA {
a: string
}
interface TypeB {
b: string
}
const testFunction = (x: TypeA | TypeB): string => {
return (x as TypeA).a || (x as TypeB).b;
}
testFunction({ a: 'Hello' }); // 'Hello'
testFunction({ b: 'World' }); // 'World'
Intellij accepts this syntax:
function getItemName(item: TypeA): string;
function getItemName(item: TypeB): string;
function getItemName(item): string {
return item.hasOwnProperty('itemName') ? item.itemName : item.itemTitle;
}
the official way according to the typescript docs is this:
https://www.typescriptlang.org/docs/handbook/functions.html
I won't complicate things. If you're really sure that your object has either the one or the other property, a name = item['itemName'] || item['itemTitle'] or name = item.hasOwnProperty('itemName') ? item['itemName'] : item['itemTitle'] would be sufficient.
Note that TypeScript usually stops complaining if you access properties using the bracket notation instead of the dot notation. I would suggest adding a comment, though.
Use typeguards:
interface TypeA {
itemName: string;
}
interface TypeB {
itemTitle: string;
}
function isTypeA(val: any): val is TypeA
{
return val.hasOwnProperty('itemName');
}
function isTypeB(val: any): val is TypeB
{
return val.hasOwnProperty('itemTitle');
}
function getItemName(item: TypeA | TypeB): string
{
let name = '';
if (isTypeA(item))
{
name = item.itemName;
}
else
{
name = item.itemTitle;
}
return name;
}
In Ethereum private network (geth) I do have very simple contract (in Solidity).
version 1:
contract T {
string log;
function getLastLog() constant returns (string lastLog) { return log; }
function T() { log = "[call end]: T()\n"; }
struct TData {
uint amount;
}
mapping (address => uint) balance;
mapping (address => TData) mystructmap;
function setBalance(address _user, uint _balance) {
log = "[call start]: setBalance()\n";
balance[_user] = _balance;
mystructmap[_user] = TData({amount: 42});
log = "[call end]: setBalance()\n";
}
function getBalance(address _user) constant returns (uint _balance) {
return balance[_user];
}
function get42(address _user) constant returns (uint _fourtytwo) {
return mystructmap[_user].amount;
}
}
I do deploy contract and then call it like this (from web3.js):
contract.getLog()
contract.setBalance(valid_address, 55)
contract.getLog()
contract.getBalance(address)
contract.get42(address)
And I get as output result:
[call end]: T()
[call end]: setBalance()
55
42
Now I just add one new field to TData structure:
version 2:
contract T {
string log;
function getLastLog() constant returns (string lastLog) { return log; }
function T() { log = "[call end]: T()\n"; }
struct TData {
uint somedata;
uint amount;
}
mapping (address => uint) balance;
mapping (address => TData) mystructmap;
function setBalance(address _user, uint _balance) {
log = "[call start]: setBalance()\n";
balance[_user] = _balance;
mystructmap[_user] = TData({somedata: 11, amount: 42});
log = "[call end]: setBalance()\n";
}
function getBalance(address _user) external constant returns (uint _balance) {
return balance[_user];
}
function get42(address _user) external constant returns (uint _fourtytwo) {
return mystructmap[_user].amount;
}
}
I do the same calls as above:
contract.getLog()
contract.setBalance(valid_address, 55)
contract.getLog()
contract.getBalance(address)
contract.get42(address)
But now I get:
[call end]: T()
[call end]: T()
0
0
Seems like 'setBalance()' function is not executed (or exited somewhere) and state in storage is not changed.
Please help!
Thanks.
I had the same problem earlier. I'm pretty sure that it has to do with the amount of gas that you are sending with your requests. Web3 will guess but this has failed me before. Try manually sending different amounts of gas along with your request.
Here's something I'm doing:
store
.changeProduct(d.id, d.name, d.price, d.description, d.quantity,d.enabled, {from: account, gas:1000000})
Hardcoding Gas for any operation is a bad idea. You will keep getting into this kind of errors if you do that. You should check for Gas before firing the method
Use the estimate Gas API -
https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethestimategas
As and when you take your DApp public, you have to be cognizant of the fact that miners can adjust Gas prices in the geth console.
miner.setGasPrice(gasPrice);
Hope that helps!
I have a very basic question. Is it possible to convert a string into a closure? I tried evaluate() but it didn't work.
evaluate( "myFunction = function(val){ return dollarFormat( val ); }" );
What I have in mind is to save custom functions in the database as string and then run it as needed.
Thank you!
Edit: Just to clarify: I want to be able to save "function(val){ return dollarFormat( val ); }" as a string in database and be able to convert it into a functioning closure.
I would go with user2943775 answer:
<cfscript>
FileWrite("/ram/UDFs.cfm", "<cfset myFunction = function(val){ return dollarFormat( val ); }>")
include template="/ram/UDFs.cfm";
writedump(myFunction(10));
</cfscript>
And in your Application.cfc
component {
this.mappings["/ram"] = "ram://";
...
}
I came across a similar solution, though I was unable to use the in-memory filesystem due to security restrictions. In my Application.cfc, I added the following mapping:
this.mappings = {
"/models" = "#APP_ROOT_PATH#cfcs/models",
"/utils" = "#APP_ROOT_PATH#cfcs/utils",
"/modules" = "#APP_ROOT_PATH#_modules",
"/components" = "#APP_ROOT_PATH#cfcs",
"/udfs" = "#APP_ROOT_PATH#includes/udfs" // path for global (and temporary) UDFs
};
The UDF I created is as follows:
/**
* Takes a string representation of a function and returns it as a Closure
* #output false
* #return Closure
*/
private any function toClosure (required string closure) {
local.id = replace(createUUID(), "-", "", "all");
local.udfpath = "/udfs/udf#id#.cfm";
local.script = "<cfscript>local.fn#id# = #closure#;</cfscript>";
try {
fileWrite(expandPath(udfPath), script);
include udfpath;
} catch (any e) {
} finally {
try {
fileDelete(expandPath(udfPath));
} catch (any e) {}
}
if (!structkeyExists(local, "fn#id#") || !isClosure(local["fn#id#"])) {
throw (message="Unable to compile closure");
}
// return the closure
return local["fn#id#"];
}
And the result:
myFn = toClosure("function (num) { return num + 1; }");
myFn(1); // returns 2