title: ios-iap应用内购接入
categories: Ios
tags: [ios, iap, 内购, 苹果支付]
date: 2021-03-26 16:51:37
comments: false
mathjax: true
toc: true

ios-iap应用内购接入


前篇

  • 官方

    • App 内购买项目信息 - https://help.apple.com/app-store-connect/#/dev84b80958f
  • 接入Apple Pay流程 - https://juejin.cn/post/6844904001897512967
  • iOS内购(IAP)模块总结 - https://www.jianshu.com/p/bf7e42a3c73b
  • iOS的应用内支付In-app purchase的开发 - http://blog.hudongdong.com/ios/868.html
  • 2019最新iOS内购流程基本配置篇 - https://www.jianshu.com/p/94fa6793b197
  • apple苹果IOS内购申请教程协议、税务和银行业务配置

前置条件

  1. 协议是 active 状态, https://appstoreconnect.apple.com/agreements/#/

  2. 产品 id 是 非 元数据丢失 状态


流程

  1. 先创建个沙盒测试人员, 测试时不会真实扣钱. https://appstoreconnect.apple.com/access/testers

  2. 内购代码

    #import "IapHelper.h"
    #import "NetTool.h"
    #import "NSString+MyExt.h"#import <Foundation/Foundation.h>
    #import <StoreKit/StoreKit.h>
    #import <YYModel/YYModel.h>@interface IapHelper()<SKProductsRequestDelegate, SKPaymentTransactionObserver>
    @property (strong, nonatomic) CodeMsgFn _Nullable cb;
    @end@implementation IapHelperstatic IapHelper *_sharedIns = nil;
    +(instancetype) shareInstance {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{_sharedIns = [[self alloc] init] ;[[SKPaymentQueue defaultQueue] addTransactionObserver:_sharedIns];}) ;return _sharedIns ;
    }// 内扣接口
    - (void)getById:(NSString *)prodId cb:(CodeMsgFn)cb {if (![SKPaymentQueue canMakePayments]) {cb(ECodeSupportError, @"--- cant pay");return;}self.cb = cb;NSSet *set = [NSSet setWithObjects:prodId, nil];SKProductsRequest * request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];request.delegate = self;[request start];
    }// 客户端校验 receipt, 测试使用
    -(void)verify:(NSString*)url cb:(CodeMsgFn)cb {NSURL *recepitURL = [[NSBundle mainBundle] appStoreReceiptURL];NSData *receipt = [NSData dataWithContentsOfURL:recepitURL];NSDictionary *requestContents = @{@"receipt-data": [receipt base64EncodedStringWithOptions:0]};[NetTool httpPostAsync:url json:[requestContents yy_modelToJSONString] callback:^(CHttpJsonRsp * _Nonnull rsp) {cb(ECodeOk, [rsp yy_modelToJSONString]);}];
    }-(void)doCallback:(ECode)code msg:(NSString*)msg{if (self.cb) {self.cb(code, msg);self.cb = nil;}
    }// ------------------------------- 实现 SKProductsRequestDelegate 的接口
    - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {if (response.products.count == 0) {[self doCallback:ECodeTaskError msg:@"--- products count is 0"];return;}SKProduct* product = response.products[0];SKMutablePayment *payMent = [SKMutablePayment paymentWithProduct:product];payMent.quantity = 1;payMent.applicationUsername = @"orderId_001"; // 透传参数[[SKPaymentQueue defaultQueue] addPayment:payMent];
    }// ------------------------------- 实现 SKPaymentTransactionObserver 的接口
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {if (transactions.count == 0) {[self doCallback:ECodeLoginError msg:@"--- transactions count is 0"];return;}SKPaymentTransaction* transaction = transactions[0];switch (transaction.transactionState) {case SKPaymentTransactionStatePurchased:[[SKPaymentQueue defaultQueue] finishTransaction:transaction];[self doCallback:ECodeOk msg:@"--- pay success"];break;case SKPaymentTransactionStateFailed:[[SKPaymentQueue defaultQueue] finishTransaction:transaction];[self doCallback:ECodeCancel msg:@"--- SKPaymentTransactionStateFailed"];break;default:break;}
    }@end
    

