Desktop Payment Processing Application: Switching APIs from Authorize.Net to Paypal - winforms

My employer has an application he wants to make a change to. The application itself is used to process payment information and it is a desktop application.
It was pretty much just dropped in my lap. The former API used was Authorize.Net to handle credit card stuff and now he's switching over to the PayPal API.
While that may be great for him, it sucks for me as my experience with web development is near nil. I am endeavoring to keep this as a desktop application, but everything I've seen screams "ASP.NET ASP.NET ASP.NET", and as far as I am aware, ASP.NET is for web applications.
Is there any way that I can just do this in a windows form application? Is there a step-by-step for the hopelessly clueless as to how to implement the PayPal API in a C# .Net WinForms Desktop application?

You are going to have to implement a web service to talk to the PayPal API. However, you will be able to call the web service from your Winforms application. Try this StackOverflow question and answer:
Call webservice in windows application
Also, the references you are seeing should be to ASP.Net, which is different from ASP, which is Active Server Pages and is older technology.

So it turns out I was making it WAY more complicated than it needed to be. While before it was necessary with the Authorize.net to do stuff, with PayPal it actually requires (for our purposes, your mileage may vary) nothing from them other than having your stuff set up. All it requires is for you to post some properly formatted information to a url:
sUrl = "https://pilot-payflowpro.paypal.com"
WebRequest request = WebRequest.Create( sUrl );
request.Method = "POST";
string PostData =
"USER=/*User*/" +
"&VENDOR=/*Vendor*/" +
"&PARTNER=PayPal" +
"&PWD=/*PassWord*/" +
"&TRXTYPE=S" +
"&TENDER=C" +
"&ACCT=/*CC#*/" +
"&EXPDATE=/*CC Expiration Date*/" +
"&CVV2=/*CCV Code*/" +
"&AMT=/*Order Amount*/" +
"&FIRSTNAME=/*First Name*/" +
"&LASTNAME=/*Last Name*/" +
"&STREET=/*Address Street*/" +
"&CITY=/*Address City*/" +
"&STATE=/*Address State*/" +
"&ZIP=/*Zip Code*/" +
"COMMENT1=/*Any Comment*/";
byte[] bar = Encoding.UTF8.GetBytes( PostData );
request.ContentLength = bar.Length;
using ( Stream datStream = request.GetRequestStream( ) ) {
datStream.Write( bar, 0, bar.Length );
datStream.Close( );
}
string serverResponse;
WebResponse wResp = request.GetResponse( );
using ( Stream datStream = wResp.GetResponseStream( ) )
using ( StreamReader datSReader = new StreamReader( datStream ) )
serverResponse = datSReader.ReadToEnd( );
this.Response = HttpUtility.ParseQueryString(serverResponse);
IsSuccess = this.Response.Get( "RESULT" ) == "0";
if ( !IsSuccess ) MessageBox.Show( "RESULT != 0: RESULT = " + this.Response.Get( "RESULT" ) );
return IsSuccess;
This code, in its form before it was changed, came straight from the guys at PayPal, and made it a lot easier to manage transactions via a windows form application.

Related

WorkFlow Field Update using MetaData Tooling Api Salesforce

How to Create WorkFlow Field Update using MetaData Tooling Api
I am creating a metadataservice class and that object . thorw a object i am creating workflow field update but it is not working
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getOrganizationId().substring(0, 15) + ' ' + UserInfo.getSessionId().substring(15);
MetadataService.WorkflowFieldUpdate workflowFieldUpdate = new MetadataService.WorkflowFieldUpdate();
// Workflow Field Update
workflowFieldUpdate.fullName = 'TEST_Active_Permission';
workflowFieldUpdate.description = 'Activates a permission.';
workflowFieldUpdate.field = 'Expense__c.Status__c';
workflowFieldUpdate.literalValue = '1';
workflowFieldUpdate.name = 'TEST Active Permission';
workflowFieldUpdate.notifyAssignee = false;
workflowFieldUpdate.operation = 'Literal';
workflowFieldUpdate.protected_x = false;
workflowFieldUpdate.reevaluateOnChange = true;
workflowFieldUpdate.targetObject = 'Expense__c';
MetadataService.WorkflowAction wfp = workflowFieldUpdate;
MetadataService.Metadata[] theMetadata = new MetadataService.Metadata[]{};
theMetadata.add(wfp);
MetadataService.SaveResult[] results = service.createMetadata(theMetadata);
system.debug('results'+results);
That's not Tooling API, that's old school Metadata API. Somebody took the metadata API WSDL file and imported it back to SF. What error are you getting?
Keep in mind that since Winter'23 release (~September 2022) you can't create new workflow rules. Button is disabled in UI too. Field updates... you probably still can but why do you cling to retired automation?
https://admin.salesforce.com/blog/2021/go-with-the-flow-whats-happening-with-workflow-rules-and-process-builder
Note that in Metadata API documentation there's no top-level entry for WorkflowFieldUpdate. It's possible you have to create Workflow, wrap your thing in it. https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_workflow.htm Tooling API has separate entry (https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/tooling_api_objects_workflowfieldupdate.htm) but you'd need to ditch this hack and use JSON.

