블로그 이미지
래머
오늘도 열심히 개발하는 개발자입니다.

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

2014. 5. 3. 23:52 iOS


유니티에서 사용하고자 하는경우 아래 코드를 추가하시고
InitCertificateValidationCallback()을 영수증 검증 루틴 실행전 한번 호출해줄필요가 있습니다.

public static void InitCertificateValidationCallback()
        {
            ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(ValidateServerCertificate);
        }

        static bool ValidateServerCertificate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }

iOS인앱 결제 후 영수증 검증 루틴이다.

첨부된 JSON라이브러리를 c#프로젝트의 참조에 추가할 필요가 있다.

VerifyIOSReceipt 메소드의 리턴값을 판별해서 

처리하면된다.


IOS_RV_SUCCESS = 영수증 검증 성공

IOS_RV_FAIL_RETRY  = 영수증 검증에 실패 했다, 샌드박스모드에서 다시 검증이 필요하다.

IOS_RV_FAIL  = 유효하지 않은 영수증이다.


using System.Text;

using System.Net;

using System.IO;

using Newtonsoft.Json;

using Newtonsoft.Json.Linq;

using System;


public class CIOSReceiptVerificationMng

{

    public const string IOS_PRODUCT_URL = "https://buy.itunes.apple.com/verifyReceipt";

    public const string IOS_SENDBOX_URL = "https://sandbox.itunes.apple.com/verifyReceipt";


    public const int IOS_RV_SUCCESS = 0;    //ios영수증 검증 결과 성공

    public const int IOS_RV_FAIL_RETRY = 1;    //샌드박스에서 재검증필요

    public const int IOS_RV_FAIL = -1;    //검증 실패


    /*ios영수증 검증

itemID = 해당 영수증으로 결제한 아이템의 ID

receiptData = 영수증 데이터

bProduct = 프로덕트에서 검증할지 샌드박스에서 검증할지, 기본적으로 프로덕트에서 검증하고 리턴값이 IOS_RV_FAIL_RETRY  인경우에 샌드박스에서 검증한다.

*/

    public static int VerifyIOSReceipt(ref string itemID, string receiptData, bool bProduct)

    {

        try

        {

            itemID = null;


            // Verify the receipt with Apple

            string postString = string.Format("{{ \"receipt-data\" : \"{0}\" }}", receiptData);

            ASCIIEncoding ascii = new ASCIIEncoding();

            byte[] postBytes = ascii.GetBytes(postString);

            HttpWebRequest request;


            if (bProduct)

                request = WebRequest.Create(IOS_PRODUCT_URL) as HttpWebRequest;

            else

                request = WebRequest.Create(IOS_SENDBOX_URL) 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();


            HttpWebResponse response = request.GetResponse() as HttpWebResponse;

            StringBuilder sb = new StringBuilder();

            byte[] buf = new byte[8192];

            Stream resStream = response.GetResponseStream();

            string tempString = null;


            int count = 0;


            do

            {

                count = resStream.Read(buf, 0, buf.Length);

                if (count != 0)

                {

                    tempString = Encoding.ASCII.GetString(buf, 0, count);

                    sb.Append(tempString);

                }

            } while (count > 0);


            var fd = JObject.Parse(sb.ToString());


            try

            {

                resStream.Close();

                response.Close();

            }

            catch

            {

            }


            string strResult = fd["status"].ToString();

            // Receipt not valid

            if (strResult != "0")

            {

                if (strResult == "21007")

                    return IOS_RV_FAIL_RETRY;


                // Error out

                return IOS_RV_FAIL;

            }


            // Product ID does not match what we expected

            var receipt = fd["receipt"];


            /*

            if (String.Compare(receipt["product_id"].ToString().Replace("\"", "").Trim(), itemID.Trim(), true) != 0)

            {

                // Error out

                return IOS_RV_FAIL;

            }

             * */


            //제품 ID정보를 저장함

            itemID = receipt["product_id"].ToString().Replace("\"", "").Trim();


            // This product was not sold by the right app

            if (String.Compare(receipt["bid"].ToString().Replace("\"", "").Trim(), PACKAGE_NAME, true) != 0)

            {

                // Error out

                return IOS_RV_FAIL;

            }


            /*

            // This transaction didn't occur within 24 hours in either direction; somebody is reusing a receipt

            DateTime transDate = DateTime.SpecifyKind(DateTime.Parse(receipt["purchase_date"].ToString().Replace("\"", "").Replace("Etc/GMT", "")), DateTimeKind.Utc);

            TimeSpan delay = DateTime.UtcNow - transDate;

            if (delay.TotalHours > 24 || delay.TotalHours < -24)

            {

                // Error out

                return false;

            }

            */


            // Perform the purchase -- all my purchases are server-side only, which is a very secure way of doing things

            // Success!

        }

        catch// (Exception ex)

        {

            // We crashed and burned -- do something intelligent

            return IOS_RV_FAIL;

        }


        return IOS_RV_SUCCESS;

    }


}


