iap_ios.mm 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. // ***** appstore.h *****
  2. #include "iap_ios.h"
  3. @implementation BBIAPStoreDelegate
  4. -(id)initWithPeer:(BBIAPStore*)peer{
  5. if( self=[super init] ){
  6. _peer=peer;
  7. }
  8. return self;
  9. }
  10. -(void)productsRequest:(SKProductsRequest*)request didReceiveResponse:(SKProductsResponse*)response{
  11. _peer->OnRequestProductDataResponse( request,response );
  12. }
  13. -(void)paymentQueue:(SKPaymentQueue*)queue updatedTransactions:(NSArray*)transactions{
  14. _peer->OnUpdatedTransactions( queue,transactions );
  15. }
  16. -(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue*)queue{
  17. _peer->OnRestoreTransactionsFinished( queue,0 );
  18. }
  19. -(void)paymentQueue:(SKPaymentQueue*)queue restoreCompletedTransactionsFailedWithError:(NSError*)error{
  20. _peer->OnRestoreTransactionsFinished( queue,error );
  21. }
  22. -(void)request:(SKRequest*)request didFailWithError:(NSError*)error{
  23. _peer->OnRequestFailed( request,error );
  24. }
  25. @end
  26. BBProduct::BBProduct():product(0),valid(false),type(0),owned(false),interrupted(false){
  27. }
  28. BBProduct::~BBProduct(){
  29. // [product release];
  30. }
  31. // ***** IAPStore *****
  32. BBIAPStore::BBIAPStore():_running( false ),_products( 0 ),_result( -1 ){
  33. _priceFormatter=[[NSNumberFormatter alloc] init];
  34. [_priceFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
  35. [_priceFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
  36. }
  37. bool BBIAPStore::OpenStoreAsync( bbArray<bbGCVar<BBProduct>> products ){
  38. if( _running || _products.length() ) return false;
  39. if( ![SKPaymentQueue canMakePayments] ) return false;
  40. if( !_delegate ){
  41. _delegate=[[BBIAPStoreDelegate alloc] initWithPeer:this];
  42. [[SKPaymentQueue defaultQueue] addTransactionObserver:_delegate];
  43. }
  44. _products=products;
  45. id __strong *objs=new id[products.length()];
  46. for( int i=0;i<products.length();++i ){
  47. objs[i]=products[i]->identifier.ToNSString();
  48. }
  49. NSSet *set=[NSSet setWithObjects:objs count:products.length()];
  50. SKProductsRequest *request=[[SKProductsRequest alloc] initWithProductIdentifiers:set];
  51. request.delegate=_delegate;
  52. _running=true;
  53. _result=-1;
  54. [request start];
  55. return true;
  56. }
  57. bool BBIAPStore::BuyProductAsync( BBProduct *prod ){
  58. if( _running || !_products.length() || !prod || !prod->valid ) return false;
  59. if( ![SKPaymentQueue canMakePayments] ) return false;
  60. SKMutablePayment *payment=[SKMutablePayment paymentWithProduct:prod->product];
  61. _running=true;
  62. _result=-1;
  63. [[SKPaymentQueue defaultQueue] addPayment:payment];
  64. return true;
  65. }
  66. bool BBIAPStore::GetOwnedProductsAsync(){
  67. if( _running || !_products.length() ) return false;
  68. if( ![SKPaymentQueue canMakePayments] ) return false;
  69. _running=true;
  70. _result=-1;
  71. [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
  72. return true;
  73. }
  74. void BBIAPStore::CloseStore(){
  75. if( !_delegate ) return;
  76. [[SKPaymentQueue defaultQueue] removeTransactionObserver:_delegate];
  77. _delegate=0;
  78. }
  79. bool BBIAPStore::IsRunning(){
  80. return _running;
  81. }
  82. int BBIAPStore::GetResult(){
  83. return _result;
  84. }
  85. bool BBIAPStore::CanMakePayments(){
  86. return [SKPaymentQueue canMakePayments];
  87. }
  88. BBProduct *BBIAPStore::FindProduct( bbString id ){
  89. for( int i=0;i<_products.length();++i ){
  90. BBProduct *p=_products[i];
  91. if( p->identifier==id ) return p;
  92. }
  93. return 0;
  94. }
  95. void BBIAPStore::OnRequestProductDataResponse( SKProductsRequest *request,SKProductsResponse *response ){
  96. //Get product details
  97. for( SKProduct *p in response.products ){
  98. // printf( "product=%p\n",p );fflush( stdout );
  99. BBProduct *prod=FindProduct( p.productIdentifier );
  100. if( !prod ) continue;
  101. [_priceFormatter setLocale:p.priceLocale];
  102. prod->valid=true;
  103. prod->product=p; //[p retain];
  104. prod->title=bbString( p.localizedTitle );
  105. prod->identifier=bbString( p.productIdentifier );
  106. prod->description=bbString( p.localizedDescription );
  107. prod->price=bbString( [_priceFormatter stringFromNumber:p.price] );
  108. }
  109. _result=-1;
  110. for( int i=0;i<_products.length();++i ){
  111. if( !_products[i]->product ) continue;
  112. _result=0;
  113. break;
  114. }
  115. if( _result==-1 ){
  116. [[SKPaymentQueue defaultQueue] removeTransactionObserver:_delegate];
  117. _delegate=0;
  118. }
  119. _running=false;
  120. }
  121. void BBIAPStore::OnUpdatedTransactions( SKPaymentQueue *queue,NSArray *transactions ){
  122. _result=-1;
  123. for( SKPaymentTransaction *transaction in transactions ){
  124. if( transaction.transactionState==SKPaymentTransactionStatePurchased ){
  125. // printf( "IAP purchased\n" );fflush( stdout );
  126. _result=0;
  127. _running=false;
  128. }else if( transaction.transactionState==SKPaymentTransactionStateFailed ){
  129. // printf( "IAP failed %i\n",transaction.error.code );fflush( stdout );
  130. _result=(transaction.error.code==SKErrorPaymentCancelled) ? 1 : -1;
  131. _running=false;
  132. }else if( transaction.transactionState==SKPaymentTransactionStateRestored ){
  133. // printf( "IAP restored\n" );fflush( stdout );
  134. if( BBProduct *p=FindProduct( transaction.payment.productIdentifier ) ) p->owned=true;
  135. }else{
  136. // printf( "IAP ?????\n" );fflush( stdout );
  137. continue;
  138. }
  139. [queue finishTransaction:transaction];
  140. }
  141. }
  142. void BBIAPStore::OnRestoreTransactionsFinished( SKPaymentQueue *queue,NSError *error ){
  143. _result=error ? (error.code==SKErrorPaymentCancelled ? 1 : -1) : 0;
  144. _running=false;
  145. }
  146. void BBIAPStore::OnRequestFailed( SKRequest *request,NSError *error ){
  147. [[SKPaymentQueue defaultQueue] removeTransactionObserver:_delegate];
  148. _delegate=0;
  149. _running=false;
  150. }
  151. void BBIAPStore::gcMark(){
  152. bbGCMark( _products );
  153. }