- objective-c - iOS 5 : Can you override UIAppearance customisations in specific classes?
- iphone - 如何将 CGFontRef 转换为 UIFont?
- ios - 以编程方式关闭标记的信息窗口 google maps iOS
- ios - Xcode 5 - 尝试验证存档时出现 "No application records were found"
我正在为应用程序内购买实现收据验证服务器端,如 Receipt Validation Programming guide 所述.
每当我尝试将收据编码为 Base64 并将其发送到我的服务器时,我都会收到来自 Apple 的错误消息。但是,如果我手动将未编码的 base64 复制粘贴到服务器上,在那里对其进行编码并触发对 Apple 的 REST 调用,他们的 iTunes 服务器会正确响应。
我不确定我在客户端做错了什么。代码非常简单:
-(NSString*) retrieveReceiptFromCompletedTransaction:(SKPaymentTransaction*)transaction
{
NSData *receiptData;
NSString *receiptString;
NSBundle *bundle = [NSBundle mainBundle];
if ([bundle respondsToSelector:@selector(appStoreReceiptURL)]) {
NSURL *receiptURL = [bundle performSelector:@selector(appStoreReceiptURL)];
receiptData= [NSData dataWithContentsOfURL:receiptURL];
}
else {
receiptData = transaction.transactionReceipt;
}
receiptString = [receiptData base64EncodedStringWithOptions:0];
return receiptString;
}
有什么想法吗?
最佳答案
我正在写下完整的方法来帮助初学者。
从您的 iTunes 帐户生成共享 key 。
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
SKPaymentTransactionStatePurchased
{
.....
case SKPaymentTransactionStatePurchased:
if ([transaction.payment.productIdentifier
isEqualToString:PRICEPLAN1]) {
//[server PurchasedClinicalToDoList];
[self completeTransaction: transaction];
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
5:验证收据
- (void) completeTransaction: (SKPaymentTransaction *)transaction
{
// NSString* receiptString = [[NSString alloc] initWithString:transaction.payment.productIdentifier];
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
NSString *jsonObjectString = [receipt base64EncodedStringWithOptions:0];
[self validateViaOwnServer:jsonObjectString];
[self validateDirectly: receipt];
}
6.ValidateViaServerSideCodes:
-(void)validateViaOwnServer :(NSString*)receipt
{
NSString* BASEURl = @"XXXXXXXXX/XXX/XXXX";
NSString *TestReceipt= [BASEURl stringByAppendingString:@"/InApp/iOS/updatePurchase"];
NSDictionary *params = @ {@"receipt" :receipt]};
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager TestReceipt
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseData) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
}
7.直接验证:
-(void) validateDirectly :(NSData*)receipt
{
// Sent to the server by the device
// Create the JSON object that describes the request
NSError *error;
// NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents options:0 error:&error];
NSData *requestData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithObjectsAndKeys:
[receipt base64EncodedStringWithOptions:0],@"receipt-data",
SHARED_SECRET,@"password",
nil]
options:NSJSONWritingPrettyPrinted
error:&error
];
if(!requestData) {
/* ... Handle error ... */ }
// Create a POST request with the receipt data.
NSURL *storeURL = [NSURL URLWithString:@"https://buy.itunes.apple.com/verifyReceipt"];
//@"https://sandbox.itunes.apple.com/verifyReceipt"
NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL]; [storeRequest setHTTPMethod:@"POST"];
[storeRequest setHTTPBody:requestData];
// Make a connection to the iTunes Store on a background queue.
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
completionHandler:^(NSURLResponse *response, NSData *data, NSError
*connectionError) {
if (connectionError) {
/* ... Handle error ... */
// NSLog(@"CONNECTION ERROR");
} else {
NSError *error;
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (!jsonResponse) { // NSLog(@"NOT JSON");
/* ... Handle error ...*/ }
else{
/* ... YES VALIDATED ...*/
}/* ... Send a response back to the device ... */
}
}];
}
8:服务器端代码(Java)
字符串网址 = "https://buy.itunes.apple.com/verifyReceipt ";
try {
URL url = new URL(URL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
//conn.setRequestProperty("Content-Type", "text/plain");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Content-Type", "application/json");
String input = "{\"receipt-data\": \""+receiptData+"\", \"password\": \"69744THESECRETKEYXXX\"}";
OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
appleJson += output;
// System.out.println(output);
}
conn.disconnect();
appleReceipt = gson.fromJson(appleJson, AppleReceipt.class);
purchaseStartDate = appleReceipt.getReceipt().getIn_app().get(1).getOriginal_purchase_date_ms();
expiryDate = appleReceipt.getReceipt().getIn_app().get(1).getExpires_date_ms();
// System.out.println("Apple receipt expiry date="+appleReceipt.getReceipt().getIn_app().get(1).getExpires_date_ms());
// System.out.println("Apple receipt expiry date="+appleReceipt.getReceipt().getIn_app().get(1).getExpires_date_ms());
关于ios - 将应用内购买收据数据发送到我的服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19499258/
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 6年前关闭。 Improve t
我们有一个专有的销售系统,我们已经使用了一段时间了。最近我们添加了“购买”方面,以便我们可以比较匹配产品的平均购买/销售价格以及查看库存状况。 在 MySQL 中,我有 2 个表:tblPurchas
在查看 Paypal 文档以寻找针对这种情况的解决方案后,我一头雾水。我想要的是一种让购物车订阅(定期付款)和购买商品的方法。有没有一种方法可以解决这个问题,或者我是否必须做一些自定义的事情(如果我使
我想知道是否可以使用youtube api获取可购买或可租借的电影列表。当我转到youtube网站并登录到Google帐户时,我可以看到要购买的电影及其价格。 我想在我的应用程序(http://www
我使用 JavaScript 购买 SDK 和 Node.js。 const fetch = require('node-fetch'); const shopify = require('shopi
我购买了三个不同期限的不同订阅。我已经配置了测试账户,我可以进行测试购买。对于这些购买,谷歌不向我收费,但它们看起来非常像真实的。购买成功后,应用内结算会向我发送一些有关我的购买的数据,例如 pack
我目前正在实现应用内购买,并且刚刚阅读了一些帖子,说需要恢复购买按钮,否则苹果将拒绝应用。 我不想在我的 UI 设计中添加第二个按钮。 所以我的问题是... 有没有办法检查用户之前是否进行过应用内购买
我的应用中有多个项目。我有两个设备。如果我在这些设备中的第一个上购买商品,然后尝试在另一个设备上购买相同的商品,我不能。(Google play intent 显示消息 - 商品已拥有!然后它崩溃了.
有没有办法检测何时通过应用商店为您的应用进行了购买? 检测应用内购买似乎很容易(即我们的服务器可以收到通知),但是对于直接购买有没有办法做到这一点? 如果没有,是否有一些用户的唯一标识符(例如购买时通
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我计划在用户使用该应用程序成功扫描二维码时为应用内购买提供折扣。我知道无法为现有商品提供折扣。我打算以折扣价添加另一件商品。有没有人以前有过使用这种方法的经验? 提前致谢 最佳答案 没有办法直接这样做
我很好奇其他商店在基础应用程序框架方面做了什么?我将应用程序框架视为能够提供额外或扩展的功能以提高基于它构建的应用程序的质量。 有各种开箱即用的框架,例如 Spring(或 Spring.NET)等。
我们正在开发一款使用非续订订阅 IAP 模型的应用。在沙盒中测试订阅购买流程时,我们看到弹出两 strip 有“购买”按钮的消息。 显示第一条消息和产品信息:“您想以 xx.xx 美元购买一个订阅吗?
我的老板购买了 Microsoft 365,它包含三种产品。他现在要求我设计一个管理系统,比如员工自助服务门户。我特此寻求有关从哪里开始或使用哪种产品的建议,因为我对此很陌生。 我尝试了一些研究,发现
我的老板购买了 Microsoft 365,它包含三种产品。他现在要求我设计一个管理系统,比如员工自助服务门户。我特此寻求有关从哪里开始或使用哪种产品的建议,因为我对此很陌生。 我尝试了一些研究,发现
我刚刚了解了IAP Cracker的存在,并试图找出在我的应用中验证IAP购买的最佳方法。 我无法确定的是IAP Cracker是否可以处理“消耗性”商品。如果没有,我没有什么可担心的。 这是维护/验
我正在编写一个允许应用内购买的简单应用。我已经使用 SKU 代码 android.test.purchased 进行了测试,一切正常。 我进入我的 google play 控制台,创建了一个应用程序,
我即将启动一个应用程序,该应用程序将包含多个“应用程序内购买”。 我想做的是有一种方法可以提供少量免费的“应用内购买”来选择评论家等人。 在 apple 框架内有没有办法做到这一点,如果没有,我可以采
所以我在这个网站上工作,用户可以在该网站上发布他们的商品,其他用户可以将一些商品添加到他们的购物车并在线购买。 我考虑的流程是这样的: 商家发布商品及其信用卡/ Paypal 信息。 买家将(来自不同
我对这个主题进行了广泛的研究,但我的知识仍然很模糊。我正在寻找一个简单站点的基本 DV,但我看到每个在线 SSL 都具有三个级别, Root->Intermidiate (充当 Root 的代理)和我
我是一名优秀的程序员,十分优秀!