2016-09-28 16 views
0

私はSwiftでiOSアプリを開発しており、アプリ内購入の領収書検証を実装しようとしています。私はSwiftでこれを達成する方法を考え出すことができませんでした。代わりに、this質問のGiulio Roggeroの例を見て、私のアプリがNode.jsのLambda関数writtinを通してリクエストを送信するようにしました。私のスウィフトコードは次のようになります。lambdaを使用したNode.jsによるiOSの受け取り確認

let receiptPath = Bundle.main.appStoreReceiptURL?.path 
    if FileManager.default.fileExists(atPath: receiptPath!){ 
     var receiptData:NSData? 
     do{ 
      receiptData = try NSData(contentsOf: Bundle.main.appStoreReceiptURL!, options: NSData.ReadingOptions.alwaysMapped) 
     } 
     catch{ 
      print("ERROR: " + error.localizedDescription) 
     } 
     let receiptString = receiptData?.base64EncodedString(options: .endLineWithLineFeed) 
     let invocationRequest = AWSLambdaInvokerInvocationRequest() 
     invocationRequest?.functionName = "sendReceiptRequest" 
     invocationRequest?.invocationType = AWSLambdaInvocationType.requestResponse 
     invocationRequest?.payload = ["receipt-data" : receiptString!, "password" : SUBSCRIPTION_SECRET] 

     let lambdaInvoker = AWSLambdaInvoker.default() 
     lock() 
     lambdaInvoker.invoke(invocationRequest!).continue(with: AWSExecutor.mainThread(), with: { (task:AWSTask!) -> AnyObject! in 
      if task.error != nil { 
       self.sendErrorPopup("Error: \(task.error?.localizedDescription)") 
      } else { 
       print("TOKEN: ", task.result) 
      } 
      self.unlock() 
      return nil 
     })} 

マイラムダNode.jsの機能は、たとえば次のよう、次のようになります。しかし

function (receiptData_base64, password, production, cb) 
{ 
var url = production ? 'buy.itunes.apple.com' : 'sandbox.itunes.apple.com' 
var receiptEnvelope = { 
    "receipt-data": receiptData_base64, 
    "password":password 
}; 
var receiptEnvelopeStr = JSON.stringify(receiptEnvelope); 
var options = { 
    host: url, 
    port: 443, 
    path: '/verifyReceipt', 
    method: 'POST', 
    headers: { 
     'Content-Type': 'application/x-www-form-urlencoded', 
     'Content-Length': Buffer.byteLength(receiptEnvelopeStr) 
    } 
}; 

var req = https.request(options, function(res) { 
    res.setEncoding('utf8'); 
    res.on('data', function (chunk) { 
     console.log("body: " + chunk); 
     cb(true, chunk); 
    }); 
    res.on('error', function (error) { 
     console.log("error: " + error); 
     cb(false, error); 
    }); 
}); 
req.write(receiptEnvelopeStr); 
req.end(); 
} 

、ラムダテストを介して、または、私のいずれかを介して、このコードを実行するときアプリで、単にResponse body: {"errorMessage":"true"}というエラーメッセージが表示されます。私はコードを微調整してより多くの予想されるエラーを作成できることに気がつきました。たとえば、領収書データの値が他にある場合、21002エラーコードが返されます。 21007エラーが発生します。問題の一部は、コールバックがどのように動作するはずかを正確にはわからないということです。ブロックhttps.requestはSwiftで何をしようとしているのですか?レシートデータを変更すると異なる結果が生じるため、領収書データが正しくフォーマットされているという印象を受けます。なぜ最終結果はまだエラーですか?

編集:私は以前に気付かなかった

何かが、私は、ライン「ボディ:(レシートデータ)」ラムダ関数を実行したときにということである、表示される場所(レシートデータ)ベース64符号化されたデータIがあります関数に送信されます。これは私がエラーコールバックブロックにまったく到達していないと思わせ、エラーが私のアプリにコールバックの結果を返信する方法と関係があることを私に思い出させます。このブロックとは何ですか:

var req = https.request(options, function(res) { 
res.setEncoding('utf8'); 
res.on('data', function (chunk) { 
    console.log("body: " + chunk); 
    cb(true, chunk); 
}); 
res.on('error', function (error) { 
    console.log("error: " + error); 
    cb(false, error); 
}); 
}); 

コールバックを受け取るための許可を有効にする必要がありますか?

+0

あなたの正しいJSONを得ようとしていますあなたが送っているbase64の領収書データ。特に+を%2bに置き換える必要があります。また、私はあなたのアプリからそれを渡すのではなく、node.jsコードにあなたのサブスクリプションを秘密にすることをお勧めします – Paulw11

+0

私はreceiptString = receiptString!.replacingOccurrences(of: "+"、with: "%2b")、 "errorMessage:true"と同じ結果を得ます。しかし、私はラムダでは、関数が実際に "console.log(" body: "+ chunk);"という行に到達していることに気付きました。私はこれが何をすべきかを本当に理解していないので、私は実際にAppleからの返答を得ているのだろうかと思っていますが、私のアプリに返信する方法が間違っています。 – user3726962

答えて

0

最終的には、thisの例に従い、Node.jsの代わりにPythonを使用して問題を解決しました。私は前に自分のコードで何が間違っていたのかまだ分かりませんが、SwiftのBase64エンコーディングとPython Lambda関数にレシートデータとパスワードを送ることで正しい結果が得られました。この後に、潜在的な問題を発見する人のための

0

  1. ここでの大きな問題は、Content-Typeが間違っているということです。あなたは、JSONをポストする必要があります。コードはそれを行いますが、間違った型を使用してサーバーに使用している形式を伝えます。 application/jsonでなく、application/x-www-form-urlencodedである必要があります。
  2. Base64をアップルのサーバーに送信は、少なくとも(少なくとも先週現在)に行末が含まれていてはいけません。私はこれがここの問題だとは知らないが、それは私が過去にヒットしたもので、.endLineWithLineFeedは私を疑わしいものにする。
  3. サーバー間の切り替えに使用されるアルゴリズム。プロダクションとサンドボックスの切り替えを許可するのではなく、プロダクションサーバーへの受信確認を試みる必要があります。結果オブジェクトのstatus21007の場合、コードはサンドボックスサーバーに対して同じ受信確認を試行する必要があります。領収書がデコードされて確認されると、クライアントは領収書をチェックして、それが検証されたサーバーと(必要に応じて)サンドボックスの領収書を無視するかどうかを確認できます。
0

スウィフトコードでは、「task.error!= nilを」あなたはエラー

lambdaInvoker.invoke(invocationRequest!).continue(with: AWSExecutor.mainThread(), with: { (task:AWSTask!) -> AnyObject! in 
    if task.error != nil { 
     self.sendErrorPopup("Error: \(task.error?.localizedDescription)") 
    } else { 
     print("TOKEN: ", task.result) 
    } 

を持っていますが、あなたのノードのコードでは、あなたは道のコールバックを呼び出します。最初のパラメータがnilであることを行っていない、あなたの誤りである

cb(true, chunk); 

をおで、この行を置き換える必要があります。

cb(null, chunk); 

あなたは%エンコーディングを試してみてくださいそのよう

関連する問題