PHP and Web Services 学习笔记

Thinkphp命令行创建Service(服务层)扩展包 阅读详情
来源: http://www.douzi.org/blog  
学习材料是: [Wrox]Professional Open Source Web Services
Chapter 8 PHP and Web Services
英文版电子书下载[pdf]

全文分为三个部分:
  1. 概述。PHP进行Web Services开发的优点,在Unix系统上安装配置PHP
  2. 在PHP中使用SOAP。NuSOAP工具包,NuSOAP的高级Web Service功能,如HTTP代理,SOAP over HTTPS,document style messaging。还将讨论如何解决一些PHP Web Services编程将会遇到的问题,如安全问题,语言到数据类型的映射
  3. PHP中的XML-RPC。XML-RPC的特性,XML-RPC与SOAP的对比,然后使用Useful, Inc.实现来创建XML-RPC的客户端和服务器程序
下面是第一部分。


Section 1. 概述

PHP中已经通过绑定了Expat parser内置了XML支持,额外的还可以使用一些扩展程序(extension),如domxml(通过使用libxml库提供DOM, Xpath, Xlink支持),xslt(为复杂的第三方XSLT库如Sablotron和libxslt提供的外包程序)。

另一个对Web Service 开发有用的PHP扩展程序是CURL(Client URL Library)。CURL允许你通过不同的协议,如HTTP, HTTPS, FTP, telnet, LDAP来通讯,其中的HTTPS对Web Services与服务器进行安全连接尤其有用。

SOAP vs XML-RPC 优缺点:
  • 强大的类型扩展 (SOAP)
  • 用户自定义字符集,如US-ASCII, UTF-8, UTF-16 (SOAP)
  • Specifies recipient [指定容器?] (SOAP)
  • 容器遇到无法理解的报文则失败 (SOAP)
  • 易于使用 (XML-RPC)
  • 设计简单 (XML-RPC)
