Showing
5 changed files
with
183 additions
and
4 deletions
app/Console/Commands/DevGoogle.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace App\Console\Commands; | ||
4 | + | ||
5 | +use App\Payment\GooglePayment; | ||
6 | +use Illuminate\Console\Command; | ||
7 | + | ||
8 | +class DevGoogle extends Command | ||
9 | +{ | ||
10 | + /** | ||
11 | + * The name and signature of the console command. | ||
12 | + * | ||
13 | + * @var string | ||
14 | + */ | ||
15 | + protected $signature = 'dev:gp'; | ||
16 | + | ||
17 | + /** | ||
18 | + * The console command description. | ||
19 | + * | ||
20 | + * @var string | ||
21 | + */ | ||
22 | + protected $description = 'Command description'; | ||
23 | + | ||
24 | + /** | ||
25 | + * Create a new command instance. | ||
26 | + * | ||
27 | + * @return void | ||
28 | + */ | ||
29 | + public function __construct() | ||
30 | + { | ||
31 | + parent::__construct(); | ||
32 | + } | ||
33 | + | ||
34 | + /** | ||
35 | + * Execute the console command. | ||
36 | + * | ||
37 | + * @return int | ||
38 | + */ | ||
39 | + public function handle() | ||
40 | + { | ||
41 | + $gp = new GooglePayment(); | ||
42 | + | ||
43 | + | ||
44 | + return 0; | ||
45 | + } | ||
46 | +} |
... | @@ -33,11 +33,24 @@ class PayController extends Controller | ... | @@ -33,11 +33,24 @@ class PayController extends Controller |
33 | * Store a newly created resource in storage. | 33 | * Store a newly created resource in storage. |
34 | * | 34 | * |
35 | * @param \Illuminate\Http\Request $request | 35 | * @param \Illuminate\Http\Request $request |
36 | - * @return \Illuminate\Http\Response | 36 | + * @param \App\Payment\PaymentFactory $factory |
37 | + * @return \Illuminate\Http\JsonResponse | ||
37 | */ | 38 | */ |
38 | - public function store(Request $request) | 39 | + public function store(Request $request, PaymentFactory $factory) |
39 | { | 40 | { |
40 | // 回调 | 41 | // 回调 |
42 | + $order_sn = $request->post('order_sn'); | ||
43 | + $pay_type = $request->post('pay_type'); | ||
44 | + $token = $request->post('token'); | ||
45 | + | ||
46 | +// $order = Order::query()->where('order_sn', $order_sn)->first(); | ||
47 | +// | ||
48 | +// if ($order->status != Order::UNPAID) return Response::fail('订单错误!'); | ||
49 | + | ||
50 | + $payment = $factory->init($pay_type)->notify($order_sn, $token); | ||
51 | + | ||
52 | + if ($payment) return Response::success(['order_sn' => $order_sn], '支付成功'); | ||
53 | + else return Response::fail('订单错误!'); | ||
41 | } | 54 | } |
42 | 55 | ||
43 | /** | 56 | /** | ... | ... |
... | @@ -22,11 +22,11 @@ class GooglePayment implements PaymentInterface | ... | @@ -22,11 +22,11 @@ class GooglePayment implements PaymentInterface |
22 | 22 | ||
23 | const IS_SANDBOX = true; | 23 | const IS_SANDBOX = true; |
24 | 24 | ||
25 | - | 25 | + public $client; |
26 | 26 | ||
27 | public function __construct() | 27 | public function __construct() |
28 | { | 28 | { |
29 | - | 29 | + $this->client = $this->getGoogleClient(); |
30 | } | 30 | } |
31 | 31 | ||
32 | 32 | ||
... | @@ -35,4 +35,122 @@ class GooglePayment implements PaymentInterface | ... | @@ -35,4 +35,122 @@ class GooglePayment implements PaymentInterface |
35 | { | 35 | { |
36 | // 查询订单对应的产品id | 36 | // 查询订单对应的产品id |
37 | } | 37 | } |
38 | + | ||
39 | + private function getGoogleClient() | ||
40 | + { | ||
41 | + // load our config.json that contains our credentials for accessing google's api as a json string | ||
42 | + $configJson = public_path().'/client_secret_724392566830-jv6gqcb7vv8q9vavihhu5siccdit35op.apps.googleusercontent.com.json'; | ||
43 | + | ||
44 | + // define an application name | ||
45 | + $applicationName = 'Parlando一言临境'; | ||
46 | + | ||
47 | + // create the client | ||
48 | + $client = new \Google_Client(); | ||
49 | + $client->setApplicationName($applicationName); | ||
50 | + $client->setAuthConfig($configJson); | ||
51 | + $client->setAccessType('offline'); // necessary for getting the refresh token | ||
52 | + $client->setApprovalPrompt ('force'); // necessary for getting the refresh token | ||
53 | + // scopes determine what google endpoints we can access. keep it simple for now. | ||
54 | + $client->setScopes( | ||
55 | + [ | ||
56 | + \Google\Service\Oauth2::USERINFO_PROFILE, | ||
57 | + \Google\Service\Oauth2::USERINFO_EMAIL, | ||
58 | + \Google\Service\Oauth2::OPENID, | ||
59 | + \Google_Service_AndroidPublisher::ANDROIDPUBLISHER, | ||
60 | + \Google\Service\Drive::DRIVE_METADATA_READONLY // allows reading of google drive metadata | ||
61 | + ] | ||
62 | + ); | ||
63 | + $client->setIncludeGrantedScopes(true); | ||
64 | + | ||
65 | + // google 服务端默认获得受权 | ||
66 | + $client->useApplicationDefaultCredentials(); | ||
67 | + // 设置 google client_email | ||
68 | + $client->setSubject("client_email"); | ||
69 | + | ||
70 | + return $client; | ||
71 | + } | ||
72 | + | ||
73 | + public function notify($order_sn, $token) | ||
74 | + { | ||
75 | + $order = Order::query()->where('order_sn', $order_sn)->first(); | ||
76 | + | ||
77 | + if ($order->status != Order::UNPAID) return false; | ||
78 | + | ||
79 | + $validator =new \Google_Service_AndroidPublisher($this->client); | ||
80 | + | ||
81 | + $packageName = 'pub.yiyan.parlando.Parlando'; | ||
82 | + $productId = 'test.yiyan.vip.1.month'; | ||
83 | +// $token = '客户端传过来的 支付凭证'; | ||
84 | + $optps = array(); | ||
85 | + /** | ||
86 | + * 成功会返回 | ||
87 | + * 返回字段解释 https://developers.google.com/android-publisher/api-ref/purchases/products | ||
88 | + * | ||
89 | + * 返回字段解释 中文翻译 | ||
90 | + * consumptionState int 消费类产品的消费状态 0有待消费1已消耗 | ||
91 | + * developerPayload string onyx系统生成的唯一ID | ||
92 | + * kind sgring 购买的对象 | ||
93 | + * orderId sgring 客户支付订单ID(google play 订单ID) | ||
94 | + * purchaseState int 订单的采购状态 0购买1取消 | ||
95 | + * purchaseTimeMillis int 时间戳 | ||
96 | + * purchaseType int 扩展字段 0 测试 1促销 | ||
97 | + * Array( | ||
98 | + * [consumptionState] => 1 | ||
99 | + * [developerPayload] => 你的订单号 | ||
100 | + * [kind] => androidpublisher#productPurchase | ||
101 | + * [orderId] => google play 订单号 | ||
102 | + * [purchaseState] => 0 | ||
103 | + * [purchaseTimeMillis] => 1542187625018 | ||
104 | + * [purchaseType] => | ||
105 | + * ) | ||
106 | + */ | ||
107 | + try { | ||
108 | + $resp = $validator->purchases_products->get($packageName, $productId, $token, $optps); | ||
109 | + // 对象转数组 | ||
110 | + $resp = get_object_vars($resp); | ||
111 | + } catch (\Exception $e) { | ||
112 | + Log::debug('got error = ' . $e->getMessage() . PHP_EOL); | ||
113 | + throw new \Exception('got error = ' . $e->getMessage() . PHP_EOL); | ||
114 | + } | ||
115 | + | ||
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 | + } | ||
144 | + | ||
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 | + } | ||
38 | } | 156 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -8,6 +8,7 @@ | ... | @@ -8,6 +8,7 @@ |
8 | "php": "^7.3|^8.0", | 8 | "php": "^7.3|^8.0", |
9 | "dcat/laravel-admin": "2.*", | 9 | "dcat/laravel-admin": "2.*", |
10 | "fruitcake/laravel-cors": "^2.0", | 10 | "fruitcake/laravel-cors": "^2.0", |
11 | + "google/apiclient": "^2.0", | ||
11 | "guzzlehttp/guzzle": "^7.0.1", | 12 | "guzzlehttp/guzzle": "^7.0.1", |
12 | "jiannei/laravel-enum": "^3.0", | 13 | "jiannei/laravel-enum": "^3.0", |
13 | "jiannei/laravel-response": "^4.0", | 14 | "jiannei/laravel-response": "^4.0", | ... | ... |
public/client_secret_724392566830-jv6gqcb7vv8q9vavihhu5siccdit35op.apps.googleusercontent.com.json
0 → 100644
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://www.yiyan.pub/auth/google/callback"],"javascript_origins":["https://www.yiyan.pub","http://www.yiyan.pub"]}} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment