최근에 DeveloperPayload(개발자가 임의로 만든 payload값) 기능이 구글에서 없어졌습니다. 때문에 해당 부분을 삭제했습니다. (2021-1-8)
서버 검증을 위해, 구글에 계정 만들고, 개발자 페이지에서 p12 파일 만들고 그러는 거는 검색해 보시면 쉽게 보실 수 있어요.
아래 페이지에 잘 정리 돼 있더라구요.
http://theeye.pe.kr/archives/2570
여기서는 c#으로 서버를 개발 했을 경우, 서버 검증하는 코드를 넣었습니다.
서버 검증은 3가지 방법이 있는데,
https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#oauth-2.0-protocol
여기서는 [ServiceAccountCredential]을 이용한 방법입니다.
1. 클라이언트에서 서버로 결과 보내기
아래 클라이언트 부분의 코드는 유니티엔진의 인앱 라이브러리를 이용한 것 입니다.
// 유저 인앱 완료 시, 실행되는 이벤트
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
{
//결과를 저장하기 위한 클래스 객체
IapResultData result_data = new IapResultData();
try
{
//인앱 구매 전, 게임 서버로부터 받은 payload값
JObject json_object = JObject.Parse(e.purchasedProduct.receipt);
string payload = (string)json_object["Payload"];
//결과값에 파싱에 문제되는 문자들이 섞여있습니다. 아래같이 직접 없애주세요.
payload.Replace("\\", "");
JObject payload_object = JObject.Parse(payload);
string payload_json = (string)payload_object["json"];
JObject payload_json_object = JObject.Parse(payload_json);
string payload_json_purchaseToken = (string)payload_json_object["purchaseToken"];
result_data.m_data_id = m_curr_shop_data.m_id;
result_data.m_pid = m_curr_shop_data.m_pid;
result_data.m_token = payload_json_purchaseToken;
//위 값들을 서버로 전송합니다~
NetworkManager.Instance.SendBuyIapItemFinishReq(result_data);
}
catch (Exception ex)
{
return PurchaseProcessingResult.Complete;
}
return PurchaseProcessingResult.Complete;
}
2. 서버에서 받은 데이터로 검증하기
//클라이언트로 받은 결과를 저장하는 클래스 입니다.
public class IapResultData
{
public int m_data_id; //제 겜에서 사용하는 상품 데이터 id
public string m_pid; //구글 상품 id
public string m_token; //구글 인앱 결과에 있습니다.
}
//스레드로 처리하려다 보니 따로 request 객체를 만들어 사용했습니다. 몰라도 돼요
public class IapVerifyRequestData
{
public IapResultData m_iap_result_data { get; set; }
public jdUserToken m_user_token { get; set; }
public IapVerifyRequestData()
{
}
public IapVerifyRequestData(IapResultData data, jdUserToken user_token)
{
m_iap_result_data = data;
m_user_token = user_token;
}
}
//클라이언트로 받은 영수증 정보로 서버 검증을 합니다.
private void processRequest(IapVerifyRequestData iap_data)
{
try
{
//구글api 계정
String serviceAccountEmail = "xxxxx@xxxxxxxxx.iam.gserviceaccount.com";
//위 계정에서 만든 key.p12 파일.
var certificate = new X509Certificate2(@"key.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { AndroidPublisherService.Scope.Androidpublisher }
}.FromCertificate(certificate));
AndroidPublisherService android_service = new AndroidPublisherService(
new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = "com.jd.games.BattleGame",
}
);
//검증 요청
var request = android_service.Purchases.Products.Get("com.xxx.앱패키지명",
iap_data.m_iap_result_data.m_pid,
iap_data.m_iap_result_data.m_token);
var purchase_state = request.Execute();
IapVerifyResultData result_data = new IapVerifyResultData();
//결과 예시 입니다.
//{
// "consumptionState" : 1, // 0 아직 컨슘 안됨, 1 컨슘됨
// "developerPayload" : "",
// "kind" : "androidpublisher#productPurchase",
// "purchaseState" : 0, // 0 구매완료, 1 취소
// "purchaseTimeMillis" : "1454502702978"
//}
//유니티에서 인앱 구매하는 경우 자동으로 컨슘까지 됩니다.
// 페이로드 값이 제대로 왔는지 확인합니다.
// 페이로드 체크 안하시면 안해도 됩니다.
result_data.m_shop_data_id = iap_data.m_iap_result_data.m_data_id;
result_data.m_purchase_state = (int)purchase_state.PurchaseState;
result_data.m_consume_state = (int)purchase_state.ConsumptionState;
result_data.m_fail_reason = FailReason.FAIL_REASON_NONE;
//인앱 결과를 처리...
}
catch (Exception exc)
{
//문제 발생 시 처리
}
}
'게임을 만들자 > 게임 서버(C#)' 카테고리의 다른 글
c#, SocketAsyncEventArgs 메모리 릭 현상 (0) | 2021.03.20 |
---|---|
C#, 외부 프로세스 실행 (0) | 2021.03.16 |
윈도우 서버 TCPNoDelay, TcpAckFrequency 설정 (1) | 2020.12.23 |
c# 각도, 라디안, 벡터 간 변환 (0) | 2020.10.24 |
c#, 점 - 선분 간의 거리 구하기 (0) | 2020.10.13 |