火山鱼 發表於 2020-4-7 17:54:00

(转)iOS开发之内购-AppStore

<h2>前言</h2>
<p>本文会给大家详细介绍iOS内购,虽然之前网上也有内购的教程,但是还不够详细,我重新整理出一份教程,希望对大家有所帮助。</p>
<blockquote>
<p>基于Xcode7.1.1版本,模拟器iphone6,9.1系统。<br>部分地方直接摘自网络,省时省心省力。<br>多图预警!!!<br>转载请注明出处@yimouleng<br><span id="more-182"></span></p>

</blockquote>
<h2>一. 创建测试App</h2>
<h3>创建App-1</h3>
<p>首先你需要登录&nbsp;App的ItunesConnection,你会看到如下界面</p>
<p><img src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore1.png"></p>
<p>简单的介绍一下这几个选项</p>
<blockquote>
<ul>
<li>1.我的App主要用于管理自己的App应用,例如编辑资料,上架,下架等。</li>
<li>2.销售和趋势主要是来查看App在各个平台的下载量,收入等方面数据,里面有曲线图等图文结合的方式给我们参考。</li>
<li>3.付款和财务报告显示的是你的收入以及付款等相关信息。</li>
<li>4.iAd主要是跟广告有关,开发者可以登录到Workbench,通过iAd对应用的广告进行控制。</li>
<li>5.用户和职能用于生成相应账号,例如苹果沙河测试账号。</li>
<li>6.协议,税务和银行业务则是你银行相关账户的信息设置。</li>

</ul>

</blockquote>
<p>在这里我们选择第一个选项,我的App, 然后点击左上角的加号,新建一个用来测试用的App。</p>
<p><img class="alignnone lazyload" alt="" width="986" height="468" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore2.png"></p>
<p>我们会看到弹出的窗口</p>
<p><img class="alignnone lazyload" alt="" width="912" height="1002" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore6.png"></p>
<p>在这里有几个需要填写的地方,名称自己取,平台IOS,语言选择了简体中文,套装ID也就是你的<code>Bundle Identifier</code>,需要你在Certificates页面&nbsp;申请BundleID,在这里简单的给大家介绍一下。</p>
<h3>申请BundleID</h3>
<p>打开Certificates页面&nbsp;,在左侧选择 Identifiers,并点击加号,申请一个新的Identifiers。</p>
<p><img class="alignnone lazyload" alt="" width="1238" height="1140" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore3.png"></p>
<p>在这里Name可以随意填写,我填写的是TestAppStroeTestDemo,而用来使用的BundleID,我们在这里必须选择第一个选项唯一的,不用选择通配。在下面的选项中, 我们只需要勾选一个&nbsp;<code>Apple Pay</code>即可,其他选项看自己需求,我在这里只选择了它。<br><img class="alignnone lazyload" alt="" width="834" height="1040" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore4.png"></p>
<p>之后一路Done即可。</p>
<h3>创建App-2</h3>
<p>之后我们回到创建App,选择好自己刚创建的 BundleID ,填写SKU, SKU是你App的专用ID,我在这里随意填写,直接复制了App名。点击创建,我们的测试App则创建成功。</p>
<h2>二.添加内购</h2>
<p>App创建好之后,我们打开创建的App,在左上角选择功能,会看到左侧的App 内购买项目。我们点击右下角的加号,为App添加内购项目。</p>
<p><img class="alignnone lazyload" alt="" width="2490" height="958" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore7.png"></p>
<p>之后我们会看到类型的选项,如下图</p>
<p><img class="alignnone lazyload" alt="" width="996" height="851" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore8.png"></p>
<p>官方的注释写的很清楚了,只在这里简单的说下前两种</p>
<blockquote>
<p>消耗型项目 就像你玩游戏需要买金币,买钻石等,只要花钱就可以无限次的购买<br>非消耗型项目 就像你在App Store购买App,买了一次之后就不用再买第二次,你拥有永久使用权。</p>

