반응형

P12로 구글 토큰 얻기


시간마다 토큰을 갱신을 해야하지만 이 방법을 사용하면 필요할때만 토큰 생성가능함.


빨간색 부분은 경로나 파일명에 맞게 변경


리소스에 p12 파일 추가해놓고 리소스에서 가져옴.


출저 : http://zavitax.wordpress.com/2012/12/17/logging-in-with-google-service-account-in-c-jwt/



public class GoogleJsonWebToken

{

    private const string SCOPE_AUTH_ANDROIDPUBLISHER = @"https://www.googleapis.com/auth/androidpublisher";

    public static dynamic GetAccessToken()

    {

        // header

        var header = new { typ = "JWT", alg = "RS256" };

        var times = GetExpiryAndIssueDate();

        var claimset = new

        {

            iss = "gather-heroes@api-",

            scope = SCOPE_AUTH_ANDROIDPUBLISHER,

            aud = @"https://accounts.google.com/o/oauth2/token",

            iat = times[0],

            exp = times[1],

        };

        JavaScriptSerializer ser = new JavaScriptSerializer();

        // encoded header

        var headerSerialized = ser.Serialize(header);

        var headerBytes = Encoding.UTF8.GetBytes(headerSerialized);

        var headerEncoded = Base64UrlEncode(headerBytes);

        ///////////////

        ///certificate

        ////////////////            

        byte[] dataKey = null;

        using (var stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("ProjectNameSpace. Resources.Google.Play.Android.Developer-906baXXXX.p12"))

        {

            dataKey = new byte[stream.Length];

            stream.Read(dataKey, 0, dataKey.Length);

        }

        X509Certificate2 certificate = new X509Certificate2(dataKey, "notasecret");

        // encoded claimset

        var claimsetSerialized = ser.Serialize(claimset);

        var claimsetBytes = Encoding.UTF8.GetBytes(claimsetSerialized);

        var claimsetEncoded = Base64UrlEncode(claimsetBytes);

        // input

        var input = headerEncoded + "." + claimsetEncoded;

        var inputBytes = Encoding.UTF8.GetBytes(input);

        // signiture

        var rsa = certificate.PrivateKey as RSACryptoServiceProvider;

        var cspParam = new CspParameters

        {

            KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName,

            KeyNumber = rsa.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2

        };

        var aescsp = new RSACryptoServiceProvider(cspParam) { PersistKeyInCsp = false };

        var signatureBytes = aescsp.SignData(inputBytes, "SHA256");

        var signatureEncoded = Base64UrlEncode(signatureBytes);

        // jwt

        var jwt = headerEncoded + "." + claimsetEncoded + "." + signatureEncoded;

        var client = new WebClient();

        client.Encoding = Encoding.UTF8;

        var uri = @"https://accounts.google.com/o/oauth2/token";

        var content = new NameValueCollection();

        content["assertion"] = jwt;

        content["grant_type"] = "urn:ietf:params:oauth:grant-type:jwt-bearer";

        string response = Encoding.UTF8.GetString(client.UploadValues(uri, "POST", content));

        var result = ser.Deserialize<dynamic>(response);

        return result;

    }

    private static int[] GetExpiryAndIssueDate()

    {

        var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

        var issueTime = DateTime.UtcNow;

        var iat = (int)issueTime.Subtract(utc0).TotalSeconds;

        var exp = (int)issueTime.AddMinutes(55).Subtract(utc0).TotalSeconds;

        return new[] { iat, exp };

    }

    private static string Base64UrlEncode(byte[] input)

    {

        var output = Convert.ToBase64String(input);

        output = output.Split('=')[0]; // Remove any trailing '='s

        output = output.Replace('+', '-'); // 62nd char of encoding

        output = output.Replace('/', '_'); // 63rd char of encoding

        return output;

    }

}


얻은 토큰으로 인앱 영수증 검증


{

    var auth = GoogleJsonWebToken.GetAccessToken();

    string url = "https://www.googleapis.com/androidpublisher/v2/applications/"

    + this.Params["appid"] + "/purchases/products/" + this.Params["productid"] + "/tokens/" + this.Params["token"] + "?access_token=" + auth["access_token"];


                System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();

                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));


var client = new System.Net.Http.HttpClient();

    client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

    var req = client.GetAsync(new Uri(url));

    try

    {

        if (req.Result.IsSuccessStatusCode)

        {

            var result = req.Result.Content.ReadAsStringAsync().Result;

            Receipt _result = JsonConvert.DeserializeObject<Receipt>(result);

            if (_result.PurchaseState == 0)

            {

                /*

                아이템 지급 및 로그 기록

                */

            }

        }

    }

    catch

    {

    }

}

 

반응형

'개발관련 > C#' 카테고리의 다른 글

ObjectSerialize  (0) 2017.08.10
Aes 암호화/복호화  (0) 2017.08.10
모든 타입 xmlWriter  (0) 2017.08.10
XmlSerializer  (0) 2017.08.03
Http Handler 비동기 처리  (0) 2017.07.25

+ Recent posts