Skip to content

Commit

Permalink
Merge pull request #27 from martinbutt/master
Browse files Browse the repository at this point in the history
@pasxel's service accounts patch with readme fix
  • Loading branch information
aporat committed Apr 28, 2016
2 parents 2d53c4a + d9dcd80 commit 5b89a43
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 131 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,29 @@ try {
// success
```

Or [Using a service account](https://developers.google.com/android-publisher/getting_started#using_a_service_account)

Create service account [Service Account flow](https://developers.google.com/identity/protocols/OAuth2ServiceAccount)

```php
use ReceiptValidator\GooglePlay\ServiceAccountValidator as PlayValidator;
$validator = new PlayValidator([
'client_email' => '[email protected]',
'p12_key_path' => file_get_contents('MyProject.p12'),
]);

try {
$response = $validator->setPackageName('PACKAGE_NAME')
->setProductId('PRODUCT_ID')
->setPurchaseToken('PURCHASE_TOKEN')
->validate();
} catch (Exception $e){
var_dump($e->getMessage());
// example message: Error calling GET ....: (404) Product not found for this application.
}
// success
```


### Amazon App Store ###

Expand Down
33 changes: 33 additions & 0 deletions examples/test_play_service_account.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);

$root = realpath(dirname(dirname(__FILE__)));
$library = "$root/library";

$path = array($library, get_include_path());
set_include_path(implode(PATH_SEPARATOR, $path));

require_once $root . '/vendor/autoload.php';

use ReceiptValidator\GooglePlay\ServiceAccountValidator as PlayValidator;

// google authencation
$client_email = '[email protected]';
$p12_key_path = 'MyProject.p12';

// receipt data
$package_name = 'com.example';
$product_id = 'coins_10000';
$purchase_token = 'xxxxxx';

$validator = new PlayValidator(['client_email' => $client_email, 'p12_key_path' => $p12_key_path]);

try {
$response = $validator->setPackageName($package_name)->setProductId($product_id)->setPurchaseToken($purchase_token)->validate();
} catch (Exception $e) {
echo 'got error = ' . $e->getMessage() . PHP_EOL;
}

print_R($response);
114 changes: 114 additions & 0 deletions src/GooglePlay/AbstractValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php

namespace ReceiptValidator\GooglePlay;

abstract class AbstractValidator
{
const TYPE_PURCHASE = 1;
const TYPE_SUBSCRIPTION = 2;

/**
* google client
*
* @var \Google_Client
*/
protected $_client = null;

/**
* @var \Google_Service_AndroidPublisher
*/
protected $_androidPublisherService = null;

/**
* @var string
*/
protected $_package_name = null;

/**
* @var string
*/
protected $_purchase_token = null;

/**
* @var int
*/
protected $_purchase_type = self::TYPE_PURCHASE;

/**
* @var string
*/
protected $_product_id = null;

public function __construct($options = [])
{
$this->initClient($options);
$this->_androidPublisherService = new \Google_Service_AndroidPublisher($this->_client);
}

abstract protected function initClient($options = []);

/**
*
* @param string $package_name
* @return \ReceiptValidator\GooglePlay\Validator
*/
public function setPackageName($package_name)
{
$this->_package_name = $package_name;

return $this;
}

/**
*
* @param string $purchase_token
* @return \ReceiptValidator\GooglePlay\Validator
*/
public function setPurchaseToken($purchase_token)
{
$this->_purchase_token = $purchase_token;

return $this;
}

/**
*
* @param int $purchase_type
* @return \ReceiptValidator\GooglePlay\Validator
*/
public function setPurchaseType($purchase_type)
{
$this->_purchase_type = $purchase_type;

return $this;
}

/**
*
* @param string $product_id
* @return \ReceiptValidator\GooglePlay\Validator
*/
public function setProductId($product_id)
{
$this->_product_id = $product_id;

return $this;
}

public function validate()
{
switch ($this->_purchase_type) {
case self::TYPE_SUBSCRIPTION:
$request = $this->_androidPublisherService->purchases_subscriptions;
break;
default:
$request = $this->_androidPublisherService->purchases_products;
}

$response = $request->get(
$this->_package_name, $this->_product_id, $this->_purchase_token
);

return $response;
}
}
20 changes: 20 additions & 0 deletions src/GooglePlay/ServiceAccountValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace ReceiptValidator\GooglePlay;

class ServiceAccountValidator extends AbstractValidator
{
protected function initClient($options = [])
{
$credentials = new \Google_Auth_AssertionCredentials(
$options['client_email'],
[\Google_Service_AndroidPublisher::ANDROIDPUBLISHER],
$options['p12_key_path']
);
$this->_client = new \Google_Client();
$this->_client->setAssertionCredentials($credentials);
if ($this->_client->getAuth()->isAccessTokenExpired()) {
$this->_client->getAuth()->refreshTokenWithAssertion();
}
}
}
157 changes: 26 additions & 131 deletions src/GooglePlay/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,137 +3,32 @@

use ReceiptValidator\RunTimeException as RunTimeException;

class Validator
class Validator extends AbstractValidator
{
const TYPE_PURCHASE = 1;
const TYPE_SUBSCRIPTION = 2;

/**
* google client
*
* @var Google_Client
*/
protected $_client = null;

/**
* @var \Google_Service_AndroidPublisher
*/
protected $_androidPublisherService = null;

/**
* @var string
*/
protected $_package_name = null;

/**
* @var string
*/
protected $_purchase_token = null;

/**
* @var int
*/
protected $_purchase_type = self::TYPE_PURCHASE;

/**
* @var string
*/
protected $_product_id = null;

public function __construct(array $options = array())
{
$this->_client = new \Google_Client();
$this->_client->setClientId($options['client_id']);
$this->_client->setClientSecret($options['client_secret']);

$cached_access_token_path = sys_get_temp_dir() . '/' . 'googleplay_access_token_' . md5($options['client_id']) . '.txt';

touch($cached_access_token_path);
chmod($cached_access_token_path, 0770);

try {
$this->_client->setAccessToken(file_get_contents($cached_access_token_path));
} catch (\Exception $e) {
// skip exceptions when the access token is not valid
}

try {
if ($this->_client->isAccessTokenExpired()) {
$this->_client->refreshToken($options['refresh_token']);
file_put_contents($cached_access_token_path, $this->_client->getAccessToken());
}
} catch (\Exception $e) {
throw new RuntimeException('Failed refreshing access token - ' . $e->getMessage());
}

$this->_androidPublisherService = new \Google_Service_AndroidPublisher($this->_client);

}


/**
*
* @param string $package_name
* @return \ReceiptValidator\GooglePlay\Validator
*/
public function setPackageName($package_name)
{
$this->_package_name = $package_name;

return $this;
}

/**
*
* @param string $purchase_token
* @return \ReceiptValidator\GooglePlay\Validator
*/
public function setPurchaseToken($purchase_token)
{
$this->_purchase_token = $purchase_token;

return $this;
}

/**
*
* @param int $purchase_type
* @return \ReceiptValidator\GooglePlay\Validator
*/
public function setPurchaseType($purchase_type)
{
$this->_purchase_type = $purchase_type;

return $this;
}

/**
*
* @param string $product_id
* @return \ReceiptValidator\GooglePlay\Validator
*/
public function setProductId($product_id)
{
$this->_product_id = $product_id;

return $this;
}


public function validate()
{
switch ($this->_purchase_type) {
case self::TYPE_SUBSCRIPTION:
$request = $this->_androidPublisherService->purchases_subscriptions;
break;
default:
$request = $this->_androidPublisherService->purchases_products;
protected function initClient($options = [])
{
$this->_client = new \Google_Client();
$this->_client->setClientId($options['client_id']);
$this->_client->setClientSecret($options['client_secret']);

$cached_access_token_path = sys_get_temp_dir() . '/' . 'googleplay_access_token_' . md5($options['client_id']) . '.txt';

touch($cached_access_token_path);
chmod($cached_access_token_path, 0770);

try {
$this->_client->setAccessToken(file_get_contents($cached_access_token_path));
} catch (\Exception $e) {
// skip exceptions when the access token is not valid
}

try {
if ($this->_client->isAccessTokenExpired()) {
$this->_client->refreshToken($options['refresh_token']);
file_put_contents($cached_access_token_path, $this->_client->getAccessToken());
}
} catch (\Exception $e) {
throw new RuntimeException('Failed refreshing access token - ' . $e->getMessage());
}
}

$response = $request->get(
$this->_package_name, $this->_product_id, $this->_purchase_token
);

return $response;
}
}

0 comments on commit 5b89a43

Please sign in to comment.