原文出处:http://www.cnblogs.com/dark-angel/archive/2011/11/16/2251489.html
CIapProcess.h
#import <Foundation/Foundation.h>
#import <StoreKit/StoreKit.h>
@protocol IapProcessDelegate <NSObject>
-(
void
)iapProcessBegin;
-(
void
)iapProcessEndWithError:(NSString*)errorString;
-(
void
)showProductByArray:(NSArray*)profuctArray;
-(
void
)transactionSuccess:(SKPaymentTransaction*)transaction;
-(
void
)transactionFail:(SKPaymentTransaction*)transaction;
-(
void
)restoredSuccess:(SKPaymentTransaction*)transaction;
-(
void
)restoredFailWithString:(NSString*)error;
@end
@
interface
CIapProcess : NSObject<SKProductsRequestDelegate, SKPaymentTransactionObserver>
@property(nonatomic,copy)NSString* productId;
@property(nonatomic,assign)id<IapProcessDelegate>
delegate
;
-(
void
)resquestProductList:(NSArray*)identifierArray;
//请求产品列表
-(
void
)resquestProductByIdentifier:(NSString*)identifier;
//请求产品
-(
void
)restorePurchas;
//恢复产品
-(
void
)payforProductByIdentifier:(NSString*)identifier;
//进入付费处理
@end
|
CIapProcess.m
#import "CIapProcess.h" #import "Reachability.h" @interface CIapProcess() -(BOOL)checkNetWork; -(BOOL)iapBegin; @end @implementation CIapProcess @synthesize delegate; @synthesize productId; //请求产品列表,有多个id -(void)resquestProductList:(NSArray*)identifierArray{ if (![self iapBegin]) { return; } self.productId = nil; SKProductsRequest* request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:identifierArray]]; request.delegate = self; [request start]; } //请求产品,一个id -(void)resquestProductByIdentifier:(NSString*)identifier{ if (![self iapBegin]) { return; } self.productId = identifier; SKProductsRequest* productRequest=[[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:identifier]]; productRequest.delegate=self; [productRequest start]; } //恢复产品 -(void)restorePurchas{ if (![self iapBegin]) { return; } [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]; } //开始进行IAP处理 -(BOOL)iapBegin{ if ([self.delegate respondsToSelector:@selector(iapProcessBegin)]) { [self.delegate iapProcessBegin]; } return [self checkNetWork]; } -(BOOL)checkNetWork{ Reachability* reachability = [Reachability reachabilityWithHostName:@"www.apple.com"]; NetworkStatus status = [reachability currentReachabilityStatus]; if (NotReachable != status) { return YES; } if ([self.delegate respondsToSelector:@selector(iapProcessEndWithError:)]) { [self.delegate iapProcessEndWithError:@"没有可用的网络"]; } return NO; } - (id)init { self = [super init]; if (self) { // Initialization code here. } return self; } -(void)payforProductByIdentifier:(NSString*)identifier{ if ([SKPaymentQueue canMakePayments]) { SKPayment* payment = [SKPayment paymentWithProductIdentifier:identifier]; [[SKPaymentQueue defaultQueue] addPayment:payment]; }else{ if ([self.delegate respondsToSelector:@selector(iapProcessEndWithError:)]) { [self.delegate iapProcessEndWithError:@"You are not authorized to purchase from AppStore"]; } } } #pragma mark- #pragma mark SKProductsRequestDelegate - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{ NSArray* productArray = [[NSArray alloc] initWithArray:response.products]; switch ([productArray count]) { case 0: if ([self.delegate respondsToSelector:@selector(iapProcessEndWithError:)]) { [self.delegate iapProcessEndWithError:@"产品不存在"]; } break; case 1: [self payforProductByIdentifier:[[productArray objectAtIndex:0] productIdentifier]]; break; default: if ([self.delegate respondsToSelector:@selector(showProductByArray:)]) { [self.delegate showProductByArray:productArray]; } break; } [request autorelease]; } #pragma mark - #pragma mark SKPaymentTransactionObserver - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{ for (SKPaymentTransaction* transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchased: if ([self.delegate respondsToSelector:@selector(transactionSuccess:)]) { [self.delegate transactionSuccess:transaction]; } break; case SKPaymentTransactionStateFailed: if ([self.delegate respondsToSelector:@selector(transactionFail:)]) { [self.delegate transactionFail:transaction]; } break; case SKPaymentTransactionStateRestored: if ([self.delegate respondsToSelector:@selector(restoredSuccess:)]) { [self.delegate restoredSuccess:transaction]; } break; default: break; } [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; } } - (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error{ if ([self.delegate respondsToSelector:@selector(restoredFailWithString:)]) { [self.delegate restoredFailWithString:[error description]]; } } - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue{ if (0 >= [queue.transactions count]) { if ([self.delegate respondsToSelector:@selector(restoredFailWithString:)]) { [self.delegate restoredFailWithString:@"没有可以恢复的交易"]; } } } @end
为了方便,这里将那几个代理方法设置为必需实现,你可以只实现部分。
附上检测网络用的那个类:
Reachability.h
#import <Foundation/Foundation.h> #import <SystemConfiguration/SystemConfiguration.h> typedef enum { NotReachable = 0, ReachableViaWiFi, ReachableViaWWAN } NetworkStatus; #define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification" @interface Reachability: NSObject { BOOL localWiFiRef; SCNetworkReachabilityRef reachabilityRef; } //reachabilityWithHostName- Use to check the reachability of a particular host name. + (Reachability*) reachabilityWithHostName: (NSString*) hostName; //reachabilityWithAddress- Use to check the reachability of a particular IP address. + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; //reachabilityForInternetConnection- checks whether the default route is available. // Should be used by applications that do not connect to a particular host + (Reachability*) reachabilityForInternetConnection; //reachabilityForLocalWiFi- checks whether a local wifi connection is available. + (Reachability*) reachabilityForLocalWiFi; //Start listening for reachability notifications on the current run loop - (BOOL) startNotifier; - (void) stopNotifier; - (NetworkStatus) currentReachabilityStatus; //WWAN may be available, but not active until a connection has been established. //WiFi may require a connection for VPN on Demand. - (BOOL) connectionRequired; @end
Reachability.m
#import <sys/socket.h> #import <netinet/in.h> #import <netinet6/in6.h> #import <arpa/inet.h> #import <ifaddrs.h> #import <netdb.h> #import <CoreFoundation/CoreFoundation.h> #import "Reachability.h" #define kShouldPrintReachabilityFlags 1 static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment) { #if kShouldPrintReachabilityFlags NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n", (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-', comment ); #endif } @implementation Reachability static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) { #pragma unused (target, flags) NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback"); NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback"); //We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively // in case someon uses the Reachablity object in a different thread. NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init]; Reachability* noteObject = (Reachability*) info; // Post a notification to notify the client that the network reachability changed. [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject]; [myPool release]; } - (BOOL) startNotifier { BOOL retVal = NO; SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL}; if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)) { if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) { retVal = YES; } } return retVal; } - (void) stopNotifier { if(reachabilityRef!= NULL) { SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); } } - (void) dealloc { [self stopNotifier]; if(reachabilityRef!= NULL) { CFRelease(reachabilityRef); } [super dealloc]; } + (Reachability*) reachabilityWithHostName: (NSString*) hostName; { Reachability* retVal = NULL; SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]); if(reachability!= NULL) { retVal= [[[self alloc] init] autorelease]; if(retVal!= NULL) { retVal->reachabilityRef = reachability; retVal->localWiFiRef = NO; } } return retVal; } + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); Reachability* retVal = NULL; if(reachability!= NULL) { retVal= [[[self alloc] init] autorelease]; if(retVal!= NULL) { retVal->reachabilityRef = reachability; retVal->localWiFiRef = NO; } } return retVal; } + (Reachability*) reachabilityForInternetConnection; { struct sockaddr_in zeroAddress; bzero(&zeroAddress, sizeof(zeroAddress)); zeroAddress.sin_len = sizeof(zeroAddress); zeroAddress.sin_family = AF_INET; return [self reachabilityWithAddress: &zeroAddress]; } + (Reachability*) reachabilityForLocalWiFi; { struct sockaddr_in localWifiAddress; bzero(&localWifiAddress, sizeof(localWifiAddress)); localWifiAddress.sin_len = sizeof(localWifiAddress); localWifiAddress.sin_family = AF_INET; // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0 localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress]; if(retVal!= NULL) { retVal->localWiFiRef = YES; } return retVal; } #pragma mark Network Flag Handling - (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags { PrintReachabilityFlags(flags, "localWiFiStatusForFlags"); BOOL retVal = NotReachable; if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect)) { retVal = ReachableViaWiFi; } return retVal; } - (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags { PrintReachabilityFlags(flags, "networkStatusForFlags"); if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) { // if target host is not reachable return NotReachable; } BOOL retVal = NotReachable; if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) { // if target host is reachable and no connection is required // then we'll assume (for now) that your on Wi-Fi retVal = ReachableViaWiFi; } if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) { // ... and the connection is on-demand (or on-traffic) if the // calling application is using the CFSocketStream or higher APIs if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) { // ... and no [user] intervention is needed retVal = ReachableViaWiFi; } } if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) { // ... but WWAN connections are OK if the calling application // is using the CFNetwork (CFSocketStream?) APIs. retVal = ReachableViaWWAN; } return retVal; } - (BOOL) connectionRequired; { NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef"); SCNetworkReachabilityFlags flags; if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) { return (flags & kSCNetworkReachabilityFlagsConnectionRequired); } return NO; } - (NetworkStatus) currentReachabilityStatus { NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef"); NetworkStatus retVal = NotReachable; SCNetworkReachabilityFlags flags; if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) { if(localWiFiRef) { retVal = [self localWiFiStatusForFlags: flags]; } else { retVal = [self networkStatusForFlags: flags]; } } return retVal; } @end