Office.context.mailbox.item.body.getAsync() method does not work in outlook mac 2016

In office 365 outlook add-in, Office.context.mailbox.item.body.getAsync() method does not work in outlook Mac. But it works fine in safari and chrome.
office js reference is "https://appsforoffice.microsoft.com/lib/1/hosted/office.js"
here is the code of add-in read app
var _item = Office.context.mailbox.item;
var body = _item.body;
// Get the body asynchronous as text
body.getAsync(Office.CoercionType.Text, function (asyncResult) {
if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) {
}
else {
$('#subject').html(asyncResult.value.trim());
}
});
That function is part of requirement set 1.3; the Mac add ins only support requirement set 1.1.
Had the same issue but there is a workaround. You could achieve this with makeEwsRequestAsync() method, which is provided in requirements set 1.1. This requires you to make a SOAP request and to parse the response data to get the email body. In the SOAP request, use:
' <t:AdditionalProperties>' +
' <t:FieldURI FieldURI="item:TextBody"/>' +
' </t:AdditionalProperties>' +
This will return a response that you can parse.
For reference:
https://dev.outlook.com/reference/add-ins/1.1/Office.context.mailbox.html#makeEwsRequestAsync

Hosting nodeJS app with firebase

So I have this web-app using angularJS and nodeJS. I don't want to just use localhost to demo my project because it doesn't looks cool at all when I type "node server.js" and then go to localhost.....
Since I intend to use Firebase for the data, I have noticed that Firebase provides hosting. I tried it, but it seems to only host the index.html and not through/using server.js. I have customized files for the server to use/update. So, how can I tell Firebase Hosting to use my server and related files when hosting?
Is it possible to tell Firebase, hey, run "node server.js" to host my index.html?
I'm guessing by the way you are wording the question you want to see this site from "the internet".
Two routes you could go here.
a) Serve your index through Firebase hosting. Firebase only hosts assets. If your Angular app is being served through Node then you will need to change your architecture to be more SPA-ish
SPA-ish would be like an index bootstrap that interacts with the backend purely through API's.
You would host the API server on something more appropriate like through Nodejitsu.
b) Serve the whole thing through something like Nodejitsu (hosting platform) or your very own VM managed by a different kind of hosting company like BuyVM.net.
Another idea, is if your nodejs app is independent of the angularjs app (however they use shared data, and perform operations on that data model) you could separate the two and connect them only via firebase.
Firebase hosting -> index.html and necessary angularjs files.
Locally (your PC) -> server.js which just connects to firebase and trigger on changed data.
I have done this for a few projects and it's a handy way to access the outside world (internet) while maintaining some semblence of security by not opening ports blindly.
I was able to do this to control a chromecast at my house while at a friends house
Here's an example from my most recent project (I'm trying to make a DVR).
https://github.com/onaclov2000/webdvr/blob/master/app.js
var FB_URL = '';
var Firebase = require('firebase');
var os = require('os')
var myRootRef = new Firebase(FB_URL);
var interfaces = os.networkInterfaces();
var addresses = [];
for (k in interfaces) {
for (k2 in interfaces[k]) {
var address = interfaces[k][k2];
if (address.family == 'IPv4' && !address.internal) {
addresses.push(address.address)
}
}
}
// Push my IP to firebase
// Perhaps a common "devices" location would be handy
var ipRef = myRootRef.push({
"type": "local",
"ip": addresses[0]
});
myRootRef.on('child_changed', function(childSnapshot, prevChildName) {
// code to handle child data changes.
var data = childSnapshot.val();
var localref = childSnapshot.ref();
if (data["commanded"] == "new") {
console.log("New Schedule Added");
var schedule = require('node-schedule');
var date = new Date(data["year"], data["month"], data["day"], data["hh"], data["mm"], 0);
console.log(date);
var j = schedule.scheduleJob(date, function(channel, program, length){
console.log("Recording Channel " + channel + " and program " + program + " for " + length + "ms");
}.bind(null, data["channel"], data["program"], data["length"]));
localref.update({"commanded" : "waiting"});
}
});
When I change my "commanded" data at the FB_URL, to "new" (which can be accomplished by angularjs VERY Simply, using an ng-click operation for example) it'll schedule a recording for a particular date and time (not all actually functional at the moment).
I might be late but since 3 years have passed there is an solution available now from Firebase in the form of cloud functions
Its not straight forward but looks promising if one can refactor their code a bit