Newtonsoft.Json.dll


Newtonsoft.Json.xml





'iOS' 카테고리의 다른 글

앱스토어 가이드라인  (0) 2015.10.10
iOS사파리 브라우져를 열어서 특정 사이트로 이동  (0) 2014.05.05
posted by 래머
2014. 5. 3. 23:43 안드로이드

첨부된 바운시캐슬 암호화 라이브러리를 참조에 추가하고 사용해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using System;
 
using System.Security.Cryptography;
 
using System.IO;
 
using System.Text;
 
using System.Xml;
 
using System.Collections.Generic;
 
using System.Linq;
 
using Org.BouncyCastle.Security;
 
using Org.BouncyCastle.Crypto;
 
using Org.BouncyCastle.Crypto.Parameters;
 
 
 
 
/*
사용법
GoogleSignatureVerify gsv = new GoogleSignatureVerify("발급받은 API키");
if (gsv.Verify("결제데이터", 사인데이터))
{
//성공시 처리
}
*/
 
public class GoogleSignatureVerify
 
    {
 
        RSAParameters _rsaKeyInfo;
 
 
 
 
        public GoogleSignatureVerify(String GooglePublicKey)
 
        {
 
            RsaKeyParameters rsaParameters = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(GooglePublicKey));
 
 
 
 
            byte[] rsaExp = rsaParameters.Exponent.ToByteArray();
 
            byte[] Modulus = rsaParameters.Modulus.ToByteArray();
 
 
 
 
            // Microsoft RSAParameters modulo wants leading zero's removed so create new array with leading zero's removed
 
            int Pos = 0;
 
            for (int i = 0; i < Modulus.Length; i++)
 
            {
 
                if (Modulus[i] == 0)
 
                {
 
                    Pos++;
 
                }
 
                else
 
                {
 
                    break;
 
                }
 
            }
 
            byte[] rsaMod = new byte[Modulus.Length - Pos];
 
            Array.Copy(Modulus, Pos, rsaMod, 0, Modulus.Length - Pos);
 
 
 
 
            // Fill the Microsoft parameters
 
            _rsaKeyInfo = new RSAParameters()
 
            {
 
                Exponent = rsaExp,
 
                Modulus = rsaMod
 
            };
 
        }
 
 
 
 
        public bool Verify(String Message, String Signature)
 
        {
 
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
 
            {
 
                rsa.ImportParameters(_rsaKeyInfo);
 
                return rsa.VerifyData(Encoding.ASCII.GetBytes(Message), "SHA1", Convert.FromBase64String(Signature));
 
            }
 
        }
 
    }
 
 
 
cs

BouncyCastle.Crypto.dll

유니티를 사용하신다면 아래 유니티 패키지를 임포트 하시면 바운시 캐슬 라이브러리소스가 임포트됩니다.


BouncyCastle.unitypackage



