iap_ios.mm 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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. _delegate=[[BBIAPStoreDelegate alloc] initWithPeer:this];
  34. [[SKPaymentQueue defaultQueue] addTransactionObserver:_delegate];
  35. _priceFormatter=[[NSNumberFormatter alloc] init];
  36. [_priceFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
  37. [_priceFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
  38. }
  39. bool BBIAPStore::OpenStoreAsync( bbArray<bbGCVar<BBProduct>> products ){
  40. if( _running || _products.length() ) return false;
  41. if( ![SKPaymentQueue canMakePayments] ) return false;
  42. _products=products;
  43. id __strong *objs=new id[products.length()];
  44. for( int i=0;i<products.length();++i ){
  45. objs[i]=products[i]->identifier.ToNSString();
  46. }
  47. NSSet *set=[NSSet setWithObjects:objs count:products.length()];
  48. SKProductsRequest *request=[[SKProductsRequest alloc] initWithProductIdentifiers:set];
  49. request.delegate=_delegate;
  50. _running=true;
  51. _result=-1;
  52. [request start];
  53. return true;
  54. }
  55. bool BBIAPStore::BuyProductAsync( BBProduct *prod ){
  56. if( _running || !_products.length() || !prod || !prod->valid ) return false;
  57. if( ![SKPaymentQueue canMakePayments] ) return false;
  58. SKMutablePayment *payment=[SKMutablePayment paymentWithProduct:prod->product];
  59. _running=true;
  60. _result=-1;
  61. [[SKPaymentQueue defaultQueue] addPayment:payment];
  62. return true;
  63. }
  64. bool BBIAPStore::GetOwnedProductsAsync(){
  65. if( _running || !_products.length() ) return false;
  66. if( ![SKPaymentQueue canMakePayments] ) return false;
  67. _running=true;
  68. _result=-1;
  69. [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
  70. return true;
  71. }
  72. bool BBIAPStore::IsRunning(){
  73. return _running;
  74. }
  75. int BBIAPStore::GetResult(){
  76. return _result;
  77. }
  78. BBProduct *BBIAPStore::FindProduct( bbString id ){
  79. for( int i=0;i<_products.length();++i ){
  80. BBProduct *p=_products[i];
  81. if( p->identifier==id ) return p;
  82. }
  83. return 0;
  84. }
  85. void BBIAPStore::OnRequestProductDataResponse( SKProductsRequest *request,SKProductsResponse *response ){
  86. //Get product details
  87. for( SKProduct *p in response.products ){
  88. printf( "product=%p\n",p );fflush( stdout );
  89. BBProduct *prod=FindProduct( p.productIdentifier );
  90. if( !prod ) continue;
  91. [_priceFormatter setLocale:p.priceLocale];
  92. prod->valid=true;
  93. prod->product=p; //[p retain];
  94. prod->title=bbString( p.localizedTitle );
  95. prod->identifier=bbString( p.productIdentifier );
  96. prod->description=bbString( p.localizedDescription );
  97. prod->price=bbString( [_priceFormatter stringFromNumber:p.price] );
  98. }
  99. _result=-1;
  100. for( int i=0;i<_products.length();++i ){
  101. if( !_products[i]->product ) continue;
  102. _result=0;
  103. break;
  104. }
  105. _running=false;
  106. }
  107. void BBIAPStore::OnUpdatedTransactions( SKPaymentQueue *queue,NSArray *transactions ){
  108. _result=-1;
  109. for( SKPaymentTransaction *transaction in transactions ){
  110. if( transaction.transactionState==SKPaymentTransactionStatePurchased ){
  111. _result=0;
  112. _running=false;
  113. }else if( transaction.transactionState==SKPaymentTransactionStateFailed ){
  114. _result=(transaction.error.code==SKErrorPaymentCancelled) ? 1 : -1;
  115. _running=false;
  116. }else if( transaction.transactionState==SKPaymentTransactionStateRestored ){
  117. if( BBProduct *p=FindProduct( transaction.payment.productIdentifier ) ) p->owned=true;
  118. }else{
  119. continue;
  120. }
  121. [queue finishTransaction:transaction];
  122. }
  123. }
  124. void BBIAPStore::OnRestoreTransactionsFinished( SKPaymentQueue *queue,NSError *error ){
  125. _result=error ? (error.code==SKErrorPaymentCancelled ? 1 : -1) : 0;
  126. _running=false;
  127. }
  128. void BBIAPStore::OnRequestFailed( SKRequest *request,NSError *error ){
  129. _running=false;
  130. }
  131. void BBIAPStore::gcMark(){
  132. bbGCMark( _products );
  133. }