File Coverage

blib/lib/Web/MarketReceipt/Verifier/GooglePlay.pm
Criterion Covered Total %
statement 41 45 91.1
branch 10 16 62.5
condition n/a
subroutine 12 12 100.0
pod 0 1 0.0
total 63 74 85.1


line stmt bran cond sub pod time code
1             package Web::MarketReceipt::Verifier::GooglePlay;
2 2     2   111621 use Mouse;
  2         28963  
  2         9  
3 2     2   763 use Mouse::Util::TypeConstraints;
  2         5  
  2         10  
4             extends 'Web::MarketReceipt::Verifier';
5 2     2   816 use utf8;
  2         18  
  2         15  
6              
7 2     2   508 use Web::MarketReceipt;
  2         4  
  2         62  
8 2     2   13 use Carp;
  2         11  
  2         141  
9 2     2   1219 use Crypt::OpenSSL::RSA;
  2         24926  
  2         102  
10 2     2   26 use MIME::Base64;
  2         7  
  2         270  
11 2     2   19 use JSON::XS;
  2         7  
  2         435  
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   22 no Mouse;
  2         6  
  2         29  
27              
28             sub verify {
29 2     2 0 40 my ($self, %args) = @_;
30              
31             # TODO 例外処理
32 2         13 my $signed_data = decode_base64 $args{signed_data};
33 2         6 my $signature = decode_base64 $args{signature};
34              
35 2         12 my $verification_result = $self->public_key->verify($signed_data, $signature);
36 2         35 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       14 orders => [ map { $self->_order2hash($_) } @{ $raw_json->{orders} } ],
  1 100       4  
  1 50       4  
45             ) : (
46             orders => [ $self->_order2hash($raw_json) ],
47             ),
48             ) : (),
49             );
50             }
51              
52             sub _order2hash {
53 2     2   5 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         14 state => $self->_purchase_state($order->{purchaseState}),
60             quantity => 1,
61             environment => 'Production',
62             };
63             }
64              
65             sub _purchase_state {
66 2     2   5 my ($self, $purchase_state) = @_;
67              
68             # REMIND: if you want to add state to these, you must be added to Web::MarketReceipt::Order#OrderState
69 2 100       11 if ($purchase_state == 0) {
    50          
    50          
    50          
    50          
70 1         13 return 'purchased';
71             } elsif ($purchase_state == 1) {
72 0         0 return 'canceled';
73             } elsif ($purchase_state == 2) {
74 0         0 return 'refunded';
75             } elsif ($purchase_state == 3) {
76 0         0 return 'expired';
77             } elsif ($purchase_state == 4) {
78 1         21 return 'pending';
79             }
80              
81 0           croak sprintf 'invalid purchase state: %s', $purchase_state;
82             }
83              
84             1;