配置PHP:
  • Apache: 为了让PHP作为Apache的模块方式运行,使用 --with-apxs选项编译,如 --with-apxs=/www/bin/apxs。[我现在使用的Apache2, 我编译的PHP使用的选项是--with-apxs2=/usr/sbin/apxs]
  • DOMXML: 可选功能,对解析XML文档十分有帮助。需要预先安装好libxml库(版本>=2.4.2),编译时使用 --with-dom=DIR 选项(缺省DIR为/usr)
    http://www.xmlsoft.org/downloads.html
    libxml 2.6.4 - sources - 2.52 MB
  • XSLT: 可选功能,对转换XML资料为其他类型的文档有帮助。编译时使用 --enable-xslt --with-xslt-sablot 选项。必须预先安装Sablotron XSLT库(http://www.gingerall.com/),(缺省DIR为/usr/lib或者/usr/local/lib)。
    Sablotron 1.0.1 - sources - 470 kB
  • CURL: 如前所述,若提供SSL支持则是必须安装的。编译时使用 --with-curl=DIR 选项。也同样需要预先安装CURL库(版本>=7.0.2-beta)。 [我的PHP已经安装了。CURL Information: libcurl/7.10.7 OpenSSL/0.9.7c zlib/1.1.4]
继续昨天的学习。今天主要是关于NuSOAP




Section 2. SOAP

NuSOAP介绍:
NuSOAP是一组开源的,用来通过HTTP收发SOAP消息的PHP类,由NuSphere Corporation ( http://www.nusphere.com
) 开发。NuSOAP的一个优势是他不是一个扩展程序,而是纯粹用PHP代码写的,所以适用范围比较广。

结构:

安装配置:
从 http://dietrich.ganx4.com/nusoap/ 下载,从zip文件中解出nusoap.php文件放到include目录,在你的脚本前面加上
include('nusoap.php');
就搞定了。

范例:
下面是一个简单的SOAP client程序: soap_client.php 执行

<?php
//simple client
require('nusoap.php');

//要发送的变量
$myString="world";

//parameters must be passed as an array
//变量必须要转换成数组的形式
$parameters=array($myString);

//创建一个soapclient对象,参数是server的URL
$s=new soapclient('http://www.douzi.org/me/php_ws/soap_server.php');

//调用远程方法,返回值存放在$result
//返回值为PHP的变量类型,如string, integer, array
$result=$s->call('echoString', $parameters);

//错误检测
if (!$err=$s->getError()) {
    echo
'Result: '.$result; //success
} else {
    echo
'Error: '.$err;
}

//调试,以下是SOAP请求(request)和回应(response)的报文,包括HTTP头
echo "<xmp>".$s->request."</xmp>";
echo
"<xmp>".$s->response."</xmp>";

?>


相应的server端程序: soap_server.php

<?php
//simple server
require('nusoap.php');

//创建一个新的soap_server对象,并注册允许远程调用的方法
$s=new soap_server;
$s->register('echoString');
$s->register('echoArray');

/*
[文章中说: 缺少了注册这一步,任何PHP函数都将可以进行远程调用,这将是一个极大的安全隐患。但是我尝试过注册是必须的。而且只有将结果return的函数才能直接声明为远程方法,比如echo()就不行,而strtolower()就可以。]
*/

function echoString($inputString) {
    
//类性检查
    
if(is_string($inputString)) {
        return
"Hello, ".$inputString;
    } else {
        
//soap_fault类用于产生错误信息
        
return new soap_fault('client', '', 'The parameter to this service must be a string.');
        
//soap_fault(faultcode, faultactor, faultstring, faultdetail);
        //上面是错误处理类的构造函数的格式
        //faultcode   必须值。可以设置为client或server,来表明错误发生在哪一端。
        //faultactor  在NuSOAP中尚未实现。
        //faultstring 错误信息。
        //faultdetail 详细错误信息。你可以使用XML标记。

        //除了构造函数外,soap_fault类还有一个serialize()方法
        //它将错误信息序列化,然后返回一个完整的SOAP报文,范例:
        /*
        $fault = new soap_fault('client', '', 'The inputString parameter must not be empty');
        echo $fault->serialize();
        */
    
}
}

//演示数组类型的使用
function echoArray($inputString) {
    return
$inputString[0]."+".$inputString[1];

}

//最后一步是把所有的收到的post数据都传递给SOAP server的service方法。它将处理请求,并调用相应的函数。
$s->service($HTTP_RAW_POST_DATA);
?>



复杂数据类型的使用:
  1. 数组。以下是生成的SOAP的Body部分代码:
    <SOAP-ENV:Body>
      <ns1:echoArray xmlns:ns1="http://testuri.org">
        <soapVal xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]">
          <item xsi:type="xsd:string">string1</item>
          <item xsi:type="xsd:string">string2</item>
        </soapVal>
      </ns1:echoArray>
    </SOAP-ENV:Body>


  2. 生成复合数据类型(compound types samples),使用soapval。以下是生成的SOAP的Body部分代码:
    <myAddress xmlns:ns3398="http://myNamespace.com" xsi:type="ns3398:address">
      <street xsi:type="xsd:string">123 Freezing Lane</street>
      <city xsi:type="xsd:string">Nome</city>
      <state xsi:type="xsd:string">Alaska</state>
      <zip xsi:type="xsd:int">12345</zip>
      <phonenumbers>
        <home xsi:type="xsd:string">1234567890</home>
        <mobile xsi:type="xsd:string">0987654321</mobile>
      </phonenumbers>
    </myAddress>



    程序范例: soapval.php 执行

    <?php
    //soapval: general compound types samples
    include('nusoap.php');

    $address=array(
        
    'street'=>'123 Freezing Lane',
        
    'city'=>'Nome',
        
    'state'=>'Alaska',
        
    'zip'=>12345,
        
    'phonenumbers'=>array('home'=>'1234567890', 'mobile'=>'0987654321')
    );

    $s=new soapval('myAddress', 'address', $address, '', 'http://myNamespace.com');

    print
    "<xmp>".$s->serialize()."</xmp>";

    ?>



WSDL
WSDL是一种用于描述Web Service的XML语言。它是一种机读格式,把所有的访问服务所必须的信息提供给Web Service客户端。NuSOAP专门提供一个类进行WDSL文件的解析,并且从中提取信息。soapclient对象使用wsdl类来减轻开发者调用服务的难度。通过WSDL信息的帮助来创建报文,程序员仅仅需要知道操作的名字和参数就能调用它。

