GooglePayment.php 12.7 KB
<?php
/**
 * Created by PhpStorm.
 * User: lishuai
 * Date: 2022/2/15
 * Time: 4:23 PM
 */

namespace App\Payment;

use App\Models\MembershipGood;
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;

class GooglePayment implements PaymentInterface
{

    const IS_SANDBOX = true;

    const SUBSCRIPTION_RECOVERED = 1; //- 从帐号保留状态恢复了订阅。
    const SUBSCRIPTION_RENEWED = 2;  // 续订了处于活动状态的订阅。
    const SUBSCRIPTION_CANCELED = 3;  // 自愿或非自愿地取消了订阅。如果是自愿取消,在用户取消时发送。
    const SUBSCRIPTION_PURCHASED = 4;  // 购买了新的订阅。
    const SUBSCRIPTION_ON_HOLD = 5;  // 订阅已进入帐号保留状态(如果已启用)。
    const SUBSCRIPTION_IN_GRACE_PERIOD = 6;  // 订阅已进入宽限期(如果已启用)。
    const SUBSCRIPTION_RESTARTED = 7;  // 用户已通过 Play > 帐号 > 订阅重新激活其订阅(需要选择使用订阅恢复功能)。
    const SUBSCRIPTION_PRICE_CHANGE_CONFIRMED = 8;  // 用户已成功确认订阅价格变动。
    const SUBSCRIPTION_DEFERRED = 9;  // 订阅的续订时间点已延期。
    const SUBSCRIPTION_PAUSED = 10;  // 订阅已暂停。
    const SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED = 11;  // 订阅暂停计划已更改。
    const SUBSCRIPTION_REVOKED = 12;  // 用户在到期时间之前已撤消订阅。
    const SUBSCRIPTION_EXPIRED = 13;  // 订阅已到期。

    const ONE_TIME_PRODUCT_PURCHASED  = 1;  //用户成功购买了一次性商品。
    const ONE_TIME_PRODUCT_CANCELED = 2;  // 用户已取消待处理的一次性商品购买交易。

    public $client;

    public function __construct()
    {
        $this->client = $this->getGoogleClient();
    }

    public function prepare(Order $order)
    {
        // 查询订单对应的产品id
    }

    public function verify(Order $order, $token)
    {
        // 绑定order 和 originalTransactionId
        $order->status = Order::PAID;
        $order->save();

        // 修改用户状态
        $profile = UserProfile::query()->find($order->user_id);
        $profile->is_vip = UserProfile::WAIT_VIP;
        $profile->save();
        return true;
    }

