Fixed compatibility with phonegap 2.7.0

- Changed interface 'Phonegap.exec' to 'cordova.exec'
- Use paymentWithProduct instead of paymentWithProductIndentifier
because It was deprecated in iOS 5.0
- Changed interface of requestProductData parameters
- Add prefix in NSLog
This commit is contained in:
davidshimjs
2013-05-07 15:31:21 +09:00
parent e854eb1ec6
commit 77480d70c6
3 changed files with 148 additions and 125 deletions

View File

@@ -9,52 +9,42 @@
#import <Foundation/Foundation.h>
#import <StoreKit/StoreKit.h>
#ifdef PHONEGAP_FRAMEWORK
#import <PhoneGap/PGPlugin.h>
#else
#import "PGPlugin.h"
#endif
#ifdef PHONEGAP_FRAMEWORK
#import <PhoneGap/NSData+Base64.h>
#else
#import "NSData+Base64.h"
#endif
#import <Cordova/CDVPlugin.h>
#import <Cordova/NSData+Base64.h>
#import "SKProduct+LocalizedPrice.h"
@interface InAppPurchaseManager : PGPlugin <SKPaymentTransactionObserver> {
@interface InAppPurchaseManager : CDVPlugin <SKPaymentTransactionObserver> {
NSMutableDictionary* list;
}
- (void) setup:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
- (void) makePurchase:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
- (void) requestProductData:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
- (void) requestProductsData:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
@property (nonatomic, retain) NSMutableDictionary* list;
- (void) setup:(CDVInvokedUrlCommand*)command;
- (void) makePurchase:(CDVInvokedUrlCommand*)command;
- (void) requestProductData:(CDVInvokedUrlCommand*)command;
- (void) requestProductsData:(CDVInvokedUrlCommand*)command;
- (void) restoreCompletedTransactions:(CDVInvokedUrlCommand*)command;
//- (void) setup:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
//- (void) makePurchase:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
//- (void) requestProductData:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
//- (void) requestProductsData:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
- (void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions;
- (void) paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error;
- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue;
@end
@interface ProductsRequestDelegate : NSObject <SKProductsRequestDelegate>{
NSString* successCallback;
NSString* failCallback;
InAppPurchaseManager* command;
@interface ProductsRequestDelegate : NSObject <SKProductsRequestDelegate>
{
InAppPurchaseManager* plugin;
CDVInvokedUrlCommand* command;
}
@property (nonatomic, copy) NSString* successCallback;
@property (nonatomic, copy) NSString* failCallback;
@property (nonatomic, retain) InAppPurchaseManager* command;
@property (nonatomic, retain) InAppPurchaseManager* plugin;
@property (nonatomic, retain) CDVInvokedUrlCommand* command;
@end;
@interface BatchProductsRequestDelegate : NSObject <SKProductsRequestDelegate> {
NSString* callback;
InAppPurchaseManager* command;
InAppPurchaseManager* plugin;
CDVInvokedUrlCommand* command;
}
@property (nonatomic, copy) NSString* callback;
@property (nonatomic, retain) InAppPurchaseManager* command;
@property (nonatomic, retain) InAppPurchaseManager* plugin;
@property (nonatomic, retain) CDVInvokedUrlCommand* command;
@end;

View File

@@ -6,7 +6,9 @@
*/
var InAppPurchaseManager = function() {
PhoneGap.exec('InAppPurchaseManager.setup');
cordova.exec(null, function () {
// It occurs when user can't purchase anything
}, "InAppPurchaseManager", "setup", []);
}
/**
@@ -21,7 +23,9 @@ InAppPurchaseManager.prototype.makePurchase = function(productId, quantity) {
if(!q) {
q = 1;
}
return PhoneGap.exec('InAppPurchaseManager.makePurchase', productId, q);
// return
cordova.exec(null, null, "InAppPurchaseManager", "makePurchase", [productId, q]);
}
/**
@@ -31,7 +35,8 @@ InAppPurchaseManager.prototype.makePurchase = function(productId, quantity) {
*/
InAppPurchaseManager.prototype.restoreCompletedTransactions = function() {
return PhoneGap.exec('InAppPurchaseManager.restoreCompletedTransactions');
// return
cordova.exec(null, null, "InAppPurchaseManager", "restoreCompletedTransactions", []);
}
@@ -45,19 +50,7 @@ InAppPurchaseManager.prototype.restoreCompletedTransactions = function() {
*/
InAppPurchaseManager.prototype.requestProductData = function(productId, successCallback, failCallback) {
var key = 'f' + this.callbackIdx++;
window.plugins.inAppPurchaseManager.callbackMap[key] = {
success: function(productId, title, description, price ) {
if (productId == '__DONE') {
delete window.plugins.inAppPurchaseManager.callbackMap[key]
return;
}
successCallback(productId, title, description, price);
},
fail: failCallback
}
var callback = 'window.plugins.inAppPurchaseManager.callbackMap.' + key;
PhoneGap.exec('InAppPurchaseManager.requestProductData', productId, callback + '.success', callback + '.fail');
cordova.exec(successCallback, failCallback, "InAppPurchaseManager", "requestProductData", [productId]);
}
/**
@@ -85,13 +78,7 @@ InAppPurchaseManager.prototype.requestProductData = function(productId, successC
* strings which were rejected by the app store.
*/
InAppPurchaseManager.prototype.requestProductsData = function(productIds, callback) {
var key = 'b' + this.callbackIdx++;
window.plugins.inAppPurchaseManager.callbackMap[key] = function(validProducts, invalidProductIds) {
delete window.plugins.inAppPurchaseManager.callbackMap[key];
callback(validProducts, invalidProductIds);
};
var callbackName = 'window.plugins.inAppPurchaseManager.callbackMap.' + key;
PhoneGap.exec('InAppPurchaseManager.requestProductsData', callbackName, {productIds: productIds});
cordova.exec(callback, null, "InAppPurchaseManager", "requestProductsData", [productIds]);
};
/* function(transactionIdentifier, productId, transactionReceipt) */
@@ -104,7 +91,9 @@ InAppPurchaseManager.prototype.onRestored = null;
InAppPurchaseManager.prototype.onFailed = null;
/* function() */
InAppPurchaseManager.prototype.onRestoreCompletedTransactionsFinished = null;
InAppPurchaseManager.prototype.onRestoreCompletedTransactionsFinished = function () {
console.log("restored transaction");
};
/* function(errorCode) */
InAppPurchaseManager.prototype.onRestoreCompletedTransactionsFailed = null;
@@ -112,7 +101,6 @@ InAppPurchaseManager.prototype.onRestoreCompletedTransactionsFailed = null;
/* This is called from native.*/
InAppPurchaseManager.prototype.updatedTransactionCallback = function(state, errorCode, errorText, transactionIdentifier, productId, transactionReceipt) {
alert(state);
switch(state) {
case "PaymentTransactionStatePurchased":
if(window.plugins.inAppPurchaseManager.onPurchased)
@@ -156,6 +144,7 @@ InAppPurchaseManager.prototype.runQueue = function() {
if(!this.eventQueue.length || (!this.onPurchased && !this.onFailed && !this.onRestored)) {
return;
}
var args;
/* We can't work directly on the queue, because we're pushing new elements onto it */
var queue = this.eventQueue.slice();
@@ -182,15 +171,39 @@ InAppPurchaseManager.prototype.unWatchQueue = function() {
}
}
InAppPurchaseManager.prototype.callbackMap = {};
InAppPurchaseManager.prototype.callbackIdx = 0;
InAppPurchaseManager.prototype.eventQueue = [];
InAppPurchaseManager.prototype.timer = null;
PhoneGap.addConstructor(function() {
if(!window.plugins) {
window.plugins = {};
}
window.plugins.inAppPurchaseManager = InAppPurchaseManager.manager = new InAppPurchaseManager();
});
document.addEventListener("deviceready", function() {
window.plugins = window.plugins || {};
window.plugins.inAppPurchaseManager = InAppPurchaseManager.manager = new InAppPurchaseManager();
window.plugins.inAppPurchaseManager.onPurchased = function(transactionIdentifier, productId, transactionReceipt) {
console.log('purchased: ' + productId);
// If failed a receipt validation on server, you can restore transaction this payment.
// window.plugins.inAppPurchaseManager.restoreCompletedTransactions();
}
// Perhaps It did rollback a transaction
window.plugins.inAppPurchaseManager.onRestored = function(transactionIdentifier, productId, transactionReceipt) {
console.log('restored: ' + productId);
/* See the developer guide for details of what to do with this */
}
// Failed to purchase an item
window.plugins.inAppPurchaseManager.onFailed = function(errno, errtext) {
alert(errtext);
}
// requestProductData -> { id, title, description, price }
// requestProductsData -> [[{ id, title, description, price }, ... ], [invaildID]]
// plugins.inAppPurchaseManager.requestProductData("1", function(result) {
// window.plugins.inAppPurchaseManager.makePurchase(result.id, 1 /* quantity */);
// }, function(id) {
// console.log("[In JS] Invalid product id: " + id);
// }
// );
});

View File

@@ -30,25 +30,33 @@
@end
@implementation InAppPurchaseManager
@synthesize list;
-(void) setup:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
-(void) setup:(CDVInvokedUrlCommand*)command
{
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
CDVPluginResult* pluginResult = nil;
self.list = [[NSMutableDictionary alloc] init];
// If user can make payments, It'll occur success callback
if ([SKPaymentQueue canMakePayments]) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
- (void) requestProductData:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
- (void) requestProductData:(CDVInvokedUrlCommand*)command
{
if([arguments count] < 3) {
return;
}
NSLog(@"Getting product data");
NSSet *productIdentifiers = [NSSet setWithObject:[arguments objectAtIndex:0]];
NSLog(@"[IAP] Getting product data");
NSSet *productIdentifiers = [NSSet setWithObject:[command.arguments objectAtIndex:0]];
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
ProductsRequestDelegate* delegate = [[[ProductsRequestDelegate alloc] init] retain];
delegate.command = self;
delegate.successCallback = [arguments objectAtIndex:1];
delegate.failCallback = [arguments objectAtIndex:2];
delegate.command = command;
delegate.plugin = self;
productsRequest.delegate = delegate;
[productsRequest start];
@@ -58,46 +66,52 @@
* Request product data for the productIds given in the option with
* key "productIds". See js for further documentation.
*/
- (void) requestProductsData:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
- (void) requestProductsData:(CDVInvokedUrlCommand*)command
{
if([arguments count] < 1) {
if([command.arguments count] < 1) {
return;
}
NSSet *productIdentifiers = [NSSet setWithArray:[options objectForKey:@"productIds"]];
NSSet *productIdentifiers = [NSSet setWithArray:[command.arguments objectAtIndex:0]];
NSLog(@"Getting products data");
NSLog(@"[IAP] Getting products data");
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
BatchProductsRequestDelegate* delegate = [[[BatchProductsRequestDelegate alloc] init] retain];
delegate.command = self;
delegate.callback = [arguments objectAtIndex:0];
delegate.command = command;
delegate.plugin = self;
productsRequest.delegate = delegate;
[productsRequest start];
}
- (void) makePurchase:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
- (void) makePurchase:(CDVInvokedUrlCommand*)command
{
NSLog(@"About to do IAP");
if([arguments count] < 1) {
NSLog(@"[IAP] About to do IAP");
if([command.arguments count] < 1) {
return;
}
SKMutablePayment *payment = [SKMutablePayment paymentWithProductIdentifier:[arguments objectAtIndex:0]];
// paymentWithProductIndentifier was deprecated in iOS 5.0
SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:[self.list objectForKey:[command.arguments objectAtIndex:0]]];
if([arguments count] > 1) {
id quantity = [arguments objectAtIndex:1];
if([command.arguments count] > 1) {
id quantity = [command.arguments objectAtIndex:1];
if ([quantity respondsToSelector:@selector(integerValue)]) {
payment.quantity = [quantity integerValue];
}
}
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (void) restoreCompletedTransactions:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
- (void) restoreCompletedTransactions:(CDVInvokedUrlCommand*)command
{
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
CDVPluginResult* pluginResult = nil;
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
// SKPaymentTransactionObserver methods
@@ -129,7 +143,7 @@
state = @"PaymentTransactionStateFailed";
error = transaction.error.localizedDescription;
errorCode = transaction.error.code;
NSLog(@"error %d %@", errorCode, error);
NSLog(@"[IAP] error %d %@", errorCode, error);
break;
@@ -141,10 +155,10 @@
break;
default:
NSLog(@"Invalid state");
NSLog(@"[IAP] Invalid state");
continue;
}
NSLog(@"state: %@", state);
NSLog(@"[IAP] state: %@", state);
NSArray *callbackArgs = [NSArray arrayWithObjects:
NILABLE(state),
[NSNumber numberWithInt:errorCode],
@@ -154,8 +168,9 @@
NILABLE(transactionReceipt),
nil];
NSString *js = [NSString stringWithFormat:@"plugins.inAppPurchaseManager.updatedTransactionCallback.apply(plugins.inAppPurchaseManager, %@)", [callbackArgs JSONSerialize]];
NSLog(@"js: %@", js);
[self writeJavascript: js];
NSLog(@"[IAP] js: %@", js);
[self.webView stringByEvaluatingJavaScriptFromString:js];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
@@ -164,55 +179,56 @@
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
NSString *js = [NSString stringWithFormat:@"plugins.inAppPurchaseManager.onRestoreCompletedTransactionsFailed(%d)", error.code];
[self writeJavascript: js];
[self.webView stringByEvaluatingJavaScriptFromString:js];
}
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
NSString *js = @"plugins.inAppPurchaseManager.onRestoreCompletedTransactionsFinished()";
[self writeJavascript: js];
[self.webView stringByEvaluatingJavaScriptFromString:js];
}
@end
@implementation ProductsRequestDelegate
@synthesize successCallback, failCallback, command;
@synthesize command, plugin;
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSLog(@"got iap product response");
NSLog(@"[IAP] got iap product response");
for (SKProduct *product in response.products) {
NSLog(@"sending js for %@", product.productIdentifier);
NSArray *callbackArgs = [NSArray arrayWithObjects:
NILABLE(product.productIdentifier),
NILABLE(product.localizedTitle),
NILABLE(product.localizedDescription),
NILABLE(product.localizedPrice),
nil];
NSString *js = [NSString stringWithFormat:@"%@.apply(plugins.inAppPurchaseManager, %@)", successCallback, [callbackArgs JSONSerialize]];
NSLog(@"js: %@", js);
[command writeJavascript: js];
NSLog(@"[IAP] sending for %@", product.productIdentifier);
NSDictionary *callbackArgs = [NSDictionary dictionaryWithObjectsAndKeys:
NILABLE(product.productIdentifier), @"id",
NILABLE(product.localizedTitle), @"title",
NILABLE(product.localizedDescription), @"description",
NILABLE(product.localizedPrice), @"price",
nil];
[self.plugin.list setObject:product forKey:[NSString stringWithFormat:@"%@", product.productIdentifier]];
CDVPluginResult* pluginResult = nil;
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:callbackArgs];
[self.plugin.commandDelegate sendPluginResult:pluginResult callbackId:self.command.callbackId];
}
for (NSString *invalidProductId in response.invalidProductIdentifiers) {
NSLog(@"sending fail (%@) js for %@", failCallback, invalidProductId);
NSLog(@"[IAP] sending fail for %@", invalidProductId);
[command writeJavascript: [NSString stringWithFormat:@"%@('%@')", failCallback, invalidProductId]];
CDVPluginResult* pluginResult = nil;
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:invalidProductId];
[self.plugin.commandDelegate sendPluginResult:pluginResult callbackId:self.command.callbackId];
}
NSLog(@"done iap");
[command writeJavascript: [NSString stringWithFormat:@"%@('__DONE')", successCallback]];
NSLog(@"[IAP] done iap");
[request release];
[self release];
}
- (void) dealloc
{
[successCallback release];
[failCallback release];
[plugin release];
[command release];
[super dealloc];
}
@@ -226,11 +242,11 @@
*/
@implementation BatchProductsRequestDelegate
@synthesize callback, command;
@synthesize plugin, command;
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSMutableArray *validProducts = [NSMutableArray array];
for (SKProduct *product in response.products) {
[validProducts addObject:
[NSDictionary dictionaryWithObjectsAndKeys:
@@ -239,21 +255,25 @@
NILABLE(product.localizedDescription), @"description",
NILABLE(product.localizedPrice), @"price",
nil]];
[self.plugin.list setObject:product forKey:[NSString stringWithFormat:@"%@", product.productIdentifier]];
}
NSArray *callbackArgs = [NSArray arrayWithObjects:
NILABLE(validProducts),
NILABLE(response.invalidProductIdentifiers),
nil];
NSString *js = [NSString stringWithFormat:@"%@.apply(plugins.inAppPurchaseManager, %@);", callback, [callbackArgs JSONSerialize]];
[command writeJavascript: js];
CDVPluginResult* pluginResult = nil;
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:callbackArgs];
[self.plugin.commandDelegate sendPluginResult:pluginResult callbackId:self.command.callbackId];
[request release];
[self release];
}
- (void) dealloc {
[callback release];
[plugin release];
[command release];
[super dealloc];
}