forked from mirrors/linphone-iphone
continue
This commit is contained in:
parent
aefc92a0dd
commit
5c02755992
7 changed files with 88 additions and 28 deletions
|
|
@ -21,28 +21,28 @@
|
|||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="title" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="6" id="Np2-5N-fTR" userLabel="ptitle">
|
||||
<rect key="frame" x="0.0" y="6" width="55" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="description..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" id="4s8-UV-skT" userLabel="pdescription">
|
||||
<rect key="frame" x="119" y="6" width="136" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="$0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" id="jzs-nJ-jrK" userLabel="pprice">
|
||||
<rect key="frame" x="63" y="6" width="48" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" id="Bcv-Vz-Tq1" userLabel="ppurchased">
|
||||
<rect key="frame" x="263" y="6" width="79" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||
</switch>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
|
|
|
|||
|
|
@ -30,14 +30,16 @@ extern NSString *const kLinphoneIAPurchaseNotification;
|
|||
#define IAPPurchaseSucceeded @"IAPPurchaseSucceeded"
|
||||
#define IAPRestoreFailed @"IAPRestoreFailed"
|
||||
#define IAPRestoreSucceeded @"IAPRestoreSucceeded"
|
||||
#define IAPReceiptFailed @"IAPReceiptFailed"
|
||||
#define IAPReceiptSucceeded @"IAPReceiptSucceeded"
|
||||
|
||||
typedef NSString* IAPPurchaseNotificationStatus;
|
||||
|
||||
@property (nonatomic, retain) IAPPurchaseNotificationStatus status;
|
||||
@property (nonatomic, copy) NSString *errlast;
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray *productsAvailable;
|
||||
@property (nonatomic, strong) NSMutableArray *productsPurchased;
|
||||
@property (nonatomic, strong) NSMutableArray *productsRestored;
|
||||
@property (nonatomic, strong) NSMutableArray *productsIDPurchased;
|
||||
|
||||
- (void)loadProducts;
|
||||
- (BOOL)isPurchased:(SKProduct*)product;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#import "InAppProductsManager.h"
|
||||
#import "Utils.h"
|
||||
#import "LinphoneManager.h"
|
||||
|
||||
NSString *const kLinphoneIAPurchaseNotification = @"LinphoneIAProductsNotification";
|
||||
|
||||
|
|
@ -29,6 +30,7 @@ NSString *const kLinphoneIAPurchaseNotification = @"LinphoneIAProductsNotificati
|
|||
- (instancetype)init {
|
||||
if ((self = [super init]) != nil) {
|
||||
ready = false;
|
||||
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
|
||||
[self loadProducts];
|
||||
}
|
||||
return self;
|
||||
|
|
@ -40,6 +42,7 @@ NSString *const kLinphoneIAPurchaseNotification = @"LinphoneIAProductsNotificati
|
|||
}
|
||||
//TODO: move this list elsewhere
|
||||
NSArray * list = [[[NSArray alloc] initWithArray:@[@"test.auto_renew_7days", @"test.non_renew", @"test.one_time", @"test.auto_renew_1month_withfree"]] autorelease];
|
||||
_productsIDPurchased = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
|
||||
SKProductsRequest *productsRequest = [[SKProductsRequest alloc]
|
||||
initWithProductIdentifiers:[NSSet setWithArray:list]];
|
||||
|
|
@ -49,7 +52,7 @@ NSString *const kLinphoneIAPurchaseNotification = @"LinphoneIAProductsNotificati
|
|||
|
||||
- (void)productsRequest:(SKProductsRequest *)request
|
||||
didReceiveResponse:(SKProductsResponse *)response {
|
||||
_productsAvailable= [[NSMutableArray arrayWithArray: response.products] retain];
|
||||
_productsAvailable = [[NSMutableArray arrayWithArray: response.products] retain];
|
||||
|
||||
LOGI(@"Found %lu products available", (unsigned long)_productsAvailable.count);
|
||||
|
||||
|
|
@ -64,8 +67,8 @@ NSString *const kLinphoneIAPurchaseNotification = @"LinphoneIAProductsNotificati
|
|||
}
|
||||
|
||||
- (BOOL)isPurchased:(SKProduct*)product {
|
||||
for (SKProduct *prod in _productsPurchased) {
|
||||
if (prod == product) {
|
||||
for (NSString *prod in _productsIDPurchased) {
|
||||
if ([prod isEqual: product.productIdentifier]) {
|
||||
bool isBought = true;
|
||||
LOGE(@"%@ is %s bought.", product.localizedTitle, isBought?"":"NOT");
|
||||
return isBought;
|
||||
|
|
@ -87,11 +90,55 @@ NSString *const kLinphoneIAPurchaseNotification = @"LinphoneIAProductsNotificati
|
|||
|
||||
-(void)restore {
|
||||
LOGI(@"Restoring user purchases...");
|
||||
if (! [SKPaymentQueue canMakePayments]) { LOGF(@"Not allowed to do in app purchase!!!"); }
|
||||
_productsRestored = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
if (! [SKPaymentQueue canMakePayments]) {
|
||||
LOGF(@"Not allowed to do in app purchase!!!");
|
||||
}
|
||||
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
|
||||
}
|
||||
|
||||
- (void)checkReceipt: (SKPaymentTransaction*)transaction {
|
||||
NSData *receiptData = nil;
|
||||
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
|
||||
// Test whether the receipt is present at the above URL
|
||||
if(![[NSFileManager defaultManager] fileExistsAtPath:[receiptURL path]]) {
|
||||
receiptData = [NSData dataWithContentsOfURL:receiptURL];
|
||||
} else {
|
||||
LOGI(@"Could not find any receipt in application, using the transaction one!");
|
||||
receiptData = transaction.transactionReceipt;
|
||||
}
|
||||
|
||||
// We must validate the receipt on our server
|
||||
NSURL *storeURL = [NSURL URLWithString:[[LinphoneManager instance] lpConfigStringForKey:@"inapp_receipt_validation_url"]];
|
||||
NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
|
||||
[storeRequest setHTTPMethod:@"POST"];
|
||||
[storeRequest setHTTPBody:receiptData];
|
||||
|
||||
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
|
||||
[NSURLConnection sendAsynchronousRequest:storeRequest
|
||||
queue:queue
|
||||
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
|
||||
if (data == nil) {
|
||||
LOGE(@"Server replied nothing, aborting now.");
|
||||
} else if (connectionError) {
|
||||
LOGE(@"Could not verify the receipt, aborting now: (%d) %@.", connectionError.code, connectionError);
|
||||
} else {
|
||||
NSError *jsonError;
|
||||
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
|
||||
if (jsonError == nil) {
|
||||
// Hourray, we can finally unlock purchase stuff in app!
|
||||
LOGI(@"In apps purchased are %@", jsonResponse);
|
||||
LOGE(@"To do: [_productsIDPurchased addObject:transaction.payment.productIdentifier];");
|
||||
[self postNotificationforStatus:IAPReceiptSucceeded];
|
||||
return;
|
||||
} else {
|
||||
LOGE(@"Impossible to parse receipt JSON response, aborting now because of %@: %@.", jsonError, [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]);
|
||||
}
|
||||
}
|
||||
// Something failed when checking the receipt
|
||||
[self postNotificationforStatus:IAPReceiptFailed];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
|
||||
for(SKPaymentTransaction * transaction in transactions) {
|
||||
switch (transaction.transactionState) {
|
||||
|
|
@ -99,9 +146,24 @@ NSString *const kLinphoneIAPurchaseNotification = @"LinphoneIAProductsNotificati
|
|||
break;
|
||||
case SKPaymentTransactionStatePurchased:
|
||||
case SKPaymentTransactionStateRestored:
|
||||
[_productsPurchased addObject:transaction];
|
||||
[self checkReceipt: transaction];
|
||||
[self completeTransaction:transaction forStatus:IAPPurchaseSucceeded];
|
||||
break;
|
||||
|
||||
// case SKPaymentTransactionStatePurchasing:
|
||||
// break;
|
||||
// case SKPaymentTransactionStateDeferred:
|
||||
// [self transactionDeferred:transaction];
|
||||
// break;
|
||||
// case SKPaymentTransactionStatePurchased:
|
||||
// [self completeTransaction:transaction];
|
||||
// break;
|
||||
// case SKPaymentTransactionStateRestored:
|
||||
// [self restoreTransaction:transaction];
|
||||
// break;
|
||||
// case SKPaymentTransactionStateFailed:
|
||||
// [self failedTransaction:transaction];
|
||||
// break;
|
||||
default:
|
||||
_errlast = [NSString stringWithFormat:@"Purchase of %@ failed.",transaction.payment.productIdentifier];
|
||||
[self completeTransaction:transaction forStatus:IAPPurchaseFailed];
|
||||
|
|
@ -112,7 +174,7 @@ NSString *const kLinphoneIAPurchaseNotification = @"LinphoneIAProductsNotificati
|
|||
|
||||
- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions {
|
||||
for(SKPaymentTransaction * transaction in transactions) {
|
||||
NSLog(@"%@ was removed from the payment queue.", transaction.payment.productIdentifier);
|
||||
LOGI(@"%@ was removed from the payment queue.", transaction.payment.productIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -123,19 +185,8 @@ NSString *const kLinphoneIAPurchaseNotification = @"LinphoneIAProductsNotificati
|
|||
}
|
||||
}
|
||||
|
||||
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
|
||||
{
|
||||
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
|
||||
LOGI(@"All restorable transactions have been processed by the payment queue.");
|
||||
// for (SKPayment *payment in queue) {
|
||||
// [queue transactions]
|
||||
// [_productsRestored addObject:payment.productIdentifier];
|
||||
// }
|
||||
|
||||
for (SKPaymentTransaction *transaction in queue.transactions) {
|
||||
NSString *productID = transaction.payment.productIdentifier;
|
||||
[_productsRestored addObject:productID];
|
||||
NSLog (@"product id is %@" , productID);
|
||||
}
|
||||
}
|
||||
|
||||
-(void)postNotificationforStatus:(IAPPurchaseNotificationStatus)status {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
selector:@selector(onIAPPurchaseNotification:)
|
||||
name:kLinphoneIAPurchaseNotification
|
||||
object:nil];
|
||||
|
||||
[[self tableView] reloadData];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
|
|
@ -36,7 +38,9 @@
|
|||
}
|
||||
|
||||
- (void)onIAPPurchaseNotification:(NSNotification*)notif {
|
||||
if ([[iapm status] isEqual: IAPAvailableSucceeded]) {
|
||||
if ([[iapm status] isEqual: IAPAvailableSucceeded]
|
||||
|| [[iapm status] isEqualToString: IAPRestoreSucceeded]
|
||||
|| [[iapm status] isEqualToString: IAPPurchaseSucceeded]) {
|
||||
[[self tableView] reloadData];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
</tableView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="XrD-Mn-6EM" userLabel="restoreButton">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Restore">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
|
|
|
|||
|
|
@ -53,4 +53,5 @@ display_filter_auto_rotate=0
|
|||
|
||||
[app]
|
||||
#contact_display_username_only=1
|
||||
#contact_filter_on_default_domain=1
|
||||
#contact_filter_on_default_domain=1
|
||||
inapp_receipt_validation_url=https://linphone.org/inapp/veriyReceipt
|
||||
|
|
@ -51,4 +51,6 @@ stun=stun.linphone.org
|
|||
[video]
|
||||
display_filter_auto_rotate=0
|
||||
|
||||
[app]
|
||||
inapp_receipt_validation_url=https://linphone.org/inapp/veriyReceipt
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue