<commit_before>from Crypto.Hash import SHA
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from pyinapp.errors import InAppValidationError
from pyinapp.purchase import Purchase
import base64
import json

purchase_state_ok = 0


class GooglePlayValidator(object):

    def __init__(self, bundle_id, api_key):
        self.bundle_id = bundle_id
        self.public_key = RSA.importKey(base64.standard_b64decode(api_key))

    def validate(self, receipt, signature):
        ok = self._validate_signature(receipt, signature)

        if not ok:
            raise InAppValidationError('Bad signature')

        try:
            receipt_json = json.loads(receipt)

            if receipt_json['packageName'] != self.bundle_id:
                raise InAppValidationError('Bundle id mismatch')

            if receipt_json['purchaseState'] != purchase_state_ok:
                raise InAppValidationError('Item is not purchased')

            purchase = {
                'transaction_id': receipt_json['orderId'],
                'product_id': receipt_json['productId'],
                'quantity': 1,
                'purchased_at': receipt_json['purchaseTime']
            }
            return Purchase(**purchase)
        except (KeyError, ValueError):
            raise InAppValidationError('Bad receipt')

    def _validate_signature(self, receipt, signature):
        try:
            encoded_receipt = receipt.encode()
            sha = SHA.new(encoded_receipt)
            verifier = PKCS1_v1_5.new(self.public_key)
            signature = base64.standard_b64decode(signature)
            return verifier.verify(sha, signature)
        except (TypeError, ValueError):
            return False<commit_msg>Separate purchase extracting into method<commit_after>from Crypto.Hash import SHA
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from pyinapp.errors import InAppValidationError
from pyinapp.purchase import Purchase
import base64
import json

purchase_state_ok = 0


class GooglePlayValidator(object):

    def __init__(self, bundle_id, api_key):
        self.bundle_id = bundle_id
        self.public_key = RSA.importKey(base64.standard_b64decode(api_key))

    def validate(self, receipt, signature):
        ok = self._validate_signature(receipt, signature)

        if not ok:
            raise InAppValidationError('Bad signature')

        try:
            receipt_json = json.loads(receipt)

            if receipt_json['packageName'] != self.bundle_id:
                raise InAppValidationError('Bundle id mismatch')

            if receipt_json['purchaseState'] != purchase_state_ok:
                raise InAppValidationError('Item is not purchased')

            return self._extract_purchase(receipt_json)
        except (KeyError, ValueError):
            raise InAppValidationError('Bad receipt')

    def _validate_signature(self, receipt, signature):
        try:
            encoded_receipt = receipt.encode()
            sha = SHA.new(encoded_receipt)
            verifier = PKCS1_v1_5.new(self.public_key)
            signature = base64.standard_b64decode(signature)
            return verifier.verify(sha, signature)
        except (TypeError, ValueError):
            return False

    def _extract_purchase(self, node):
        purchase = {
            'transaction_id': node['orderId'],
            'product_id': node['productId'],
            'quantity': 1,
            'purchased_at': node['purchaseTime']
        }
        return Purchase(**purchase)
{'fraction_non_alphanumeric': 0.0829323521086895, 'fraction_numerical': 0.010189640532125671, 'mean_word_length': 2.628336755646817, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5902820', 'n_tokens_mistral': 1015, 'n_tokens_neox': 943, 'n_words': 218}