</blockquote>
<p>在这里为了方便测试,我们选择第一种&nbsp;<code>消耗型项目</code>&nbsp;。来到内购项目填写页面,如下图。</p>
<p><img class="alignnone lazyload" alt="" width="892" height="494" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore9.png"></p>
<p>这里有几个选项,需要填写商品名称,产品ID以及价格等级,简单说明一下</p>
<blockquote>
<p>1.商品名称根据你的消费道具的实际意义来说明,比如“100颗宝石”,“100金币”等。<br>2.产品ID是比较重要的,由项目自定义,只要唯一即可,因为测试,我在这里随便填写的123,在实际应用中,一定要认真填写。<br>3.价格等级的话“查看价格表”中有对应的说明,可以对照着表中每个国家的货币价格与等级来选择</p>

</blockquote>
<p>接下来是语言选择,和上传快照如下图</p>
<p><img class="alignnone lazyload" alt="" width="945" height="644" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore10.png"></p>
<p>点击添加语言,填写名称和描述,这里我们依然选择简体中文,如下</p>
<p><img class="alignnone lazyload" alt="" width="721" height="356" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore11.png"></p>
<p>审核备注,根据实际情况填写,可以不填。而下面的屏幕快照,则是商品图片,以像素为单位,最低尺寸为321,390,尺寸需求如下图,上传即可。</p>
<p><img class="alignnone lazyload" alt="" width="938" height="218" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore12.png"></p>
<p>到这里为止, 我们的内购项目则添加完成。接下来则是测试阶段了。</p>
<h2>三.申请沙盒测试账号(用来测试购买项目)</h2>
<p>这个账号,是利用苹果的沙盒测试环境来模拟AppStore的购买流程,你肯定不会想要用真实RMB去购买测试吧?<br>首先我们回到iTunes Connect中,在这里我们选择<code>用户和职能</code>。</p>
<p><img class="alignnone lazyload" alt="" width="1249" height="478" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore13.png"></p>
<p>然后在上面的第三个选项沙箱技术测试员中点击加号,添加测试员。</p>
<p><img class="alignnone lazyload" alt="" width="664" height="171" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore14.png"></p>
<p>在信息填写页面只简单说两句。</p>
<blockquote>
<p>所有信息都可以随意填写,不用管是否真实。<br>App Store地区选择,一定要选对,它对应的是你创建的App的地区, 你App是中国的话, 在这里我们依然选择中国。<br>此账号只能用来测试,不要在正式的appstore上使用</p>

</blockquote>
<p>填写完毕,点击保存后,我们则生成一个测试账号,当然这个账号是可以随时删除和添加的。</p>
<p><img class="alignnone lazyload" alt="" width="617" height="161" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore15.png"></p>
<h2>四.核心代码</h2>
<p>之后终于到了我们撸代码的时候了,点开你的Xcode创建你的项目!</p>
<blockquote>
<p>首先我们需要在项目工程中加入“storekit.framework”,加入头文件#import &lt;StoreKit/StoreKit.h&gt;<br>在.h文件中加入“SKPaymentTransactionObserver,SKProductsRequestDelegate”监听机制<br>代码很简单,直接在.m文件在中填写,添加了二次验证,防止越狱手机等内购。如下,</p>

</blockquote>
<p>.m文件</p>
<pre class="line-numbers prism-highlightlanguage-objectivec" data-start="1"><code class="language-objectivec"><span class="token comment">//
<span class="token comment">//ViewController.m
<span class="token comment">//内购
<span class="token comment">//
<span class="token comment">//Created by Ely on 15/12/15.
<span class="token comment">//Copyright © 2015年 Ely. All rights reserved.
<span class="token comment">//

<span class="token macro property">#<span class="token directive keyword">import "ViewController.h"
<span class="token macro property">#<span class="token directive keyword">import &lt;StoreKit/StoreKit.h&gt;
<span class="token macro property">#<span class="token directive keyword">import "SVProgressHUD.h"

<span class="token keyword">@interface ViewController <span class="token punctuation">(<span class="token punctuation">)<span class="token operator">&lt;SKPaymentTransactionObserver<span class="token punctuation">,SKProductsRequestDelegate<span class="token operator">&gt;
<span class="token keyword">@property <span class="token punctuation">(nonatomic<span class="token punctuation">,strong<span class="token punctuation">) NSArray <span class="token operator">*profuctIdArr<span class="token punctuation">;
<span class="token keyword">@property <span class="token punctuation">(nonatomic<span class="token punctuation">,copy<span class="token punctuation">) NSString <span class="token operator">*currentProId<span class="token punctuation">;

