paypal订阅与google订阅的不同之处:

1. google设置首周优惠时,用户第一次订阅会有优惠,用户退订之后再次订阅就不会执行首周订阅优惠; 而paypal设置首周优惠时,用户的每次取消后订阅都视为新订阅,都满足首周优惠条件

2. paypal订阅成功回调时不会返回 “订阅到期的时间”

订阅流程及创建计划查看:https://blog.csdn.net/weixin_39461487/article/details/125900163

1、后台创建订阅计划

正式环境创建订阅计划地址:

PayPal Subscription | Automate repeat payments | PayPal US

沙盒环境创建订阅计划计划:

  • 对于您的一个沙盒业务帐户-->https://www.sandbox.paypal.com/billing/plans
  • 对于您的live帐户-->https://www.paypal.com/billing/plans

2、curl请求并订阅计划

2.1 初始化参数

class PaypalService extends Service
{public $baseUrl;public $paypalParams;public $access_token;public function __construct($config = []){parent::__construct();$this->paypalParams = ['return_url' => '支付成功跳转地址','cancel_url' => '支付失败跳转地址','client_id' => '','client_secret' => '',];if (!'test') {$this->baseUrl = 'https://api.paypal.com';} else {$this->baseUrl = 'https://api.sandbox.paypal.com';}}
}

2.2 获取token

官方文档地址:https://developer.paypal.com/api/rest/authentication/

public function getToken($is_expires=false){$redis = new RedisStore();$key = 'paypal_token';$token = $redis->get($key);if($token && !$is_expires) {$this->access_token = $token;return true;}$ch = curl_init();curl_setopt($ch, CURLOPT_URL,  $this->baseUrl . "/v1/oauth2/token");curl_setopt($ch, CURLOPT_HEADER, false);curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_USERPWD, $this->paypalParams['client_id'] . ':' . $this->paypalParams['client_secret']);curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=client_credentials");$result = curl_exec($ch);if (empty($result)) {curl_close($ch);return false;} else {curl_close($ch);$result = json_decode($result);$redis->set($key, $result->access_token);$redis->expireAt($key, $result->expires_in - 300);$this->access_token = $result->access_token;return true;}}

2.3 创建订阅

官方文档地址:https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_create

