作者 lihan
1 个管道 的构建 通过 耗费 1 秒

支付宝

正在显示 32 个修改的文件 包含 0 行增加4829 行删除

要显示太多修改。

为保证性能只显示 32 of 32+ 个文件。

# Auto detect text files and perform LF normalization
* text=auto
\ No newline at end of file
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\ No newline at end of file
# ThinkPHP5 电脑与手机支付扩展库(2017年9月18日)
## 使用说明
- 在默认配置情况下,将文件夹拷贝到根目录即可, 其中<code>extend</code>目录为支付扩展目录, <code>application\extra\alipay.php</code>为配置文件
- 需要在配置文件<code>application\extra\alipay.php</code>中填写必要的参数
## 注意
错误采用抛出异常的方式, 可根据自己的业务在统一接口进行修改
## 用法
#### 电脑网站支付 Pagepay.php
调用 <code>\alipay\Pagepay::pay($params)</code> 即可
#### 手机网站支付 Wappay.php
调用 <code>\alipay\Wappay::pay($params)</code> 即可
#### 交易查询接口 Query.php
调用 <code>\alipay\Query::exec($query_no)</code> 即可
#### 交易退款接口 Refund.php
调用 <code>\alipay\Refund::exec($params)</code> 即可
#### 退款统一订单查询 RefundQuery.php
调用 <code>\alipay\RefundQuery::exec($params)</code> 即可
#### 交易关闭接口 Close.php
调用 <code>\alipay\Close::exec($query_no)</code> 即可
#### 查询账单下载地址接口 Datadownload.php
调用 <code>\alipay\Datadownload::exec($bill_type, $bill_date)</code> 即可
#### 验签 Notify.php
调用 <code>\alipay\Notify::check($params)</code> 即可
#### 通知处理步骤建议
1. 验签
2. 判断订单状态
3. 进行业务操作
###### 一下两个类仅为建议, 帮助理解, 可根据具体业务进行变更, 详细理解可参考[官方文档和SDK](https://docs.open.alipay.com/270/105902/)
- <code>application\common\NotifyHandler.php</code> 通知操作的处理类
- <code>application\example\Notify.php</code> 具体实现
<?php
namespace app\common\controller;
use think\Controller;
/**
* 通知控制器
*/
abstract class NotifyHandler extends Controller
{
protected $params;
public function init()
{
// 1.验签和参数校检
$result = $this->checkSignAndOrder();
if($result) {
// 2.订单处理
$this->orderHandle();
echo "success"; //请不要修改或删除
} else {
echo "fail"; //请不要修改或删除
}
}
// 1.验签和校检参数
public function checkSignAndOrder()
{
$this->getOrder();
if(empty($this->params)) {
$this->processError('订单不存在');
}
$result = \alipay\Notify::check($this->params);
if(!$result) {
$this->processError('校检失败');
}
return $result;
}
// 2.订单处理
public function orderHandle()
{$_POST['trade_status'] = 'TRADE_SUCCESS';
if($_POST['trade_status'] == 'TRADE_SUCCESS') {
$orderStatus = $this->checkOrderStatus();
if(!$orderStatus) {
// 判断订单状态, 如果订单未做过处理, 则处理自己核心业务
$handlerResult = $this->handle();
if(!$handlerResult) {
// 如果订单未处理成功
exit('fail');
}
}
}
}
/**
* 获取订单信息, 用于校检
* @return array 订单数组, 必须包含订单号和订单金额
* @param string $params['out_trade_no'] 商户订单
* @param float $params['total_amount'] 订单金额
*/
abstract protected function getOrder();
/**
* 检测订单状态, 用于判断订单是否已经做过处理
* 原因: 本次业务处理较慢, 没来得及echo 'success', 同一订单的通知多次到达, 会造成多次修改数据库, 所以有必要进行订单状态确认
*
* @return Boolean true表示已经处理过 false表示未处理过
*/
abstract protected function checkOrderStatus();
/**
* 处理自己业务
* @return Boolean true表示业务处理 false表示处理失败
*/
abstract protected function handle();
/**
* 统一错误处理接口
* @param string $msg 错误描述
*/
private static function processError($msg)
{
throw new \think\Exception($msg);
}
}
\ No newline at end of file
<?php
namespace app\example\controller;
use think\Db;
use app\common\controller\NotifyHandler;
/**
* 通知处理控制器
*
* 完善getOrder, 获取订单信息, 注意必须数组必须包含out_trade_no与total_amount
* 完善checkOrderStatus, 返回订单状态, 按要求返回布尔值
* 完善handle, 进行业务处理, 按要求返回布尔值
*
* 请求地址为index, NotifyHandler会自动调用以上三个方法
*/
class Notify extends NotifyHandler
{
protected $params; // 订单信息
public function index()
{
parent::init();
}
/**
* 获取订单信息, 必须包含订单号和订单金额
*
* @return string $params['out_trade_no'] 商户订单
* @return float $params['total_amount'] 订单金额
*/
public function getOrder()
{
// 以下仅示例
$out_trade_no = $_POST['out_trade_no'];
$order = Db::name('order')->where('out_trade_no', $out_trade_no)->find();
$params = [
'out_trade_no' => $order['out_trade_no'],
'total_amount' => $order['total_amount'],
'status' => $order['status'],
'id' => $order['id']
];
$this->params = $params;
}
/**
* 检查订单状态
*
* @return Boolean true表示已经处理过 false表示未处理过
*/
public function checkOrderStatus()
{
// 以下仅示例
if($this->params['status'] == 0) {
// 表示未处理
return false;
} else {
return true;
}
}
/**
* 业务处理
* @return Boolean true表示业务处理成功 false表示处理失败
*/
public function handle()
{
// 以下仅示例
$result = Db::name('order')->where('id', $this->params['id'])->update(['status'=>1]);
if($result) {
return true;
} else {
return false;
}
}
}
\ No newline at end of file
<?php
/**
* 支付宝支付
*/
return [
//应用ID,您的APPID。
'app_id' => "",
//商户私钥, 请把生成的私钥文件中字符串拷贝在此
'merchant_private_key' => "",
//异步通知地址
'notify_url' => "",
//同步跳转
'return_url' => "",
//编码格式
'charset' => "UTF-8",
//签名方式
'sign_type'=>"RSA2",
//支付宝网关
'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
//支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
'alipay_public_key' => "",
];
<?php
namespace alipay;
use think\Loader;
Loader::import('alipay.pay.service.AlipayTradeService');
loader::import('alipay.pay.buildermodel.AlipayTradeCloseContentBuilder');
/**
* 统一收单交易关闭接口
*
* 用法:
* 调用 \alipay\Close::exec($query_no) 即可
*
* ----------------- 求职 ------------------
* 姓名: zhangchaojie 邮箱: zhangchaojie_php@qq.com 应届生
* 期望职位: PHP初级工程师 地点: 深圳(其他城市亦可)
* 能力:
* 1.熟悉小程序开发, 前后端皆可
* 2.后端, PHP基础知识扎实, 熟悉ThinkPHP5框架, 用TP5做过CMS, 商城, API接口
* 3.MySQL, Linux都在进行进一步学习
*
*/
class Close
{
// 商户订单号(out_trade_no) or 支付宝交易号(trade_no) 二选一
const QUERY_TYPE = 'trade_no';
public static function exec($query_no)
{
// 1.构建请求参数
$RequestBuilder = new \AlipayTradeCloseContentBuilder();
if (self::QUERY_TYPE == 'trade_no') {
$RequestBuilder->setTradeNo(trim($query_no));
} else {
$RequestBuilder->setOutTradeNo(trim($query_no));
}
// 2.获取配置
$config = config('alipay');
$aop = new \AlipayTradeService($config);
// 3.发起请求
$response = $aop->Close($RequestBuilder);
// 4.转为数组格式返回
$response = json_decode(json_encode($response), true);
// 5.进行结果处理
if (!empty($response['code']) && $response['code'] != '10000') {
self::processError('交易关闭接口出错, 错误码: '.$response['code'].' 错误原因: '.$response['sub_msg']);
}
return $response;
}
/**
* 统一错误处理接口
* @param string $msg 错误描述
*/
private static function processError($msg)
{
throw new \think\Exception($msg);
}
}
\ No newline at end of file
<?php
namespace alipay;
use think\Loader;
Loader::import('alipay.pay.service.AlipayTradeService');
loader::import('alipay.pay.buildermodel.AlipayDataDataserviceBillDownloadurlQueryContentBuilder');
/**
* 查询账单下载地址接口
*
* 用法:
* 调用 \alipay\Datadownload::exec($bill_type, $bill_date) 即可
*
* ----------------- 求职 ------------------
* 姓名: zhangchaojie 邮箱: zhangchaojie_php@qq.com 应届生
* 期望职位: PHP初级工程师 地点: 深圳(其他城市亦可)
* 能力:
* 1.熟悉小程序开发, 前后端皆可
* 2.后端, PHP基础知识扎实, 熟悉ThinkPHP5框架, 用TP5做过CMS, 商城, API接口
* 3.MySQL, Linux都在进行进一步学习
*
*/
class Datadownload
{
/**
* 主入口
* @param string $bill_type trade/signcustomer, trade指商户基于支付宝交易收单的业务账单;signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单;
* @param string $bill_date 日期, 单格式为yyyy-MM-dd,月账单格式为yyyy-MM
* 注意:
* 1.当日或者当月日期为无效日期,毕竟没有过当日或者当月
* 2.如果是2017年7月,请填写2017-07,不能为2017-7
*/
public static function exec($bill_type, $bill_date)
{
// 1.校检参数
self::checkParams($bill_type, $bill_date);
// 2.设置请求参数
$RequestBuilder = new \AlipayDataDataserviceBillDownloadurlQueryContentBuilder();
$RequestBuilder->setBillType($bill_type);
$RequestBuilder->setBillDate($bill_date);
// 3.获取配置
$config = config('alipay');
$Response = new \AlipayTradeService($config);
// 4.请求
$response = $Response->downloadurlQuery($RequestBuilder);
// 5.转为数组格式返回
$response = json_decode(json_encode($response), true);
// 6.进行结果处理
if (!empty($response['code']) && $response['code'] != '10000') {
self::processError('查询账单接口出错, 错误码: '.$response['code'].' 错误原因: '.$response['sub_msg']);
}
return $response;
}
/**
* 校检参数
*/
private static function checkParams($bill_type, $bill_date)
{
if (!in_array($bill_type, ['trade', 'signcustomer'])) {
self::processError('账单类型不正确');
}
if (!strtotime($bill_date)) {
self::processError('日期格式不正确');
}
}
/**
* 统一错误处理接口
* @param string $msg 错误描述
*/
private static function processError($msg)
{
throw new \think\Exception($msg);
}
}
\ No newline at end of file
<?php
namespace alipay;
use think\Loader;
Loader::import('alipay.pay.service.AlipayTradeService');
/**
* 支付回调处理类
*
* 用法:
* 调用 \alipay\Pagepay::pay($params) 即可
*
* ----------------- 求职 ------------------
* 姓名: zhangchaojie 邮箱: zhangchaojie_php@qq.com 应届生
* 期望职位: PHP初级工程师 地点: 深圳(其他城市亦可)
* 能力:
* 1.熟悉小程序开发, 前后端皆可
* 2.后端, PHP基础知识扎实, 熟悉ThinkPHP5框架, 用TP5做过CMS, 商城, API接口
* 3.MySQL, Linux都在进行进一步学习
*
*/
class Notify
{
/**
* 异步通知校检, 包括验签和数据库信息与通知信息对比
*
* @param array $params 数据库中查询到的订单信息
* @param string $params['out_trade_no'] 商户订单
* @param float $params['total_amount'] 订单金额
*/
public static function check($params)
{
// 1.第一步校检签名
$config = config('alipay');
$alipaySevice = new \AlipayTradeService($config);
$signResult = $alipaySevice->check($_POST);
// 2.和数据库信息做对比
$paramsResult = self::checkParams($params);
// 3.返回结果
if($signResult && $paramsResult) {
return true;
} else {
return false;
}
}
/**
* 判断两个数组是否一致, 两个数组的参数如下:
* $params['out_trade_no'] 商户单号
* $params['total_amount'] 订单金额
* $params['app_id'] app_id号
*/
public static function checkParams($params)
{
$notifyArr = [
'out_trade_no' => $_POST['out_trade_no'],
'total_amount' => $_POST['total_amount'],
'app_id' => $_POST['app_id'],
];
$paramsArr = [
'out_trade_no' => $params['out_trade_no'],
'total_amount' => $params['total_amount'],
'app_id' => config('alipay.app_id'),
];
$result = array_diff_assoc($paramsArr, $notifyArr);
return empty($result) ? true : false;
}
}
\ No newline at end of file
<?php
namespace alipay;
use think\Loader;
Loader::import('alipay.pay.service.AlipayTradeService');
loader::import('alipay.pay.buildermodel.AlipayTradePagePayContentBuilder');
/**
* 电脑网站支付(扫码支付或账号支付)
*
* 用法:
* 调用 \alipay\Pagepay::pay($params) 即可
*
* ----------------- 求职 ------------------
* 姓名: zhangchaojie 邮箱: zhangchaojie_php@qq.com
* 期望职位: PHP初级工程师 地点: 深圳(其他城市亦可)
* 能力:
* 1.熟悉小程序开发, 前后端皆可
* 2.后端, PHP基础知识扎实, 熟悉ThinkPHP5框架, 用TP5做过CMS, 商城, API接口
* 3.MySQL, Linux都在进行进一步学习
*/
class Pagepay
{
/**
* 主入口
* @param array $params 支付参数, 具体如下
* @param string $params['subject'] 订单标题
* @param string $params['out_trade_no'] 订单商户号
* @param float $params['total_amount'] 订单金额
*/
public static function pay($params)
{
// 1.校检参数
self::checkParams($params);
// 2.构造参数
$payRequestBuilder = new \AlipayTradePagePayContentBuilder();
$payRequestBuilder->setSubject($params['subject']);
$payRequestBuilder->setTotalAmount($params['total_amount']);
$payRequestBuilder->setOutTradeNo($params['out_trade_no']);
// 3.获取配置
$config = config('alipay');
$aop = new \AlipayTradeService($config);
/**
* 4.电脑网站支付请求(会自动跳转到支付页面)
* @param $builder 业务参数,使用buildmodel中的对象生成。
* @param $return_url 同步跳转地址,公网可以访问
* @param $notify_url 异步通知地址,公网可以访问
* @return $response 支付宝返回的信息
*/
$aop->pagePay($payRequestBuilder, $config['return_url'],$config['notify_url']);
}
/**
* 校检参数
*/
private static function checkParams($params)
{
if (empty(trim($params['out_trade_no']))) {
self::processError('商户订单号(out_trade_no)必填');
}
if (empty(trim($params['subject']))) {
self::processError('商品标题(subject)必填');
}
if (floatval(trim($params['total_amount'])) <= 0) {
self::processError('退款金额(total_amount)为大于0的数');
}
}
/**
* 统一错误处理接口
* @param string $msg 错误描述
*/
private static function processError($msg)
{
throw new \think\Exception($msg);
}
}
\ No newline at end of file
<?php
namespace alipay;
use think\Loader;
Loader::import('alipay.pay.service.AlipayTradeService');
loader::import('alipay.pay.buildermodel.AlipayTradeQueryContentBuilder');
/**
* 统一收单线下交易查询接口
*
* 用法:
* 调用 \alipay\Query::exec($query_no) 即可
*
* ----------------- 求职 ------------------
* 姓名: zhangchaojie 邮箱: zhangchaojie_php@qq.com 应届生
* 期望职位: PHP初级工程师 地点: 深圳(其他城市亦可)
* 能力:
* 1.熟悉小程序开发, 前后端皆可
* 2.后端, PHP基础知识扎实, 熟悉ThinkPHP5框架, 用TP5做过CMS, 商城, API接口
* 3.MySQL, Linux都在进行进一步学习
*
*/
class Query
{
// 商户订单号(out_trade_no) or 支付宝交易号(trade_no) 二选一
const QUERY_TYPE = 'trade_no';
public static function exec($query_no)
{
// 1.设置请求参数
$RequestBuilder = new \AlipayTradeQueryContentBuilder();
if (self::QUERY_TYPE == 'trade_no') {
$RequestBuilder->setTradeNo(trim($query_no));
} else {
$RequestBuilder->setOutTradeNo($query_no);
}
// 2.获取配置
$config = config('alipay');
$aop = new \AlipayTradeService($config);
// 3.发起请求
$response = $aop->Query($RequestBuilder);
// 4.转为数组格式返回
$response = json_decode(json_encode($response), true);
// 5.进行结果处理
if (!empty($response['code']) && $response['code'] != '10000') {
self::processError('交易查询接口出错, 错误码: '.$response['code'].' 错误原因: '.$response['sub_msg']);
}
return $response;
}
/**
* 统一错误处理接口
* @param string $msg 错误描述
*/
private static function processError($msg)
{
throw new \think\Exception($msg);
}
}
\ No newline at end of file
<?php
namespace alipay;
use think\Loader;
Loader::import('alipay.pay.service.AlipayTradeService');
loader::import('alipay.pay.buildermodel.AlipayTradeRefundContentBuilder');
/**
* 统一收单交易退款接口
*
* 用法:
* 调用 \alipay\Refund::exec($params) 即可
*
* ----------------- 求职 ------------------
* 姓名: zhangchaojie 邮箱: zhangchaojie_php@qq.com 应届生
* 期望职位: PHP初级工程师 地点: 深圳(其他城市亦可)
* 能力:
* 1.熟悉小程序开发, 前后端皆可
* 2.后端, PHP基础知识扎实, 熟悉ThinkPHP5框架, 用TP5做过CMS, 商城, API接口
* 3.MySQL, Linux都在进行进一步学习
*
*/
class Refund
{
/**
* 主入口
* @param array $params 退款参数, 具体如下
* @param string $params['trade_no']/$params['out_trade_no'] 商户订单号或支付宝单号其中之一
* @param string $params['out_request_no'] 商户退款号(可选, 如同一笔交易多次退款, 则必填)
* @param float $params['refund_amount'] 退款金额
*/
public static function exec($params)
{
// 1.校检参数
self::checkParams($params);
// 2.构造请求参数
$RequestBuilder = self::builderParams($params);
// 3.获取配置
$config = config('alipay');
$aop = new \AlipayTradeService($config);
// 4.发送请求
$response = $aop->Refund($RequestBuilder);
// 5.转为数组格式返回
$response = json_decode(json_encode($response), true);
// 6.进行结果处理
if (!empty($response['code']) && $response['code'] != '10000') {
self::processError('交易退款接口出错, 错误码: '.$response['code'].' 错误原因: '.$response['sub_msg']);
}
return $response;
}
/**
* 校检参数
*/
private static function checkParams($params)
{
if (empty($params['trade_no']) && empty($params['out_trade_no'])) {
self::processError('商户订单号(out_trade_no)和支付宝单号(trade_no)不得通知为空');
}
if (floatval(trim($params['refund_amount'])) <= 0) {
self::processError('退款金额(refund_amount)为大于0的数');
}
}
/**
* 构造请求参数
*/
private static function builderParams($params)
{
$RequestBuilder = new \AlipayTradeRefundContentBuilder();
// 1.判断单号类型
if (isset($params['trade_no'])) {
$RequestBuilder->setTradeNo($params['trade_no']);
} else {
$RequestBuilder->setOutTradeNo($params['trade_no']);
}
// 2.判断是否部分退款
if (!empty($params['out_request_no'])) {
$RequestBuilder->setOutRequestNo($params['out_request_no']);
}
$RequestBuilder->setRefundAmount($params['refund_amount']);
return $RequestBuilder;
}
/**
* 统一错误处理接口
* @param string $msg 错误描述
*/
private static function processError($msg)
{
throw new \think\Exception($msg);
}
}
\ No newline at end of file
<?php
namespace alipay;
use think\Loader;
Loader::import('alipay.pay.service.AlipayTradeService');
loader::import('alipay.pay.buildermodel.AlipayTradeFastpayRefundQueryContentBuilder');
/**
* 退款统一订单查询
*
* 用法:
* 调用 \alipay\RefundQuery::exec($params) 即可
*
* ----------------- 求职 ------------------
* 姓名: zhangchaojie 邮箱: zhangchaojie_php@qq.com 应届生
* 期望职位: PHP初级工程师 地点: 深圳(其他城市亦可)
* 能力:
* 1.熟悉小程序开发, 前后端皆可
* 2.后端, PHP基础知识扎实, 熟悉ThinkPHP5框架, 用TP5做过CMS, 商城, API接口
* 3.MySQL, Linux都在进行进一步学习
*
*/
class RefundQuery
{
/**
* 主入口
* @param array $params 退款查询参数, 具体如下:
* @param string $params['trade_no']/$params['out_trade_no'] 商户订单号或支付宝单号其中之一
* @param string $params['out_request_no'] 可空, 为空时, 退款号为订单号
*/
public static function exec($params)
{
// 1.校检参数
if (empty($params['trade_no']) && empty($params['out_trade_no'])) {
throw new \think\Exception('商户订单号(out_trade_no)和支付宝单号(trade_no)不得通知为空');
}
// 2.构造请求参数
$RequestBuilder = self::builderParams($params);
// 3.获取配置
$config = config('alipay');
$aop = new \AlipayTradeService($config);
// 4.发起请求
$response = $aop->refundQuery($RequestBuilder);
// 5.转为数组格式返回
$response = json_decode(json_encode($response), true);
// 6.进行结果处理
if (!empty($response['code']) && $response['code'] != '10000') {
self::processError('退款查询接口出错, 错误码为: '.$response['code'].', 错误原因为: '.$response['sub_msg']);
}
return $response;
}
/**
* 构造请求参数
*/
private static function builderParams($params)
{
$RequestBuilder = new \AlipayTradeFastpayRefundQueryContentBuilder();
if (isset($params['trade_no'])) {
$RequestBuilder->setTradeNo($params['trade_no']);
} else {
$RequestBuilder->setOutTradeNo($params['out_trade_no']);
}
// 如果未传退款号, 则以单号为退款号查询
if (isset($params['out_request_no'])) {
$RequestBuilder->setOutRequestNo($params['out_request_no']);
} else {
$out_request_no = isset($params['trade_no']) ? $params['trade_no'] : $params['out_trade_no'];
$RequestBuilder->setOutRequestNo($out_request_no);
}
return $RequestBuilder;
}
/**
* 统一错误处理接口
* @param string $msg 错误描述
*/
private static function processError($msg)
{
throw new \think\Exception($msg);
}
}
\ No newline at end of file
<?php
namespace alipay;
use think\Loader;
Loader::import('alipay.pay.service.AlipayWapPayTradeService');
loader::import('alipay.pay.buildermodel.AlipayTradeWapPayContentBuilder');
/**
* 支付宝手机网站支付接口
*
* 用法:
* 调用 \alipay\Wappay::pay($params) 即可
*
* ----------------- 求职 ------------------
* 姓名: zhangchaojie 邮箱: zhangchaojie_php@qq.com 应届生
* 期望职位: PHP初级工程师 地点: 深圳(其他城市亦可)
* 能力:
* 1.熟悉小程序开发, 前后端皆可
* 2.后端, PHP基础知识扎实, 熟悉ThinkPHP5框架, 用TP5做过CMS, 商城, API接口
* 3.MySQL, Linux都在进行进一步学习
*
*/
class Wappay
{
/**
* 主入口
* @param array $params 支付参数, 具体如下
* @param string $params['subject'] 订单标题
* @param string $params['out_trade_no'] 订单商户号
* @param float $params['total_amount'] 订单金额
*/
public static function pay($params)
{
// 1.校检参数
self::checkParams($params);
// 2.构造参数
$payRequestBuilder = new \AlipayTradeWapPayContentBuilder();
$payRequestBuilder->setSubject($params['subject']);
$payRequestBuilder->setOutTradeNo($params['out_trade_no']);
$payRequestBuilder->setTotalAmount($params['total_amount']);
$payRequestBuilder->setTimeExpress('1m');
// 3.获取配置
$config = config('alipay');
$payResponse = new \AlipayWapPayTradeService($config);
// 4.进行请求
$result=$payResponse->wapPay($payRequestBuilder,$config['return_url'],$config['notify_url']);
}
/**
* 校检参数
*/
private static function checkParams($params)
{
if (empty(trim($params['out_trade_no']))) {
self::processError('商户订单号(out_trade_no)必填');
}
if (empty(trim($params['subject']))) {
self::processError('商品标题(subject)必填');
}
if (floatval(trim($params['total_amount'])) <= 0) {
self::processError('退款金额(total_amount)为大于0的数');
}
}
/**
* 统一错误处理接口
* @param string $msg 错误描述
*/
private static function processError($msg)
{
throw new \think\Exception($msg);
}
}
\ No newline at end of file
<?php
/**
* AOP SDK 入口文件
* 请不要修改这个文件,除非你知道怎样修改以及怎样恢复
* @author wuxiao
*/
/**
* 定义常量开始
* 在include("AopSdk.php")之前定义这些常量,不要直接修改本文件,以利于升级覆盖
*/
/**
* SDK工作目录
* 存放日志,AOP缓存数据
*/
if (!defined("AOP_SDK_WORK_DIR"))
{
define("AOP_SDK_WORK_DIR", RUNTIME_PATH);
}
/**
* 是否处于开发模式
* 在你自己电脑上开发程序的时候千万不要设为false,以免缓存造成你的代码修改了不生效
* 部署到生产环境正式运营后,如果性能压力大,可以把此常量设定为false,能提高运行速度(对应的代价就是你下次升级程序时要清一下缓存)
*/
if (!defined("AOP_SDK_DEV_MODE"))
{
define("AOP_SDK_DEV_MODE", true);
}
/**
* 定义常量结束
*/
/**
* 找到lotusphp入口文件,并初始化lotusphp
* lotusphp是一个第三方php框架,其主页在:lotusphp.googlecode.com
*/
$lotusHome = dirname(__FILE__) . DIRECTORY_SEPARATOR . "lotusphp_runtime" . DIRECTORY_SEPARATOR;
include($lotusHome . "Lotus.php");
$lotus = new Lotus;
$lotus->option["autoload_dir"] = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'aop';
$lotus->devMode = AOP_SDK_DEV_MODE;
$lotus->defaultStoreDir = AOP_SDK_WORK_DIR;
$lotus->init();
\ No newline at end of file
<?php
/**
* 多媒体文件客户端
* @author yikai.hu
* @version $Id: AlipayMobilePublicMultiMediaClient.php, v 0.1 Aug 15, 2014 10:19:01 AM yikai.hu Exp $
*/
//namespace alipay\api ;
include("AlipayMobilePublicMultiMediaExecute.php");
class AlipayMobilePublicMultiMediaClient{
private $DEFAULT_CHARSET = 'UTF-8';
private $METHOD_POST = "POST";
private $METHOD_GET = "GET";
private $SIGN = 'sign'; //get name
private $timeout = 10 ;// 超时时间
private $serverUrl;
private $appId;
private $privateKey;
private $prodCode;
private $format = 'json'; //todo
private $sign_type = 'RSA'; //todo
private $charset;
private $apiVersion = "1.0";
private $apiMethodName = "alipay.mobile.public.multimedia.download";
private $media_id = "L21pZnMvVDFQV3hYWGJKWFhYYUNucHJYP3Q9YW13ZiZ4c2lnPTU0MzRhYjg1ZTZjNWJmZTMxZGJiNjIzNDdjMzFkNzkw575";
//此处写死的,实际开发中,请传入
private $connectTimeout = 3000;
private $readTimeout = 15000;
function __construct($serverUrl = '', $appId = '', $partner_private_key = '', $format = '', $charset = 'GBK'){
$this -> serverUrl = $serverUrl;
$this -> appId = $appId;
$this -> privateKey = $partner_private_key;
$this -> format = $format;
$this -> charset = $charset;
}
/**
* getContents 获取网址内容
* @param $request
* @return text | bin
*/
public function getContents(){
//自己的服务器如果没有 curl,可用:fsockopen() 等
//1:
//2: 私钥格式
$datas = array(
"app_id" => $this -> appId,
"method" => $this -> METHOD_POST,
"sign_type" => $this -> sign_type,
"version" => $this -> apiVersion,
"timestamp" => date('Y-m-d H:i:s') ,//yyyy-MM-dd HH:mm:ss
"biz_content" => '{"mediaId":"'. $this -> media_id .'"}',
"charset" => $this -> charset
);
//要提交的数据
$data_sign = $this -> buildGetUrl( $datas );
$post_data = $data_sign;
//初始化 curl
$ch = curl_init();
//设置目标服务器
curl_setopt($ch, CURLOPT_URL, $this -> serverUrl );
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//超时时间
curl_setopt($ch, CURLOPT_TIMEOUT, $this-> timeout);
if( $this-> METHOD_POST == 'POST'){
// post数据
curl_setopt($ch, CURLOPT_POST, 1);
// post的变量
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
}
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $output;
//分离头部
//list($header, $body) = explode("\r\n\r\n", $output, 2);
$datas = explode("\r\n\r\n", $output, 2);
$header = $datas[0];
if( $httpCode == '200'){
$body = $datas[1];
}else{
$body = '';
}
return $this -> execute( $header, $body, $httpCode );
}
/**
*
* @param $request
* @return text | bin
*/
public function execute( $header = '', $body = '', $httpCode = '' ){
$exe = new AlipayMobilePublicMultiMediaExecute( $header, $body, $httpCode );
return $exe;
}
public function buildGetUrl( $query = array() ){
if( ! is_array( $query ) ){
//exit;
}
//排序参数,
$data = $this -> buildQuery( $query );
// 私钥密码
$passphrase = '';
$key_width = 64;
//私钥
$privateKey = $this -> privateKey;
$p_key = array();
//如果私钥是 1行
if( ! stripos( $privateKey, "\n" ) ){
$i = 0;
while( $key_str = substr( $privateKey , $i * $key_width , $key_width) ){
$p_key[] = $key_str;
$i ++ ;
}
}else{
//echo '一行?';
}
$privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" . implode("\n", $p_key) ;
$privateKey = $privateKey ."\n-----END RSA PRIVATE KEY-----";
// echo "\n\n私钥:\n";
// echo( $privateKey );
// echo "\n\n\n";
//私钥
$private_id = openssl_pkey_get_private( $privateKey , $passphrase);
// 签名
$signature = '';
if("RSA2"==$this->sign_type){
openssl_sign($data, $signature, $private_id, OPENSSL_ALGO_SHA256 );
}else{
openssl_sign($data, $signature, $private_id, OPENSSL_ALGO_SHA1 );
}
openssl_free_key( $private_id );
//加密后的内容通常含有特殊字符,需要编码转换下
$signature = base64_encode($signature);
$signature = urlencode( $signature );
//$signature = 'XjUN6YM1Mc9HXebKMv7GTLy7gmyhktyOgKk2/Jf+cz4DtP6udkzTdpkjW2j/Z4ZSD7xD6CNYI1Spz4yS93HPT0a5X9LgFWYY8SaADqe+ArXg+FBSiTwUz49SE//Xd9+LEiIRsSFkbpkuiGoO6mqJmB7vXjlD5lx6qCM3nb41wb8=';
$out = $data .'&'. $this -> SIGN .'='. $signature;
// echo "\n\n 加密后:\n";
// echo( $out );
// echo "\n\n\n";
return $out ;
}
/*
* 查询参数排序 a-z
* */
public function buildQuery( $query ){
if ( !$query ) {
return null;
}
//将要 参数 排序
ksort( $query );
//重新组装参数
$params = array();
foreach($query as $key => $value){
$params[] = $key .'='. $value ;
}
$data = implode('&', $params);
return $data;
}
}
<?php
/**
* 多媒体文件客户端
* @author yuanwai.wang
* @version $Id: AlipayMobilePublicMultiMediaExecute.php, v 0.1 Aug 15, 2014 10:19:01 AM yuanwai.wang Exp $
*/
//namespace alipay\api ;
class AlipayMobilePublicMultiMediaExecute{
private $code = 200 ;
private $msg = '';
private $body = '';
private $params = '';
private $fileSuffix = array(
"image/jpeg" => 'jpg', //+
"text/plain" => 'text'
);
/*
* @$header : 头部
* */
function __construct( $header, $body, $httpCode ){
$this -> code = $httpCode;
$this -> msg = '';
$this -> params = $header ;
$this -> body = $body;
}
/**
*
* @return text | bin
*/
public function getCode(){
return $this -> code ;
}
/**
*
* @return text | bin
*/
public function getMsg(){
return $this -> msg ;
}
/**
*
* @return text | bin
*/
public function getType(){
$subject = $this -> params ;
$pattern = '/Content\-Type:([^;]+)/';
preg_match($pattern, $subject, $matches);
if( $matches ){
$type = $matches[1];
}else{
$type = 'application/download';
}
return str_replace( ' ', '', $type );
}
/**
*
* @return text | bin
*/
public function getContentLength(){
$subject = $this -> params ;
$pattern = '/Content-Length:\s*([^\n]+)/';
preg_match($pattern, $subject, $matches);
return (int)( isset($matches[1] ) ? $matches[1] : '' );
}
public function getFileSuffix( $fileType ){
$type = isset( $this -> fileSuffix[ $fileType ] ) ? $this -> fileSuffix[ $fileType ] : 'text/plain' ;
if( !$type ){
$type = 'json';
}
return $type;
}
/**
*
* @return text | bin
*/
public function getBody(){
//header('Content-type: image/jpeg');
return $this -> body ;
}
/**
* 获取参数
* @return text | bin
*/
public function getParams(){
return $this -> params ;
}
}
<?php
require_once 'AopEncrypt.php';
class AopClient {
//应用ID
public $appId;
//私钥文件路径
public $rsaPrivateKeyFilePath;
//私钥值
public $rsaPrivateKey;
//网关
public $gatewayUrl = "https://openapi.alipay.com/gateway.do";
//返回数据格式
public $format = "json";
//api版本
public $apiVersion = "1.0";
// 表单提交字符集编码
public $postCharset = "UTF-8";
public $alipayPublicKey = null;
public $alipayrsaPublicKey;
public $debugInfo = false;
private $fileCharset = "UTF-8";
private $RESPONSE_SUFFIX = "_response";
private $ERROR_RESPONSE = "error_response";
private $SIGN_NODE_NAME = "sign";
//加密XML节点名称
private $ENCRYPT_XML_NODE_NAME = "response_encrypted";
private $needEncrypt = false;
//签名类型
public $signType = "RSA";
//加密密钥和类型
public $encryptKey;
public $encryptType = "AES";
protected $alipaySdkVersion = "alipay-sdk-php-20161101";
public function generateSign($params, $signType = "RSA") {
return $this->sign($this->getSignContent($params), $signType);
}
public function rsaSign($params, $signType = "RSA") {
return $this->sign($this->getSignContent($params), $signType);
}
protected function getSignContent($params) {
ksort($params);
$stringToBeSigned = "";
$i = 0;
foreach ($params as $k => $v) {
if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {
// 转换成目标字符集
$v = $this->characet($v, $this->postCharset);
if ($i == 0) {
$stringToBeSigned .= "$k" . "=" . "$v";
} else {
$stringToBeSigned .= "&" . "$k" . "=" . "$v";
}
$i++;
}
}
unset ($k, $v);
return $stringToBeSigned;
}
protected function sign($data, $signType = "RSA") {
if($this->checkEmpty($this->rsaPrivateKeyFilePath)){
$priKey=$this->rsaPrivateKey;
$res = "-----BEGIN RSA PRIVATE KEY-----\n" .
wordwrap($priKey, 64, "\n", true) .
"\n-----END RSA PRIVATE KEY-----";
}else {
$priKey = file_get_contents($this->rsaPrivateKeyFilePath);
$res = openssl_get_privatekey($priKey);
}
($res) or die('您使用的私钥格式错误,请检查RSA私钥配置');
if ("RSA2" == $signType) {
openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256);
} else {
openssl_sign($data, $sign, $res);
}
if(!$this->checkEmpty($this->rsaPrivateKeyFilePath)){
openssl_free_key($res);
}
$sign = base64_encode($sign);
return $sign;
}
protected function curl($url, $postFields = null) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$postBodyString = "";
$encodeArray = Array();
$postMultipart = false;
if (is_array($postFields) && 0 < count($postFields)) {
foreach ($postFields as $k => $v) {
if ("@" != substr($v, 0, 1)) //判断是不是文件上传
{
$postBodyString .= "$k=" . urlencode($this->characet($v, $this->postCharset)) . "&";
$encodeArray[$k] = $this->characet($v, $this->postCharset);
} else //文件上传用multipart/form-data,否则用www-form-urlencoded
{
$postMultipart = true;
$encodeArray[$k] = new \CURLFile(substr($v, 1));
}
}
unset ($k, $v);
curl_setopt($ch, CURLOPT_POST, true);
if ($postMultipart) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $encodeArray);
} else {
curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString, 0, -1));
}
}
if ($postMultipart) {
$headers = array('content-type: multipart/form-data;charset=' . $this->postCharset . ';boundary=' . $this->getMillisecond());
} else {
$headers = array('content-type: application/x-www-form-urlencoded;charset=' . $this->postCharset);
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$reponse = curl_exec($ch);
if (curl_errno($ch)) {
throw new Exception(curl_error($ch), 0);
} else {
$httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (200 !== $httpStatusCode) {
throw new Exception($reponse, $httpStatusCode);
}
}
curl_close($ch);
return $reponse;
}
protected function getMillisecond() {
list($s1, $s2) = explode(' ', microtime());
return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
}
protected function logCommunicationError($apiName, $requestUrl, $errorCode, $responseTxt) {
$localIp = isset ($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_ADDR"] : "CLI";
$logger = new LtLogger;
$logger->conf["log_file"] = rtrim(AOP_SDK_WORK_DIR, '\\/') . '/' . "logs/aop_comm_err_" . $this->appId . "_" . date("Y-m-d") . ".log";
$logger->conf["separator"] = "^_^";
$logData = array(
date("Y-m-d H:i:s"),
$apiName,
$this->appId,
$localIp,
PHP_OS,
$this->alipaySdkVersion,
$requestUrl,
$errorCode,
str_replace("\n", "", $responseTxt)
);
$logger->log($logData);
}
/**
* 生成用于调用收银台SDK的字符串
* @param $request SDK接口的请求参数对象
* @return string
* @author guofa.tgf
*/
public function sdkExecute($request) {
$this->setupCharsets($request);
$params['app_id'] = $this->appId;
$params['method'] = $request->getApiMethodName();
$params['format'] = $this->format;
$params['sign_type'] = $this->signType;
$params['timestamp'] = date("Y-m-d H:i:s");
$params['alipay_sdk'] = $this->alipaySdkVersion;
$params['charset'] = $this->postCharset;
$version = $request->getApiVersion();
$params['version'] = $this->checkEmpty($version) ? $this->apiVersion : $version;
if ($notify_url = $request->getNotifyUrl()) {
$params['notify_url'] = $notify_url;
}
$dict = $request->getApiParas();
$params['biz_content'] = $dict['biz_content'];
ksort($params);
$params['sign'] = $this->generateSign($params, $this->signType);
foreach ($params as &$value) {
$value = $this->characet($value, $params['charset']);
}
return http_build_query($params);
}
/*
页面提交执行方法
@param:跳转类接口的request; $httpmethod 提交方式。两个值可选:post、get
@return:构建好的、签名后的最终跳转URL(GET)或String形式的form(POST)
auther:笙默
*/
public function pageExecute($request,$httpmethod = "POST") {
$this->setupCharsets($request);
if (strcasecmp($this->fileCharset, $this->postCharset)) {
// writeLog("本地文件字符集编码与表单提交编码不一致,请务必设置成一样,属性名分别为postCharset!");
throw new Exception("文件编码:[" . $this->fileCharset . "] 与表单提交编码:[" . $this->postCharset . "]两者不一致!");
}
$iv=null;
if(!$this->checkEmpty($request->getApiVersion())){
$iv=$request->getApiVersion();
}else{
$iv=$this->apiVersion;
}
//组装系统参数
$sysParams["app_id"] = $this->appId;
$sysParams["version"] = $iv;
$sysParams["format"] = $this->format;
$sysParams["sign_type"] = $this->signType;
$sysParams["method"] = $request->getApiMethodName();
$sysParams["timestamp"] = date("Y-m-d H:i:s");
$sysParams["alipay_sdk"] = $this->alipaySdkVersion;
$sysParams["terminal_type"] = $request->getTerminalType();
$sysParams["terminal_info"] = $request->getTerminalInfo();
$sysParams["prod_code"] = $request->getProdCode();
$sysParams["notify_url"] = $request->getNotifyUrl();
$sysParams["return_url"] = $request->getReturnUrl();
$sysParams["charset"] = $this->postCharset;
//获取业务参数
$apiParams = $request->getApiParas();
if (method_exists($request,"getNeedEncrypt") &&$request->getNeedEncrypt()){
$sysParams["encrypt_type"] = $this->encryptType;
if ($this->checkEmpty($apiParams['biz_content'])) {
throw new Exception(" api request Fail! The reason : encrypt request is not supperted!");
}
if ($this->checkEmpty($this->encryptKey) || $this->checkEmpty($this->encryptType)) {
throw new Exception(" encryptType and encryptKey must not null! ");
}
if ("AES" != $this->encryptType) {
throw new Exception("加密类型只支持AES");
}
// 执行加密
$enCryptContent = encrypt($apiParams['biz_content'], $this->encryptKey);
$apiParams['biz_content'] = $enCryptContent;
}
//print_r($apiParams);
$totalParams = array_merge($apiParams, $sysParams);
//待签名字符串
$preSignStr = $this->getSignContent($totalParams);
//签名
$totalParams["sign"] = $this->generateSign($totalParams, $this->signType);
if ("GET" == $httpmethod) {
//拼接GET请求串
$requestUrl = $this->gatewayUrl."?".$preSignStr."&sign=".urlencode($totalParams["sign"]);
return $requestUrl;
} else {
//拼接表单字符串
return $this->buildRequestForm($totalParams);
}
}
/**
* 建立请求,以表单HTML形式构造(默认)
* @param $para_temp 请求参数数组
* @return 提交表单HTML文本
*/
protected function buildRequestForm($para_temp) {
$sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='".$this->gatewayUrl."?charset=".trim($this->postCharset)."' method='POST'>";
while (list ($key, $val) = each ($para_temp)) {
if (false === $this->checkEmpty($val)) {
//$val = $this->characet($val, $this->postCharset);
$val = str_replace("'","&apos;",$val);
//$val = str_replace("\"","&quot;",$val);
$sHtml.= "<input type='hidden' name='".$key."' value='".$val."'/>";
}
}
//submit按钮控件请不要含有name属性
$sHtml = $sHtml."<input type='submit' value='ok' style='display:none;''></form>";
$sHtml = $sHtml."<script>document.forms['alipaysubmit'].submit();</script>";
return $sHtml;
}
public function execute($request, $authToken = null, $appInfoAuthtoken = null) {
$this->setupCharsets($request);
// // 如果两者编码不一致,会出现签名验签或者乱码
if (strcasecmp($this->fileCharset, $this->postCharset)) {
// writeLog("本地文件字符集编码与表单提交编码不一致,请务必设置成一样,属性名分别为postCharset!");
throw new Exception("文件编码:[" . $this->fileCharset . "] 与表单提交编码:[" . $this->postCharset . "]两者不一致!");
}
$iv = null;
if (!$this->checkEmpty($request->getApiVersion())) {
$iv = $request->getApiVersion();
} else {
$iv = $this->apiVersion;
}
//组装系统参数
$sysParams["app_id"] = $this->appId;
$sysParams["version"] = $iv;
$sysParams["format"] = $this->format;
$sysParams["sign_type"] = $this->signType;
$sysParams["method"] = $request->getApiMethodName();
$sysParams["timestamp"] = date("Y-m-d H:i:s");
$sysParams["auth_token"] = $authToken;
$sysParams["alipay_sdk"] = $this->alipaySdkVersion;
$sysParams["terminal_type"] = $request->getTerminalType();
$sysParams["terminal_info"] = $request->getTerminalInfo();
$sysParams["prod_code"] = $request->getProdCode();
$sysParams["notify_url"] = $request->getNotifyUrl();
$sysParams["charset"] = $this->postCharset;
$sysParams["app_auth_token"] = $appInfoAuthtoken;
//获取业务参数
$apiParams = $request->getApiParas();
if (method_exists($request,"getNeedEncrypt") &&$request->getNeedEncrypt()){
$sysParams["encrypt_type"] = $this->encryptType;
if ($this->checkEmpty($apiParams['biz_content'])) {
throw new Exception(" api request Fail! The reason : encrypt request is not supperted!");
}
if ($this->checkEmpty($this->encryptKey) || $this->checkEmpty($this->encryptType)) {
throw new Exception(" encryptType and encryptKey must not null! ");
}
if ("AES" != $this->encryptType) {
throw new Exception("加密类型只支持AES");
}
// 执行加密
$enCryptContent = encrypt($apiParams['biz_content'], $this->encryptKey);
$apiParams['biz_content'] = $enCryptContent;
}
//签名
$sysParams["sign"] = $this->generateSign(array_merge($apiParams, $sysParams), $this->signType);
//系统参数放入GET请求串
$requestUrl = $this->gatewayUrl . "?";
foreach ($sysParams as $sysParamKey => $sysParamValue) {
$requestUrl .= "$sysParamKey=" . urlencode($this->characet($sysParamValue, $this->postCharset)) . "&";
}
$requestUrl = substr($requestUrl, 0, -1);
//发起HTTP请求
try {
$resp = $this->curl($requestUrl, $apiParams);
} catch (Exception $e) {
$this->logCommunicationError($sysParams["method"], $requestUrl, "HTTP_ERROR_" . $e->getCode(), $e->getMessage());
return false;
}
//解析AOP返回结果
$respWellFormed = false;
// 将返回结果转换本地文件编码
$r = iconv($this->postCharset, $this->fileCharset . "//IGNORE", $resp);
$signData = null;
if ("json" == $this->format) {
$respObject = json_decode($r);
if (null !== $respObject) {
$respWellFormed = true;
$signData = $this->parserJSONSignData($request, $resp, $respObject);
}
} else if ("xml" == $this->format) {
$respObject = @ simplexml_load_string($resp);
if (false !== $respObject) {
$respWellFormed = true;
$signData = $this->parserXMLSignData($request, $resp);
}
}
//返回的HTTP文本不是标准JSON或者XML,记下错误日志
if (false === $respWellFormed) {
$this->logCommunicationError($sysParams["method"], $requestUrl, "HTTP_RESPONSE_NOT_WELL_FORMED", $resp);
return false;
}
// 验签
$this->checkResponseSign($request, $signData, $resp, $respObject);
// 解密
if (method_exists($request,"getNeedEncrypt") &&$request->getNeedEncrypt()){
if ("json" == $this->format) {
$resp = $this->encryptJSONSignSource($request, $resp);
// 将返回结果转换本地文件编码
$r = iconv($this->postCharset, $this->fileCharset . "//IGNORE", $resp);
$respObject = json_decode($r);
}else{
$resp = $this->encryptXMLSignSource($request, $resp);
$r = iconv($this->postCharset, $this->fileCharset . "//IGNORE", $resp);
$respObject = @ simplexml_load_string($r);
}
}
return $respObject;
}
/**
* 转换字符集编码
* @param $data
* @param $targetCharset
* @return string
*/
function characet($data, $targetCharset) {
if (!empty($data)) {
$fileType = $this->fileCharset;
if (strcasecmp($fileType, $targetCharset) != 0) {
$data = mb_convert_encoding($data, $targetCharset, $fileType);
// $data = iconv($fileType, $targetCharset.'//IGNORE', $data);
}
}
return $data;
}
public function exec($paramsArray) {
if (!isset ($paramsArray["method"])) {
trigger_error("No api name passed");
}
$inflector = new LtInflector;
$inflector->conf["separator"] = ".";
$requestClassName = ucfirst($inflector->camelize(substr($paramsArray["method"], 7))) . "Request";
if (!class_exists($requestClassName)) {
trigger_error("No such api: " . $paramsArray["method"]);
}
$session = isset ($paramsArray["session"]) ? $paramsArray["session"] : null;
$req = new $requestClassName;
foreach ($paramsArray as $paraKey => $paraValue) {
$inflector->conf["separator"] = "_";
$setterMethodName = $inflector->camelize($paraKey);
$inflector->conf["separator"] = ".";
$setterMethodName = "set" . $inflector->camelize($setterMethodName);
if (method_exists($req, $setterMethodName)) {
$req->$setterMethodName ($paraValue);
}
}
return $this->execute($req, $session);
}
/**
* 校验$value是否非空
* if not set ,return true;
* if is null , return true;
**/
protected function checkEmpty($value) {
if (!isset($value))
return true;
if ($value === null)
return true;
if (trim($value) === "")
return true;
return false;
}
/** rsaCheckV1 & rsaCheckV2
* 验证签名
* 在使用本方法前,必须初始化AopClient且传入公钥参数。
* 公钥是否是读取字符串还是读取文件,是根据初始化传入的值判断的。
**/
public function rsaCheckV1($params, $rsaPublicKeyFilePath,$signType='RSA') {
$sign = $params['sign'];
$params['sign_type'] = null;
$params['sign'] = null;
return $this->verify($this->getSignContent($params), $sign, $rsaPublicKeyFilePath,$signType);
}
public function rsaCheckV2($params, $rsaPublicKeyFilePath, $signType='RSA') {
$sign = $params['sign'];
$params['sign'] = null;
return $this->verify($this->getSignContent($params), $sign, $rsaPublicKeyFilePath, $signType);
}
function verify($data, $sign, $rsaPublicKeyFilePath, $signType = 'RSA') {
if($this->checkEmpty($this->alipayPublicKey)){
$pubKey= $this->alipayrsaPublicKey;
$res = "-----BEGIN PUBLIC KEY-----\n" .
wordwrap($pubKey, 64, "\n", true) .
"\n-----END PUBLIC KEY-----";
}else {
//读取公钥文件
$pubKey = file_get_contents($rsaPublicKeyFilePath);
//转换为openssl格式密钥
$res = openssl_get_publickey($pubKey);
}
($res) or die('支付宝RSA公钥错误。请检查公钥文件格式是否正确');
//调用openssl内置方法验签,返回bool值
if ("RSA2" == $signType) {
$result = (bool)openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256);
} else {
$result = (bool)openssl_verify($data, base64_decode($sign), $res);
}
if(!$this->checkEmpty($this->alipayPublicKey)) {
//释放资源
openssl_free_key($res);
}
return $result;
}
public function checkSignAndDecrypt($params, $rsaPublicKeyPem, $rsaPrivateKeyPem, $isCheckSign, $isDecrypt) {
$charset = $params['charset'];
$bizContent = $params['biz_content'];
if ($isCheckSign) {
if (!$this->rsaCheckV2($params, $rsaPublicKeyPem)) {
echo "<br/>checkSign failure<br/>";
exit;
}
}
if ($isDecrypt) {
return $this->rsaDecrypt($bizContent, $rsaPrivateKeyPem, $charset);
}
return $bizContent;
}
public function encryptAndSign($bizContent, $rsaPublicKeyPem, $rsaPrivateKeyPem, $charset, $isEncrypt, $isSign) {
// 加密,并签名
if ($isEncrypt && $isSign) {
$encrypted = $this->rsaEncrypt($bizContent, $rsaPublicKeyPem, $charset);
$sign = $this->sign($bizContent);
$response = "<?xml version=\"1.0\" encoding=\"$charset\"?><alipay><response>$encrypted</response><encryption_type>RSA</encryption_type><sign>$sign</sign><sign_type>RSA</sign_type></alipay>";
return $response;
}
// 加密,不签名
if ($isEncrypt && (!$isSign)) {
$encrypted = $this->rsaEncrypt($bizContent, $rsaPublicKeyPem, $charset);
$response = "<?xml version=\"1.0\" encoding=\"$charset\"?><alipay><response>$encrypted</response><encryption_type>RSA</encryption_type></alipay>";
return $response;
}
// 不加密,但签名
if ((!$isEncrypt) && $isSign) {
$sign = $this->sign($bizContent);
$response = "<?xml version=\"1.0\" encoding=\"$charset\"?><alipay><response>$bizContent</response><sign>$sign</sign><sign_type>RSA</sign_type></alipay>";
return $response;
}
// 不加密,不签名
$response = "<?xml version=\"1.0\" encoding=\"$charset\"?>$bizContent";
return $response;
}
public function rsaEncrypt($data, $rsaPublicKeyPem, $charset) {
//读取公钥文件
$pubKey = file_get_contents($rsaPublicKeyPem);
//转换为openssl格式密钥
$res = openssl_get_publickey($pubKey);
$blocks = $this->splitCN($data, 0, 30, $charset);
$chrtext  = null;
$encodes  = array();
foreach ($blocks as $n => $block) {
if (!openssl_public_encrypt($block, $chrtext , $res)) {
echo "<br/>" . openssl_error_string() . "<br/>";
}
$encodes[] = $chrtext ;
}
$chrtext = implode(",", $encodes);
return $chrtext;
}
public function rsaDecrypt($data, $rsaPrivateKeyPem, $charset) {
//读取私钥文件
$priKey = file_get_contents($rsaPrivateKeyPem);
//转换为openssl格式密钥
$res = openssl_get_privatekey($priKey);
$decodes = explode(',', $data);
$strnull = "";
$dcyCont = "";
foreach ($decodes as $n => $decode) {
if (!openssl_private_decrypt($decode, $dcyCont, $res)) {
echo "<br/>" . openssl_error_string() . "<br/>";
}
$strnull .= $dcyCont;
}
return $strnull;
}
function splitCN($cont, $n = 0, $subnum, $charset) {
//$len = strlen($cont) / 3;
$arrr = array();
for ($i = $n; $i < strlen($cont); $i += $subnum) {
$res = $this->subCNchar($cont, $i, $subnum, $charset);
if (!empty ($res)) {
$arrr[] = $res;
}
}
return $arrr;
}
function subCNchar($str, $start = 0, $length, $charset = "gbk") {
if (strlen($str) <= $length) {
return $str;
}
$re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
$re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
$re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
$re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
preg_match_all($re[$charset], $str, $match);
$slice = join("", array_slice($match[0], $start, $length));
return $slice;
}
function parserResponseSubCode($request, $responseContent, $respObject, $format) {
if ("json" == $format) {
$apiName = $request->getApiMethodName();
$rootNodeName = str_replace(".", "_", $apiName) . $this->RESPONSE_SUFFIX;
$errorNodeName = $this->ERROR_RESPONSE;
$rootIndex = strpos($responseContent, $rootNodeName);
$errorIndex = strpos($responseContent, $errorNodeName);
if ($rootIndex > 0) {
// 内部节点对象
$rInnerObject = $respObject->$rootNodeName;
} elseif ($errorIndex > 0) {
$rInnerObject = $respObject->$errorNodeName;
} else {
return null;
}
// 存在属性则返回对应值
if (isset($rInnerObject->sub_code)) {
return $rInnerObject->sub_code;
} else {
return null;
}
} elseif ("xml" == $format) {
// xml格式sub_code在同一层级
return $respObject->sub_code;
}
}
function parserJSONSignData($request, $responseContent, $responseJSON) {
$signData = new SignData();
$signData->sign = $this->parserJSONSign($responseJSON);
$signData->signSourceData = $this->parserJSONSignSource($request, $responseContent);
return $signData;
}
function parserJSONSignSource($request, $responseContent) {
$apiName = $request->getApiMethodName();
$rootNodeName = str_replace(".", "_", $apiName) . $this->RESPONSE_SUFFIX;
$rootIndex = strpos($responseContent, $rootNodeName);
$errorIndex = strpos($responseContent, $this->ERROR_RESPONSE);
if ($rootIndex > 0) {
return $this->parserJSONSource($responseContent, $rootNodeName, $rootIndex);
} else if ($errorIndex > 0) {
return $this->parserJSONSource($responseContent, $this->ERROR_RESPONSE, $errorIndex);
} else {
return null;
}
}
function parserJSONSource($responseContent, $nodeName, $nodeIndex) {
$signDataStartIndex = $nodeIndex + strlen($nodeName) + 2;
$signIndex = strpos($responseContent, "\"" . $this->SIGN_NODE_NAME . "\"");
// 签名前-逗号
$signDataEndIndex = $signIndex - 1;
$indexLen = $signDataEndIndex - $signDataStartIndex;
if ($indexLen < 0) {
return null;
}
return substr($responseContent, $signDataStartIndex, $indexLen);
}
function parserJSONSign($responseJSon) {
return $responseJSon->sign;
}
function parserXMLSignData($request, $responseContent) {
$signData = new SignData();
$signData->sign = $this->parserXMLSign($responseContent);
$signData->signSourceData = $this->parserXMLSignSource($request, $responseContent);
return $signData;
}
function parserXMLSignSource($request, $responseContent) {
$apiName = $request->getApiMethodName();
$rootNodeName = str_replace(".", "_", $apiName) . $this->RESPONSE_SUFFIX;
$rootIndex = strpos($responseContent, $rootNodeName);
$errorIndex = strpos($responseContent, $this->ERROR_RESPONSE);
// $this->echoDebug("<br/>rootNodeName:" . $rootNodeName);
// $this->echoDebug("<br/> responseContent:<xmp>" . $responseContent . "</xmp>");
if ($rootIndex > 0) {
return $this->parserXMLSource($responseContent, $rootNodeName, $rootIndex);
} else if ($errorIndex > 0) {
return $this->parserXMLSource($responseContent, $this->ERROR_RESPONSE, $errorIndex);
} else {
return null;
}
}
function parserXMLSource($responseContent, $nodeName, $nodeIndex) {
$signDataStartIndex = $nodeIndex + strlen($nodeName) + 1;
$signIndex = strpos($responseContent, "<" . $this->SIGN_NODE_NAME . ">");
// 签名前-逗号
$signDataEndIndex = $signIndex - 1;
$indexLen = $signDataEndIndex - $signDataStartIndex + 1;
if ($indexLen < 0) {
return null;
}
return substr($responseContent, $signDataStartIndex, $indexLen);
}
function parserXMLSign($responseContent) {
$signNodeName = "<" . $this->SIGN_NODE_NAME . ">";
$signEndNodeName = "</" . $this->SIGN_NODE_NAME . ">";
$indexOfSignNode = strpos($responseContent, $signNodeName);
$indexOfSignEndNode = strpos($responseContent, $signEndNodeName);
if ($indexOfSignNode < 0 || $indexOfSignEndNode < 0) {
return null;
}
$nodeIndex = ($indexOfSignNode + strlen($signNodeName));
$indexLen = $indexOfSignEndNode - $nodeIndex;
if ($indexLen < 0) {
return null;
}
// 签名
return substr($responseContent, $nodeIndex, $indexLen);
}
/**
* 验签
* @param $request
* @param $signData
* @param $resp
* @param $respObject
* @throws Exception
*/
public function checkResponseSign($request, $signData, $resp, $respObject) {
if (!$this->checkEmpty($this->alipayPublicKey) || !$this->checkEmpty($this->alipayrsaPublicKey)) {
if ($signData == null || $this->checkEmpty($signData->sign) || $this->checkEmpty($signData->signSourceData)) {
throw new Exception(" check sign Fail! The reason : signData is Empty");
}
// 获取结果sub_code
$responseSubCode = $this->parserResponseSubCode($request, $resp, $respObject, $this->format);
if (!$this->checkEmpty($responseSubCode) || ($this->checkEmpty($responseSubCode) && !$this->checkEmpty($signData->sign))) {
$checkResult = $this->verify($signData->signSourceData, $signData->sign, $this->alipayPublicKey, $this->signType);
if (!$checkResult) {
if (strpos($signData->signSourceData, "\\/") > 0) {
$signData->signSourceData = str_replace("\\/", "/", $signData->signSourceData);
$checkResult = $this->verify($signData->signSourceData, $signData->sign, $this->alipayPublicKey, $this->signType);
if (!$checkResult) {
throw new Exception("check sign Fail! [sign=" . $signData->sign . ", signSourceData=" . $signData->signSourceData . "]");
}
} else {
throw new Exception("check sign Fail! [sign=" . $signData->sign . ", signSourceData=" . $signData->signSourceData . "]");
}
}
}
}
}
private function setupCharsets($request) {
if ($this->checkEmpty($this->postCharset)) {
$this->postCharset = 'UTF-8';
}
$str = preg_match('/[\x80-\xff]/', $this->appId) ? $this->appId : print_r($request, true);
$this->fileCharset = mb_detect_encoding($str, "UTF-8, GBK") == 'UTF-8' ? 'UTF-8' : 'GBK';
}
// 获取加密内容
private function encryptJSONSignSource($request, $responseContent) {
$parsetItem = $this->parserEncryptJSONSignSource($request, $responseContent);
$bodyIndexContent = substr($responseContent, 0, $parsetItem->startIndex);
$bodyEndContent = substr($responseContent, $parsetItem->endIndex, strlen($responseContent) + 1 - $parsetItem->endIndex);
$bizContent = decrypt($parsetItem->encryptContent, $this->encryptKey);
return $bodyIndexContent . $bizContent . $bodyEndContent;
}
private function parserEncryptJSONSignSource($request, $responseContent) {
$apiName = $request->getApiMethodName();
$rootNodeName = str_replace(".", "_", $apiName) . $this->RESPONSE_SUFFIX;
$rootIndex = strpos($responseContent, $rootNodeName);
$errorIndex = strpos($responseContent, $this->ERROR_RESPONSE);
if ($rootIndex > 0) {
return $this->parserEncryptJSONItem($responseContent, $rootNodeName, $rootIndex);
} else if ($errorIndex > 0) {
return $this->parserEncryptJSONItem($responseContent, $this->ERROR_RESPONSE, $errorIndex);
} else {
return null;
}
}
private function parserEncryptJSONItem($responseContent, $nodeName, $nodeIndex) {
$signDataStartIndex = $nodeIndex + strlen($nodeName) + 2;
$signIndex = strpos($responseContent, "\"" . $this->SIGN_NODE_NAME . "\"");
// 签名前-逗号
$signDataEndIndex = $signIndex - 1;
if ($signDataEndIndex < 0) {
$signDataEndIndex = strlen($responseContent)-1 ;
}
$indexLen = $signDataEndIndex - $signDataStartIndex;
$encContent = substr($responseContent, $signDataStartIndex+1, $indexLen-2);
$encryptParseItem = new EncryptParseItem();
$encryptParseItem->encryptContent = $encContent;
$encryptParseItem->startIndex = $signDataStartIndex;
$encryptParseItem->endIndex = $signDataEndIndex;
return $encryptParseItem;
}
// 获取加密内容
private function encryptXMLSignSource($request, $responseContent) {
$parsetItem = $this->parserEncryptXMLSignSource($request, $responseContent);
$bodyIndexContent = substr($responseContent, 0, $parsetItem->startIndex);
$bodyEndContent = substr($responseContent, $parsetItem->endIndex, strlen($responseContent) + 1 - $parsetItem->endIndex);
$bizContent = decrypt($parsetItem->encryptContent, $this->encryptKey);
return $bodyIndexContent . $bizContent . $bodyEndContent;
}
private function parserEncryptXMLSignSource($request, $responseContent) {
$apiName = $request->getApiMethodName();
$rootNodeName = str_replace(".", "_", $apiName) . $this->RESPONSE_SUFFIX;
$rootIndex = strpos($responseContent, $rootNodeName);
$errorIndex = strpos($responseContent, $this->ERROR_RESPONSE);
// $this->echoDebug("<br/>rootNodeName:" . $rootNodeName);
// $this->echoDebug("<br/> responseContent:<xmp>" . $responseContent . "</xmp>");
if ($rootIndex > 0) {
return $this->parserEncryptXMLItem($responseContent, $rootNodeName, $rootIndex);
} else if ($errorIndex > 0) {
return $this->parserEncryptXMLItem($responseContent, $this->ERROR_RESPONSE, $errorIndex);
} else {
return null;
}
}
private function parserEncryptXMLItem($responseContent, $nodeName, $nodeIndex) {
$signDataStartIndex = $nodeIndex + strlen($nodeName) + 1;
$xmlStartNode="<".$this->ENCRYPT_XML_NODE_NAME.">";
$xmlEndNode="</".$this->ENCRYPT_XML_NODE_NAME.">";
$indexOfXmlNode=strpos($responseContent,$xmlEndNode);
if($indexOfXmlNode<0){
$item = new EncryptParseItem();
$item->encryptContent = null;
$item->startIndex = 0;
$item->endIndex = 0;
return $item;
}
$startIndex=$signDataStartIndex+strlen($xmlStartNode);
$bizContentLen=$indexOfXmlNode-$startIndex;
$bizContent=substr($responseContent,$startIndex,$bizContentLen);
$encryptParseItem = new EncryptParseItem();
$encryptParseItem->encryptContent = $bizContent;
$encryptParseItem->startIndex = $signDataStartIndex;
$encryptParseItem->endIndex = $indexOfXmlNode+strlen($xmlEndNode);
return $encryptParseItem;
}
function echoDebug($content) {
if ($this->debugInfo) {
echo "<br/>" . $content;
}
}
}
\ No newline at end of file
<?php
/**
* 加密工具类
*
* User: jiehua
* Date: 16/3/30
* Time: 下午3:25
*/
/**
* 加密方法
* @param string $str
* @return string
*/
function encrypt($str,$screct_key){
//AES, 128 模式加密数据 CBC
$screct_key = base64_decode($screct_key);
$str = trim($str);
$str = addPKCS7Padding($str);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_CBC),1);
$encrypt_str = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $screct_key, $str, MCRYPT_MODE_CBC);
return base64_encode($encrypt_str);
}
/**
* 解密方法
* @param string $str
* @return string
*/
function decrypt($str,$screct_key){
//AES, 128 模式加密数据 CBC
$str = base64_decode($str);
$screct_key = base64_decode($screct_key);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_CBC),1);
$encrypt_str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $screct_key, $str, MCRYPT_MODE_CBC);
$encrypt_str = trim($encrypt_str);
$encrypt_str = stripPKSC7Padding($encrypt_str);
return $encrypt_str;
}
/**
* 填充算法
* @param string $source
* @return string
*/
function addPKCS7Padding($source){
$source = trim($source);
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$pad = $block - (strlen($source) % $block);
if ($pad <= $block) {
$char = chr($pad);
$source .= str_repeat($char, $pad);
}
return $source;
}
/**
* 移去填充算法
* @param string $source
* @return string
*/
function stripPKSC7Padding($source){
$source = trim($source);
$char = substr($source, -1);
$num = ord($char);
if($num==62)return $source;
$source = substr($source,0,-$num);
return $source;
}
\ No newline at end of file
<?php
/**
* TODO 补充说明
*
* User: jiehua
* Date: 16/3/30
* Time: 下午8:55
*/
class EncryptParseItem {
public $startIndex;
public $endIndex;
public $encryptContent;
}
\ No newline at end of file
<?php
/**
* TODO 补充说明
*
* User: jiehua
* Date: 16/3/30
* Time: 下午8:51
*/
class EncryptResponseData {
public $realContent;
public $returnContent;
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: jiehua
* Date: 15/5/2
* Time: 下午6:21
*/
class SignData {
public $signSourceData=null;
public $sign=null;
}
\ No newline at end of file
<?php
/**
* ALIPAY API: alipay.account.exrate.advice.accept request
*
* @author auto create
* @since 1.0, 2016-05-23 14:55:42
*/
class AlipayAccountExrateAdviceAcceptRequest
{
/**
* 标准的兑换交易受理接口
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.account.exrate.advice.accept";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}
<?php
/**
* ALIPAY API: alipay.account.exrate.allclientrate.query request
*
* @author auto create
* @since 1.0, 2016-05-23 14:55:48
*/
class AlipayAccountExrateAllclientrateQueryRequest
{
/**
* 查询客户的所有币种对最新有效汇率
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.account.exrate.allclientrate.query";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}
<?php
/**
* ALIPAY API: alipay.account.exrate.ratequery request
*
* @author auto create
* @since 1.0, 2016-05-23 14:55:56
*/
class AlipayAccountExrateRatequeryRequest
{
/**
* 对于部分签约境内当面付的商家,为了能够在境外进行推广,因此需要汇率进行币种之间的转换,本接口提供此业务场景下的汇率查询服务
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.account.exrate.ratequery";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}
<?php
/**
* ALIPAY API: alipay.acquire.cancel request
*
* @author auto create
* @since 1.0, 2014-06-12 17:17:06
*/
class AlipayAcquireCancelRequest
{
/**
* 操作员ID。
**/
private $operatorId;
/**
* 操作员的类型:
0:支付宝操作员
1:商户的操作员
如果传入其它值或者为空,则默认设置为1
**/
private $operatorType;
/**
* 支付宝合作商户网站唯一订单号。
**/
private $outTradeNo;
/**
* 该交易在支付宝系统中的交易流水号。
最短16位,最长64位。
如果同时传了out_trade_no和trade_no,则以trade_no为准。
**/
private $tradeNo;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setOperatorId($operatorId)
{
$this->operatorId = $operatorId;
$this->apiParas["operator_id"] = $operatorId;
}
public function getOperatorId()
{
return $this->operatorId;
}
public function setOperatorType($operatorType)
{
$this->operatorType = $operatorType;
$this->apiParas["operator_type"] = $operatorType;
}
public function getOperatorType()
{
return $this->operatorType;
}
public function setOutTradeNo($outTradeNo)
{
$this->outTradeNo = $outTradeNo;
$this->apiParas["out_trade_no"] = $outTradeNo;
}
public function getOutTradeNo()
{
return $this->outTradeNo;
}
public function setTradeNo($tradeNo)
{
$this->tradeNo = $tradeNo;
$this->apiParas["trade_no"] = $tradeNo;
}
public function getTradeNo()
{
return $this->tradeNo;
}
public function getApiMethodName()
{
return "alipay.acquire.cancel";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}
<?php
/**
* ALIPAY API: alipay.acquire.close request
*
* @author auto create
* @since 1.0, 2014-06-12 17:17:06
*/
class AlipayAcquireCloseRequest
{
/**
* 卖家的操作员ID
**/
private $operatorId;
/**
* 支付宝合作商户网站唯一订单号
**/
private $outTradeNo;
/**
* 该交易在支付宝系统中的交易流水号。
最短16位,最长64位。
如果同时传了out_trade_no和trade_no,则以trade_no为准
**/
private $tradeNo;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setOperatorId($operatorId)
{
$this->operatorId = $operatorId;
$this->apiParas["operator_id"] = $operatorId;
}
public function getOperatorId()
{
return $this->operatorId;
}
public function setOutTradeNo($outTradeNo)
{
$this->outTradeNo = $outTradeNo;
$this->apiParas["out_trade_no"] = $outTradeNo;
}
public function getOutTradeNo()
{
return $this->outTradeNo;
}
public function setTradeNo($tradeNo)
{
$this->tradeNo = $tradeNo;
$this->apiParas["trade_no"] = $tradeNo;
}
public function getTradeNo()
{
return $this->tradeNo;
}
public function getApiMethodName()
{
return "alipay.acquire.close";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}
<?php
/**
* ALIPAY API: alipay.acquire.createandpay request
*
* @author auto create
* @since 1.0, 2016-11-22 19:31:24
*/
class AlipayAcquireCreateandpayRequest
{
/**
* 证书签名
**/
private $alipayCaRequest;
/**
* 对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。
**/
private $body;
/**
* 买家支付宝账号,可以为email或者手机号。
**/
private $buyerEmail;
/**
* 买家支付宝账号对应的支付宝唯一用户号。
以2088开头的纯16位数字。
**/
private $buyerId;
/**
* 描述多渠道收单的渠道明细信息,json格式,具体请参见“4.5 渠道明细说明”。
**/
private $channelParameters;
/**
* 订单金额币种。
目前只支持传入156(人民币)。
如果为空,则默认设置为156。
**/
private $currency;
/**
* 动态ID。
**/
private $dynamicId;
/**
* 动态ID类型:
&#1048698;
soundwave:声波
&#1048698;
qrcode:二维码
&#1048698;
barcode:条码
&#1048698;
wave_code:声波,等同soundwave
&#1048698;
qr_code:二维码,等同qrcode
&#1048698;
bar_code:条码,等同barcode
建议取值wave_code、qr_code、bar_code。
**/
private $dynamicIdType;
/**
* 用于商户的特定业务信息的传递,只有商户与支付宝约定了传递此参数且约定了参数含义,此参数才有效。
比如可传递声波支付场景下的门店ID等信息,以json格式传输,具体请参见“4.7 业务扩展参数说明”。
**/
private $extendParams;
/**
* xml或json
**/
private $formatType;
/**
* 描述商品明细信息,json格式,具体请参见“4.3 商品明细说明”。
**/
private $goodsDetail;
/**
* 设置未付款交易的超时时间,一旦超时,该笔交易就会自动被关闭。
取值范围:1m~15d。
m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。
该参数数值不接受小数点,如1.5h,可转换为90m。
该功能需要联系支付宝配置关闭时间。
**/
private $itBPay;
/**
* 描述预付卡相关的明细信息,json格式,具体请参见“4.8 预付卡明细参数说明”。
**/
private $mcardParameters;
/**
* 卖家的操作员ID。
**/
private $operatorId;
/**
* 操作员的类型:
&#1048698;
0:支付宝操作员
&#1048698;
1:商户的操作员
如果传入其它值或者为空,则默认设置为1。
**/
private $operatorType;
/**
* 支付宝合作商户网站唯一订单号。
**/
private $outTradeNo;
/**
* 订单中商品的单价。
如果请求时传入本参数,则必须满足total_fee=price×quantity的条件。
**/
private $price;
/**
* 订单中商品的数量。
如果请求时传入本参数,则必须满足total_fee=price×quantity的条件。
**/
private $quantity;
/**
* 业务关联ID集合,用于放置商户的订单号、支付流水号等信息,json格式,具体请参见“4.6 业务关联ID集合说明”。
**/
private $refIds;
/**
* 描述分账明细信息,json格式,具体请参见“4.4 分账明细说明”。
**/
private $royaltyParameters;
/**
* 卖家的分账类型,目前只支持传入ROYALTY(普通分账类型)。
**/
private $royaltyType;
/**
* 卖家支付宝账号,可以为email或者手机号。
如果seller_id不为空,则以seller_id的值作为卖家账号,忽略本参数。
**/
private $sellerEmail;
/**
* 卖家支付宝账号对应的支付宝唯一用户号。
以2088开头的纯16位数字。
如果和seller_email同时为空,则本参数默认填充partner的值。
**/
private $sellerId;
/**
* 收银台页面上,商品展示的超链接。
**/
private $showUrl;
/**
* 商品的标题/交易标题/订单标题/订单关键字等。
该参数最长为128个汉字。
**/
private $subject;
/**
* 该笔订单的资金总额,取值范围[0.01,100000000],精确到小数点后2位。
**/
private $totalFee;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setAlipayCaRequest($alipayCaRequest)
{
$this->alipayCaRequest = $alipayCaRequest;
$this->apiParas["alipay_ca_request"] = $alipayCaRequest;
}
public function getAlipayCaRequest()
{
return $this->alipayCaRequest;
}
public function setBody($body)
{
$this->body = $body;
$this->apiParas["body"] = $body;
}
public function getBody()
{
return $this->body;
}
public function setBuyerEmail($buyerEmail)
{
$this->buyerEmail = $buyerEmail;
$this->apiParas["buyer_email"] = $buyerEmail;
}
public function getBuyerEmail()
{
return $this->buyerEmail;
}
public function setBuyerId($buyerId)
{
$this->buyerId = $buyerId;
$this->apiParas["buyer_id"] = $buyerId;
}
public function getBuyerId()
{
return $this->buyerId;
}
public function setChannelParameters($channelParameters)
{
$this->channelParameters = $channelParameters;
$this->apiParas["channel_parameters"] = $channelParameters;
}
public function getChannelParameters()
{
return $this->channelParameters;
}
public function setCurrency($currency)
{
$this->currency = $currency;
$this->apiParas["currency"] = $currency;
}
public function getCurrency()
{
return $this->currency;
}
public function setDynamicId($dynamicId)
{
$this->dynamicId = $dynamicId;
$this->apiParas["dynamic_id"] = $dynamicId;
}
public function getDynamicId()
{
return $this->dynamicId;
}
public function setDynamicIdType($dynamicIdType)
{
$this->dynamicIdType = $dynamicIdType;
$this->apiParas["dynamic_id_type"] = $dynamicIdType;
}
public function getDynamicIdType()
{
return $this->dynamicIdType;
}
public function setExtendParams($extendParams)
{
$this->extendParams = $extendParams;
$this->apiParas["extend_params"] = $extendParams;
}
public function getExtendParams()
{
return $this->extendParams;
}
public function setFormatType($formatType)
{
$this->formatType = $formatType;
$this->apiParas["format_type"] = $formatType;
}
public function getFormatType()
{
return $this->formatType;
}
public function setGoodsDetail($goodsDetail)
{
$this->goodsDetail = $goodsDetail;
$this->apiParas["goods_detail"] = $goodsDetail;
}
public function getGoodsDetail()
{
return $this->goodsDetail;
}
public function setItBPay($itBPay)
{
$this->itBPay = $itBPay;
$this->apiParas["it_b_pay"] = $itBPay;
}
public function getItBPay()
{
return $this->itBPay;
}
public function setMcardParameters($mcardParameters)
{
$this->mcardParameters = $mcardParameters;
$this->apiParas["mcard_parameters"] = $mcardParameters;
}
public function getMcardParameters()
{
return $this->mcardParameters;
}
public function setOperatorId($operatorId)
{
$this->operatorId = $operatorId;
$this->apiParas["operator_id"] = $operatorId;
}
public function getOperatorId()
{
return $this->operatorId;
}
public function setOperatorType($operatorType)
{
$this->operatorType = $operatorType;
$this->apiParas["operator_type"] = $operatorType;
}
public function getOperatorType()
{
return $this->operatorType;
}
public function setOutTradeNo($outTradeNo)
{
$this->outTradeNo = $outTradeNo;
$this->apiParas["out_trade_no"] = $outTradeNo;
}
public function getOutTradeNo()
{
return $this->outTradeNo;
}
public function setPrice($price)
{
$this->price = $price;
$this->apiParas["price"] = $price;
}
public function getPrice()
{
return $this->price;
}
public function setQuantity($quantity)
{
$this->quantity = $quantity;
$this->apiParas["quantity"] = $quantity;
}
public function getQuantity()
{
return $this->quantity;
}
public function setRefIds($refIds)
{
$this->refIds = $refIds;
$this->apiParas["ref_ids"] = $refIds;
}
public function getRefIds()
{
return $this->refIds;
}
public function setRoyaltyParameters($royaltyParameters)
{
$this->royaltyParameters = $royaltyParameters;
$this->apiParas["royalty_parameters"] = $royaltyParameters;
}
public function getRoyaltyParameters()
{
return $this->royaltyParameters;
}
public function setRoyaltyType($royaltyType)
{
$this->royaltyType = $royaltyType;
$this->apiParas["royalty_type"] = $royaltyType;
}
public function getRoyaltyType()
{
return $this->royaltyType;
}
public function setSellerEmail($sellerEmail)
{
$this->sellerEmail = $sellerEmail;
$this->apiParas["seller_email"] = $sellerEmail;
}
public function getSellerEmail()
{
return $this->sellerEmail;
}
public function setSellerId($sellerId)
{
$this->sellerId = $sellerId;
$this->apiParas["seller_id"] = $sellerId;
}
public function getSellerId()
{
return $this->sellerId;
}
public function setShowUrl($showUrl)
{
$this->showUrl = $showUrl;
$this->apiParas["show_url"] = $showUrl;
}
public function getShowUrl()
{
return $this->showUrl;
}
public function setSubject($subject)
{
$this->subject = $subject;
$this->apiParas["subject"] = $subject;
}
public function getSubject()
{
return $this->subject;
}
public function setTotalFee($totalFee)
{
$this->totalFee = $totalFee;
$this->apiParas["total_fee"] = $totalFee;
}
public function getTotalFee()
{
return $this->totalFee;
}
public function getApiMethodName()
{
return "alipay.acquire.createandpay";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}
<?php
/**
* ALIPAY API: alipay.acquire.precreate request
*
* @author auto create
* @since 1.0, 2014-05-28 11:57:10
*/
class AlipayAcquirePrecreateRequest
{
/**
* 对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body
**/
private $body;
/**
* 描述多渠道收单的渠道明细信息,json格式
**/
private $channelParameters;
/**
* 订单金额币种。目前只支持传入156(人民币)。
如果为空,则默认设置为156
**/
private $currency;
/**
* 公用业务扩展信息。用于商户的特定业务信息的传递,只有商户与支付宝约定了传递此参数且约定了参数含义,此参数才有效。
比如可传递二维码支付场景下的门店ID等信息,以json格式传输。
**/
private $extendParams;
/**
* 描述商品明细信息,json格式。
**/
private $goodsDetail;
/**
* 订单支付超时时间。设置未付款交易的超时时间,一旦超时,该笔交易就会自动被关闭。
取值范围:1m~15d。
m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。
该参数数值不接受小数点,如1.5h,可转换为90m。
该功能需要联系支付宝配置关闭时间。
**/
private $itBPay;
/**
* 操作员的类型:
0:支付宝操作员
1:商户的操作员
如果传入其它值或者为空,则默认设置为1
**/
private $operatorCode;
/**
* 卖家的操作员ID
**/
private $operatorId;
/**
* 支付宝合作商户网站唯一订单号
**/
private $outTradeNo;
/**
* 订单中商品的单价。
如果请求时传入本参数,则必须满足total_fee=price×quantity的条件
**/
private $price;
/**
* 订单中商品的数量。
如果请求时传入本参数,则必须满足total_fee=price×quantity的条件
**/
private $quantity;
/**
* 分账信息。
描述分账明细信息,json格式
**/
private $royaltyParameters;
/**
* 分账类型。卖家的分账类型,目前只支持传入ROYALTY(普通分账类型)
**/
private $royaltyType;
/**
* 卖家支付宝账号,可以为email或者手机号。如果seller_id不为空,则以seller_id的值作为卖家账号,忽略本参数
**/
private $sellerEmail;
/**
* 卖家支付宝账号对应的支付宝唯一用户号,以2088开头的纯16位数字。如果和seller_email同时为空,则本参数默认填充partner的值
**/
private $sellerId;
/**
* 收银台页面上,商品展示的超链接
**/
private $showUrl;
/**
* 商品购买
**/
private $subject;
/**
* 订单金额。该笔订单的资金总额,取值范围[0.01,100000000],精确到小数点后2位。
**/
private $totalFee;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBody($body)
{
$this->body = $body;
$this->apiParas["body"] = $body;
}
public function getBody()
{
return $this->body;
}
public function setChannelParameters($channelParameters)
{
$this->channelParameters = $channelParameters;
$this->apiParas["channel_parameters"] = $channelParameters;
}
public function getChannelParameters()
{
return $this->channelParameters;
}
public function setCurrency($currency)
{
$this->currency = $currency;
$this->apiParas["currency"] = $currency;
}
public function getCurrency()
{
return $this->currency;
}
public function setExtendParams($extendParams)
{
$this->extendParams = $extendParams;
$this->apiParas["extend_params"] = $extendParams;
}
public function getExtendParams()
{
return $this->extendParams;
}
public function setGoodsDetail($goodsDetail)
{
$this->goodsDetail = $goodsDetail;
$this->apiParas["goods_detail"] = $goodsDetail;
}
public function getGoodsDetail()
{
return $this->goodsDetail;
}
public function setItBPay($itBPay)
{
$this->itBPay = $itBPay;
$this->apiParas["it_b_pay"] = $itBPay;
}
public function getItBPay()
{
return $this->itBPay;
}
public function setOperatorCode($operatorCode)
{
$this->operatorCode = $operatorCode;
$this->apiParas["operator_code"] = $operatorCode;
}
public function getOperatorCode()
{
return $this->operatorCode;
}
public function setOperatorId($operatorId)
{
$this->operatorId = $operatorId;
$this->apiParas["operator_id"] = $operatorId;
}
public function getOperatorId()
{
return $this->operatorId;
}
public function setOutTradeNo($outTradeNo)
{
$this->outTradeNo = $outTradeNo;
$this->apiParas["out_trade_no"] = $outTradeNo;
}
public function getOutTradeNo()
{
return $this->outTradeNo;
}
public function setPrice($price)
{
$this->price = $price;
$this->apiParas["price"] = $price;
}
public function getPrice()
{
return $this->price;
}
public function setQuantity($quantity)
{
$this->quantity = $quantity;
$this->apiParas["quantity"] = $quantity;
}
public function getQuantity()
{
return $this->quantity;
}
public function setRoyaltyParameters($royaltyParameters)
{
$this->royaltyParameters = $royaltyParameters;
$this->apiParas["royalty_parameters"] = $royaltyParameters;
}
public function getRoyaltyParameters()
{
return $this->royaltyParameters;
}
public function setRoyaltyType($royaltyType)
{
$this->royaltyType = $royaltyType;
$this->apiParas["royalty_type"] = $royaltyType;
}
public function getRoyaltyType()
{
return $this->royaltyType;
}
public function setSellerEmail($sellerEmail)
{
$this->sellerEmail = $sellerEmail;
$this->apiParas["seller_email"] = $sellerEmail;
}
public function getSellerEmail()
{
return $this->sellerEmail;
}
public function setSellerId($sellerId)
{
$this->sellerId = $sellerId;
$this->apiParas["seller_id"] = $sellerId;
}
public function getSellerId()
{
return $this->sellerId;
}
public function setShowUrl($showUrl)
{
$this->showUrl = $showUrl;
$this->apiParas["show_url"] = $showUrl;
}
public function getShowUrl()
{
return $this->showUrl;
}
public function setSubject($subject)
{
$this->subject = $subject;
$this->apiParas["subject"] = $subject;
}
public function getSubject()
{
return $this->subject;
}
public function setTotalFee($totalFee)
{
$this->totalFee = $totalFee;
$this->apiParas["total_fee"] = $totalFee;
}
public function getTotalFee()
{
return $this->totalFee;
}
public function getApiMethodName()
{
return "alipay.acquire.precreate";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}
<?php
/**
* ALIPAY API: alipay.acquire.query request
*
* @author auto create
* @since 1.0, 2014-05-28 11:58:01
*/
class AlipayAcquireQueryRequest
{
/**
* 支付宝合作商户网站唯一订单号
**/
private $outTradeNo;
/**
* 该交易在支付宝系统中的交易流水号。
最短16位,最长64位。
如果同时传了out_trade_no和trade_no,则以trade_no为准。
**/
private $tradeNo;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setOutTradeNo($outTradeNo)
{
$this->outTradeNo = $outTradeNo;
$this->apiParas["out_trade_no"] = $outTradeNo;
}
public function getOutTradeNo()
{
return $this->outTradeNo;
}
public function setTradeNo($tradeNo)
{
$this->tradeNo = $tradeNo;
$this->apiParas["trade_no"] = $tradeNo;
}
public function getTradeNo()
{
return $this->tradeNo;
}
public function getApiMethodName()
{
return "alipay.acquire.query";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}
<?php
/**
* ALIPAY API: alipay.acquire.refund request
*
* @author auto create
* @since 1.0, 2014-06-12 17:17:03
*/
class AlipayAcquireRefundRequest
{
/**
* 卖家的操作员ID。
**/
private $operatorId;
/**
* 操作员的类型:
0:支付宝操作员
1:商户的操作员
如果传入其它值或者为空,则默认设置为1。
**/
private $operatorType;
/**
* 商户退款请求单号,用以标识本次交易的退款请求。
如果不传入本参数,则以out_trade_no填充本参数的值。同时,认为本次请求为全额退款,要求退款金额和交易支付金额一致。
**/
private $outRequestNo;
/**
* 商户网站唯一订单号
**/
private $outTradeNo;
/**
* 业务关联ID集合,用于放置商户的退款单号、退款流水号等信息,json格式
**/
private $refIds;
/**
* 退款金额;退款金额不能大于订单金额,全额退款必须与订单金额一致。
**/
private $refundAmount;
/**
* 退款原因说明。
**/
private $refundReason;
/**
* 该交易在支付宝系统中的交易流水号。
最短16位,最长64位。
如果同时传了out_trade_no和trade_no,则以trade_no为准
**/
private $tradeNo;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setOperatorId($operatorId)
{
$this->operatorId = $operatorId;
$this->apiParas["operator_id"] = $operatorId;
}
public function getOperatorId()
{
return $this->operatorId;
}
public function setOperatorType($operatorType)
{
$this->operatorType = $operatorType;
$this->apiParas["operator_type"] = $operatorType;
}
public function getOperatorType()
{
return $this->operatorType;
}
public function setOutRequestNo($outRequestNo)
{
$this->outRequestNo = $outRequestNo;
$this->apiParas["out_request_no"] = $outRequestNo;
}
public function getOutRequestNo()
{
return $this->outRequestNo;
}
public function setOutTradeNo($outTradeNo)
{
$this->outTradeNo = $outTradeNo;
$this->apiParas["out_trade_no"] = $outTradeNo;
}
public function getOutTradeNo()
{
return $this->outTradeNo;
}
public function setRefIds($refIds)
{
$this->refIds = $refIds;
$this->apiParas["ref_ids"] = $refIds;
}
public function getRefIds()
{
return $this->refIds;
}
public function setRefundAmount($refundAmount)
{
$this->refundAmount = $refundAmount;
$this->apiParas["refund_amount"] = $refundAmount;
}
public function getRefundAmount()
{
return $this->refundAmount;
}
public function setRefundReason($refundReason)
{
$this->refundReason = $refundReason;
$this->apiParas["refund_reason"] = $refundReason;
}
public function getRefundReason()
{
return $this->refundReason;
}
public function setTradeNo($tradeNo)
{
$this->tradeNo = $tradeNo;
$this->apiParas["trade_no"] = $tradeNo;
}
public function getTradeNo()
{
return $this->tradeNo;
}
public function getApiMethodName()
{
return "alipay.acquire.refund";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}
<?php
/**
* ALIPAY API: alipay.app.token.get request
*
* @author auto create
* @since 1.0, 2016-07-29 19:56:12
*/
class AlipayAppTokenGetRequest
{
/**
* 应用安全码
**/
private $secret;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setSecret($secret)
{
$this->secret = $secret;
$this->apiParas["secret"] = $secret;
}
public function getSecret()
{
return $this->secret;
}
public function getApiMethodName()
{
return "alipay.app.token.get";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}