<span class="token keyword">@end

<span class="token keyword">@implementation ViewController

<span class="token operator">- <span class="token punctuation">(<span class="token keyword">void<span class="token punctuation">)viewDidLoad <span class="token punctuation">{
    <span class="token punctuation">[<span class="token keyword">super viewDidLoad<span class="token punctuation">]<span class="token punctuation">;
    <span class="token comment">// Do any additional setup after loading the view, typically from a nib.

    <span class="token punctuation">[<span class="token keyword">self createPay<span class="token punctuation">]<span class="token punctuation">;
<span class="token punctuation">}


<span class="token operator">- <span class="token punctuation">(<span class="token keyword">void<span class="token punctuation">)createPay
<span class="token punctuation">{
    <span class="token punctuation">[<span class="token punctuation"> addTransactionObserver<span class="token punctuation">:<span class="token keyword">self<span class="token punctuation">]<span class="token punctuation">;
    <span class="token keyword">self<span class="token punctuation">.profuctIdArr <span class="token operator">= <span class="token operator">@<span class="token punctuation">[<span class="token string">@"123"<span class="token punctuation">]<span class="token punctuation">;

    UIButton <span class="token operator">*button <span class="token operator">= <span class="token punctuation"><span class="token punctuation">;
    button<span class="token punctuation">.frame <span class="token operator">= <span class="token function">CGRectMake<span class="token punctuation">(<span class="token number">100<span class="token punctuation">, <span class="token number">100<span class="token punctuation">, <span class="token number">100<span class="token punctuation">, <span class="token number">100<span class="token punctuation">)<span class="token punctuation">;
    button<span class="token punctuation">.backgroundColor <span class="token operator">= <span class="token punctuation"><span class="token punctuation">;
    <span class="token punctuation"><span class="token punctuation">;
    <span class="token punctuation"><span class="token punctuation">;
    button<span class="token punctuation">.tag <span class="token operator">= <span class="token number">100<span class="token punctuation">;
    <span class="token punctuation">[<span class="token keyword">self<span class="token punctuation">.view addSubview<span class="token punctuation">:button<span class="token punctuation">]<span class="token punctuation">;
<span class="token punctuation">}

<span class="token operator">- <span class="token punctuation">(<span class="token keyword">void<span class="token punctuation">)btnClick<span class="token punctuation">:<span class="token punctuation">(UIButton <span class="token operator">*<span class="token punctuation">)button
<span class="token punctuation">{
    NSString <span class="token operator">*product <span class="token operator">= <span class="token keyword">self<span class="token punctuation">.profuctIdArr<span class="token punctuation"><span class="token punctuation">;
    _currentProId <span class="token operator">= product<span class="token punctuation">;
    <span class="token keyword">if<span class="token punctuation">(<span class="token punctuation"><span class="token punctuation">)<span class="token punctuation">{
      <span class="token punctuation">[<span class="token keyword">self requestProductData<span class="token punctuation">:product<span class="token punctuation">]<span class="token punctuation">;
    <span class="token punctuation">}<span class="token keyword">else<span class="token punctuation">{
      <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"不允许程序内付费"<span class="token punctuation">)<span class="token punctuation">;
    <span class="token punctuation">}
<span class="token punctuation">}

<span class="token comment">//请求商品
<span class="token operator">- <span class="token punctuation">(<span class="token keyword">void<span class="token punctuation">)requestProductData<span class="token punctuation">:<span class="token punctuation">(NSString <span class="token operator">*<span class="token punctuation">)type<span class="token punctuation">{
    <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"-------------请求对应的产品信息----------------"<span class="token punctuation">)<span class="token punctuation">;

    <span class="token punctuation"><span class="token punctuation">;

    NSArray <span class="token operator">*product <span class="token operator">= <span class="token punctuation">[<span class="token punctuation"> initWithObjects<span class="token punctuation">:type<span class="token punctuation">,nil<span class="token punctuation">]<span class="token punctuation">;

    NSSet <span class="token operator">*nsset <span class="token operator">= <span class="token punctuation"><span class="token punctuation">;
    SKProductsRequest <span class="token operator">*request <span class="token operator">= <span class="token punctuation">[<span class="token punctuation"> initWithProductIdentifiers<span class="token punctuation">:nsset<span class="token punctuation">]<span class="token punctuation">;
    request<span class="token punctuation">.delegate <span class="token operator">= <span class="token keyword">self<span class="token punctuation">;
    <span class="token punctuation"><span class="token punctuation">;

