Showing
5 changed files
with
169 additions
and
89 deletions
... | @@ -38,9 +38,9 @@ class DevGoogle extends Command | ... | @@ -38,9 +38,9 @@ class DevGoogle extends Command |
38 | */ | 38 | */ |
39 | public function handle() | 39 | public function handle() |
40 | { | 40 | { |
41 | - dd(1); | 41 | +// dd(1); |
42 | $gp = new GooglePayment(); | 42 | $gp = new GooglePayment(); |
43 | - | 43 | + dd($gp->client); |
44 | 44 | ||
45 | return 0; | 45 | return 0; |
46 | } | 46 | } | ... | ... |
... | @@ -106,12 +106,12 @@ class PayController extends Controller | ... | @@ -106,12 +106,12 @@ class PayController extends Controller |
106 | // | 106 | // |
107 | } | 107 | } |
108 | 108 | ||
109 | - public function iapCallback(Request $request,$service) | 109 | + public function iapCallback(Request $request, PaymentFactory $factory, $service) |
110 | { | 110 | { |
111 | $all = $request->all(); | 111 | $all = $request->all(); |
112 | - Log::debug($all['message']['data']); | ||
113 | - Log::debug(base64_decode($all['message']['data'])); | ||
114 | 112 | ||
115 | - return 'ok'; | 113 | + $factory->init($service)->notify($all['message']['data']); |
114 | + | ||
115 | + return Response::ok(); | ||
116 | } | 116 | } |
117 | } | 117 | } | ... | ... |
... | @@ -13,6 +13,7 @@ use App\Models\Order; | ... | @@ -13,6 +13,7 @@ use App\Models\Order; |
13 | use App\Models\User; | 13 | use App\Models\User; |
14 | use App\Models\UserProfile; | 14 | use App\Models\UserProfile; |
15 | use Carbon\Carbon; | 15 | use Carbon\Carbon; |
16 | +use Google\Service\AndroidPublisher\SubscriptionPurchasesAcknowledgeRequest; | ||
16 | use GuzzleHttp\Client; | 17 | use GuzzleHttp\Client; |
17 | use Illuminate\Support\Facades\Log; | 18 | use Illuminate\Support\Facades\Log; |
18 | use Illuminate\Support\Facades\Redis; | 19 | use Illuminate\Support\Facades\Redis; |
... | @@ -47,7 +48,11 @@ class GooglePayment implements PaymentInterface | ... | @@ -47,7 +48,11 @@ class GooglePayment implements PaymentInterface |
47 | // create the client | 48 | // create the client |
48 | $client = new \Google_Client(); | 49 | $client = new \Google_Client(); |
49 | $client->setApplicationName($applicationName); | 50 | $client->setApplicationName($applicationName); |
50 | - $client->setAuthConfig($configJson); | 51 | + try{ |
52 | + $client->setAuthConfig($configJson); | ||
53 | + }catch (\Google\Exception $exception){ | ||
54 | + Log::debug('用户授权出错了'.$exception->getMessage()); | ||
55 | + } | ||
51 | $client->setAccessType('offline'); // necessary for getting the refresh token | 56 | $client->setAccessType('offline'); // necessary for getting the refresh token |
52 | $client->setApprovalPrompt ('force'); // necessary for getting the refresh token | 57 | $client->setApprovalPrompt ('force'); // necessary for getting the refresh token |
53 | // scopes determine what google endpoints we can access. keep it simple for now. | 58 | // scopes determine what google endpoints we can access. keep it simple for now. |
... | @@ -60,97 +65,160 @@ class GooglePayment implements PaymentInterface | ... | @@ -60,97 +65,160 @@ class GooglePayment implements PaymentInterface |
60 | \Google\Service\Drive::DRIVE_METADATA_READONLY // allows reading of google drive metadata | 65 | \Google\Service\Drive::DRIVE_METADATA_READONLY // allows reading of google drive metadata |
61 | ] | 66 | ] |
62 | ); | 67 | ); |
63 | - $client->setIncludeGrantedScopes(true); | 68 | +// $client->setIncludeGrantedScopes(true); |
64 | 69 | ||
65 | // google 服务端默认获得受权 | 70 | // google 服务端默认获得受权 |
66 | - $client->useApplicationDefaultCredentials(); | 71 | +// $client->useApplicationDefaultCredentials(); |
67 | // 设置 google client_email | 72 | // 设置 google client_email |
68 | - $client->setSubject("client_email"); | 73 | +// $client->setSubject("client_email"); |
69 | 74 | ||
70 | return $client; | 75 | return $client; |
71 | } | 76 | } |
72 | 77 | ||
73 | - public function notify($order_sn, $token) | 78 | +// public function notify($order_sn, $token) |
79 | +// { | ||
80 | +// $order = Order::query()->where('order_sn', $order_sn)->first(); | ||
81 | +// | ||
82 | +// if ($order->status != Order::UNPAID) return false; | ||
83 | +// | ||
84 | +// $validator =new \Google_Service_AndroidPublisher($this->client); | ||
85 | +// | ||
86 | +// $packageName = 'pub.yiyan.parlando.Parlando'; | ||
87 | +// $productId = 'test.yiyan.vip.1.month'; | ||
88 | +//// $token = '客户端传过来的 支付凭证'; | ||
89 | +// $optps = array(); | ||
90 | +// /** | ||
91 | +// * 成功会返回 | ||
92 | +// * 返回字段解释 https://developers.google.com/android-publisher/api-ref/purchases/products | ||
93 | +// * | ||
94 | +// * 返回字段解释 中文翻译 | ||
95 | +// * consumptionState int 消费类产品的消费状态 0有待消费1已消耗 | ||
96 | +// * developerPayload string onyx系统生成的唯一ID | ||
97 | +// * kind sgring 购买的对象 | ||
98 | +// * orderId sgring 客户支付订单ID(google play 订单ID) | ||
99 | +// * purchaseState int 订单的采购状态 0购买1取消 | ||
100 | +// * purchaseTimeMillis int 时间戳 | ||
101 | +// * purchaseType int 扩展字段 0 测试 1促销 | ||
102 | +// * Array( | ||
103 | +// * [consumptionState] => 1 | ||
104 | +// * [developerPayload] => 你的订单号 | ||
105 | +// * [kind] => androidpublisher#productPurchase | ||
106 | +// * [orderId] => google play 订单号 | ||
107 | +// * [purchaseState] => 0 | ||
108 | +// * [purchaseTimeMillis] => 1542187625018 | ||
109 | +// * [purchaseType] => | ||
110 | +// * ) | ||
111 | +// */ | ||
112 | +// try { | ||
113 | +// $resp = $validator->purchases_products->get($packageName, $productId, $token, $optps); | ||
114 | +// // 对象转数组 | ||
115 | +// $resp = get_object_vars($resp); | ||
116 | +// } catch (\Exception $e) { | ||
117 | +// Log::debug('got error = ' . $e->getMessage() . PHP_EOL); | ||
118 | +// throw new \Exception('got error = ' . $e->getMessage() . PHP_EOL); | ||
119 | +// } | ||
120 | +// | ||
121 | +// if ($resp['consumptionState'] != 1) return false; | ||
122 | +// | ||
123 | +// /** 修改订单状态*/ | ||
124 | +// $order->pay_time = Carbon::now(); | ||
125 | +// $order->status = Order::PAID; | ||
126 | +// $order->save(); | ||
127 | +// | ||
128 | +// /** 给用户加会员*/ | ||
129 | +// $goods = MembershipGood::query()->find($order->order_goods->goods_id); | ||
130 | +// if ($goods->limit_unit == '月') { | ||
131 | +// $days = intval($goods->limit_days) * 30;// 计算天数 | ||
132 | +// } elseif ($goods->limit_unit == '年') { | ||
133 | +// $days = intval($goods->limit_days) * 365;// 计算天数 | ||
134 | +// } else { | ||
135 | +// $days = intval($goods->limit_days) * 1;// 计算天数 | ||
136 | +// } | ||
137 | +// $user = UserProfile::query()->find($order->user_id); | ||
138 | +// if ($user->is_vip == 0){ | ||
139 | +// $user->is_vip = 1; | ||
140 | +// $user->create_vip_time = Carbon::now(); | ||
141 | +// $user->expire_vip_time = Carbon::now()->addDays($days); | ||
142 | +// }else{ | ||
143 | +// if (Carbon::now()->gte($user->expire_vip_time)){ // 已经过期了 | ||
144 | +// $user->expire_vip_time = Carbon::now()->addDays($days); | ||
145 | +// }else{ | ||
146 | +// $user->expire_vip_time = Carbon::parse($user->expire_vip_time)->addDays($days); | ||
147 | +// } | ||
148 | +// } | ||
149 | +// | ||
150 | +// $user->buy_number += 1; | ||
151 | +// $user->buy_amount += $order->pay_amount; | ||
152 | +// $user->last_buy_time = Carbon::now(); | ||
153 | +// $user->save(); | ||
154 | +// | ||
155 | +// /** 修改订单状态*/ | ||
156 | +// $order->status = Order::DONE; | ||
157 | +// $order->save(); | ||
158 | +// | ||
159 | +// return true; | ||
160 | +// } | ||
161 | + | ||
162 | + public function notify($string) | ||
74 | { | 163 | { |
75 | - $order = Order::query()->where('order_sn', $order_sn)->first(); | 164 | + //subscriptionNotification(订阅相关)、oneTimeProductNotification(一次性购买相关)testNotification(测试发布相关) 三个不会同时存在任意2个 |
76 | - | 165 | + //subscriptionNotification说明 |
77 | - if ($order->status != Order::UNPAID) return false; | 166 | + |
78 | - | 167 | + //参数名 说明 |
79 | - $validator =new \Google_Service_AndroidPublisher($this->client); | 168 | + //version 此通知的版本。最初,此值为“1.0”。此版本与其他版本字段不同。 |
80 | - | 169 | + //notificationType int 订阅的 notificationType 可以参考下面的表 |
81 | - $packageName = 'pub.yiyan.parlando.Parlando'; | 170 | + //purchaseToken 购买订阅时向用户设备提供的令牌 |
82 | - $productId = 'test.yiyan.vip.1.month'; | 171 | + //subscriptionId 所购买订阅的 ID(例如“monthly001”) |
83 | -// $token = '客户端传过来的 支付凭证'; | 172 | + |
84 | - $optps = array(); | 173 | + //SUBSCRIPTION_RECOVERED - 从帐号保留状态恢复了订阅。 |
85 | - /** | 174 | + //SUBSCRIPTION_RENEWED - 续订了处于活动状态的订阅。 |
86 | - * 成功会返回 | 175 | + //SUBSCRIPTION_CANCELED - 自愿或非自愿地取消了订阅。如果是自愿取消,在用户取消时发送。 |
87 | - * 返回字段解释 https://developers.google.com/android-publisher/api-ref/purchases/products | 176 | + //SUBSCRIPTION_PURCHASED - 购买了新的订阅。 |
88 | - * | 177 | + //SUBSCRIPTION_ON_HOLD - 订阅已进入帐号保留状态(如果已启用)。 |
89 | - * 返回字段解释 中文翻译 | 178 | + //SUBSCRIPTION_IN_GRACE_PERIOD - 订阅已进入宽限期(如果已启用)。 |
90 | - * consumptionState int 消费类产品的消费状态 0有待消费1已消耗 | 179 | + //SUBSCRIPTION_RESTARTED - 用户已通过 Play > 帐号 > 订阅重新激活其订阅(需要选择使用订阅恢复功能)。 |
91 | - * developerPayload string onyx系统生成的唯一ID | 180 | + //SUBSCRIPTION_PRICE_CHANGE_CONFIRMED - 用户已成功确认订阅价格变动。 |
92 | - * kind sgring 购买的对象 | 181 | + //SUBSCRIPTION_DEFERRED - 订阅的续订时间点已延期。 |
93 | - * orderId sgring 客户支付订单ID(google play 订单ID) | 182 | + //SUBSCRIPTION_PAUSED - 订阅已暂停。 |
94 | - * purchaseState int 订单的采购状态 0购买1取消 | 183 | + //SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED - 订阅暂停计划已更改。 |
95 | - * purchaseTimeMillis int 时间戳 | 184 | + //SUBSCRIPTION_REVOKED - 用户在到期时间之前已撤消订阅。 |
96 | - * purchaseType int 扩展字段 0 测试 1促销 | 185 | + //SUBSCRIPTION_EXPIRED - 订阅已到期。 |
97 | - * Array( | 186 | + |
98 | - * [consumptionState] => 1 | 187 | + $data = base64_decode($string); |
99 | - * [developerPayload] => 你的订单号 | 188 | + |
100 | - * [kind] => androidpublisher#productPurchase | 189 | + $packageName = $data['packageName']; |
101 | - * [orderId] => google play 订单号 | 190 | + if (isset($data['subscriptionNotification'])) { |
102 | - * [purchaseState] => 0 | 191 | + $subscriptionId = $data['subscriptionNotification']['subscriptionId']; |
103 | - * [purchaseTimeMillis] => 1542187625018 | 192 | + $purchaseToken = $data['subscriptionNotification']['purchaseToken']; |
104 | - * [purchaseType] => | 193 | + |
105 | - * ) | 194 | + |
106 | - */ | 195 | + //1.3. 根据解密后的内容去google接口做查询校验并发货(关键参数expiryTimeMillis) |
107 | - try { | 196 | + //根据解密后的内容去google接口做校验 |
108 | - $resp = $validator->purchases_products->get($packageName, $productId, $token, $optps); | 197 | + //Google文档地址 |
109 | - // 对象转数组 | 198 | + //请求域名(Get/form): |
110 | - $resp = get_object_vars($resp); | 199 | + //https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token} |
111 | - } catch (\Exception $e) { | 200 | + $validator =new \Google_Service_AndroidPublisher($this->client); |
112 | - Log::debug('got error = ' . $e->getMessage() . PHP_EOL); | 201 | + $resp = $validator->purchases_subscriptions->get($packageName, $subscriptionId, $purchaseToken); |
113 | - throw new \Exception('got error = ' . $e->getMessage() . PHP_EOL); | 202 | + |
114 | - } | 203 | + Log::debug('新订阅人员:===================='); |
204 | + Log::debug(var_export($resp,true)); | ||
205 | + Log::debug("购买状态" . $resp->getAcknowledgementState()); //0。待确认 1. 已确认 | ||
206 | + | ||
207 | + //1.4. 消耗该笔订单 | ||
208 | + //Google文档地址 | ||
209 | + //请求域名(Post/form) | ||
210 | + //https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token}:acknowledge | ||
211 | + | ||
212 | + $acknowledge = new SubscriptionPurchasesAcknowledgeRequest(); | ||
213 | + $acknowledge->developerPayload = ''; // todo 可以将我们系统的订单号、用户支付金额等存入谷歌订单里 | ||
214 | + $resp = $validator->purchases_subscriptions->acknowledge($packageName, $subscriptionId, $purchaseToken,$acknowledge); | ||
215 | + | ||
216 | + Log::debug('消耗结果:===================='); | ||
217 | + Log::debug(var_export($resp,true)); | ||
218 | + | ||
219 | + // todo 发货 | ||
115 | 220 | ||
116 | - if ($resp['consumptionState'] != 1) return false; | ||
117 | - | ||
118 | - /** 修改订单状态*/ | ||
119 | - $order->pay_time = Carbon::now(); | ||
120 | - $order->status = Order::PAID; | ||
121 | - $order->save(); | ||
122 | - | ||
123 | - /** 给用户加会员*/ | ||
124 | - $goods = MembershipGood::query()->find($order->order_goods->goods_id); | ||
125 | - if ($goods->limit_unit == '月') { | ||
126 | - $days = intval($goods->limit_days) * 30;// 计算天数 | ||
127 | - } elseif ($goods->limit_unit == '年') { | ||
128 | - $days = intval($goods->limit_days) * 365;// 计算天数 | ||
129 | - } else { | ||
130 | - $days = intval($goods->limit_days) * 1;// 计算天数 | ||
131 | - } | ||
132 | - $user = UserProfile::query()->find($order->user_id); | ||
133 | - if ($user->is_vip == 0){ | ||
134 | - $user->is_vip = 1; | ||
135 | - $user->create_vip_time = Carbon::now(); | ||
136 | - $user->expire_vip_time = Carbon::now()->addDays($days); | ||
137 | - }else{ | ||
138 | - if (Carbon::now()->gte($user->expire_vip_time)){ // 已经过期了 | ||
139 | - $user->expire_vip_time = Carbon::now()->addDays($days); | ||
140 | - }else{ | ||
141 | - $user->expire_vip_time = Carbon::parse($user->expire_vip_time)->addDays($days); | ||
142 | - } | ||
143 | } | 221 | } |
144 | 222 | ||
145 | - $user->buy_number += 1; | ||
146 | - $user->buy_amount += $order->pay_amount; | ||
147 | - $user->last_buy_time = Carbon::now(); | ||
148 | - $user->save(); | ||
149 | - | ||
150 | - /** 修改订单状态*/ | ||
151 | - $order->status = Order::DONE; | ||
152 | - $order->save(); | ||
153 | - | ||
154 | - return true; | ||
155 | } | 223 | } |
156 | } | 224 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
1 | -{"web":{"client_id":"724392566830-jv6gqcb7vv8q9vavihhu5siccdit35op.apps.googleusercontent.com","project_id":"pc-api-7482901338487549764-603","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"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","redirect_uris":["https://api.yiyan.pub/auth/google/callback","http://api.parlando.ink/auth/google/callback","https://www.yiyan.pub/auth/google/callback"],"javascript_origins":["https://www.yiyan.pub","http://www.yiyan.pub","http://api.parlando.ink","https://api.parlando.ink"]}} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +{"web":{"client_id":"724392566830-jv6gqcb7vv8q9vavihhu5siccdit35op.apps.googleusercontent.com","project_id":"pc-api-7482901338487549764-603","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","redirect_uris":["https://api.parlando.ink/auth/google/callback"],"javascript_origins":["https://www.yiyan.pub","https://api.parlando.ink"]}} | ||
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
1 | +{ | ||
2 | + "type": "service_account", | ||
3 | + "project_id": "pc-api-7482901338487549764-603", | ||
4 | + "private_key_id": "566eccf76b913f7999fe0f2b433c6970ebf15eb8", | ||
5 | + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCd4Ujb46oBo1A3\nxqC0+tYJB5exDYLXmL0NVYdYYh14MYcqWigYt4NZjlyWvWHktLEBKMXddEiHCmv/\nCQzl/LBz8ONhhBaSXBxCJvmZUcuq5C1ciCQ353rohBbT4BCcDo3NphkBs/DDzgIh\nuljBS7XVoRoyv2+yrWqaricyCNqUccvDaFk3R9AZDTIYkeD4qE2reTE5Z05LOMKv\nxaUeSFZoeXb6WWQklU5TxYVFgaFg1iANyKBBVCWEylK7w9PaZTyFZnxsONTDyVxn\nm5//VfZxYg07cNO8/xLSUj3NBT22E5lEyjRgMBVX4DFvxpZrOlTVY1XO7cND5+yD\noLvDcobjAgMBAAECggEAJzHcsqpMdGek7JPlJcj4BfnakNv31apXlM3c8fY5trMl\nCUCkn64/b6ZGGi4d9XdeUhlbNeU+dDgEI6aNizM2YzI0YOs351HyugGPCZ8i3uQS\n1tv9kdtnyf2w5RzFQtjiH2HS53dSmGm2YcUvb51qIQUDygF4q3Ud+BSwKl3EVgGe\nB7VtoXKYkdLDNytsWm8ifzuc6PViY2VFOA7t9qyH9ytE5klvn9GjJzht6Cm32iYO\ntjikU7SeNZJNm0a6wcI00HzMPSLk5jN+p1mOvV37dyQpPwizHR790RYkoy15GicP\nE1j1j5bQc06emXcUFOWYnXtc7J/ECzFIgbs4K/i6QQKBgQDcE8eDZLrgxSOuscu1\n3UyYsCCM6L3BCFnLIbRjvNd1yA4w8Gq3RJ6pINEAvXgayj2517X10QwF0V+AU8UB\nuEHrc/2PtpRozSxKd/CCMT2Y9qr+4yfh9cDTQbBXXzO24uzB5+c4Zo9LR4FzVgKh\nFr8lnXdUD+qWUYXF0f6DzJrfkwKBgQC3poLC5VV8fa6WSK4B+quHcMFWO0pON3P+\njTckyBW7t+Ad5DIdW01LqAa4ciQFuZcYcnDH41lOpkliIbA+CGGVsN6DQhIHDn4H\nOTVDhZRO7ErcEfPhq0P+C50fBVb7bFcQWMOAQxIbwWXLCHZtCc93S//beucYQbIe\nVrFTQrMtcQKBgHo8njdzznyj4uLYLC6yYSX5xcqeRy8dZUp3SQuQyxfHa2JxVsS+\nX2XPLWc81aYDqO89SfrkBsqAdYwAe08uOab+wNp+7cWcGDqwjayyjuUUNPvnzbIq\n3tQ4CyssXLv7JMe69+mSxYppiBQ4tLMmwDqzUKEnSgP9+dBbiANKtMbzAoGAHZBK\ngIFWj6HT1xGAIYVu03DNTspgndLDc3jcJamoBf4FsAoqHxuxh7pWyp5lOh60OhVC\nHot0tvqB2bA+pN3Ih8ZfK5YZPNWSaCtHbcU1KLdVHbQuJGfjnCPWeUXsyLCaG2GO\npzkk0x8A+fw0xDzODxBG8dgJF5iLyeJ+zT5xhaECgYEAlGXBbqd8hmwYQscTMLjq\nLGzjid9WeFRiV8xCUKFF+ToTBga7j899uRQdWDTpQRc+QSs3nspPJ9Splvbxk9Xz\n5qiIiX3qBFxyCNEH8c9EwQtLfwDkD2qFD68/5cFTyG61uYmKNNtjIa7p4gXF56E7\nLo1vnD2GtG62LkJfzJnCsaE=\n-----END PRIVATE KEY-----\n", | ||
6 | + "client_email": "google-pay-for-parlando@pc-api-7482901338487549764-603.iam.gserviceaccount.com", | ||
7 | + "client_id": "115677870448624637412", | ||
8 | + "auth_uri": "https://accounts.google.com/o/oauth2/auth", | ||
9 | + "token_uri": "https://oauth2.googleapis.com/token", | ||
10 | + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", | ||
11 | + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/google-pay-for-parlando%40pc-api-7482901338487549764-603.iam.gserviceaccount.com" | ||
12 | +} |
-
Please register or login to post a comment