李帅

1.打印谷歌订阅日志

......@@ -38,9 +38,9 @@ class DevGoogle extends Command
*/
public function handle()
{
dd(1);
// dd(1);
$gp = new GooglePayment();
dd($gp->client);
return 0;
}
......
......@@ -106,12 +106,12 @@ class PayController extends Controller
//
}
public function iapCallback(Request $request,$service)
public function iapCallback(Request $request, PaymentFactory $factory, $service)
{
$all = $request->all();
Log::debug($all['message']['data']);
Log::debug(base64_decode($all['message']['data']));
return 'ok';
$factory->init($service)->notify($all['message']['data']);
return Response::ok();
}
}
......
......@@ -13,6 +13,7 @@ use App\Models\Order;
use App\Models\User;
use App\Models\UserProfile;
use Carbon\Carbon;
use Google\Service\AndroidPublisher\SubscriptionPurchasesAcknowledgeRequest;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
......@@ -47,7 +48,11 @@ class GooglePayment implements PaymentInterface
// create the client
$client = new \Google_Client();
$client->setApplicationName($applicationName);
$client->setAuthConfig($configJson);
try{
$client->setAuthConfig($configJson);
}catch (\Google\Exception $exception){
Log::debug('用户授权出错了'.$exception->getMessage());
}
$client->setAccessType('offline'); // necessary for getting the refresh token
$client->setApprovalPrompt ('force'); // necessary for getting the refresh token
// scopes determine what google endpoints we can access. keep it simple for now.
......@@ -60,97 +65,160 @@ class GooglePayment implements PaymentInterface
\Google\Service\Drive::DRIVE_METADATA_READONLY // allows reading of google drive metadata
]
);
$client->setIncludeGrantedScopes(true);
// $client->setIncludeGrantedScopes(true);
// google 服务端默认获得受权
$client->useApplicationDefaultCredentials();
// $client->useApplicationDefaultCredentials();
// 设置 google client_email
$client->setSubject("client_email");
// $client->setSubject("client_email");
return $client;
}
public function notify($order_sn, $token)
// public function notify($order_sn, $token)
// {
// $order = Order::query()->where('order_sn', $order_sn)->first();
//
// if ($order->status != Order::UNPAID) return false;
//
// $validator =new \Google_Service_AndroidPublisher($this->client);
//
// $packageName = 'pub.yiyan.parlando.Parlando';
// $productId = 'test.yiyan.vip.1.month';
//// $token = '客户端传过来的 支付凭证';
// $optps = array();
// /**
// * 成功会返回
// * 返回字段解释 https://developers.google.com/android-publisher/api-ref/purchases/products
// *
// * 返回字段解释 中文翻译
// * consumptionState int 消费类产品的消费状态 0有待消费1已消耗
// * developerPayload string onyx系统生成的唯一ID
// * kind sgring 购买的对象
// * orderId sgring 客户支付订单ID(google play 订单ID)
// * purchaseState int 订单的采购状态 0购买1取消
// * purchaseTimeMillis int 时间戳
// * purchaseType int 扩展字段 0 测试 1促销
// * Array(
// * [consumptionState] => 1
// * [developerPayload] => 你的订单号
// * [kind] => androidpublisher#productPurchase
// * [orderId] => google play 订单号
// * [purchaseState] => 0
// * [purchaseTimeMillis] => 1542187625018
// * [purchaseType] =>
// * )
// */
// try {
// $resp = $validator->purchases_products->get($packageName, $productId, $token, $optps);
// // 对象转数组
// $resp = get_object_vars($resp);
// } catch (\Exception $e) {
// Log::debug('got error = ' . $e->getMessage() . PHP_EOL);
// throw new \Exception('got error = ' . $e->getMessage() . PHP_EOL);
// }
//
// if ($resp['consumptionState'] != 1) return false;
//
// /** 修改订单状态*/
// $order->pay_time = Carbon::now();
// $order->status = Order::PAID;
// $order->save();
//
// /** 给用户加会员*/
// $goods = MembershipGood::query()->find($order->order_goods->goods_id);
// if ($goods->limit_unit == '月') {
// $days = intval($goods->limit_days) * 30;// 计算天数
// } elseif ($goods->limit_unit == '年') {
// $days = intval($goods->limit_days) * 365;// 计算天数
// } else {
// $days = intval($goods->limit_days) * 1;// 计算天数
// }
// $user = UserProfile::query()->find($order->user_id);
// if ($user->is_vip == 0){
// $user->is_vip = 1;
// $user->create_vip_time = Carbon::now();
// $user->expire_vip_time = Carbon::now()->addDays($days);
// }else{
// if (Carbon::now()->gte($user->expire_vip_time)){ // 已经过期了
// $user->expire_vip_time = Carbon::now()->addDays($days);
// }else{
// $user->expire_vip_time = Carbon::parse($user->expire_vip_time)->addDays($days);
// }
// }
//
// $user->buy_number += 1;
// $user->buy_amount += $order->pay_amount;
// $user->last_buy_time = Carbon::now();
// $user->save();
//
// /** 修改订单状态*/
// $order->status = Order::DONE;
// $order->save();
//
// return true;
// }
public function notify($string)
{
$order = Order::query()->where('order_sn', $order_sn)->first();
if ($order->status != Order::UNPAID) return false;
$validator =new \Google_Service_AndroidPublisher($this->client);
$packageName = 'pub.yiyan.parlando.Parlando';
$productId = 'test.yiyan.vip.1.month';
// $token = '客户端传过来的 支付凭证';
$optps = array();
/**
* 成功会返回
* 返回字段解释 https://developers.google.com/android-publisher/api-ref/purchases/products
*
* 返回字段解释 中文翻译
* consumptionState int 消费类产品的消费状态 0有待消费1已消耗
* developerPayload string onyx系统生成的唯一ID
* kind sgring 购买的对象
* orderId sgring 客户支付订单ID(google play 订单ID)
* purchaseState int 订单的采购状态 0购买1取消
* purchaseTimeMillis int 时间戳
* purchaseType int 扩展字段 0 测试 1促销
* Array(
* [consumptionState] => 1
* [developerPayload] => 你的订单号
* [kind] => androidpublisher#productPurchase
* [orderId] => google play 订单号
* [purchaseState] => 0
* [purchaseTimeMillis] => 1542187625018
* [purchaseType] =>
* )
*/
try {
$resp = $validator->purchases_products->get($packageName, $productId, $token, $optps);
// 对象转数组
$resp = get_object_vars($resp);
} catch (\Exception $e) {
Log::debug('got error = ' . $e->getMessage() . PHP_EOL);
throw new \Exception('got error = ' . $e->getMessage() . PHP_EOL);
}
//subscriptionNotification(订阅相关)、oneTimeProductNotification(一次性购买相关)testNotification(测试发布相关) 三个不会同时存在任意2个
//subscriptionNotification说明
//参数名 说明
//version 此通知的版本。最初,此值为“1.0”。此版本与其他版本字段不同。
//notificationType int 订阅的 notificationType 可以参考下面的表
//purchaseToken 购买订阅时向用户设备提供的令牌
//subscriptionId 所购买订阅的 ID(例如“monthly001”)
//SUBSCRIPTION_RECOVERED - 从帐号保留状态恢复了订阅。
//SUBSCRIPTION_RENEWED - 续订了处于活动状态的订阅。
//SUBSCRIPTION_CANCELED - 自愿或非自愿地取消了订阅。如果是自愿取消,在用户取消时发送。
//SUBSCRIPTION_PURCHASED - 购买了新的订阅。
//SUBSCRIPTION_ON_HOLD - 订阅已进入帐号保留状态(如果已启用)。
//SUBSCRIPTION_IN_GRACE_PERIOD - 订阅已进入宽限期(如果已启用)。
//SUBSCRIPTION_RESTARTED - 用户已通过 Play > 帐号 > 订阅重新激活其订阅(需要选择使用订阅恢复功能)。
//SUBSCRIPTION_PRICE_CHANGE_CONFIRMED - 用户已成功确认订阅价格变动。
//SUBSCRIPTION_DEFERRED - 订阅的续订时间点已延期。
//SUBSCRIPTION_PAUSED - 订阅已暂停。
//SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED - 订阅暂停计划已更改。
//SUBSCRIPTION_REVOKED - 用户在到期时间之前已撤消订阅。
//SUBSCRIPTION_EXPIRED - 订阅已到期。
$data = base64_decode($string);
$packageName = $data['packageName'];
if (isset($data['subscriptionNotification'])) {
$subscriptionId = $data['subscriptionNotification']['subscriptionId'];
$purchaseToken = $data['subscriptionNotification']['purchaseToken'];
//1.3. 根据解密后的内容去google接口做查询校验并发货(关键参数expiryTimeMillis)
//根据解密后的内容去google接口做校验
//Google文档地址
//请求域名(Get/form):
//https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token}
$validator =new \Google_Service_AndroidPublisher($this->client);
$resp = $validator->purchases_subscriptions->get($packageName, $subscriptionId, $purchaseToken);
Log::debug('新订阅人员:====================');
Log::debug(var_export($resp,true));
Log::debug("购买状态" . $resp->getAcknowledgementState()); //0。待确认 1. 已确认
//1.4. 消耗该笔订单
//Google文档地址
//请求域名(Post/form)
//https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token}:acknowledge
$acknowledge = new SubscriptionPurchasesAcknowledgeRequest();
$acknowledge->developerPayload = ''; // todo 可以将我们系统的订单号、用户支付金额等存入谷歌订单里
$resp = $validator->purchases_subscriptions->acknowledge($packageName, $subscriptionId, $purchaseToken,$acknowledge);
Log::debug('消耗结果:====================');
Log::debug(var_export($resp,true));
// todo 发货
if ($resp['consumptionState'] != 1) return false;
/** 修改订单状态*/
$order->pay_time = Carbon::now();
$order->status = Order::PAID;
$order->save();
/** 给用户加会员*/
$goods = MembershipGood::query()->find($order->order_goods->goods_id);
if ($goods->limit_unit == '月') {
$days = intval($goods->limit_days) * 30;// 计算天数
} elseif ($goods->limit_unit == '年') {
$days = intval($goods->limit_days) * 365;// 计算天数
} else {
$days = intval($goods->limit_days) * 1;// 计算天数
}
$user = UserProfile::query()->find($order->user_id);
if ($user->is_vip == 0){
$user->is_vip = 1;
$user->create_vip_time = Carbon::now();
$user->expire_vip_time = Carbon::now()->addDays($days);
}else{
if (Carbon::now()->gte($user->expire_vip_time)){ // 已经过期了
$user->expire_vip_time = Carbon::now()->addDays($days);
}else{
$user->expire_vip_time = Carbon::parse($user->expire_vip_time)->addDays($days);
}
}
$user->buy_number += 1;
$user->buy_amount += $order->pay_amount;
$user->last_buy_time = Carbon::now();
$user->save();
/** 修改订单状态*/
$order->status = Order::DONE;
$order->save();
return true;
}
}
\ No newline at end of file
......
{"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
{"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
......
{
"type": "service_account",
"project_id": "pc-api-7482901338487549764-603",
"private_key_id": "566eccf76b913f7999fe0f2b433c6970ebf15eb8",
"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",
"client_email": "google-pay-for-parlando@pc-api-7482901338487549764-603.iam.gserviceaccount.com",
"client_id": "115677870448624637412",
"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_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/google-pay-for-parlando%40pc-api-7482901338487549764-603.iam.gserviceaccount.com"
}