<span class="token punctuation">}

<span class="token comment">//收到产品返回信息
<span class="token operator">- <span class="token punctuation">(<span class="token keyword">void<span class="token punctuation">)productsRequest<span class="token punctuation">:<span class="token punctuation">(SKProductsRequest <span class="token operator">*<span class="token punctuation">)request didReceiveResponse<span class="token punctuation">:<span class="token punctuation">(SKProductsResponse <span class="token operator">*<span class="token punctuation">)response<span class="token punctuation">{

    <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"--------------收到产品反馈消息---------------------"<span class="token punctuation">)<span class="token punctuation">;
    NSArray <span class="token operator">*product <span class="token operator">= response<span class="token punctuation">.products<span class="token punctuation">;
    <span class="token keyword">if<span class="token punctuation">(<span class="token punctuation"> <span class="token operator">== <span class="token number">0<span class="token punctuation">)<span class="token punctuation">{
      <span class="token punctuation"><span class="token punctuation">;
      <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"--------------没有商品------------------"<span class="token punctuation">)<span class="token punctuation">;
      <span class="token keyword">return<span class="token punctuation">;
    <span class="token punctuation">}

    <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"productID:%@"<span class="token punctuation">, response<span class="token punctuation">.invalidProductIdentifiers<span class="token punctuation">)<span class="token punctuation">;
    <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"产品付费数量:%lu"<span class="token punctuation">,<span class="token punctuation">(<span class="token keyword">unsigned <span class="token keyword">long<span class="token punctuation">)<span class="token punctuation"><span class="token punctuation">)<span class="token punctuation">;

    SKProduct <span class="token operator">*p <span class="token operator">= nil<span class="token punctuation">;
    <span class="token keyword">for <span class="token punctuation">(SKProduct <span class="token operator">*pro <span class="token keyword">in product<span class="token punctuation">) <span class="token punctuation">{
      <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"%@"<span class="token punctuation">, <span class="token punctuation"><span class="token punctuation">)<span class="token punctuation">;
      <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"%@"<span class="token punctuation">, <span class="token punctuation"><span class="token punctuation">)<span class="token punctuation">;
      <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"%@"<span class="token punctuation">, <span class="token punctuation"><span class="token punctuation">)<span class="token punctuation">;
      <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"%@"<span class="token punctuation">, <span class="token punctuation"><span class="token punctuation">)<span class="token punctuation">;
      <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"%@"<span class="token punctuation">, <span class="token punctuation"><span class="token punctuation">)<span class="token punctuation">;

      <span class="token keyword">if<span class="token punctuation">(<span class="token punctuation"><span class="token punctuation">)<span class="token punctuation">{
            p <span class="token operator">= pro<span class="token punctuation">;
      <span class="token punctuation">}
    <span class="token punctuation">}

    SKPayment <span class="token operator">*payment <span class="token operator">= <span class="token punctuation"><span class="token punctuation">;

    <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"发送购买请求"<span class="token punctuation">)<span class="token punctuation">;
    <span class="token punctuation">[<span class="token punctuation"> addPayment<span class="token punctuation">:payment<span class="token punctuation">]<span class="token punctuation">;
<span class="token punctuation">}

<span class="token comment">//请求失败
<span class="token operator">- <span class="token punctuation">(<span class="token keyword">void<span class="token punctuation">)request<span class="token punctuation">:<span class="token punctuation">(SKRequest <span class="token operator">*<span class="token punctuation">)request didFailWithError<span class="token punctuation">:<span class="token punctuation">(NSError <span class="token operator">*<span class="token punctuation">)error<span class="token punctuation">{
    <span class="token punctuation"><span class="token punctuation">;
    <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"------------------错误-----------------:%@"<span class="token punctuation">, error<span class="token punctuation">)<span class="token punctuation">;
<span class="token punctuation">}