public function createSubscriptions($subscriptions_plan_id, $start_time = null, $is_expires=false){if(!$this->access_token) $this->getToken();if ($start_time === null) $start_time = date('c', time()+5);$subscriptionsData = ["plan_id" => $subscriptions_plan_id,"start_time" => $start_time,"quantity" => "1","auto_renewal" => 'true',"application_context" => [
//                "brand_name" => "Your brand name","locale" => "en-US","shipping_preference" => "NO_SHIPPING","user_action" => "SUBSCRIBE_NOW","payment_method" => ["payer_selected" => "PAYPAL","payee_preferred" => "IMMEDIATE_PAYMENT_REQUIRED"],"return_url" => $this->paypalParams['return_url'],"cancel_url" => $this->paypalParams['cancel_url'],]];$ch1 = curl_init();curl_setopt($ch1, CURLOPT_URL, $this->baseUrl . "/v1/billing/subscriptions");curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch1, CURLOPT_POSTFIELDS, json_encode($subscriptionsData));curl_setopt($ch1, CURLOPT_POST, true);curl_setopt($ch1, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $this->access_token,'Accept: application/json','Content-Type: application/json']);$result = json_decode(curl_exec($ch1));curl_close($ch1);if($result->error == 'invalid_token') {// token 失效时重新获取token$this->getToken(true);return $this->createSubscriptions($subscriptions_plan_id, $start_time, true);}if($result->debug_id) {return ['code' => false, 'msg' => $result->details[0]->description];}return ['code' => true, 'url' => $result->links[0]->href, 'agreement_id' => $result->id];}

2.4 查询用户订阅详情

官方文档地址:https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_get

public function getSubscriptionDetails($subscription_id, $is_expires=false){if(!$this->access_token) $this->getToken();$ch1 = curl_init();curl_setopt($ch1, CURLOPT_URL, $this->baseUrl . "/v1/billing/subscriptions/" . $subscription_id);curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch1, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $this->access_token,'Accept: application/json','Content-Type: application/json',]);$result = json_decode(curl_exec($ch1));curl_close($ch1);if($result->error == 'invalid_token') {// token 失效时重新获取token$this->getToken(true);return $this->getSubscriptionDetails($subscription_id, true);}return json_decode(json_encode($result), true);}

2.5 封装完整代码

class PaypalService extends Service
{public $baseUrl;public $paypalParams;public $access_token;public function __construct($config = []){parent::__construct();$this->paypalParams = ['return_url' => '支付成功跳转地址','cancel_url' => '支付失败跳转地址','client_id' => '','client_secret' => '',];if (!'test') {$this->baseUrl = 'https://api.paypal.com';} else {$this->baseUrl = 'https://api.sandbox.paypal.com';}}/*** 获取token* @param false $is_expires 是否强制更新token* https://developer.paypal.com/api/rest/authentication/* @return false|mixed*/public function getToken($is_expires=false){$redis = new RedisStore();$key = 'paypal_token';$token = $redis->get($key);if($token && !$is_expires) {$this->access_token = $token;return true;}$ch = curl_init();curl_setopt($ch, CURLOPT_URL,  $this->baseUrl . "/v1/oauth2/token");curl_setopt($ch, CURLOPT_HEADER, false);curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_USERPWD, $this->paypalParams['client_id'] . ':' . $this->paypalParams['client_secret']);curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=client_credentials");$result = curl_exec($ch);if (empty($result)) {curl_close($ch);return false;} else {curl_close($ch);$result = json_decode($result);$redis->set($key, $result->access_token);$redis->expireAt($key, $result->expires_in - 300);$this->access_token = $result->access_token;return true;}}/*** 创建订阅* @param $subscriptions_plan_id* @param null $start_time* @param false $is_expires 是否强制更新token* https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_create* @return array*/public function createSubscriptions($subscriptions_plan_id, $start_time = null, $is_expires=false){if(!$this->access_token) $this->getToken();if ($start_time === null) $start_time = date('c', time()+5);$subscriptionsData = ["plan_id" => $subscriptions_plan_id,"start_time" => $start_time,"quantity" => "1","auto_renewal" => 'true',"application_context" => [
//                "brand_name" => "Your brand name","locale" => "en-US","shipping_preference" => "NO_SHIPPING","user_action" => "SUBSCRIBE_NOW","payment_method" => ["payer_selected" => "PAYPAL","payee_preferred" => "IMMEDIATE_PAYMENT_REQUIRED"],"return_url" => $this->paypalParams['return_url'],"cancel_url" => $this->paypalParams['cancel_url'],]];$ch1 = curl_init();curl_setopt($ch1, CURLOPT_URL, $this->baseUrl . "/v1/billing/subscriptions");curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch1, CURLOPT_POSTFIELDS, json_encode($subscriptionsData));curl_setopt($ch1, CURLOPT_POST, true);curl_setopt($ch1, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $this->access_token,'Accept: application/json','Content-Type: application/json']);$result = json_decode(curl_exec($ch1));curl_close($ch1);if($result->error == 'invalid_token') {// token 失效时重新获取token$this->getToken(true);return $this->createSubscriptions($subscriptions_plan_id, $start_time, true);}if($result->debug_id) {return ['code' => false, 'msg' => $result->details[0]->description];}return ['code' => true, 'url' => $result->links[0]->href, 'agreement_id' => $result->id];}/*** 获取订阅计划详情* @param $subscription_id* @param false $is_expires 是否强制获取token* https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_get* @return mixed*/public function getSubscriptionDetails($subscription_id, $is_expires=false){if(!$this->access_token) $this->getToken();$ch1 = curl_init();curl_setopt($ch1, CURLOPT_URL, $this->baseUrl . "/v1/billing/subscriptions/" . $subscription_id);curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch1, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $this->access_token,'Accept: application/json','Content-Type: application/json',]);$result = json_decode(curl_exec($ch1));curl_close($ch1);if($result->error == 'invalid_token') {// token 失效时重新获取token$this->getToken(true);return $this->getSubscriptionDetails($subscription_id, true);}return json_decode(json_encode($result), true);}
}

3、订阅支付

$subscription = $this->createSubscriptions('计划id');
if($subscription['code'] === false) {return ['code' => ErrorCode::EC_UNKNOWN,'msg' => 'Paypal Subscriptions Error: ' . $subscription['msg'],'data' => [],];
}// 购买商品下单流程...
// 成功返回的结果
// 'url' => $subscription['url'],
// 'agreement_id' => $subscription['agreement_id'],

返回结果:

id:paypal生成的订阅ID

links[0]['href']:去支付的链接

object(stdClass)#189 (4) {["status"]=>string(16) "APPROVAL_PENDING"["id"]=>string(14) "I-BU64KX8FTG3C"["create_time"]=>string(20) "2022-08-09T05:32:29Z"["links"]=>array(3) {[0]=>object(stdClass)#219 (3) {["href"]=>string(90) "https://www.sandbox.paypal.com/webapps/billing/subscriptions?ba_token=BA-3P5459826W8205613"["rel"]=>string(7) "approve"["method"]=>string(3) "GET"}[1]=>object(stdClass)#220 (3) {["href"]=>string(70) "https://api.sandbox.paypal.com/v1/billing/subscriptions/I-BU64KX8FTG3C"["rel"]=>string(4) "edit"["method"]=>string(5) "PATCH"}[2]=>object(stdClass)#221 (3) {["href"]=>string(70) "https://api.sandbox.paypal.com/v1/billing/subscriptions/I-BU64KX8FTG3C"["rel"]=>string(4) "self"["method"]=>string(3) "GET"}}
}

4、订阅回调

回调需要配置webhook及回调地址

事件说明:Webhook event names

public function actionPaypal()
{$payload = @file_get_contents('php://input');$content = "=========".date('Y-m-d H:i:s',time())."==========\r\n";file_put_contents('paypal_success.log', $content . $payload . "\r\n",FILE_APPEND);$content = json_decode($payload);
}

首次订阅成功会回调两个事件:

1.BILLING.SUBSCRIPTION.ACTIVATED

=========2022-08-02 05:58:58==========
{"id":"WH-2JK13221SH228131A-85M888883CF992091V","event_version":"1.0","create_time":"2022-08-02T09:58:37.896Z","resource_type":"subscription","resource_version":"2.0","event_type":"BILLING.SUBSCRIPTION.ACTIVATED","summary":"Subscription activated","resource":{"quantity":"1","subscriber":{"email_address":"wwww@personal.example.com","payer_id":"BNMR2YZQJ9Q2L","name":{"given_name":"John","surname":"Doe"}},"create_time":"2022-08-02T09:58:05Z","plan_overridden":false,"shipping_amount":{"currency_code":"USD","value":"0.0"},"start_time":"2022-08-02T09:57:17Z","update_time":"2022-08-02T09:58:06Z","billing_info":{"outstanding_balance":{"currency_code":"USD","value":"0.0"},"cycle_executions":[{"tenure_type":"TRIAL","sequence":1,"cycles_completed":1,"cycles_remaining":0,"current_pricing_scheme_version":1,"total_cycles":1},{"tenure_type":"REGULAR","sequence":2,"cycles_completed":0,"cycles_remaining":0,"current_pricing_scheme_version":1,"total_cycles":0}],"last_payment":{"amount":{"currency_code":"USD","value":"0.99"},"time":"2022-08-02T09:58:05Z"},"next_billing_time":"2022-08-03T10:00:00Z","failed_payments_count":0},"links":[{"href":"https://api.sandbox.paypal.com/v1/billing/subscriptions/I-DL5L53KM3N/cancel","rel":"cancel","method":"POST","encType":"application/json"},{"href":"https://api.sandbox.paypal.com/v1/billing/subscriptions/I-DL5L53KM3N","rel":"edit","method":"PATCH","encType":"application/json"},{"href":"https://api.sandbox.paypal.com/v1/billing/subscriptions/I-DL5L53KM3N","rel":"self","method":"GET","encType":"application/json"},{"href":"https://api.sandbox.paypal.com/v1/billing/subscriptions/I-DL5L53KM3N/suspend","rel":"suspend","method":"POST","encType":"application/json"},{"href":"https://api.sandbox.paypal.com/v1/billing/subscriptions/I-DL5L53KM3N/capture","rel":"capture","method":"POST","encType":"application/json"}],"id":"I-DL5L53KM3N","plan_id":"P-4G238388SD824MLUPJNY","status":"ACTIVE","status_update_time":"2022-08-02T09:58:06Z"},"links":[{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-2JK13221SH228131A-85M80963CF992091V","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-2JK13221SH228131A-85M80963CF992091V/resend","rel":"resend","method":"POST"}]}

2.  PAYMENT.SALE.COMPLETED

=========2022-08-02 05:58:58==========
{"id":"WH-4AU27166UL181633V-3BU78225VU943751T","event_version":"1.0","create_time":"2022-08-02T09:58:43.670Z","resource_type":"sale","event_type":"PAYMENT.SALE.COMPLETED","summary":"Payment completed for $ 0.99 USD","resource":{"billing_agreement_id":"I-DL5L53KM3N","amount":{"total":"0.99","currency":"USD","details":{"subtotal":"0.99"}},"payment_mode":"INSTANT_TRANSFER","update_time":"2022-08-02T09:58:05Z","create_time":"2022-08-02T09:58:05Z","protection_eligibility_type":"ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE","transaction_fee":{"currency":"USD","value":"0.33"},"protection_eligibility":"ELIGIBLE","links":[{"method":"GET","rel":"self","href":"https://api.sandbox.paypal.com/v1/payments/sale/4DN9460xxx61205Y"},{"method":"POST","rel":"refund","href":"https://api.sandbox.paypal.com/v1/payments/sale/4DN9460xxx61205Y/refund"}],"id":"4DN9460xxx61205Y","state":"completed","invoice_number":""},"links":[{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-4AU27166UL181633V-3BU78225VU943751T","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-4AU27166UL181633V-3BU78225VU943751T/resend","rel":"resend","method":"POST"}]}

续订时只会回调:PAYMENT.SALE.COMPLETED

=========2022-08-03 06:25:06==========
{"id":"WH-4AU27166UL181633V-3BU78225VU943751T","event_version":"1.0","create_time":"2022-08-02T09:58:43.670Z","resource_type":"sale","event_type":"PAYMENT.SALE.COMPLETED","summary":"Payment completed for $ 0.99 USD","resource":{"billing_agreement_id":"I-DL5L53KM3N","amount":{"total":"0.99","currency":"USD","details":{"subtotal":"0.99"}},"payment_mode":"INSTANT_TRANSFER","update_time":"2022-08-02T09:58:05Z","create_time":"2022-08-02T09:58:05Z","protection_eligibility_type":"ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE","transaction_fee":{"currency":"USD","value":"0.33"},"protection_eligibility":"ELIGIBLE","links":[{"method":"GET","rel":"self","href":"https://api.sandbox.paypal.com/v1/payments/sale/4DN9460xxx61205Y"},{"method":"POST","rel":"refund","href":"https://api.sandbox.paypal.com/v1/payments/sale/4DN9460xxx61205Y/refund"}],"id":"4DN9460xxx61205Y","state":"completed","invoice_number":""},"links":[{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-4AU27166UL181633V-3BU78225VU943751T","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-4AU27166UL181633V-3BU78225VU943751T/resend","rel":"resend","method":"POST"}]}

4.1 订阅创建回调

事件:BILLING.SUBSCRIPTION.ACTIVATED

if($content->resource_type == 'subscription') {// 新建订阅if($content->event_type == 'BILLING.SUBSCRIPTION.ACTIVATED') {// 验证订单信息$agreement_id = $content->resource->id;$goodId = $content->resource->plan_id;// 支付价格$price = $content->resource->billing_info->last_payment->amount->value;// 创建时间$start_time = strtotime(str_replace('T', ' ', trim($content->resource->create_time, 'Z')));// 状态更新时间$update_time = strtotime(str_replace('T', ' ', trim($content->resource->update_time, 'Z')));// todo 验证并记录用户订阅时间...}
}

4.2 支付成功或续订成功回调

事件:PAYMENT.SALE.COMPLETED

因订阅回调与支付成功回调不知道哪个先后,所以此处订单表内记录了两个订阅的字段,agreement_id:创建订阅时返回的id,out_trade_no:订单编号

如果此支付成功回调与订阅回调时间小于1小时,证明此支付成功回调与订阅回调为同一订单,我再处理默认首次订阅处理回调走BILLING.SUBSCRIPTION.ACTIVATED

if($content->resource_type == 'sale') {if($content->event_type == 'PAYMENT.SALE.COMPLETED') {$agreement_id = $content->resource->billing_agreement_id; // 若是订阅,此字段为同意协议id,$payment_intent_new = $content->resource->id; // 订单id$update_time = strtotime(str_replace('T', ' ', trim($content->resource->update_time, 'Z')));// 支付价格$price = $content->resource->amount->total;if($agreement_id) {// 因订阅回调与支付成功回调不知道哪个先后,根据agreement_id查询首订阅订单,如果存在后续验证,不存在说明此回调在前,订阅成功回调在后,首订阅默认执行订阅成功回调$objTradeInfoOld = VipBuy::find()->andWhere(['agreement_id' => $agreement_id, 'status' => VipBuy::STATUS_SUCCESS])->one();if(objTradeInfoOld) {if($update_time - $objTradeInfoOld->notify_time <= 3600) {// 如果此支付成功回调与订阅回调时间小于1小时,证明此支付成功回调与订阅回调为同一订单return true;}$objTradeInfo = VipBuy::find()->andWhere(['out_trade_no' => $payment_intent_new, 'goods_id' => $objTradeInfoOld->goods_id, 'product' => $product])->one();if($objTradeInfo->status == VipBuy::STATUS_SUCCESS) return true;if(!$objTradeInfo) {// 此为续订订单,生成新订单并执行其他逻辑}}}}
}

4.3 取消订阅回调

取消订阅流程:

事件:BILLING.SUBSCRIPTION.CANCELLED

if($content->resource_type == 'subscription') {// 取消订阅if($content->event_type == 'BILLING.SUBSCRIPTION.CANCELLED' && $content->resource->status == 'CANCELLED') {$payment_intent = $content->resource->id;$goodId = $content->resource->plan_id;// 状态更新时间,可记录为用户取消订阅时间$update_time = strtotime(str_replace('T', ' ', trim($content->resource->status_update_time, 'Z')));// todo 取消订阅后续操作...}
}

订阅完成

php 实现paypal订阅相关推荐

  1. Java paypal如何实现付费订阅(循环扣费)

    背景 业务需求要集成Paypal,实现循环扣款功能,初识PayPal开发文档,搞得人一脸懵逼,终于完整实现所有功能,这里对如何使用Paypal的支付接口做下总结. 账号申请 页面地址:https:// ...

  2. java对接PayPal实现自动续费功能

    欢迎大家进群,一起探讨学习 微信公众号,每天给大家提供技术干货 博主技术笔记 博主网站地址1 博主网站地址2 博主开源微服架构前后端分离技术博客项目源码地址,欢迎各位star 由于同事对接PayPal ...

  3. Paypal 实现自动订阅

    官方给出的自动续费分五步 Intergrate Subscriptions.实际开发中,还需要实现支付结果处理和订阅管理等: 事先创建计划,并激活: 用户创建订阅,跳转到paypal网站等待用户同意: ...

  4. java 对接 PayPal 或者 Stripe 支付,订阅

    简单说一下订阅的思路,要处理的问题(PayPal和stripe差不多): 1.注册开发者平台账号,获取key,secret 2.动态创建商品,设置价格:从数据库取出商品和价格,代码创建 3.创建完商品 ...

  5. PayPal 支付-Checkout 收银台和 Subscription 订阅计划全过程分享

    废话不多说,我们先从请求的生命周期来分析,逐步实现整个过程. 一.生命周期 1. Checkout - 收银台支付 拆解流程如图所示 (过程类似支付宝的收银台): 流程详解: 本地应用组装好参数并请求 ...

  6. 全球支付平台paypal社招一面,二面合并面经

    来自:程序员面试 作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 paypal一面面经 1.做一下自我介绍吧,你的XXX项目说一下?你这个线程池的核心线程数怎么设置的?主要考虑啥? 你这 ...

  7. python每月定时_paypal每月订阅计划设置为每月的第一天,并进行每月定期付款 – django python...

    我想设置一个月度订阅计划. 每个月初,买家将收取100美元的费用. 这是我制作的结算方案代码: billing_plan = paypalrestsdk.BillingPlan({ "nam ...

  8. Feed43自定义 RSS 订阅源

    Google Reader 的关闭后,到处充斥着 RSS 将死的论调.如今看来并没有想象中的那么惨,许多人依旧喜欢沿用 RSS 作为自己获取信息的方式. 前段时间,少数派 Matrix 进行了一次关于 ...

  9. python订阅kafka_程序员基础解答:什么是Kafka?

    Kafka的成长正在蹦沙卡拉卡! 在<财富> 500强公司中,超过三分之一的公司使用Kafka.这些公司包括排名前十的旅行社,排名前十的银行中有七个,排名前十的保险公司中有八个,排名前十的 ...

最新文章

  1. python银行家算法代码_避免死锁的银行家算法C++程序实现
  2. gaokao--选择开发什么项目
  3. 2016中国知识管理发展的7个趋势
  4. 【移动通信】移动通信基础
  5. 新的C库Bionic的介绍
  6. 让你的div可拖动(手机端)
  7. 利用 Azure Functions 实现无服务器体系结构
  8. 贝加尔湖,冰雪奇缘之旅
  9. IP 基础知识“全家桶”,45 张图一套带走!
  10. 有关linux用户和用户组管理的知识详解
  11. 谷歌编码_如何通过学习编码赢得Google之旅
  12. [转]OC与JS的交互详解
  13. 查询数据库内共有多少张表
  14. 手机壳定制商城小程序系统 手机壳定制商城小程序源码
  15. 公里导线时有没有计算机类计算方法,基于Matlab的导线网坐标计算. (1).doc
  16. netlogo笔记(4):森林火灾模拟与模型改进
  17. 风力摆控制系统2015年全国大学生电子设计竞赛B题
  18. 江西省谷歌高清卫星地图下载
  19. Python升级pip失败解决办法
  20. 如何用快启动pe修复win10系统引导?

热门文章

  1. 易烊千玺入围华鼎奖最佳男主,他会成为岁数最小的影帝吗?
  2. 富士康:等夏普状况好转后,会交给日本人来管理
  3. undefined reference to `__gxx_personality_sj0'错误解决办法
  4. 黑莓软件测试简历,[测评]黑莓应用程序 BlackBerry Appworld v2.0 测试
  5. 【Cesium Sandcastle 研究2】- Camera
  6. Excel打开csv文件出现乱码的解决办法
  7. 从零开始学爬虫系列4:快速下载视频
  8. 服务器远程端口怎么修改
  9. Confluence 决定(Decisions )蓝图
  10. python过去电脑网关不可用怎么办_电脑显示默认网关不可用的解决技巧