File Coverage

blib/lib/Web/MarketReceipt/Verifier/GooglePlay.pm
Criterion Covered Total %
statement 40 44 90.9
branch 5 14 35.7
condition n/a
subroutine 12 12 100.0
pod 0 1 0.0
total 57 71 80.2


line stmt bran cond sub pod time code
1             package Web::MarketReceipt::Verifier::GooglePlay;
2 2     2   106642 use Mouse;
  2         22898  
  2         10  
3 2     2   677 use Mouse::Util::TypeConstraints;
  2         3  
  2         9  
4             extends 'Web::MarketReceipt::Verifier';
5 2     2   658 use utf8;
  2         13  
  2         13  
6              
7 2     2   423 use Web::MarketReceipt;
  2         4  
  2         61  
8 2     2   10 use Carp;
  2         15  
  2         121  
9 2     2   416 use Crypt::OpenSSL::RSA;
  2         5237  
  2         50  
10 2     2   22 use MIME::Base64;
  2         4  
  2         86  
11 2     2   10 use JSON::XS;
  2         2  
  2         243  
12              
13             subtype 'Crypt::OpenSSL::RSA' => as 'Object' => where { $_->isa('Crypt::OpenSSL::RSA') };
14             coerce 'Crypt::OpenSSL::RSA'
15             => from 'Str',
16             => via { Crypt::OpenSSL::RSA->new_public_key($_) };
17              
18             # need pem format
19             has public_key => (
20             is => 'ro',
21             isa => 'Crypt::OpenSSL::RSA',
22             required => 1,
23             coerce => 1,
24             );
25              
26 2     2   11 no Mouse;
  2         4  
  2         10  
27              
28             sub verify {
29 2     2 0 12 my ($self, %args) = @_;
30              
31             # TODO 例外処理
32 2         11 my $signed_data = decode_base64 $args{signed_data};
33 2         7 my $signature = decode_base64 $args{signature};
34              
35 2         14 my $verification_result = $self->public_key->verify($signed_data, $signature);
36 2         39 my $raw_json = decode_json $signed_data;
37              
38             Web::MarketReceipt->new(
39             is_success => $verification_result ? 1 : 0,
40             store => 'GooglePlay',
41             raw => $raw_json,
42             $verification_result ? (
43             exists $raw_json->{orders} ? (
44 2 50       17 orders => [ map { $self->_order2hash($_) } @{ $raw_json->{orders} } ],
  1 100       4  
  1 50       3  
45             ) : (
46             orders => [ $self->_order2hash($raw_json) ],
47             ),
48             ) : (),
49             );
50             }
51              
52             sub _order2hash {
53 2     2   4 my ($self, $order) = @_;
54              
55             return {
56             product_identifier => $order->{productId},
57             unique_identifier => 'GooglePlay:' . $order->{orderId},
58             purchased_epoch => int( $order->{purchaseTime}/1000 ),
59 2         17 state => $self->_purchase_state($order->{purchaseState}),
60             quantity => 1,
61             environment => 'Production',
62             };
63             }
64              
65             sub _purchase_state {
66 2     2   7 my ($self, $purchase_state) = @_;
67              
68 2 50       6 if ($purchase_state == 0) {
    0          
    0          
    0          
69 2         34 return 'purchased';
70             } elsif ($purchase_state == 1) {
71 0           return 'canceled';
72             } elsif ($purchase_state == 2) {
73 0           return 'refunded';
74             } elsif ($purchase_state == 3) {
75 0           return 'expired';
76             }
77              
78 0           croak sprintf 'invalid purchase state: %s', $purchase_state;
79             }
80              
81             1;