通过NuSOAP使用WSDL提供以下几点优点:
  • 所有的服务元文件,如命名空间(namespaces),endpoint URLs,参数名(parameter names)等等都可以直接从WSDL文件获得,这样就允许客户端动态的适应服务器端的变化。因为从服务器随时可以获得,所以这些数据不再需要在用户脚本中使用硬性编码。
  • 它允许我们使用soap_proxy类。这个类派生自soapclient类,增加了WDSL文件中详细列出的操作所对应的方法。现在用户通过它可以直接调用这些方法。
  • soapclient类包含一个getProxy()方法,它返回一个soap_proxy类的一个对象。soap_proxy类派生自soapclient类,增加了对应于WSDL文档中定义的操作的方法,并且允许用户调用一个endpoint的远程方法。这仅仅适用于soapclient对象用WDSL文件初始化的情况。优点是易于用户使用,缺点是性能--PHP中创建对象是耗时的--且不为功利目的服务(and this functionality serves no utilitarian purpose)。

范例: wsdl.php 执行

<?php
//wsdl的一个简单演示文件
include('nusoap.php');

//SOAP源为一个提供明星生卒年月的service
//首先我们创建一个soapclient对象,把WSDL文件的URL传递给构造函数,
//之后还要使用第二个参数以便使client知道我们传递过来的是WSDL,而不是SOAP endpoint。
$s=new soapclient('http://www.abundanttech.com/webservices/deadoralive/deadoralive.wsdl', 'wsdl');

//生成proxy类
$p=$s->getProxy();

//调用远程函数
$sq=$p->getTodaysBirthdays();

if (!
$err=$p->getError()) {
    
print_r($sq);
} else {
    print
"ERROR: $err";
}

print
'REQUEST:<xmp>'.$p->request.'</xmp>';
print
'RESPONSE:<xmp>'.str_replace('><', ">/n<", $p->response).'</xmp>';

?>


附:一个有用的Web Services的演示站点:

http://www.mindreef.net/soapscope/wsdldemo

这是最后一节,感觉PHP还是很适合做client的。这节主要是关于XML-RPC的。
我原来曾经有一篇XML-RPC学习笔记,内容和这个很类似。




Section 3. XML-RPC

XML-RPC的数据类型

XML-RPC仅支持有限的几种数据类型。下面是和PHP数据类型的的对应关系:

Useful Inc. XML-RPC实现 -- phpxmlrpc

我们使用的XML-RPC工具包是Useful, Inc.的Edd Dumbill制作的,下载网址 http://phpxmlrpc.sourceforge.net ,其中完整包括client和server的XML-RPC实现。

客户端和服务器端分别由 xmlrpc_client 类和 xmlrpc_server 类实现,主要用于接收和发送XML-RPC报文。xmlrpcval 类用于将PHP变量编码为XML-RPC等价数据类型和向远程方法传递参数。相反的过程使用 xmlrpc_decode() 函数。XML-RPC报文使用 xmlrpcmsg 类通过传递给它一个参数表来创建。

xmlrpc_client 类发送使用 xmlrpcmsg 类创建的XML-RPC报文,在服务器端, xmlrpc_server 类解析这些收到的报文为 xmlrpcmsg 对象。然后这个对象被作为一个单独参数传递给用户函数。该函数必须返回一个 xmlrpcresp 对象, xmlrpc_server 类将其用于序列化并返回给客户端。这个基本的体系结构如下图所示。

安装和配置

在 http://phpxmlrpc.sourceforge.net 下载,解包,然后将 xmlrpc.inc 和 xmlrpcs.inc 放置到你的包含路径即可。

客户端程序首部只要加入下面的包含语句:
include('xmlrpc.inc');

服务器端程序首部要加入下面的包含语句:
include('xmlrpc.inc');
include('xmlrpcs.inc'); //服务器端代码

范例

XML-RPC client: xmlrpc_client.php 执行


<?php
//xmlrpc_client.php
//XML-RPC客户端演示程序
require('xmlrpc.inc');

