Set Signature Image for Accountless Signer DocuSign - docusignapi

I wanted to use my own logic for requesting signature but after the signature is complete, I want to send the Signed Image (as png) to DocuSign Envelope. I looked at the "Set Signature Image for Accountless Signer" flow and it seemed to be working fine, but the signature image is not embedded in my envelope.
This is what I am doing
Get the Account Information
Create Envelope from a Template as "Created(Draft)" status
Add a recipient
Add a Signature Tab
Update the Envelope Status from "Created" to "Sent"
Set the Signature Image for Recipient.
Everything seems to be working fine without any errors. But I dont see the image. Please let me know if I am doing anything wrong or if you have any examples of Sending Signature Image to Envelopes.

Feel free to contact us for a more creative solution, however the easiest way to get a signature on an iPad is to delegate the signature image collection to DocuSign altogether. here is a way to get a signature on a template (you can also do it with document byte stream). This is taken from the GitHub gist: https://gist.github.com/Ergin008/5645812.
The view for signing can be displayed in a webview in your iOS app.
//
// API Walkthrough 8 - Launch the signing (recipient) view of an envelope in an embedded session
//
// To run this sample:
// 1. Copy the below code into your iOS project
// 2. Enter your email, password, integrator key, name, templateId, and roleName and save
// 3. Run the code
//
- (void)embeddedSigning
{
// Enter your info:
NSString *email = #"<#email#>";
NSString *password = #"<#password#>";
NSString *integratorKey = #"<#integratorKey#>";
NSString *name = #"<#name#>";
// use same name as template role you saved through the Console UI
NSString *roleName = #"<#roleName#>";
// need to login to the console and copy a valid templateId into this string
NSString *templateId = #"<#templateId#>";
///////////////////////////////////////////////////////////////////////////////////////
// STEP 1 - Login (retrieves accountId and baseUrl)
///////////////////////////////////////////////////////////////////////////////////////
NSString *loginURL = #"https://demo.docusign.net/restapi/v2/login_information";
NSMutableURLRequest *loginRequest = [[NSMutableURLRequest alloc] init];
[loginRequest setHTTPMethod:#"GET"];
[loginRequest setURL:[NSURL URLWithString:loginURL]];
// set JSON formatted X-DocuSign-Authentication header (XML format also accepted)
NSDictionary *authenticationHeader = #{ #"Username": email, #"Password" : password, #"IntegratorKey" : integratorKey };
// jsonStringFromObject() function defined below...
[loginRequest setValue:[self jsonStringFromObject:authenticationHeader] forHTTPHeaderField:#"X-DocuSign-Authentication"];
// also set the Content-Type header (other accepted type is application/xml)
[loginRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
//*** make an asynchronous web request
[NSURLConnection sendAsynchronousRequest:loginRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *loginResponse, NSData *loginData, NSError *loginError) {
if (loginError) { // succesful GET returns status 200
NSLog(#"Error sending request %#. Got Response %# Error is: %#", loginRequest, loginResponse, loginError);
return;
}
// we use NSJSONSerialization to parse the JSON formatted response
NSError *jsonError = nil;
NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:loginData options:kNilOptions error:&jsonError];
NSArray *loginArray = responseDictionary[#"loginAccounts"];
// parse the accountId and baseUrl from the response and use in the next request
NSString *accountId = loginArray[0][#"accountId"];
NSString *baseUrl = loginArray[0][#"baseUrl"];
//--- display results
NSLog(#"\naccountId = %#\nbaseUrl = %#\n", accountId, baseUrl);
///////////////////////////////////////////////////////////////////////////////////////
// STEP 2 - Create Envelope via Template and send the envelope
///////////////////////////////////////////////////////////////////////////////////////
// append "/envelopes" URI to your baseUrl and use as endpoint for signature request call
NSString *envelopesURL = [NSString stringWithFormat:#"%#/envelopes",baseUrl];
NSMutableURLRequest *signatureRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:envelopesURL]];
[signatureRequest setHTTPMethod:#"POST"];
[signatureRequest setURL:[NSURL URLWithString:envelopesURL]];
// construct a JSON formatted signature request body (multi-line for readability)
NSDictionary *signatureRequestData = #{#"accountId": accountId,
#"emailSubject" : #"Embedded Sending API call",
#"emailBlurb" : #"email body goes here",
#"templateId" : templateId,
#"templateRoles" : [NSArray arrayWithObjects: #{#"email":email, #"name": name, #"roleName": roleName, #"clientUserId": #"1001" }, nil ],
#"status" : #"sent"
};
// convert request body into an NSData object
NSData* data = [[self jsonStringFromObject:signatureRequestData] dataUsingEncoding:NSUTF8StringEncoding];
// attach body to the request
[signatureRequest setHTTPBody:data];
// authentication and content-type headers
[signatureRequest setValue:[self jsonStringFromObject:authenticationHeader] forHTTPHeaderField:#"X-DocuSign-Authentication"];
[signatureRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
// Send the signature request...
[NSURLConnection sendAsynchronousRequest:signatureRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *envelopeResponse, NSData *envelopeData, NSError *envelopeError) {
NSError *jsonError = nil;
NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:envelopeData options:kNilOptions error:&jsonError];
NSLog(#"Signature request sent, envelope info is: \n%#\n", responseDictionary);
// parse envelopeId from resposne as it will be used in next request
NSString *envelopeId = responseDictionary[#"envelopeId"];
///////////////////////////////////////////////////////////////////////////////////////
// STEP 3 - Get the Embedded Signing View (aka recipient view) of the envelope
///////////////////////////////////////////////////////////////////////////////////////
// append /envelopes/{envelopeId}/views/recipient to baseUrl and use in request
NSString *embeddedURL = [NSString stringWithFormat:#"%#/envelopes/%#/views/recipient", baseUrl, envelopeId];
NSMutableURLRequest *embeddedRequest = [[NSMutableURLRequest alloc] init];
[embeddedRequest setHTTPMethod:#"POST"];
[embeddedRequest setURL:[NSURL URLWithString:embeddedURL]];
// simply set the returnUrl in the request body (user is directed here after signing)
NSDictionary *embeddedRequestData = #{#"returnUrl": #"http://www.docusign.com/devcenter",
#"authenticationMethod" : #"none",
#"email" : email,
#"userName" : name,
#"clientUserId" : #"1001" // must match clientUserId set is step 2
};
// convert request body into an NSData object
NSData* data = [[self jsonStringFromObject:embeddedRequestData] dataUsingEncoding:NSUTF8StringEncoding];
// attach body to the request
[embeddedRequest setHTTPBody:data];
// set JSON formatted X-DocuSign-Authentication header (XML format also accepted)
NSDictionary *authenticationHeader = #{ #"Username": email, #"Password" : password, #"IntegratorKey" : integratorKey };
// jsonStringFromObject() function defined below...
[embeddedRequest setValue:[self jsonStringFromObject:authenticationHeader] forHTTPHeaderField:#"X-DocuSign-Authentication"];
// also set the Content-Type header (other accepted type is application/xml)
[embeddedRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
//*** make an asynchronous web request
[NSURLConnection sendAsynchronousRequest:embeddedRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *embeddedResponse, NSData *embeddedData, NSError *embeddedError) {
if (embeddedError) { // succesful POST returns status 201
NSLog(#"Error sending request %#. Got Response %# Error is: %#", embeddedRequest, embeddedResponse, embeddedError);
return;
}
// we use NSJSONSerialization to parse the JSON formatted response
NSError *jsonError = nil;
NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:embeddedData options:kNilOptions error:&jsonError];
NSString *embeddedURLToken = responseDictionary[#"url"];
//--- display results
NSLog(#"URL token created - please navigate to the following URL to start the embedded signing workflow:\n\n%#\n\n", embeddedURLToken);
}];
}];
}];
}
- (NSString *)jsonStringFromObject:(id)object {
NSString *string = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:object options:0 error:nil] encoding:NSUTF8StringEncoding];
return string;
}

Related

example of parsing a receipt for an in-app purchase using iOS Xamarin?

I am trying to implement purchase validation for my app. I see that I can send the purchase receipt to my server to verify with Apple. However, I cannot figure out the correct way to POST the NSData to my URL for validation. Something like this:
public void CompleteTransaction (SKPaymentTransaction transaction) {
var productId = transaction.Payment.ProductIdentifier;
NSUrl receiptURL = NSBundle.MainBundle.AppStoreReceiptUrl;
NSData theData = NSData.FromUrl (receiptURL);
RestRequest request = new RestRequest(validationURL, Method.POST);
request.AddBody(theData); // ??
restClient.ExecuteAsync<bool>((response) =>
{
FinishTransaction(transaction, response.Data);
});
}
Does anyone have an example? I am using RestSharp.
Thanks!
davevr
OK, found how to do it. The trick was to parse the receipt into a dictionary and then pull the key out of that. Sample code:
public void CompleteTransaction (SKPaymentTransaction transaction) {
var productId = transaction.Payment.ProductIdentifier;
NSUrl receiptURL = NSBundle.MainBundle.AppStoreReceiptUrl;
NSData receipt = NSData.FromUrl (receiptURL);
// here is the code I was missing
NSDictionary requestContents = NSDictionary.FromObjectAndKey((NSString)receipt.GetBase64EncodedString(
NSDataBase64EncodingOptions.None),
(NSString)"receipt-data");
string receiptData = (requestContents["receipt-data"] as NSString).ToString();
RestRequest request = new RestRequest(<url to your server>, Method.POST);
request.AddParameter ("receipt-data", receiptData );
apiClient.ExecuteAsync<bool>(request, (response) =>
{
FinishTransaction (transaction, response.Data);
});
Once that is done, you can do the validation on the Apple server. There is lots of sample code on the net for that part.

Passbook : get base64 string from the server, convert and save pkpass to iOS

#import <PassKit/PassKit.h>
// convert base64 string to pkpass data
NSData *passData = [[NSData alloc] initWithBase64EncodedString:strEncodeData options:0];
NSLog(passData);
// init a pass object with the data
PKPass *pass = [[PKPass alloc] initWithData:passData];
NSLog(pass);
//init a pass library
PKPassLibrary *passLib = [[PKPassLibrary alloc] init];
//check if pass library contains this pass already
if([passLib containsPass:pass]) {
//pass already exists in library, show an error message
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Pass Exists" message:#"The pass you are trying to add to Passbook is already present." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
} else {
//present view controller to add the pass to the library
PKAddPassesViewController *vc = [[PKAddPassesViewController alloc] initWithPass:pass];
[vc setDelegate:(id)self];
[self presentViewController:vc animated:YES completion:nil];
}
I am tring to save passbook to ios wallet. I need to use base64 data instead of uri because of secure issue. The flow I assumed for this is like below
get base64 string from the server.
convert base64 to pkpass data with "initWithBase64EncodedString"
save pkpass to wallet with "PKAddPassesViewController"
With above code, the progress is stop on second step with nil error, even the decoded base64 string is correct. So I cannot be sure the code after 2nd step will functionate without errors.
thanks for answer in advance.
I know its late but i ran into the same problem after lot of research figure the issue is with initWithBase64EncodedString:passBase64 when base64 string decode from server response with mime type like:data:application/vnd.apple.pkpass;base6 NSData get nil. Maybe its a bug but if you use NSData+Base64 classes from https://github.com/l4u/NSData-Base64 its old but you can configure it to work with ARC and than convert data from base64 string to NSData problem goes away.

Google UrlShortener "ipRefererBlocked"

I have a site hosted on Azure where the calls to the Google UrlShortner API are being blocked. I receive the error:
{
"error": {
"errors": [
{
"domain": "usageLimits",
"reason": "ipRefererBlocked",
"message": "There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed.",
"extendedHelp": "https://console.developers.google.com"
}
],
"code": 403,
"message": "There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed."
}
}
The API works fine running locally and I have added the ip address to the API project credentials in the developer console. This appears to be an issue with Azure but I don't see where anyone has an answer.
Any suggestions would be great!
I was never able to get this resolved even using a static ip. Work around was tinyUrl. Their api worked flawlessly.
Yes use tiny URL, but not their API. I was never able to get their API to work.
+ (void) shortenLink:(NSString*) link andPerformBlock:(void (^)(NSString*, NSError*))block {
NSURLRequest* shortenedLinkRequest = [LinkShortener createTinyURLShortenerRequest:link];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:shortenedLinkRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSString*shortenedLink = #"";
UIAlertView* alert = nil;
if ([data length] > 0 && error == nil) {
NSString* shortenedLink = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
if (block) {
block(shortenedLink, error);
}
}
}
+ (NSURLRequest*) createTinyURLShortenerRequest:(NSString*) link {
NSString* escapedLink = [link stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];;
NSString* tinyURLShortenerURL = [NSString stringWithFormat:#"http://tinyurl.com/api-create.php?url=%#", escapedLink];
NSURL* tinyURLShortenerUrl = [NSURL URLWithString:tinyURLShortenerURL];
NSMutableURLRequest* shortenedLinkRequest = [NSMutableURLRequest requestWithURL:tinyURLShortenerUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:URL_SHORTENER_TIMEOUT];
[shortenedLinkRequest setHTTPMethod:#"GET"];
return shortenedLinkRequest;
}

iOS 7 Core Data and iCloud sync

I am looking to integrate in my new app the option to sync core data in iCloud and so share the information on users devices. I looked around on the web but haven't found a good example or tutorial on how to do this with iOS7.
The last that I have done is to analyze the Apple receipt demo app and included in my app. It seams to work, at least at first view. Adding a record on one device and after a short while, the other device show the data - so far I was happy.
BUT, after restoring the app, the information was gone, on both devices. So i looked into the app (iExplorer) and have found the local Core Data and all my data is there. The next that I have observed is that the debugger shows this: (XXX) are of course not the real values :-)
2014-07-09 19:40:12.830 XXX[199:3507] -[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](771): CoreData: Ubiquity: mobile~XXXXX:XXX
Using local storage: 1
2014-07-09 19:40:12.837 XXX[199:60b] asynchronously added persistent store!
2014-07-09 19:40:13.478 XXX[199:1803] -[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](771): CoreData: Ubiquity: mobile~XXXXX:XXX
Using local storage: 0
What means first it seams like to use the local storage but than change to local storage 0.
this is the code used from Apple's demo app:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
// assign the PSC to our app delegate ivar before adding the persistent store in the background
// this leverages a behavior in Core Data where you can create NSManagedObjectContext and fetch requests
// even if the PSC has no stores. Fetch requests return empty arrays until the persistent store is added
// so it's possible to bring up the UI and then fill in the results later
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
// prep the store path and bundle stuff here since NSBundle isn't totally thread safe
NSPersistentStoreCoordinator* psc = persistentStoreCoordinator;
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:#"XXX.sqlite"];
// do this asynchronously since if this is the first time this particular device is syncing with preexisting
// iCloud content it may take a long long time to download
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
// this needs to match the entitlements and provisioning profile
NSURL *cloudURL = [fileManager URLForUbiquityContainerIdentifier:nil];
NSString* coreDataCloudContent = [[cloudURL path] stringByAppendingPathComponent:#"XXXXX"];
cloudURL = [NSURL fileURLWithPath:coreDataCloudContent];
// The API to turn on Core Data iCloud support here.
NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:#"XXX", NSPersistentStoreUbiquitousContentNameKey, cloudURL, NSPersistentStoreUbiquitousContentURLKey, [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,nil];
NSError *error = nil;
[psc lock];
if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
Typical reasons for an error here include:
* The persistent store is not accessible
* The schema for the persistent store is incompatible with current managed object model
Check the error message to determine what the actual problem was.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
[psc unlock];
// tell the UI on the main thread we finally added the store and then
// post a custom notification to make your views do whatever they need to such as tell their
// NSFetchedResultsController to -performFetch again now there is a real store
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"asynchronously added persistent store!");
[[NSNotificationCenter defaultCenter] postNotificationName:#"RefetchAllDatabaseData" object:self userInfo:nil];
});
});
return persistentStoreCoordinator;
}
Could anyone help with tutorial or solution?
Try these sample apps for iOS and OSX.
http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/

Feed Dialog not working on iOS SDK 3.0 beta (API error code 110)

I am updating my app to use the new Facebook SDK for iOS (3.0). However, I have run across an issue trying to use the feed dialog. I followed the instructions on Facebook's developer website regarding how to use the feed dialog with the new SDK, but I am getting this error when I show the dialog:
API Error Code: 110
API Error Description: Invalid user id
Error Message: Missing user cookie (to validate session user)
Here is my code:
Facebook *facebook = [[Facebook alloc] initWithAppId:FBSession.activeSession.appID andDelegate:nil];
facebook.accessToken = FBSession.activeSession.accessToken;
facebook.expirationDate = FBSession.activeSession.expirationDate;
NSMutableDictionary *feedParams = [[NSMutableDictionary alloc] init];
[feedParams setObject:self.video.alternateLink.href
forKey:#"link"];
// link title = video title
[feedParams setObject:self.video.title.stringValue
forKey:#"name"];
// link picture = video thumbnail
[feedParams setObject:self.video.mediaGroup.highQualityThumbnail.URLString
forKey:#"picture"];
NSDictionary *privacyDict = [NSDictionary dictionaryWithObjectsAndKeys:#"CUSTOM", #"value", #"SELF", #"friends", nil];
SBJSON *jsonWriter = [[SBJSON alloc] init];
[feedParams setObject:[jsonWriter stringWithObject:privacyDict error:NULL]
forKey:#"privacy"];
[jsonWriter release];
[facebook dialog:#"feed"
andParams:feedParams
andDelegate:self];
[feedParams release];
self.facebook = facebook;
[facebook release];
It seems like an authentication problem, but I am passing a valid access token to the Facebook object, so I'm not sure what the problem is. If anybody could help me, that would be great. Thanks.
You may use FBSession.activeSession when integrating with the legacy Facebook class, as you have shown. One possible gotcha when you use activeSession, rather than directly instantiating a session object, is that it may not be open. Here is a simple sample that shows the form for integrating the Facebook class with active session:
if (FBSession.activeSession.isOpen) {
// Create a Facebook instance
Facebook *facebook = [[Facebook alloc] initWithAppId:FBSession.activeSession.appID
andDelegate:nil]; // commonly self
// Set the session information for the Facebook instance
facebook.accessToken = FBSession.activeSession.accessToken;
facebook.expirationDate = FBSession.activeSession.expirationDate;
// Put together the dialog parameters
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"I'm using the the Facebook SDK for iOS", #"name",
#"Facebook for iOS", #"caption",
#"Check out the Facebook SDK for iOS!", #"description",
#"https://developers.facebook.com/ios", #"link",
#"http://www.facebookmobileweb.com/hackbook/img/facebook_icon_large.png", #"picture",
nil];
// Invoke the dialog
[facebook dialog:#"feed" andParams:params andDelegate:nil];
[facebook release];
}
If the active session is not open, then you would get a failure along the lines of what you are seeing. A call along the lines of the following, somewhere earlier in your logic remedy this:
[FBSession openActiveSessionWithAllowLoginUI:YES];
Hope this helps!

Resources