Getting the credits balance from Facebook with the Facebook C# SDK in a Silverlight in browser app

I have been able to get my Silverlight App connected to Facebook and get authenticated.
I am trying to pull the users credits balance into my Silverlight app the documentation at developers.facebook.com/docs/creditsapi has a one line example that references the Facebook Credits Sample application from Githu that is writen in php. looking at the file from the Githu example facebookapi_php5_restlib.php and the documentation Converting Facebook PHP examples I should be able to get the balance with something like this.
private void GetBalance()
{
var fb = new FacebookClient ( auth.Session.AccessToken );
dynamic me = fb.Get ( "me" );
Dictionary<string, object> parms = new Dictionary<string, object> ( );
parms.Add ( me.id, "credit_balance" );
fb.GetAsync ("/facebook/users/getInfo", parms, GetResults );
}
private void GetResults ( FacebookAsyncResult asyncResult )
{
}
With this variation I get back an error
asyncResult.error - {"(OAuthException) Unknown path components: /getinfo"}
I have tried diffent variation on the API path but have not been able to get this call to work and am hoping someone will be able to point me in the right direction.
You need to be on the Facebook credits special incentives scheme for this to work. In order to apply for the scheme you must have a live app that uses credits as its sole currency.
You can apply for the scheme here.

WebClient issue

I am trying to get contents of http://www.yahoo.com using WebClient#DownloadStringAsync(). However as Silverlight doesn't allow cross domain calls i am getting TargetInvocationException. I know we have to put clientaccesspolicy.xml and crossdomain.xml in our web server root but that is possible only if i have control on my services. Currently Google is not under my control ;), so how do i handle it?
I've did a workaround by making a WCF service in my web application and then calling WebClient. This works perfectly but it is rather ineffecient. Is there any other better way than this?
Thanks in advance :)
Silverlight's cross domain restricitions cause many developers to implement workarounds. If you need to display the html page you get back you should look into Silverlight 4 (WebBrowser) control although this only seems to work when running out-of-browser mode.
If you need to parse through the content you can try some of the following:
For a managed code solution the proxy service you have already implemented is your best option.
Write a Java applet that returns this information. Silverlight can interopt to javascript which can interopt into Java applets. This also works in the reverse but a little difficult to setup. (If you need more info on this let me know).
Use javascript XmlHttpRequest to get the data you want from the source. This can be difficult when supporting multiple browsers. This link shows an example of how to do this (you will need to scroll down). Javascript get Html
Code:
var xmlHttpRequestHandler = new Object();
var requestObject;
xmlHttpRequestHandler.createXmlHttpRequest = function(){
var XmlHttpRequestObject;
if(typeof XMLHttpRequest != "undefined")
{
XmlHttpRequestObject = new XMLHttpRequest();
}
else if(window.ActiveXObject)
{
var tryPossibleVersions =["MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp","Microsoft.XMLHttp"];
for(i=0;i<tryPossibleVersions.length;i++)
{
try
{
XmlHttpRequestObject = new ActiveXObject(tryPossibleVersions[i]);
break;
}
catch(xmlHttpRequestObjectError)
{
// Ignore Exception
}
}
}
return XmlHttpRequestObject;}
function getHtml(){
var url = document.getElementById('url').value;
if(url.length > 0)
{
requestObject = xmlHttpRequestHandler.createXmlHttpRequest();
requestObject.onreadystatechange=onReadyStateChangeResponse;
requestObject.open("Get",url, true);
requestObject.send(null);
}}
function onReadyStateChangeResponse(){
var ready, status;
try
{
ready = requestObject.readyState;
status = requestObject.status;
}
catch(e) {}
if(ready == 4 && status == 200)
{
alert(requestObject.responseText);
}}

Resources