posted by 래머
2014. 5. 3. 23:11 안드로이드
유니티에서 사용하고자 하는경우 아래 코드를 추가하시고
InitCertificateValidationCallback()을 영수증 검증 루틴 실행전 한번 호출해줄필요가 있습니다.

public static void InitCertificateValidationCallback()
        {
            ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(ValidateServerCertificate);
        }

        static bool ValidateServerCertificate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }

c#으로 작성된 서버 또는 유니티 등에서 티스토어의 인앱 결제 영수증 검증을 다음과 같이 하면된다.



readonly string TSTORE_RECEIPT_VERIFY_URL_PRODUCT = "https://iap.tstore.co.kr/digitalsignconfirm.iap";  //실서비스용서버주소

        readonly string TSTORE_RECEIPT_VERIFY_URL_DEV = "https://iapdev.tstore.co.kr/digitalsignconfirm.iap"; //개발용서버주소

        readonly string TSTORE_RECEIPT_VERIFY_FORMAT = "{{\"txid\" : \"{0}\", \"appid\" : \"{1}\", \"signdata\" : \"{2}\"}}";

        //TStore 영수증 검중구현, 

//bProduct : 서비스/개발용 서버중 어느 서버에서 검증할지

//strAppID : 티스토어에 배포한 프로그램에 할당받은 ID

//strTXID : 인앱 결제후 결과 값으로 넘어온 것중 txid

//strReceipt : 인앱결제 후 결과 값으로 넘어온 영수증 정보

//리턴값이 true인경우 영수증검증에 성공한것이다.

//애플의 영수증을 검증하는 것처럼 먼저 bProduct에 true를 해서 영수증검증을 해보고 만일 실패 하는경우

//false를 줘서 검증을 시도하도록 하면 된다.

        bool VerifyTStoreReceipt(bool bProduct, string strAppID, string strTXID, string strReceipt)

        {

            try

            {

                // Verify the receipt with Apple

                string postString = String.Format(TSTORE_RECEIPT_VERIFY_FORMAT, strTXID, strAppID, strReceipt);

                ASCIIEncoding ascii = new ASCIIEncoding();

                byte[] postBytes = ascii.GetBytes(postString);

                HttpWebRequest request;


                if (bProduct)

                    request = WebRequest.Create(TSTORE_RECEIPT_VERIFY_URL_PRODUCT) as HttpWebRequest;

                else

                    request = WebRequest.Create(TSTORE_RECEIPT_VERIFY_URL_DEV) 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();


                HttpWebResponse response = request.GetResponse() as HttpWebResponse;

                StringBuilder sb = new StringBuilder();

                byte[] buf = new byte[8192];

                Stream resStream = response.GetResponseStream();

                string tempString = null;


                int count = 0;


                do

                {

                    count = resStream.Read(buf, 0, buf.Length);

                    if (count != 0)

                    {

                        tempString = Encoding.ASCII.GetString(buf, 0, count);

                        sb.Append(tempString);

                    }

                } while (count > 0);


                var fd = JObject.Parse(sb.ToString());


                try

                {

                    resStream.Close();

                    response.Close();

                }

                catch

                {

                }


                string strResult = fd["status"].ToString();

                string strDetail = fd["detail"].ToString();


                // Receipt not valid

                if (strResult == null || strResult != "0" || strDetail == null || strDetail != "0000")

                {

#if DEBUG

                    CLogMng.Instance().Debug("tstore purchase failed : " + sb.ToString());

                    CLogMng.Instance().Debug("txid : " + strTXID);

                    CLogMng.Instance().Debug("signdata : " + strReceipt);

#endif

                    return false;

                }

            }

            catch// (Exception ex)

            {

                // We crashed and burned -- do something intelligent

                return false;

            }


            return true;

        }




posted by 래머
2014. 5. 2. 00:39 안드로이드



[구글인앱]Selling In-app Products(인앱 제품 판매) #1

Selling In-app Products(인앱 제품판매)