验证 receipt

  • 参考: https://developer.apple.com/cn/documentation/storekit/in-app_purchase/validating_receipts_with_the_app_store/
  • 生产环境 url: https://buy.itunes.apple.com/verifyReceipt
  • 沙盒环境 url: https://sandbox.itunes.apple.com/verifyReceipt

验证流程: 先使用生产环境 url 去验证, 如果返回的 status 为 0, 表示是生成环境产生的正式购买; 如果返回的 status 为 21007, 表示是 测试人员产生的测试购买, 弹窗会显示环境是 sandbox.

  • 返回值

    {"receipt":{"receipt_type":"ProductionSandbox","adam_id":0,"app_item_id":0,"bundle_id":"aaa.bbb.com","application_version":"1","download_id":0,"version_external_identifier":0,"receipt_creation_date":"2021-03-29 09:46:49 Etc/GMT","receipt_creation_date_ms":"1617011209000","receipt_creation_date_pst":"2021-03-29 02:46:49 America/Los_Angeles","request_date":"2021-03-29 09:46:54 Etc/GMT","request_date_ms":"1617011214550","request_date_pst":"2021-03-29 02:46:54 America/Los_Angeles","original_purchase_date":"2013-08-01 07:00:00 Etc/GMT","original_purchase_date_ms":"1375340400000","original_purchase_date_pst":"2013-08-01 00:00:00 America/Los_Angeles","original_application_version":"1.0","in_app":[{"quantity":"1","product_id":"chips90","transaction_id":"1000000123123123","original_transaction_id":"1000000123123123","purchase_date":"2021-03-29 09:46:48 Etc/GMT","purchase_date_ms":"1617011208000","purchase_date_pst":"2021-03-29 02:46:48 America/Los_Angeles","original_purchase_date":"2021-03-29 09:46:48 Etc/GMT","original_purchase_date_ms":"1617011208000","original_purchase_date_pst":"2021-03-29 02:46:48 America/Los_Angeles","is_trial_period":"false"}]},"environment":"Sandbox","status":0 // 0 就是成功的标记
    }
    

踩坑

产品状态 元数据丢失

需要填写 审核信息, 包裹 截图 和 备注, 状态就会修改为 准备提交


拉取 产品 id 为空

可以以下几个原因

  1. 产品状态是 元数据丢失, 不是 准备提交

  2. 付费 app 协议没有同意, 需要同意后才行 (需要账户持有人才能同意, 协作伙伴不行), 状态是 有效 状态才行.

    https://appstoreconnect.apple.com/agreements/#/


付费 app 协议 地址错误

付费 app 协议 同意前可能遇到 地址错误要修正, 报错: The address entered appears to be invalid.

报这样的错只要提交三次就行了, 这是什么鬼操作.

