[iOS]swift版内购
//内购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版内购的更多相关文章
- iOS:苹果内购实践
iOS 苹果的内购 一.介绍 苹果规定,凡是虚拟的物品(例如:QQ音乐的乐币)进行交易时,都必须走苹果的内购通道,苹果要收取大约30%的抽成,所以不允许接入第三方的支付方式(微信.支付宝等),当然开发 ...
- iOS开发苹果内购的介绍与实现
1.iOS开发苹果内购的介绍 1.1 介绍 苹果规定,凡是虚拟的物品(例如:QQ音乐的乐币)进行交易时,都必须走苹果的内购通道,苹果要收取大约30%的抽成,所以不允许接入第三方的支付方式(微信.支付宝 ...
- iOS开发系列——内购、GameCenter、iCloud、Passbook系统服务开发汇总
社交 Social 现在很多应用都内置“社交分享”功能,可以将看到的新闻.博客.广告等内容分享到微博.微信.QQ.空间等,其实从iOS6.0开始苹果官方就内置了Social.framework专门来实 ...
- ios swift版 sqlite3详解
iOS中的SQLite3的封装与详细应用 SQLite是一个开源的嵌入式关系数据库,特点是易使用.高效.安全可靠.可移植性强. iOS中的本地持久化存储 NSUserDefault:一般用于存储小规模 ...
- [Xcode 实际操作]九、实用进阶-(31)为IAP(支付方式)内购功能的具体实现和测试
目录:[Swift]Xcode实际操作 本文将演示如何为IAP(支付方式)内购功能的具体实现和测试. 内购是苹果市场上的一种常见的盈利方式. 在项目中确保已经安装了第三方库[Pod],双击[Podfi ...
- AppStore ipa (苹果内购)笔记
内购示意图 准备条件 苹果的开发者证书,已经为应用启用App内购,并在Xcode更新配置文件 itunes store设置 itunes中创建App及其它设置 参考:iOS应用程序内购/内付费(一) ...
- iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总
--系统应用与系统服务 iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用 ...
- iOS开发系列通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开
--系统应用与系统服务 iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用 ...
- [Swift通天遁地]四、网络和线程-(15)程序内购功能
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
随机推荐
- JAVA验证身份证号码是否合法
package com.chauvet.utils; import java.text.ParseException; import java.text.SimpleDateFormat; impor ...
- 让thinkphp 5 支持pathinfo 的 nginx ,去掉index.php
在TP5.0中查阅tp5官方文档,注意:5.0取消了URL模式的概念,并且普通模式的URL访问不再支持.phthinfo 是什么? PHP中的全局变量$_SERVER['PATH_INFO']是一个很 ...
- win7下VS2010编译python3
转自:http://www.cnblogs.com/fortwo/archive/2013/04/16/3023871.html 1.首先从python.org上:http://www.python. ...
- consul dns 转发配置
测试使用dnsmasq. 优势:可以方便的进行应该编码,进行动态域名解析,容错处理. 因为consul 默认的dns 为127.0.0.1 8600 所以配置如下: 文件目录: /etc/d ...
- chrome扩展程序开发之在目标页面执行自己的JS
大家都知道JS是执行在client的.所以,假设我们自己写一个浏览器的话.是一定能够往下载下来的网页源码中加入js的.可惜我们没有这个能力.只是幸运的是,chrome的扩展程序能够帮我们做到这件事. ...
- uGUI知识点剖析之RectTransform
http://www.2fz1.com/post/unity-ugui-recttransform/#jtss-tsina uGUI知识点剖析之RectTransform 一.基本要点 RectTra ...
- socket初步
简单demo:https://blog.csdn.net/ns_code/article/details/14105457
- 带ssl的websocket例子
还是在那个websocket_demo的例子 rebar-creator create-app websocket_demo tree一下看看大概目录 ├── cert │ ├── cowboy- ...
- 【转】jMeter入门实例
人们对从认识事物都有一个具体到抽象的过程,学习Jmeter也不例外,通过一个实例来进行学习,一方面可以让初学者有所见即所得的信心,另一方面,其实也是在初学者心中留下了对这事物的一个朦胧的印象,这在以后 ...
- [Java][Web]Response学习
// 在 http 中,meta 标签可以模拟响应头 response.setHeader("Content-type", "text/html;charset=UTF- ...