<span class="token operator">- <span class="token punctuation">(<span class="token keyword">void<span class="token punctuation">)requestDidFinish<span class="token punctuation">:<span class="token punctuation">(SKRequest <span class="token operator">*<span class="token punctuation">)request<span class="token punctuation">{
    <span class="token punctuation"><span class="token punctuation">;
    <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"------------反馈信息结束-----------------"<span class="token punctuation">)<span class="token punctuation">;
<span class="token punctuation">}
<span class="token comment">//沙盒测试环境验证
<span class="token macro property">#<span class="token directive keyword">define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"
<span class="token comment">//正式环境验证
<span class="token macro property">#<span class="token directive keyword">define AppStore @"https://buy.itunes.apple.com/verifyReceipt"
<span class="token comment">/**
*验证购买,避免越狱软件模拟苹果请求达到非法购买问题
*
*/
<span class="token operator">-<span class="token punctuation">(<span class="token keyword">void<span class="token punctuation">)verifyPurchaseWithPaymentTransaction<span class="token punctuation">{
    <span class="token comment">//从沙盒中获取交易凭证并且拼接成请求体数据
    NSURL <span class="token operator">*receiptUrl<span class="token operator">=<span class="token punctuation">[<span class="token punctuation"> appStoreReceiptURL<span class="token punctuation">]<span class="token punctuation">;
    NSData <span class="token operator">*receiptData<span class="token operator">=<span class="token punctuation"><span class="token punctuation">;

    NSString <span class="token operator">*receiptString<span class="token operator">=<span class="token punctuation"><span class="token punctuation">;<span class="token comment">//转化为base64字符串

    NSString <span class="token operator">*bodyString <span class="token operator">= <span class="token punctuation"><span class="token punctuation">;<span class="token comment">//拼接请求数据
    NSData <span class="token operator">*bodyData <span class="token operator">= <span class="token punctuation"><span class="token punctuation">;


    <span class="token comment">//创建请求到苹果官方进行购买验证
    NSURL <span class="token operator">*url<span class="token operator">=<span class="token punctuation"><span class="token punctuation">;
    NSMutableURLRequest <span class="token operator">*requestM<span class="token operator">=<span class="token punctuation"><span class="token punctuation">;
    requestM<span class="token punctuation">.HTTPBody<span class="token operator">=bodyData<span class="token punctuation">;
    requestM<span class="token punctuation">.HTTPMethod<span class="token operator">=<span class="token string">@"POST"<span class="token punctuation">;
    <span class="token comment">//创建连接并发送同步请求
    NSError <span class="token operator">*error<span class="token operator">=nil<span class="token punctuation">;
    NSData <span class="token operator">*responseData<span class="token operator">=<span class="token punctuation"><span class="token punctuation">;
    <span class="token keyword">if <span class="token punctuation">(error<span class="token punctuation">) <span class="token punctuation">{
      <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"验证购买过程中发生错误,错误信息:%@"<span class="token punctuation">,error<span class="token punctuation">.localizedDescription<span class="token punctuation">)<span class="token punctuation">;
      <span class="token keyword">return<span class="token punctuation">;
    <span class="token punctuation">}
    NSDictionary <span class="token operator">*dic<span class="token operator">=<span class="token punctuation"><span class="token punctuation">;
    <span class="token function">NSLog<span class="token punctuation">(<span class="token string">@"%@"<span class="token punctuation">,dic<span class="token punctuation">)</span><span class="token punctuation">;
    </span><span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation"> intValue</span><span class="token punctuation">]</span><span class="token operator">==</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">{
      </span><span class="token function">NSLog</span><span class="token punctuation">(</span><span class="token string">@"购买成功!"</span><span class="token punctuation">)</span><span class="token punctuation">;
      NSDictionary </span><span class="token operator">*dicReceipt</span><span class="token operator">= dic</span><span class="token punctuation">[</span><span class="token string">@"receipt"</span><span class="token punctuation">]</span><span class="token punctuation">;
      NSDictionary </span><span class="token operator">*dicInApp</span><span class="token operator">=</span><span class="token punctuation"> firstObject</span><span class="token punctuation">]</span><span class="token punctuation">;
      NSString </span><span class="token operator">*productIdentifier</span><span class="token operator">= dicInApp</span><span class="token punctuation">[</span><span class="token string">@"product_id"</span><span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">//读取产品标识
      </span><span class="token comment">//如果是消耗品则记录购买数量,非消耗品则记录是否购买过
      NSUserDefaults </span><span class="token operator">*defaults</span><span class="token operator">=</span><span class="token punctuation"></span><span class="token punctuation">;
      </span><span class="token keyword">if </span><span class="token punctuation">(</span><span class="token punctuation"></span><span class="token punctuation">) </span><span class="token punctuation">{
            </span><span class="token keyword">int purchasedCount</span><span class="token operator">=</span><span class="token punctuation"></span><span class="token punctuation">;</span><span class="token comment">//已购买数量
            </span><span class="token punctuation">[</span><span class="token punctuation"> setInteger</span><span class="token punctuation">:</span><span class="token punctuation">(purchasedCount</span><span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">) forKey</span><span class="token punctuation">:productIdentifier</span><span class="token punctuation">]</span><span class="token punctuation">;
      </span><span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{
            </span><span class="token punctuation"></span><span class="token punctuation">;
      </span><span class="token punctuation">}
      </span><span class="token comment">//在此处对购买记录进行存储,可以存储到开发商的服务器端
    </span><span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{
      </span><span class="token function">NSLog</span><span class="token punctuation">(</span><span class="token string">@"购买失败,未通过验证!"</span><span class="token punctuation">)</span><span class="token punctuation">;
    </span><span class="token punctuation">}
</span><span class="token punctuation">}
</span><span class="token comment">//监听购买结果
</span><span class="token operator">- </span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)paymentQueue</span><span class="token punctuation">:</span><span class="token punctuation">(SKPaymentQueue </span><span class="token operator">*</span><span class="token punctuation">)queue updatedTransactions</span><span class="token punctuation">:</span><span class="token punctuation">(NSArray </span><span class="token operator">*</span><span class="token punctuation">)transaction</span><span class="token punctuation">{


    </span><span class="token keyword">for</span><span class="token punctuation">(SKPaymentTransaction </span><span class="token operator">*tran </span><span class="token keyword">in transaction</span><span class="token punctuation">)</span><span class="token punctuation">{



      </span><span class="token keyword">switch </span><span class="token punctuation">(tran</span><span class="token punctuation">.transactionState</span><span class="token punctuation">) </span><span class="token punctuation">{
            </span><span class="token keyword">case SKPaymentTransactionStatePurchased</span><span class="token punctuation">:</span><span class="token punctuation">{
                </span><span class="token function">NSLog</span><span class="token punctuation">(</span><span class="token string">@"交易完成"</span><span class="token punctuation">)</span><span class="token punctuation">;
                </span><span class="token punctuation">[</span><span class="token keyword">self verifyPurchaseWithPaymentTransaction</span><span class="token punctuation">]</span><span class="token punctuation">;
                </span><span class="token punctuation">[</span><span class="token punctuation"> finishTransaction</span><span class="token punctuation">:tran</span><span class="token punctuation">]</span><span class="token punctuation">;

            </span><span class="token punctuation">}




                </span><span class="token keyword">break</span><span class="token punctuation">;
            </span><span class="token keyword">case SKPaymentTransactionStatePurchasing</span><span class="token punctuation">:
                </span><span class="token function">NSLog</span><span class="token punctuation">(</span><span class="token string">@"商品添加进列表"</span><span class="token punctuation">)</span><span class="token punctuation">;

                </span><span class="token keyword">break</span><span class="token punctuation">;
            </span><span class="token keyword">case SKPaymentTransactionStateRestored</span><span class="token punctuation">:</span><span class="token punctuation">{
                </span><span class="token function">NSLog</span><span class="token punctuation">(</span><span class="token string">@"已经购买过商品"</span><span class="token punctuation">)</span><span class="token punctuation">;

                </span><span class="token punctuation">[</span><span class="token punctuation"> finishTransaction</span><span class="token punctuation">:tran</span><span class="token punctuation">]</span><span class="token punctuation">;
            </span><span class="token punctuation">}
                </span><span class="token keyword">break</span><span class="token punctuation">;
            </span><span class="token keyword">case SKPaymentTransactionStateFailed</span><span class="token punctuation">:</span><span class="token punctuation">{
                </span><span class="token function">NSLog</span><span class="token punctuation">(</span><span class="token string">@"交易失败"</span><span class="token punctuation">)</span><span class="token punctuation">;
                </span><span class="token punctuation">[</span><span class="token punctuation"> finishTransaction</span><span class="token punctuation">:tran</span><span class="token punctuation">]</span><span class="token punctuation">;
                </span><span class="token punctuation"></span><span class="token punctuation">;
            </span><span class="token punctuation">}
                </span><span class="token keyword">break</span><span class="token punctuation">;
            </span><span class="token keyword">default</span><span class="token punctuation">:
                </span><span class="token keyword">break</span><span class="token punctuation">;
      </span><span class="token punctuation">}
    </span><span class="token punctuation">}
</span><span class="token punctuation">}

</span><span class="token comment">//交易结束
</span><span class="token operator">- </span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span><span id="0KSFindDIV" class="KSFIND_CLASS_SELECT">completeTransaction</span><span class="token punctuation">:</span><span class="token punctuation">(SKPaymentTransaction </span><span class="token operator">*</span><span class="token punctuation">)transaction</span><span class="token punctuation">{
    </span><span class="token function">NSLog</span><span class="token punctuation">(</span><span class="token string">@"交易结束"</span><span class="token punctuation">)</span><span class="token punctuation">;

    </span><span class="token punctuation">[</span><span class="token punctuation"> finishTransaction</span><span class="token punctuation">:transaction</span><span class="token punctuation">]</span><span class="token punctuation">;
</span><span class="token punctuation">}


</span><span class="token operator">- </span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)dealloc</span><span class="token punctuation">{
    </span><span class="token punctuation">[</span><span class="token punctuation"> removeTransactionObserver</span><span class="token punctuation">:</span><span class="token keyword">self</span><span class="token punctuation">]</span><span class="token punctuation">;
</span><span class="token punctuation">}

</span><span class="token operator">- </span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)didReceiveMemoryWarning </span><span class="token punctuation">{
    </span><span class="token punctuation">[</span><span class="token keyword">super didReceiveMemoryWarning</span><span class="token punctuation">]</span><span class="token punctuation">;
    </span><span class="token comment">// Dispose of any resources that can be recreated.
</span><span class="token punctuation">}

