제가 저번에 서버 만들면서 영수증 확인을 하기 위해서 작성한 코드 입니다.
보통 JSP나 PHP로 많이 만드실텐데 제가 암호화에 관련된 부분을 잘 몰라서
구글 셈플에서 해당 부분을 보고 java 서버로 만든 것입니다.
클라이언트에서 결제 처리할 때 받는 데이터에서
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE")
사용법은 verifyPurchase(퍼블릭키,INAPP_PURCHASE_DATA,INAPP_DATA_SIGNATURE);
클라이언트에서 서버로 INAPP_PURCHASE_DATA,INAPP_DATA_SIGNATURE를 보내야 겠지요.
퍼블릭키는 안 보내구요. 퍼블릭 키는 서버에서 보관을 하고 있으면 됩니다.
아래 소스는 영수증이 맞는지 확인을 하는 기능만을 수행 합니다.
프리덤등의 결제로 장난치는 것을 막을 수 있을 것입니다.
제 어플도 20몇회 결제중 2건이 장난이더라구요.
그리고 구글월렛 들어가서 주기적으로 확인을 해보는 것도 도움이 되는 것 같네요.
어플에 적용해서 사용하는 코드고 아직까지 결제가 잘 되고 있습니다.
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import core.Util;
public class t_inapp_verify {
private static final String KEY_FACTORY_ALGORITHM = "RSA";
private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
if( signedData == null ) return false;
if( signature == null ) return false;
if( signature.length() <= 0 ) return false;
boolean verified = false;
PublicKey key = generatePublicKey(base64PublicKey);
verified = verify(key, signedData, signature);
if(!verified) return false;
return true;
}
public static PublicKey generatePublicKey(String encodedPublicKey) {
try{
byte[] decodedKey = base64.decode(encodedPublicKey);
if(decodedKey==null) return null;
KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
if(keyFactory==null) return null;
return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
}
catch(Exception e){ Util.Except(e); }
return null;
}
public static boolean verify(PublicKey publicKey, String signedData, String signature) {
Signature sig;
try {
sig = Signature.getInstance(SIGNATURE_ALGORITHM);
sig.initVerify(publicKey);
sig.update(signedData.getBytes());
byte tmp[] = base64.decode(signature);
if(!sig.verify(tmp)) return false;
return true;
}catch(Exception e){ Util.Except(e); }
return false;
}
}

안녕하세요 Godwish님 ^^
항상 도움 주셔서 감사합니당~
다름이아니라 알려주셨던 방법을 적용하려던중에 기존에 구글에서 제공된 샘플 코드에도 위의 인증 방법이 되어있더라구요..
그래서 저도 그 방법을 사용하고 있었구요..
하지만 해킹은 여전히 발생하고 있습니다 ..
제가 실제 프리덤을 설치하고 로그를 찍어봤을때 실제 과금때와 다르지 않더라구요 그래서 위의 인증 방법도 true가 되더라구요..
혹 다른 방법 이 있지 않을까 해서 .. 댓글남깁니다 ㅠ