//内购Demo,看代码说话吧
class IAPTestViewController: UIViewController ,SKProductsRequestDelegate, SKPaymentTransactionObserver{ let VERIFY_RECEIPT_URL = "https://buy.itunes.apple.com/verifyReceipt"
let ITMS_SANDBOX_VERIFY_RECEIPT_URL = "https://sandbox.itunes.apple.com/verifyReceipt" var productDict:NSMutableDictionary! override func viewDidLoad() {
super.viewDidLoad()
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
requestProducts()//请求产品列表资料 }
deinit{
SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
} override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
} // 点击购买产品后触发的
func onSelectRechargePackages(productId: String){
//先判断是否支持内购
if(SKPaymentQueue.canMakePayments()){
buyProduct(productDict[productId] as! SKProduct)
}
else{
println("============不支持内购功能")
} }
//询问苹果的服务器能够销售哪些商品
func requestProducts(){
var set = NSSet(array: ["你的产品id1","产品id2"。。。。更多])
let request = SKProductsRequest(productIdentifiers: set as Set<NSObject>)
request.delegate = self;
request.start()
} // 以上查询的回调函数
func productsRequest(request: SKProductsRequest!, didReceiveResponse response: SKProductsResponse!) {
if (productDict == nil) {
productDict = NSMutableDictionary(capacity: response.products.count)
} for product in response.products as! [SKProduct] {
// 激活了对应的销售操作按钮,相当于商店的商品上架允许销售
println("=======Product id=======\(product.productIdentifier)")
println("===产品标题 ==========\(product.localizedTitle)")
println("====产品描述信息==========\(product.localizedDescription)")
println("=====价格: =========\(product.price)") // 填充商品字典
productDict.setObject(product, forKey: product.productIdentifier) }
}
// 购买对应的产品
func buyProduct(product: SKProduct){ var payment = SKPayment(product: product)
SKPaymentQueue.defaultQueue().addPayment(payment)
}
func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!){
// 调试
for transaction in transactions {
// 如果小票状态是购买完成
if (SKPaymentTransactionState.Purchased == transaction.transactionState) {
// 更新界面或者数据,把用户购买得商品交给用户
println("支付成了==================")
// 验证购买凭据
self.verifyPruchase() // 将交易从交易队列中删除
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction) }
else if(SKPaymentTransactionState.Failed == transaction.transactionState){
println("支付失败==================")
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
}
else if (SKPaymentTransactionState.Restored == transaction.transactionState) {//恢复购买
// 更新界面或者数据,把用户购买得商品交给用户
// ... // 将交易从交易队列中删除
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
} } }
func verifyPruchase(){
// 验证凭据,获取到苹果返回的交易凭据
// appStoreReceiptURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址
let receiptURL = NSBundle.mainBundle().appStoreReceiptURL
// 从沙盒中获取到购买凭据
let receiptData = NSData(contentsOfURL: receiptURL!)
// 发送网络POST请求,对购买凭据进行验证
let url = NSURL(string: ITMS_SANDBOX_VERIFY_RECEIPT_URL)
// 国内访问苹果服务器比较慢,timeoutInterval需要长一点
let request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy, timeoutInterval: 10.0)
request.HTTPMethod = "POST"
// 在网络中传输数据,大多情况下是传输的字符串而不是二进制数据
// 传输的是BASE64编码的字符串
/**
BASE64 常用的编码方案,通常用于数据传输,以及加密算法的基础算法,传输过程中能够保证数据传输的稳定性
BASE64是可以编码和解码的
*/
let encodeStr = receiptData?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithLineFeed) let payload = NSString(string: "{\"receipt-data\" : \"" + encodeStr! + "\"}")
println(payload)
let payloadData = payload.dataUsingEncoding(NSUTF8StringEncoding) request.HTTPBody = payloadData; // 提交验证请求,并获得官方的验证JSON结果
let result = NSURLConnection.sendSynchronousRequest(request, returningResponse: nil, error: nil) // 官方验证结果为空
if (result == nil) {
//验证失败
println("验证失败")
return
}
var dict: AnyObject? = NSJSONSerialization.JSONObjectWithData(result!, options: NSJSONReadingOptions.AllowFragments, error: nil)
if (dict != nil) {
// 比对字典中以下信息基本上可以保证数据安全
// bundle_id&application_version&product_id&transaction_id
// 验证成功
println(dict)
}
}
func restorePurchase(){
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
} }

PS:过程中遇到的问题

1.点击购买没有弹出输入账户密码框,解决方法是 到手机设置里面iTunes Store 与 App Store 里面注销你原本的账号

2.每次进来添加了 SKPaymentQueue.defaultQueue().addTransactionObserver(self) 状态监听之后,就会调用很多次 支付失败 ,原因是之前调试失败之后,没有 SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction) ,所以每次系统自动帮你请求上一次失败的操作,结果还是继续失败。

												

[iOS]swift版内购的更多相关文章

  1. iOS:苹果内购实践

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

  2. iOS开发苹果内购的介绍与实现

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

  3. iOS开发系列——内购、GameCenter、iCloud、Passbook系统服务开发汇总

    社交 Social 现在很多应用都内置“社交分享”功能,可以将看到的新闻.博客.广告等内容分享到微博.微信.QQ.空间等,其实从iOS6.0开始苹果官方就内置了Social.framework专门来实 ...

  4. ios swift版 sqlite3详解

    iOS中的SQLite3的封装与详细应用 SQLite是一个开源的嵌入式关系数据库,特点是易使用.高效.安全可靠.可移植性强. iOS中的本地持久化存储 NSUserDefault:一般用于存储小规模 ...

  5. [Xcode 实际操作]九、实用进阶-(31)为IAP(支付方式)内购功能的具体实现和测试

    目录:[Swift]Xcode实际操作 本文将演示如何为IAP(支付方式)内购功能的具体实现和测试. 内购是苹果市场上的一种常见的盈利方式. 在项目中确保已经安装了第三方库[Pod],双击[Podfi ...

  6. AppStore ipa (苹果内购)笔记

    内购示意图 准备条件 苹果的开发者证书,已经为应用启用App内购,并在Xcode更新配置文件 itunes store设置 itunes中创建App及其它设置 参考:iOS应用程序内购/内付费(一)  ...

  7. iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总

    --系统应用与系统服务 iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用 ...

  8. iOS开发系列通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开

    --系统应用与系统服务 iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用 ...

  9. [Swift通天遁地]四、网络和线程-(15)程序内购功能

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

随机推荐

  1. 解决 mklink 使用中的各种坑(硬链接,软链接/符号链接,目录链接)

    通过 mklink 命令可以创建文件或文件夹的链接,而这种链接跟快捷方式是不一样的.然而我们还可能会遇到其使用过程中的一些坑,本文将整理这些坑并提供解决方法.   0x00 背景介绍:mklink m ...

  2. windows下PyCharm运行和调试scrapy

    Scrapy是爬虫抓取框架,Pycharm是强大的python的IDE,为了方便使用需要在PyCharm对scrapy程序进行调试 python PyCharm Scrapy scrapy指令其实就是 ...

  3. mysql 安装(压缩包安装和exe安装)

    1:mysql官网:https://dev.mysql.com/downloads/file/?id=482487 2:压缩包安装:https://www.cnblogs.com/jamespan23 ...

  4. riotjs 简单使用&&browserify 构建

    项目地址: http://riotjs.com/ 备注: 为了简单使用了 browserify 进行构建 1. 项目结构 ├── app.css ├── gulpfile.js ├── index.h ...

  5. jdk1.8新特性之接口default方法

    众所周知,default是java的关键字之一,使用场景是配合switch关键字用于条件分支的默认项.但自从java的jdk1.8横空出世以后,它就被赋予了另一项很酷的能力——在接口中定义非抽象方法. ...

  6. 【转】【备忘录】MySQL性能优化的21个最佳实践 和 mysql使用索引

    今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我 们程序员需要去关注的事情.当我们去设计数据库表结构,对操作数 ...

  7. Js中常用的字符串,数组,函数扩展

    由于最近辞职在家,自己的时间相对多一点.所以就根据prototytpeJS的API,结合自己正在看的司徒大神的<javascript框架设计>,整理了下Js中常用一些字符串,数组,函数扩展 ...

  8. .NET实现多个不同有效时间Session方案思考

    什么是Session?简单讲,Session是一种服务端用于保存每个客户端用户的状态信息的机制.客户端第一次访问时,服务端从分配一个空间专门存储该客户端的信息,后续访问时便可以直接获取或者更新状态信息 ...

  9. .NET的URL重写

    [概述] URL重写就是首先获得一个进入的URL请求然后把它重新写成网站可以处理的另一个URL的过程.重写URL是非常有用的一个功能,因为它可以让你提高搜索引擎阅读和索引你的网站的能力:而且在你改变了 ...

  10. postman断言的方法

    1.在test添加断言 2.检查response的body中是否包含字符串: tests["Body matches string"] = responseBody.has(&qu ...