</span><span class="token keyword">@end



</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
<p>在这里需要注意几点,</p>
<blockquote>
<ul>
<li>代码中的<code>self.profuctIdArr</code>所填写的是你的购买项目的的ID,我这里是当时填写的ID 123。</li>
<li>在监听购买结果后,一定要调用<code>[ finishTransaction:tran];</code>来允许你从支付队列中移除交易。</li>
<li>沙盒环境测试appStore内购流程的时候,请使用没越狱的设备。</li>
<li>请务必使用真机来测试,一切以真机为准。</li>
<li>项目的Bundle identifier需要与您申请AppID时填写的bundleID一致,不然会无法请求到商品信息。</li>
<li>真机测试的时候,一定要退出原来的账号,才能用沙盒测试账号</li>
<li>二次验证,请注意区分宏, 测试用沙盒验证</li>
</ul>
</blockquote>
<p>在这里附上截图:</p>
<p>点击购买按钮</p>
<p><img class="alignnone lazyload" alt="" width="541" height="960" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore19.png"></p>
<p>选择使用现有Apple ID,填写测试账号</p>
<p><img class="alignnone lazyload" alt="" width="541" height="960" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore20.png"></p>
<p>确认是否购买</p>
<p><img class="alignnone lazyload" alt="" width="541" height="960" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore18.png"></p>
<p>购买成功</p>
<p><img class="alignnone lazyload" alt="" width="541" height="960" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore17.png"></p>
<p>最后师打印输出日志</p>
<p><img alt="" data-action="zoom" data-src="https://pic.yimouleng.com/wp-content/MusicPictures/appStore16.png"></p>
<p>到这里,我们的内购则全部完成了。<br>如还有不懂得请留言,或者 加群67784110联系我。<br>本文所写的Demo可在我的GITHUB下载,点此链接。<br>内购时遇到的问题和解决办法,我放在下一篇文章中,点此内购时遇到的问题和解决办法。</p>
<p>&nbsp;</p>
<p>原文地址:https://yimouleng.com/2015/12/17/ios-AppStore/</p><br><br>
来源:https://www.cnblogs.com/wodehao0808/p/12654855.html
頁: [1]
查看完整版本: (转)iOS开发之内购-AppStore