    private function getGoogleClient()
    {
        $credentials_file = public_path().'/pc-api-7482901338487549764-603-566eccf76b91.json';
        $client = new \Google_Client();
        try{
            $client->setAuthConfig($credentials_file);
        }catch (\Google\Exception $exception){
            Log::debug('用户授权出错了'.$exception->getMessage());
        }
        $applicationName = 'Parlando一言临境';
        $client->setApplicationName($applicationName);
        $client->setScopes(
            [
                \Google_Service_AndroidPublisher::ANDROIDPUBLISHER,
            ]
        );

        return $client;
    }

//    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)
    {
        //参数名 说明
        //version 此通知的版本。最初,此值为“1.0”。此版本与其他版本字段不同。
        //notificationType int 订阅的 notificationType 可以参考下面的表
        //purchaseToken 购买订阅时向用户设备提供的令牌
        //subscriptionId 所购买订阅的 ID(例如“monthly001”)
        $data = json_decode(base64_decode($string),true);
        Log::debug('返回的数据:====================');
        Log::debug(print_r($data,true));

        $packageName = $data['packageName'];
        if (isset($data['subscriptionNotification'])) {
            $subscriptionId = $data['subscriptionNotification']['subscriptionId'];
            $purchaseToken = $data['subscriptionNotification']['purchaseToken'];
            try{
                $validator =new \Google_Service_AndroidPublisher($this->client);
                $resp = $validator->purchases_subscriptions->get($packageName, $subscriptionId, $purchaseToken);
            }catch (\Exception $exception){
                Log::error("查询订阅出错了:==================");
                Log::error("packageName:".$packageName);
                Log::error("subscriptionId:". $subscriptionId);
                Log::error("purchaseToken:".$purchaseToken);
                Log::error("===============================");
                return false;
            }
            $orderSn = $resp->getObfuscatedExternalAccountId();
            $order = Order::query()->where('order_sn',$orderSn)->first();
            if (!$order) {
                Log::error("查无此订单");
                return false;
            }
            switch ($data['subscriptionNotification']['notificationType']){
                case self::SUBSCRIPTION_PURCHASED:
                    if ($resp->getPaymentState() == 1) $order->status = Order::DONE;
                    /** 修改订单状态*/
                    $order->pay_time = Carbon::now();
                    $order->pay_number = $resp->getOrderId();
                    $order->pay_type = $resp->getKind();
//                    $order->callback = $string;
                    $order->save();
                    /** 给用户加会员*/
                    $user = UserProfile::query()->find($order->user_id);
                    $user->is_vip = 1;
                    $user->create_vip_time = Carbon::createFromTimestampMs($resp->getStartTimeMillis());
                    $user->expire_vip_time = Carbon::createFromTimestampMs($resp->getExpiryTimeMillis());
                    $user->buy_number += 1;
                    $user->buy_amount += $order->pay_amount;
                    $user->last_buy_time = Carbon::now();
                    $user->save();
                    break;
                case self::SUBSCRIPTION_RENEWED :
                case self::SUBSCRIPTION_RESTARTED:
                    /** 给用户加会员*/
                    $user = UserProfile::query()->find($order->user_id);
                    $user->is_vip = 1;
                    $user->expire_vip_time = Carbon::createFromTimestampMs($resp->getExpiryTimeMillis());
                    $user->buy_number += 1;
                    $user->buy_amount += $order->pay_amount;
                    $user->last_buy_time = Carbon::now();
                    $user->save();
                    break;
                case self::SUBSCRIPTION_CANCELED:
                case self::SUBSCRIPTION_EXPIRED:
                    /** 给用户取消会员*/
                    $user = UserProfile::query()->find($order->user_id);
                    $user->is_vip = 0;
                    $user->expire_vip_time = Carbon::createFromTimestampMs($resp->getExpiryTimeMillis());
                    $user->save();
                    break;
                default:
                    Log::debug('特殊通知类型:'.$data['notificationType'].' ====================');
                    Log::debug(var_export($resp,true));
            }
        }elseif (isset($data['subscriptionNotification'])){
            // oneTimeProductNotification  一次性购买相关
            /**
             * 成功会返回返回字段解释   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] =>
             * )
             */

            $productId = $data['OneTimeProductNotification']['purchaseToken'];
            $purchaseToken = $data['OneTimeProductNotification']['purchaseToken'];
            try {
                $validator =new \Google_Service_AndroidPublisher($this->client);
                $resp = $validator->purchases_products->get($packageName, $productId, $purchaseToken);
            } catch (\Exception $e) {
                Log::error("查询订阅出错了:==================");
                Log::error("packageName:".$packageName);
                Log::error("productId:". $productId);
                Log::error("purchaseToken:".$purchaseToken);
                Log::error("===============================");
                return false;
            }
            // ...
            switch ($data['subscriptionNotification']['notificationType']){
                case self::ONE_TIME_PRODUCT_PURCHASED :
                case self::ONE_TIME_PRODUCT_CANCELED :
                default:
                    Log::debug('特殊通知类型:'.$data['notificationType'].' ====================');
                    Log::debug(var_export($resp,true));
                    break;
            }
        }else{
            Log::debug("收到测试通知信息 version:" . $data['testNotification']['version']);
        }

    }
}