//内购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. SqlServer使用CONVERT 对时间进行格式化

    前言 在最近使用SqlServer的时候遇到时间格式的转换,特此记录下. 本文参考:https://www.cnblogs.com/xiaoleiel/p/8301027.html,如有侵权,请联系删 ...

  2. SSZipArchive使用详解

    下载SSZipArchive,点击我.或者自己在这里下载. SSZipArchive功能: 解压zip文件 解压密码保护的zip文件 创建zip文件 追加到zip文件 压缩文件 使用一个名字来压缩NS ...

  3. Flask第六篇——项目配置文件

    我们在开发中,通常将一些需要用到的配置选项单独放在一个文件中,比如叫configs.py中.然后通过一些方式加载. 现在将加载配置文件的方法罗列如下: 1.先新建文件configs.py,文件代码: ...

  4. 在后台new出页面(组件)

    Page p = new Page();            Control u = p.LoadControl("~/folderName/controlName.ascx") ...

  5. 在Eclipse中导入dtd和xsd文件,使XML自动提示

    DTD 类型约束文件    1. Window->Preferences->XML->XML Catalog->User Specified Entries窗口中,选择Add ...

  6. 基于jquery的可查询多级select控件(可记录历史选择)

    一.功能和使用 公司有功能需求,还要一条代码引入的控件,网上找完全符合的控件比较难,寻找所花的时间还不如自己写一个,所以找个空闲时间自己写了一个   控件功能:1.可手动输入查询,也可点击下拉框查询, ...

  7. nodejs之fs模块

    nodejs中的file system文件系统模块 1.文件的读取readFile //引入文件系统模块 const fs = require('fs'); //文件读取是异步操作 fs.readFi ...

  8. cookie添加中文encoding/decoding

    添加时编码,读取是解码,否则编译不过 Cookie cookie=new Cookie("姓名","黄嘎兵"); respose.addCookie(cooki ...

  9. ubuntu :安装skype聊天工具

    如题,今天就想搞个软件在ubuntu能聊天,查一下skype,好像网上有人说不是每个安装包都用的了,skype-ubuntu-precise_4.2.0.13-1_i386.deb可以, 我在微盘下载 ...

  10. Qt学习笔记(1) hello world

    Qt的简介: Qt是一个跨平台的C++ GUI库实现,原本只是以为它只提供一些图形接口,看来我还是低估了它,采用文档Qt学习之路2开始学习,不知道这个文档是不是有点老了,管他呢,先了解下. 搭建环境: ...