//创建client对象, 三个参数依次为 path, hostname, port
$s=new xmlrpc_client('/xmlrpc/xmlrpc_server.php', 'www.windix.local', 80);

//create xmlrpcval object, which allows the encoding of our variable
//创建xmlrpcval对象,将我们的PHP变量编码为XML-RPC需要的XML形式
$inputString=new xmlrpcval('world', 'string');

//create an array of parameters
//尽管我们只有一个参数,但仍然要转换成数组的形式,因为xmlrpcmsg的第二个参数是一个参数表
$parameters=array($inputString);

//create the message object
//创建XML-RPC报文,参数分别为 远程方法名 和 参数表
$msg=new xmlrpcmsg('echoString', $parameters);

//send the message, get the response
//发送报文,返回值$rsp为一个xmlrpcresp对象,它包含以下三个方法:
//faultCode() 出错代码,如果成功将返回0
//faultString() 出错信息
//value() 返回值,以xmlrpcval对象形式存在,PHP使用前需要进行解码
$rsp=$s->send($msg);

//check for errors
if($rsp->faultcode()==0) {
    
//decode the response to a PHP type
    //xmlrpc_decode()函数用于将xmlrpcval对象解码
    
$response=xmlrpc_decode($rsp->value());

    
//print results
    
print '<pre>';
    
var_dump($response);
    print
'</pre>';
} else {
    
//print errors
    
print 'Error: '.$rsp->faultcode().', '.$rsp->faultstring().'<br>';
}

//show messages
//然后我们来查看一下报文内容
$msg->createpayload();
print
'REQUEST:<xmp>'.$msg->payload.'</xmp>';
print
'RESPONSE:<xmp>'.$rsp->serialize().'</xmp>';

?>


XML-RPC server: xmlrpc_server.php

<?php
//xmlrpc_server.php
//XML-RPC服务器端演示程序
require('xmlrpc.inc');
require(
'xmlrpcs.inc');

//service that echoes a string
//我们用于处理远程调用的自定义函数
//注意,该函数必须且只能有一个类型为xmlrpcmsg对象的参数
function echoString($msg) {

    
//decode parameters into navtive types
    //首先使用xmlrpc_decode函数进行解码
    
$inputString=xmlrpc_decode(array_shift($msg->params));

    
//check for input parameter validity
    //检查数据类型是否正确
    
if(is_string($inputString)) {
        return new
xmlrpcresp( new xmlrpcval('Hello, '.$inputString, 'string') );

    } else {
//or return a fault
        
return new xmlrpcresp(0, $xmlrpcerruser+1, "Parameter type ".gettype($inputString)." mismatched expected type.");
    }

}

//instantiate the server object and register our functions
//初始化server对象,并注册我们的函数
//下面这个数组称为"dispatch map",其中以输出函数名为主键的项又是一个数组
//包含以下三个成员:
// function  实际调用的函数名,在这里我们的函数名也是echoString,同服务名一样
// signature 可选。输入和输出参数的类型,最后一个是输出参数,前面的都是输入参数
// docstring 可选。包含你的服务的文档,甚至可以有HTML内容。

//xmlrpc_server还包含第二个可选初始化参数,如果设置为0,则服务不会立刻处理请求
//需要使用server的service()方法进程才能被执行

$s=new xmlrpc_server(array(
    
'echoString' => array(
        
'function' => 'echoString',
        
'signature' => array( array('string','string') ),
        
'docstring' => 'This service echoes Hello+input stirng.'
        
)
    ));
?>
Web Services 学习 Web Services 是应用程序组件Web Services 使用开放协议进行通信Web Services 是独立的(self-contained)并可自我描述Web Services 可通过使用UDDI来发现Web Services 可被其他应用程序使用XML 是 Web Services 的基础基本的 Web services 平台是 XML + HTTP。SOAP 指简易对象访问协议SOAP 是一种通信协议SOAP 用于应用程序之间的通信。 阅读详情

相关推荐

Web Services与RESTful API的集成与操作

本文深入探讨了网络服务(Web Services)的概念及其在异构系统集成中的应用,特别是在Web界面开发中的实践。文章详细解释了RESTful web服务的工作原理,以及如何使用HTTP协议的基本动词GET、POST、PUT和DELETE来对资源进行CRUD操作。此外,还包括了使用PHP的curl扩展从RESTful API检索、更新、创建和删除资源的示例代码,展示了RESTful API在实际开发中的具体应用。

