verifying iOS in app purchase receipt with C#

百般思念 提交于 2020-05-09 18:29:06

问题


I am verifying my ios in app purchase receipt on my server using C# web service

I got receipt as string by doing below in Xcode:

- (void) completeTransaction: (SKPaymentTransaction *)transaction
{
    NSString* receiptString = [[NSString alloc] initWithString:transaction.payment.productIdentifier];

    NSLog(@"%@",receiptString);

    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];

    NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];

    NSString *jsonObjectString = [receipt base64EncodedStringWithOptions:0];

}

and I am sending that string(receipt) to my C# web service as parameter. Here is my web service method:

[WebMethod(Description = "Purchase Item Verify")]
public string PurchaseItem(string receiptData)
 {
    string returnmessage = "";

    try
    {
        var json = "{ 'receipt-data': '" + receiptData + "'}";

        ASCIIEncoding ascii = new ASCIIEncoding();
        byte[] postBytes = Encoding.UTF8.GetBytes(json);

        HttpWebRequest request;
        request = WebRequest.Create("https://sandbox.itunes.apple.com/verifyReceipt") as HttpWebRequest;
        request.Method = "POST";
        request.ContentType = "application/json";
        request.ContentLength = postBytes.Length;

        Stream postStream = request.GetRequestStream();
        postStream.Write(postBytes, 0, postBytes.Length);
        postStream.Close();

        var sendresponse = (HttpWebResponse)request.GetResponse();

        string sendresponsetext = "";
        using (var streamReader = new StreamReader(sendresponse.GetResponseStream()))
        {
            sendresponsetext = streamReader.ReadToEnd();
        }
        returnmessage = sendresponsetext;

    }
    catch (Exception ex)
    {
        ex.Message.ToString();
    }
    return returnmessage;
}

It always return {"status":21002}. I have been searching for two days , but still can't find out the solution. Can someone help me, what am i wrong ?

**I am testing on sandbox that is why i use sandbox URL. I can verify the transaction receipt within my app.


回答1:


I got solution

The final code that works for me is:

 public string PurchaseItem(string receiptData)
{
    string returnmessage = "";
    try
    {
       // var json = "{ 'receipt-data': '" + receiptData + "'}";

        var json = new JObject(new JProperty("receipt-data", receiptData)).ToString();

        ASCIIEncoding ascii = new ASCIIEncoding();
        byte[] postBytes = Encoding.UTF8.GetBytes(json);

      //  HttpWebRequest request;
        var request = System.Net.HttpWebRequest.Create("https://sandbox.itunes.apple.com/verifyReceipt");
        request.Method = "POST";
        request.ContentType = "application/json";
        request.ContentLength = postBytes.Length;

        //Stream postStream = request.GetRequestStream();
        //postStream.Write(postBytes, 0, postBytes.Length);
        //postStream.Close();

        using (var stream = request.GetRequestStream())
        {
            stream.Write(postBytes, 0, postBytes.Length);
            stream.Flush();
        }

      //  var sendresponse = (HttpWebResponse)request.GetResponse();

        var sendresponse = request.GetResponse();

        string sendresponsetext = "";
        using (var streamReader = new StreamReader(sendresponse.GetResponseStream()))
        {
            sendresponsetext = streamReader.ReadToEnd().Trim();
        }
        returnmessage = sendresponsetext;

    }
    catch (Exception ex)
    {
        ex.Message.ToString();
    }
    return returnmessage;

Spending two and half days just to change a method. Thanks GOD.




回答2:


For managing subscriptions, @Jerry Naing's answer also requires the provision of your shared secret (can be retrieved/generated from iTunes Connect). Easiest way to include this is just to add an additional property in the line defining the json var.

var json = new JObject(new JProperty("receipt-data", receiptData), new JProperty("password", "put_your_shared_secret_here")).ToString();

Failing to provide the shared secret will result in a 21004 status response.




回答3:


Here's an alternative asynchronous implementation using HTTPClient:

public static async Task<string> CheckReceiptWithAppStore()
    {
        string responseStr = null;

        string uri = "https://sandbox.itunes.apple.com/verifyReceipt";

        string receiptData = // Get your receipt from wherever you store it

        var json = new JObject(new JProperty("receipt-data", receiptData), 
            new JProperty("password", "paste-your-shared-secret-here")).ToString();

        using (var httpClient = new HttpClient())
        {        

            if (receiptData != null)
            {
                HttpContent content = new StringContent(json);

                try
                {
                    Task<HttpResponseMessage> getResponse = httpClient.PostAsync(uri, content);
                    HttpResponseMessage response = await getResponse;
                    responseStr = await response.Content.ReadAsStringAsync();
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error verifying receipt: " + e.Message);
                }
            }
        }

        return responseStr;
    }

The shared secret is not required for non-subscription based purchases.




回答4:


This code example was also helpful to me and may help others: For C# developers there is a useful open-source project called APNS-Sharp which includes receipt verification code that works in ASP.NET. In particular, the Receipt.cs and ReceiptVerification.cs files in the Jdsoft.Apple.AppStore directory

Found it from this page about Xamarin: inapp purcasing ios Transactions and Verification



来源:https://stackoverflow.com/questions/22933133/verifying-ios-in-app-purchase-receipt-with-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!