DEPENDENCIES AND PREREQUISITES(의존성과 필요조건)

  • Android 2.2 or higher(안드로이드2.2 또는 상위버전)

YOU SHOULD ALSO READ(당신은 또한 다음을 읽을 수 있다)

In this class, you'll learn how to perform common In-app Billing operations from Android applications.
이 수업에서, 당신은 안드로이드 어플리케이션의 공통된 인앱 빌링 작
업을 어떻게 수행하는지 배울것이다.
In-app billing is a service hosted on Google Play that lets you charge for digital content or for upgrades in your app. 
인앱 빌링은 당신의 앱에있는 디지털 컨텐트에 요금을 부과하거나 업그레이드가 가능하도록  구글 플레이에서 호스트하는 서비스이다.
The In-app Billing API makes it easy for you to integrate In-app Billing into your applications. 
인앱빌링 API는 당신의 어플리케이션에 인앱빌링을 쉽게 통합하게 만든다.
You can request product details from Google Play, issue orders for in-app products, and quickly retrieve ownership information based on users' purchase history. 
당신은 제품의 상세를 구글플레이로 부터 요청하거나, 인앱제품 결제 주문을 내거나, 유저의 구매 내역으로 부터 소유권 정보를 빠르게 되찾을 수 있다.
You can also query the Google Play service for details about in-app products, such as local pricing and availability. 
또한, 지역별 가격 및 유효성과 같은 인앱 제품의 상세정보를 구글플레이 서비스로 부터 조회 할 수 있다. 
Google Play provides a checkout interface that makes user interactions with the In-app Billing service seamless, and provides a more intuitive experience to your users.
구글 플레이는  유저 상호작용 결제 인터페이스로 매끄러운 인앱 빌링 서비스를 제공하며, 좀더 직관 적인 경험을 당신의 사용자에게 제공한다.
This class describes how to get started with the Version 3 API. To learn how to use the version 2 API, seeImplementing In-App Billing (V2).
이 수업에서 어떻게 Version3 API를 시작하는지 설명한다. 버전 2 API 사용 방법을 배우기 위해, 인앱빌링2(http://developer.android.com/google/play/billing/v2/billing_integrate.html) 구현을 보라.

Lessons



Preparing Your In-app Billing Application(인앱 빌링 어플레케이션준비)
In this lesson, you will learn how to prepare your application to use the In-app Billing API and communicate with Google Play. You will also learn how to establish a connection to communicate with Google Play and verify that the In-app Billing API version that you are using is supported.
이수업에서, 당신은 인앱 빌링을 사용하기 위해서 당신의 어플리케이션이 어떤 준비를 해야 하며 어떻게 구글플레이와 소통하는지 배우게 된다. 또한 구글플레이와 통신하기 위해 연결을 수립하고, 사용하고자 하는 인앱 빌링 API를 검증하는 법을 배우게 될것이다.
Establishing In-app Billing Products for Sale(판매를 위한 인앱빌링 제품 개설)


In this lesson, you will learn how to specify the In-app Billing products for your app in Google Play and query the product details.
이수업에서, 앱의 인앱 빌링 제품 정보를 구글플레이에 어떻게 개설 하는지와 조회 하는지에 대해 배우게된다.
Purchase In-app Billing Products(인앱 빌링 제품 결제)
In this lesson, you will learn how to purchase In-app Billing products, track consumption of purchased items, and query for details of purchased items.
이수업에서는, 인앱 빌링 제품 구매방법, 구매 아이템을 소비하는법, 구매 아이템의 상세 정보조회에 대해서 배우게된다.
Testing Your In-app Billing Application(인앱 빌링 어플리케이션 테스트)
In this lesson, you will learn how to test your application to ensure that In-app Billing is functioning correctly.
이수업에서는, 인앱빌링 기능이 올바르게 작동하는지 보증하기 위해서 당신의 어플리케이션을 어떻게 테스트 하는지 배우게 될것이다.




posted by 래머
prev 1 next