weixin_30218749的博客 1011

php service层的作用,Service层的是否必要性分析及案例

序言此前,我看过这样的一个提问“Yii2框架中,有必要再分离service层么?”,从别人的回答中,自己也收获了答案,但我觉得还需要有个活生生的粟子,才具有更加清晰明了和强有力的说服力。如对我的实战经历感兴趣的继续往下看,喜欢的还可以点击推荐和收藏。在举粟子前,我先讲讲service是什么?有什么作用吧?免得还有人糊涂。1、service是什么?在面向OO的系统里,service就是biz man...

weixin_36385240的博客 1045

php实现webservices接口

php通过WSDL的方式实现webservices接口,需要在php.ini设置always_populate_raw_post_data=-1

phpweb项目分层架构

通过以上几个方面的介绍,我们已经了解到了一个典型的PHPWeb项目是如何基于分层架构来组织其内部结构的。从用户看到的界面到底层的数据存储,每一步都经过精心设计,既保证了系统的稳定运行也方便了后续维护升级。随着技术的发展,新的编程范式和工具不断涌现,但分层思想始终是构建大型复杂软件系统时不可或缺的基础之一。希望这篇文章能帮助你更好地理解和应用这一重要概念。

2401_84162761的博客 1081

PHP SOAP实现Web Services 完整实例WSDL服务端+客户端

PHP实现的Web Services 完整实例,WSDL交互。 PHP.INI,请开启php_soap。 服务端:直接解压到网站根目录下,访问地址:http://localhost/hbj/wsdl.php?wsdl 客户端:http://localhost/hbj/Client.php ,显示hello world.表示成功。

东方财富网股票API逆向分析:手把手教你破解动态参数(2024最新版)

本文详细解析了2024年东方财富网股票API的动态参数生成机制,包括回调函数、身份验证和时效控制参数的逆向工程方法。通过实战代码演示,帮助开发者破解动态参数,实现高效稳定的股票数据爬取,适用于金融数据分析和量化交易场景。

weixin_29091105的博客 1026

php service原理,深入剖析 Laravel 服务提供者实现原理

今天我们将学习 Laravel 框架另外一个核心内容「服务提供者(Service Provider)」。服务提供者的功能是完成 Laravel 应用的引导启动,或者说是将 Laravel 中的各种服务「注册」到「Laravel 服务容器」,这样才能在后续处理 HTTP 请求时使用这些服务。服务提供者基本概念我们知道 「服务提供者」是配置应用的中心,它的主要工作是使用「服务容器」实现服务容器绑定、事...

weixin_33583419的博客 455

【Java】利用反射执行Spring容器Bean指定的方法,支持多种参数自动调用

目录 使用情景 目的 实现方式 前提: 思路 核心类 测试方法 使用情景 将定时任务录入数据库(这样做的好处是定时任务可视化,也可以动态修改各个任务的执行时间),通过反射执行对应的方法; 配合Netty实现简单的HTTP请求处理框架 其他需要使用反射执行Spring方法的业务亦可 目的 很多文章都提到了反射,但是对于方法参数处理这一块都是明确了类型,不支持按照实际参数动态转换,而本篇文章提供了一个思路怎么做到方法参数的动态调用。 大家也可以...

ITjianshuzhai的博客 2334

国产InitPHP框架系列 - InitPHP框架搭建高可用WEB应用04:服务层Service使用

InitPHP框架是一款轻量级PHP开源框架,框架文档和下载地址:http://initphp.com Service层说明 1. Service来源 Service层的设计来源于Java。Java有很多优秀的设计思想,但是很多东西并不一定适合php,因为两种语言的性质不一样。 Service层是业务逻辑层,一般情况下你可以理解为MVC中的Model层,只是传统的Model层有数据

自娱自乐的代码人 6744

FreeRTOS实战:如何避免HAL_Delay在高优先级中断中的坑(附TIM6配置指南)