第一填写比如: (第一行加个 # 号, 第三行不用填)

Address
# FLAT 501,MAPPLE CELESTIA,PLOT 49,
JAY ABHERI ENCLAVE,GACHIBOWLI,HYDERABAD,

参考: https://stackoverflow.com/questions/43922778/the-address-entered-appears-to-be-invalid-please-correct-your-address-and-resu


ios-iap应用内购接入相关推荐

  1. iOS IAP应用内购详细步骤和问题总结指南

    最近公司在做APP内购会员功能 遇到了很多问题 总结记录一下 首先一定要区分Apple pay 和IAP内购的区别 可以先去看一下官方文档地址 有每个步骤的详细解释 本篇文章分为:1. 内购支付流程: ...

  2. iOS:苹果内购实践

    iOS 苹果的内购 一.介绍 苹果规定,凡是虚拟的物品(例如:QQ音乐的乐币)进行交易时,都必须走苹果的内购通道,苹果要收取大约30%的抽成,所以不允许接入第三方的支付方式(微信.支付宝等),当然开发 ...

  3. Amazon App Tester工具的安装和配置Amazon内购接入流程以及测试

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u013007305/article/d ...

  4. android--GooglePay 谷歌支付内购接入(2)

    android--GooglePay 谷歌支付内购接入(1) 一.支付返回CODE(BillingResponseCode) // * int SERVICE_TIMEOUT = -3;//服务超时 ...

  5. 关于iOS订阅型内购开发

    ####由于公司项目里面有一个类似购买一个时期的产品,原本使用消耗式内购来做,但是被苹果审核拒绝了,苹果建议(要求)使用订阅式内购来做这个,于是就来研究一下 #####1.第一步添加内购产品 首先还是 ...

  6. iOS开发 IAP苹果内购

    为什么80%的码农都做不了架构师?>>>    1.概念介绍 <1>苹果内购: App内购买是指在苹果的 App Store 中购买应用程序的方式. 在玩一些游戏类应用软 ...

  7. iOS开发支付 — 内购(IAP)

    为什么要使用内购? 如果你购买的商品,是在本App中使用和消耗的,就一定要用内购,否则会被拒绝上线,例如:游戏币.在线书籍.直播中用来打赏用的金币.app中使用的道具等.如果是直接购买商城之类的快递包 ...

  8. 【iOS】苹果内购调研

    参考文章 官方文档 iOS开发内购全套图文教程 App Store上架指导 苹果不允许 iOS 应用内置购买(IAP)使用第三方支付方式,那么跨平台的电子书阅读器怎么解决这个问题? 应用内购(In-A ...

  9. 1、ios开发之 内购

    大家都知道做iOS开发本身的收入有三种来源:出售应用.内购和广告.国内用户通常很少直接购买应用,因此对于开发者而言(特别是个人开发者),内购和广告收入就成了主要的收入来源.内购营销模式,通常软件本身是 ...

最新文章

  1. 1200亿次日均位置服务响应、20亿公里日均轨迹里程,百度地图发布新一代人工智能地图生态全景
  2. html扩展名用于保存清单文件,HTML5 manifest ApplicationCache
  3. Github之深入解析Ruby Gems缓存
  4. Python正则表达式尽可能小的匹配(遇到第一个结束字符串就停止匹配)
  5. canvas全局合成画月牙_GIF动态图,视频?都能用Python转换成字符画图像
  6. 如何创建 SVN 服务器,并搭建自己的 SVN 仓库
  7. 数据结构学习一:概述
  8. hdu 2222 Keywords Search AC自动机——多串匹配
  9. python server酱_Python使用微信收取通知
  10. kafka 生产和消费信息入门
  11. 关于vs2015每次打开都要配置opencv问题
  12. 2015年蓝桥杯A组C/C++ 第三题奇妙的数字
  13. Ubuntu安装SSTP
  14. linux卸载rpm包的命令,Linux RPM包安装、卸载和升级(rpm命令)
  15. 一次网络丢包问题排查的经历
  16. SwiftUI Swift 内功之如何在 Swift 中进行自动三角函数计算
  17. 洛谷题解P1428 小鱼比可爱
  18. 【四二学堂】标准GPS坐标,转换成百度坐标
  19. Matlab 科研绘图汇总
  20. oracle04052,案例学习Oracle错误:ORA-04052

热门文章

  1. python 安装gensim
  2. 老家见闻--一个程序员的成长史(8)
  3. go或者php编程语言,go语言开发工具有哪些
  4. 【影像组学】用3Dslicer或Python提取影像组学特征
  5. Laravel Model数据操作
  6. catboost机器学习
  7. 先睹为快!“全民吃鸡贺岁杯”总决赛现场探秘
  8. [附源码]Python计算机毕业设计仿咸鱼二手物品交易系统
  9. 使用iperf 测速
  10. 程序员为何要学会摸鱼?