本文深入剖析了在STM32 FreeRTOS项目中,于高优先级中断内调用HAL_Delay函数导致系统假死的根本原因——SysTick时基被FreeRTOS占用且优先级最低。文章提供了治本方案:通过配置TIM6作为独立且最高优先级的HAL时基,实现与FreeRTOS系统心跳的解耦,并附上详细的CubeMX配置与代码移植指南,确保系统实时性与稳定性。

weixin_29230059的博客 64

CAD的.dwg文件导入 ArcGIS:高程分析、坡度分析、坡向分析

CAD的.dwg文件导入 ArcGIS,再进行高程分析、坡度分析、坡向分析。

My_Echo_yM的博客 7238

PHP and Web Services

全文分为三个部分: 概述。PHP进行Web Services开发的优点,在Unix系统上安装配置PHP 在PHP中使用SOAP。NuSOAP 工具包,NuSOAP的高级Web Service功能,如HTTP代理,SOAP over HTTPS,document style messaging。还将讨论如何解决一些PHP Web Services编程将会遇到的问题,如安全

guoguo1980的专栏 1327

【AI Agent】Hermes Agent解析

Hermes Agent:一个具备持久化学习能力的开源AI Agent框架 核心特点: 突破传统Agent的"无状态困境",通过记忆系统(SQLite+FTS5全文检索)实现跨会话经验积累 支持200+模型自由切换,11种模型家族和15+平台接入 五层架构设计(入口层、编排层、推理层、工具执行层、存储层)实现平台无关性 47+内置工具和动态技能沉淀机制,支持从任务执行中自动提炼可复用Skill 独特的四层记忆体系(会话/每日/长期/向量索引)和辩证式用户建模 与传统Agent对比: 具备自我进化能力,通过A

sysu_lluozh 945

Pro PHP XML and Web Services

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出版、作者信息和本声明。否则将追究法律责任。http://blog.youkuaiyun.com/topmvp - topmvpPro PHP XML and Web Services is the authoritative guide to using the XML features of PHP 5 and PHP 6. No othe

TopMVP 700

提示词编程在自动化内容审核中的应用

文章标题 提示词编程在自动化内容审核中的应用 关键词:提示词编程,自动化内容审核,人工智能,算法原理,系统架构设计,项目实战 摘要 本文旨在探讨提示词

AI天才研究院 1252

《HiVT: Hierarchical Vector Transformer for Multi-Agent Motion Prediction》论文阅读之HiVT

目录摘要1.介绍2.相关工作3.方法3.1. 总体框架3.2 场景表示 3.3 分层向量Transformer3.3.1 局部编码器3.3.2 全局交互模块3.3.3 多模态未来解码器3.4 训练4.实验4.1 实验设置4.2 消融研究 4.3. 结果5.结论 准确预测周围交通参与者的未来运动对于自动驾驶车辆的安全至关重要。最近,矢量化方法由于能够捕捉交通场景中的复杂交互而在运动预测领域占据主导地位。然而,现有的方法忽略了问题的对称性并且受到昂贵的计算成本的影响,面临着在不牺牲预测性能的情况

Gavinmiaoc的博客 3340

Transbank Web Services SDK 使用指南

Transbank Web Services SDK 使用指南 1. 项目介绍 Transbank Web Services SDK 是一个由 Freshwork Studio 维护的 PHP 库,专门用于集成 Transbank 的支付服务,包括 Webpay Plus、Webpay OneClick 和 Webpay Patpass。通过使用本SDK,开发者能够轻松在他们的应用程序中实现快速、...

gitblog_00014的博客 1081

Xilinx FPGA平台GTX简易使用教程(汇总篇)

Xilinx平台GTX简易使用教程,先“知其然”,慢慢再研究“所以然”。

数字IC/FPGA杂货铺,找一找,或许有你想要的~ 3万+

PHP访问NetSuite REST Web Services

帮助PHP开发者快速起步,打通与NetSuite的接口的一个REST Webservice访问样例。包括:3种查询(ID、Q字串、SuiteQL)方式、新建、更改、删除

NetSuite知识会 946

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

上一篇: 讨论创建基于WSE的报表打印服务及其实现
下一篇: 安全性断言标记语言 SAML
smartcn
博客等级 码龄24年 1粉丝 33原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值