Commit e0421351 by yeran

fix the tlpay notify bug

0 parents
Showing with 4733 additions and 0 deletions
.idea
.DS_Store
/codecept.phar
/examples/test.php
/examples/wx/pem
/vendor/
/examples_bak/
/composer.lock
/examples/wxconfig-bak.php
/examples/wx/pem/
Payment只有在大家的使用反馈中才能得到不断的完善。
我希望通过真实的项目来驱动它不断发展,在为工作带来方便的同时尽力保持它的简洁。
# issue报Bug
由于Payment高度依赖第三方接口,因此第三方一个小的变动也会导致项目产生一个大版本号。当前主要有:
- 2.x 应该没多少人使用了,已经放弃维护
- 3.x 继续维护,只修bug,不做接口更新
- 4.x 当前开发版本,均保持当前第三方的最新接口
由于版本比较多。因此报bug建议采用以下格式:
[3/4.x]版本,在什么环境下(沙盒还是正式),调用了什么接口,出现了什么错误(最好有截图)。自己尝试过哪些办法去解决未达到预期效果
推荐所有的bug在提交时,先使用demo代码运行一下,看看能否通过。
**只提供标题,或者没有重现步骤的,将不处理**
# 贡献代码
请代码书写遵循以下规则:
- [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
- 使用4个空格作为缩紧(不是tab)
- 命名使用驼峰命名(不准使用拼音)
- 请给类、方法、变量添加注释,注释需要包含:日期、修改人、含义
## 开发流程
1. Fork [helei112g/payment](https://github.com/helei112g/payment) 到本地
2. 创建新的分支:
```shell
$ git checkout -b new_feature
```
3. 编写代码
4. Push 到你的分支:
```shell
$ git push origin new_feature
```
5. 创建 Pull Request 并描述你完成的功能或者做出的修改
所提交的部分一定自己真实测试完毕,如果是新的支付功能,需要添加对应的demo以及
相关功能的文档(暂无开源文档地址,请根据功能名称,提供 `.md`的说明文档)。
## 代码说明
为了让大家快速理解代码结构,将项目相关结构图进行说明
---------
**`遇到bug,90%都是秘钥相关导致的,微信可能与后台配置有关。请仔细检查。`**
\ No newline at end of file
Copyright (c) 2016-2017 Daniele Alessandri
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
# payment
> 支付工具包 v1.0 from riverslei/payment
\ No newline at end of file
**打赏名单**
名字 | 金额 | 说明 | 时间
---|---|---|---
北国之雪 | 30.00 | Payment好用 | 2017-05-04
里暮色中 | 50.00 | Payment越来越好(感谢发现一个bug issue#39) | 2017-05-01
lobtao | 8.88 | 你的内裤非常好用 | 2017-04-26
182xxxx | 10.00 | 支持 | 2017-04-19
来自简单 | 200.00 | 支付宝服务商模式咨询 | 2017-04-16
刘华 | 50.00 | 微信支付咨询 | 2017-04-14
靖 | 88.00 | 感谢开源 | 2017-03-19
李 | 150.00 | 打赏支持 | 2017-03-14
Alex.Ma | 6.66 | 支持 | 2017-03-13
阿笨 | 10.00 | 打算使用,先感谢一下 | 2017-03-10
彦 | 88.00 | 感觉还不错,特打赏88元,略表感谢。 | 2017-02-28
汤明洋 | 66.66 | 支持一下 | 2017-02-19
李仕建同学 | 18.88 | 新春快乐 | 2017-02-09
凡额 | 50.00 | 帮助调试,谢谢了 | 2017-01-18
Thans秦 | 66.66 | 商业使用 | 2017-01-08
John | 10.00 | 设计很棒 | 2017-01-06
Davidw | 699.00 | 支持开发2.0 | 2016-12-15
宁静致远 | 10.00 | 鼓励你,加油额 | 2016-12-13
k7 | 8.00 | 批量付款,一次成功 | 2016-11-24
洋 | 50.00 | 资助开源 | 2016-11-23
张仲东 | 50.00 | 接口封装的不错 | 2016-11-17
放下...快乐 | 1000.00 | 支付宝即时到帐处理 | 2016-11-15
Robin Core Animation | 50.00 | 解决微信支付问题 | 2016-11-04
5Z4 | 20.00 | 解决回调问题 | 2016-10-31
哈罗Joe | 1.00 | 加油~~ | 2016-8-23
小兵~招UI前端 | 50.00 | 继续努力,喝杯水吧:-) | 2016-8-14
尊称韦爵爷 | 1.00 | 赶紧出个yii的扩展 | 2016-7-22
一米市集 | 1000.00 | 希望提供技术长期合作 | 2016-7-20
张松 | 15.00 | 不错,已用到项目中 | 2016-6-17
\ No newline at end of file
<?php
namespace Payment\Notify;
use Payment\Common\PayException;
use Payment\Common\TLConfig;
use Payment\Config;
use Payment\Utils\ArrayUtil;
/**
* Class TLNotify
* 微信回调处理
* @package Payment\Notify
* anthor yeran
*/
class TLNotify extends NotifyStrategy
{
/**
* TLNotify constructor.
* @param array $config
* @throws PayException
*/
public function __construct(array $config)
{
parent::__construct($config);
try {
$this->config = new TLConfig($config);
} catch (PayException $e) {
throw $e;
}
}
/**
* 获取返回的异步通知数据
* @return array|bool
* @author yeran
*/
public function getNotifyData()
{
// php://input 带来的内存压力更小
// "{ \"key\": \"123456\" }";
$data = @file_get_contents('php://input');// 等同于微信提供的:$GLOBALS['HTTP_RAW_POST_DATA']
// 将xml数据格式化为数组
$arrData = json_decode($data,true);
if (empty($arrData)) {
return false;
}
// 移除值中的空格 xml转化为数组时,CDATA 数据会被带入额外的空格。
$arrData = ArrayUtil::paraFilter($arrData);
return $arrData;
}
/**
* 检查异步通知的数据是否正确
* @param array $data
*
* @author yeran
* @return boolean
*/
public function checkNotifyData(array $data)
{
// 检查返回数据签名是否正确
return $this->verifySign($data);
}
/**
* 检查微信返回的数据是否被篡改过
* @param array $retData
* @return boolean
* @author yeran
*/
protected function verifySign(array $retData)
{
$retSign = $retData['sign'];
$values = ArrayUtil::removeKeys($retData, ['sign', 'sign_type']);
$values = ArrayUtil::paraFilter($values);
$signStr = ArrayUtil::SignArray($values,$this->config->md5Key);
return strtoupper($signStr) === $retSign;
}
/**
*
* 封装回调函数需要的数据格式
*
* @param array $data
*
* @return array
* @author yeran
*/
protected function getRetData(array $data)
{
if ($this->config->returnRaw) {
$data['channel'] = Config::TL_CHARGE;
return $data;
}
return $data;
}
/**
* 处理完后返回的数据格式
* @param bool $flag
* @param string $msg 通知信息,错误原因
* @author yeran
* @return string
*/
protected function replyNotify($flag, $msg = 'OK')
{
// 默认为成功
$return_code ='SUCCESS';
if (! $flag) {
$return_code ='FAIL';
}
return [$return_code,$msg];
}
}
<?php
function classLoader($class)
{
$path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
$path = str_replace('Payment' . DIRECTORY_SEPARATOR, '', $path);
$file = __DIR__ . '/src/' . $path . '.php';
if (file_exists($file)) {
require_once $file;
}
}
spl_autoload_register('classLoader');
{
"name": "ldy/payment",
"type": "library",
"description": "支付宝支付、微信支付、招商一网通支付、通联支付 php SDK。",
"keywords": ["alipay", "weixin", "支付宝支付", "微信支付","通联支付", "集成支付接口SDK", "招商一网通", "一网通"],
"homepage": "",
"license": "MIT",
"authors": [
{
"name": "ldy",
"email": "932497180@qq.com",
"homepage": ""
}
],
"require": {
"php": ">=5.6",
"ext-bcmath": "*",
"ext-mbstring": "*"
},
"require-dev": {
"endroid/qrcode": "~1.9"
},
"autoload": {
"psr-4": {"Payment\\": "src/"}
}
}
<?php
/**
* @author: helei
* @createTime: 2016-08-01 11:37
* @description: 微信配置文件
*/
return [
'app_id' => '00020281', // 公众账号ID
'cus_id' => '55079104816PJXP',// 商户id
'md5_key' => '55079104816PJXP04',// md5 秘钥
'sign_type' => 'MD5',// MD5 HMAC-SHA256
'limit_pay' => ['no_credit'],
'notify_url' => 'http://172.16.2.46:8080/vo-apidemo/OrderServlet',
'redirect_url' => 'https://helei112g.github.io/',// 如果是h5支付,可以设置该值,返回到指定页面
'return_raw' => false,// 在处理回调时,是否直接返回原始数据,默认为true
];
//测试账号
//商户号:55079104816PJXP
//交易密码:Zyzswz1234
// 登录密码:Zyzs123456
//appid00020281 交易密钥:55079104816PJXP04
\ No newline at end of file
<?php
/**
* 手机app支付demo
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午5:38
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$aliConfig = require_once __DIR__ . '/../aliconfig.php';
// 订单信息
$orderNo = time() . rand(1000, 9999);
$payData = [
'body' => 'ali qr pay',
'subject' => '测试支付宝扫码支付',
'order_no' => $orderNo,
'timeout_express' => time() + 600,// 表示必须 600s 内付款
'amount' => '0.01',// 单位为元 ,最小为0.01
'return_param' => '123123',
'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1',// 客户地址
'goods_type' => '1',
'store_id' => '',
];
try {
$str = Charge::run(Config::ALI_CHANNEL_APP, $aliConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo $str;// 这里如果直接输出到页面,&not 会被转义,请注意
\ No newline at end of file
<?php
/**
* 条码支付
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午4:32
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$aliConfig = require_once __DIR__ . '/../aliconfig.php';
// 订单信息
$orderNo = time() . rand(1000, 9999);
$payData = [
'body' => 'ali bar pay',
'subject' => '测试支付宝条码支付',
'order_no' => $orderNo,
'timeout_express' => time() + 600,// 表示必须 600s 内付款
'amount' => '0.01',// 单位为元 ,最小为0.01
'return_param' => '123123',
'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1',// 客户地址
'goods_type' => '1',
'store_id' => '',
'operator_id' => '',
'terminal_id' => '',// 终端设备号(门店号或收银设备ID) 默认值 web
'alipay_store_id' => '',
'scene' => 'bar_code',// 条码支付:bar_code 声波支付:wave_code
'auth_code' => '1231212232323123123',
];
try {
$ret = Charge::run(Config::ALI_CHANNEL_BAR, $aliConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
var_dump($ret);
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>支付宝支付demo</title>
</head>
<body>
<ul>
<li><a href="appCharge.php" target="_blank">手机APP支付</a></li>
<li><a href="wapCharge.php" target="_blank">支付宝手机网站支付</a></li>
<li><a href="qrCharge.php" target="_blank">扫码支付</a></li>
<li><a href="barCharge.php" target="_blank">条码支付</a></li>
<li><a href="webCharge.php" target="_blank">电脑支付(即时到账)</a></li>
</ul>
<ul>
<li><a href="queryOrder.php" target="_blank">查询支付的订单</a></li>
<li><a href="queryRefund.php" target="_blank">查询退款的订单</a></li>
<li><a href="queryTransfer.php" target="_blank">查询转账的订单</a></li>
</ul>
<ul>
<li><a href="refund.php" target="_blank">退款订单</a></li>
<li><a href="transfer.php" target="_blank">转账操作</a></li>
</ul>
</body>
</html>
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午4:29
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$aliConfig = require_once __DIR__ . '/../aliconfig.php';
// 订单信息
$orderNo = time() . rand(1000, 9999);
$payData = [
'body' => 'ali qr pay',
'subject' => '测试支付宝扫码支付',
'order_no' => $orderNo,
'timeout_express' => time() + 600,// 表示必须 600s 内付款
'amount' => '0.01',// 单位为元 ,最小为0.01
'return_param' => '123123',
'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1',// 客户地址
'goods_type' => '1',
'store_id' => '',
];
try {
$url = Charge::run(Config::ALI_CHANNEL_QR, $aliConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo $url;
\ No newline at end of file
<?php
/**
* 查询订单
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午5:35
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Query;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$aliConfig = require_once __DIR__ . '/../aliconfig.php';
$data = [
'out_trade_no' => '14935448529859',
'trade_no' => '2017043021001004350200163279',
];
try {
$ret = Query::run(Config::ALI_CHARGE, $aliConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 查询订单退款状态
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午5:55
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Query;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$aliConfig = require_once __DIR__ . '/../aliconfig.php';
$data = [
'out_trade_no' => '14935460661343',
'trade_no' => '',
'refund_no' => '14935460994756',
];
try {
$ret = Query::run(Config::ALI_CHARGE, $aliConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 转账查询
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午6:00
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Query;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$aliConfig = require_once __DIR__ . '/../aliconfig.php';
$data = [
'trans_no' => '1493546355',
'transaction_id' => '20170430110070001500680000004577',
];
try {
$ret = Query::run(Config::ALI_TRANSFER, $aliConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 退款操作
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午5:43
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Refund;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$aliConfig = require_once __DIR__ . '/../aliconfig.php';
$refundNo = time() . rand(1000, 9999);
$data = [
'out_trade_no' => '14935460661343',
'refund_fee' => '0.01',
'reason' => '测试帐号退款',
'refund_no' => $refundNo,
];
try {
$ret = Refund::run(Config::ALI_REFUND, $aliConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 支付转账操作
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午5:57
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Transfer;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$aliConfig = require_once __DIR__ . '/../aliconfig.php';
$data = [
'trans_no' => time(),
'payee_type' => 'ALIPAY_LOGONID',
'payee_account' => 'aaqlmq0729@sandbox.com',// ALIPAY_USERID: 2088102169940354 ALIPAY_LOGONID:aaqlmq0729@sandbox.com
'amount' => '0.01',
'remark' => '转账拉,有钱了',
'payer_show_name' => '何磊',
];
try {
$ret = Transfer::run(Config::ALI_TRANSFER, $aliConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* wap网站支付
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 上午11:31
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$aliConfig = require_once __DIR__ . '/../aliconfig.php';
// 订单信息
$orderNo = time() . rand(1000, 9999);
$payData = [
'body' => 'ali wap pay',
'subject' => '测试支付宝手机网站支付',
'order_no' => $orderNo,
'timeout_express' => time() + 600,// 表示必须 600s 内付款
'amount' => '0.01',// 单位为元 ,最小为0.01
'return_param' => 'tata',// 一定不要传入汉字,只能是 字母 数字组合
'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1',// 客户地址
'goods_type' => '1',
'store_id' => '',
];
try {
$url = Charge::run(Config::ALI_CHANNEL_WAP, $aliConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
header('Location:' . $url);
\ No newline at end of file
<?php
/**
* 电脑支付 即时到账接口
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午4:34
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$aliConfig = require_once __DIR__ . '/../aliconfig.php';
// 订单信息
$orderNo = time() . rand(1000, 9999);
$payData = [
'body' => 'ali web pay',
'subject' => '测试支付宝电脑网站支付',
'order_no' => $orderNo,
'timeout_express' => time() + 600,// 表示必须 600s 内付款
'amount' => '0.01',// 单位为元 ,最小为0.01
'return_param' => '123123',
'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1',// 客户地址
'goods_type' => '1',
'store_id' => '',
// 说明地址:https://doc.open.alipay.com/doc2/detail.htm?treeId=270&articleId=105901&docType=1
// 建议什么也不填
'qr_mod' => '',
];
try {
$url = Charge::run(Config::ALI_CHANNEL_WEB, $aliConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
header('Location:' . $url);
\ No newline at end of file
<?php
/**
* @author: helei
* @createTime: 2016-07-15 17:19
* @description:
*/
// 一下配置均为本人的沙箱环境,贡献出来,大家测试
// 个人沙箱帐号:
/*
* 商家账号 naacvg9185@sandbox.com
* 商户UID 2088102169252684
* appId 2016073100130857
*/
/*
* 买家账号 aaqlmq0729@sandbox.com
* 登录密码 111111
* 支付密码 111111
*/
return [
'use_sandbox' => true,// 是否使用沙盒模式
'partner' => '2088102169252684',
'app_id' => '2016073100130857',
'sign_type' => 'RSA2',// RSA RSA2
// 可以填写文件路径,或者密钥字符串 当前字符串是 rsa2 的支付宝公钥(开放平台获取)
'ali_public_key' => 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmBjJu2eA5HVSeHb7jZsuKKbPp3w0sKEsLTVvBKQOtyb7bjQRWMWBI7FrcwEekM1nIL+rDv71uFtgv7apMMJdQQyF7g6Lnn9niG8bT1ttB8Fp0eud5L97eRjFTOa9NhxUVFjGDqQ3b88o6u20HNJ3PRckZhNaFJJQzlahCpxaiIRX2umAWFkaeQu1fcjmoS3l3BLj8Ly2zRZAnczv8Jnkp7qsVYeYt01EPsAxd6dRZRw3uqsv9pxSvyEYA7GV7XL6da+JdvXECalQeyvUFzn9u1K5ivGID7LPUakdTBUDzlYIhbpU1VS8xO1BU3GYXkAaumdWQt7f+khoFoSw+x8yqQIDAQAB',
// 可以填写文件路径,或者密钥字符串 我的沙箱模式,rsa与rsa2的私钥相同,为了方便测试
'rsa_private_key' => 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC/z+Ue/oS0GjO2
myYrkdopw5qq6Ih/xlHBx0HBE0xA2dRinpMuZeI0LUUtN54UAUZbDz8rcaOCb0je
loeYolw54tadcIw4Q2hbdeJPplldJZyi1BDYtBJZvAveeRSidHdmBSUtOtCBXUBl
JUP3I8/R4c34Ii4Pm/K4vmhwLf/zqZAedKGhYP6m5q+p8sfBHRPy97/KluLPiSTR
FqGSRmd0IitUGK+KQ5qsAfJXyN1oVR4jBYaxfx7dWkTWmxAfNqtKfMvu2a5lH6hv
ClN+w4RUDBu3939bLjCYKcAomkv3QMquMP46m+D8Ny+3mGk5L9Ul4jyxlFTlV4L4
JM3g/02xAgMBAAECggEBALZliwseHDLnd6V9g56K41ozlzBOTv6yJ6yNPgnLwAcr
HLtq76p/V8smAVIuQTPkwnJ03S0CsumlyTVhDzAltG2XN14fWDdoYiQWxU3YccIR
shFkd2CaW5jZKLA1k1moRqHM4r1P4FYjxshn12l7tHNwtdvvJL3THcxvxABovauF
OVtznpRlnfJLjn2Lg+xNsxaYy3zL8L6nL7MXUWLKvmLiZn64PFcw7cf+9n2exRDs
wn0wDCpypGqOVVXVFeZaXTwmOoxgIUAZfAExdLtabGGCAz1lTsA0+r4DW2nSTe8C
Fy1Db+fcCTm+uQ3y6jDwuS3tB8V+PQKog3+ReZp/9sECgYEA/NEr+ln6DTy7u4rC
Wq7mixRJ1kaiAUph/hADrUwhkMiUapSMNAIXblFB+BQUjFZQmXEbcvz0Y70g9Zi9
JCXVTiDTBe7jj/FK63MU0F9KY5OducpVV+RhSpNy/i1M2qeW4gO351PpPHUpRUYr
GkYvAKktqrSOdBEWD3IeKLYDXxMCgYEAwjoavGjWzD9Xckbpb8yrQ+gHfLeWDKh7
BgvoBGagyqbzIOZU9wg3dSQ2F5eMWDxWVRGqap3fIHxcA0/VMqXG1DrvSIUC4SE8
Zys515fR00c9h3W3IugHnKgdYcV7nZrJoPZXlMjPOo39FCBnfbrUOgnKwxMlz3lV
vC6465ODhKsCgYEAmUtTuTd5kTE0O+FFO6s1iztAEjc94D5z8JNRR3EUITAeHgn4
gUiLYI7Qy1WRqA5mTMPyeuS6Ywe4xnJYrWRrVDY+/if9v7f1T5K2GirNdld5mb//
w41tGMUTQt/A7AwWRvEuP4v3rnr0DVcgp4vK0EHEuO9GOUZq8+6kLtc+cBUCgYBF
J/kzEsVAjmEtkHA33ZExqaFY1+l2clrziTPAtWYVIiK5mSmxl9xfOliER/KxzDIV
MigStEmpQH5ms3s/AGXuVVmz4aBn1rSyK2L6D9WnO9t9qv1dUW68aeOkV3OvZ1jZ
lj0S/flDaSEulGclDmvYinoGwX+aAyLy0VQIlUqj5wKBgHEUEf7YDnvw/IBnF1E4
983/7zBx9skoHhpEZsh2+1or7LIw6z0m3lsNBnK0MZZBmW/7HwOtVfhXUUPbVrOJ
di70YoMynX3gjK3LTXhzISheZgcNRKTqiJgVunPokJxQRyYcAfaQeuIm9O8cCPE1
rZpNAzCdd4NSj83UZRm3YOmC',
'limit_pay' => [
//'balance',// 余额
//'moneyFund',// 余额宝
//'debitCardExpress',// 借记卡快捷
//'creditCard',//信用卡
//'creditCardExpress',// 信用卡快捷
//'creditCardCartoon',//信用卡卡通
//'credit_group',// 信用支付类型(包含信用卡卡通、信用卡快捷、花呗、花呗分期)
],// 用户不可用指定渠道支付当有多个渠道时用“,”分隔
// 与业务相关参数
'notify_url' => 'https://helei112g.github.io/v1/notify/ali',
'return_url' => 'https://helei112g.github.io/',
'return_raw' => false,// 在处理回调时,是否直接返回原始数据,默认为 true
];
<?php
/**
* 招商绑卡操作 签约
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午1:39
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Config;
use Payment\Client\Helper;
date_default_timezone_set('Asia/Shanghai');
$cmbConfig = require_once __DIR__ . '/../cmbconfig.php';
$signData = [
'date' => date('Ymd'),
'agr_no' => '430802198004014374',
'serial_no' => time() . rand(1000, 9999),
'mobile' => '13500007108',
'user_id' => '100',
'lon' => '',
'lat' => '',
'riskLevel' => '1',
];
try {
$data = Helper::run(Config::CMB_BIND, $cmbConfig, $signData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
$btnText = '点我开始签约';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>签约一网通支付</title>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
<meta content="telephone=no" name="format-detection">
<style>
.box{
padding:6px 10px
}
.button {
color: #f5efef;
background-color: #10a737;
border-color: #EEE;
font-weight: 300;
font-size: 16px;
font-family: "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
text-decoration: none;
text-align: center;
line-height: 40px;
height: 100px;
padding: 0 40px;
margin: 0;
width: 100%;
display: inline-block;
appearance: none;
cursor: pointer;
border: none;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-transition-property: all;
transition-property: all;
-webkit-transition-duration: .3s;
transition-duration: .3s;
}
.button-rounded {
border-radius: 4px;
}
.button-uppercase {
text-transform: uppercase;
}
</style>
</head>
<body>
<div class="box">
<form method="post" action="<?php echo $data['url'] ?>">
<input type="hidden" name="<?php echo $data['name'] ?>" value='<?php echo $data['value'] ?>'>
<button type="submit" class="button button-rounded button-uppercase"><?php echo $btnText ?></button>
</form>
</div>
</body>
</html>
\ No newline at end of file
<?php
/**
* 招商一网通支付
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 上午11:55
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$cmbConfig = require_once __DIR__ . '/../cmbconfig.php';
$orderNo = time() . rand(1000, 9999);
// 订单信息
$payData = [
'body' => 'test body',
'subject' => 'test subject',
'order_no' => $orderNo,// 招行订单位数变更为32位
'timeout_express' => time() + 600,// 表示必须 600s 内付款
'amount' => '0.01',// 单位为元 ,最小为0.01
'return_param' => 'tatata',
'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1',// 客户地址
'date' => date('Ymd'),
'agr_no' => '430802198004014358',// 建议用身份证
'serial_no' => time() . rand(1000, 9999),// 协议开通请求流水号,开通协议时必填
'user_id' => '888',
'mobile' => '13500007107',
'lon' => '',
'lat' => '',
'risk_level' => '3',
];
try {
$data = Charge::run(Config::CMB_CHANNEL_APP, $cmbConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
$btnText = '点我开始支付';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>一网通支付</title>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
<meta content="telephone=no" name="format-detection">
<style>
.box{
padding:6px 10px
}
.button {
color: #f5efef;
background-color: #10a737;
border-color: #EEE;
font-weight: 300;
font-size: 16px;
font-family: "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
text-decoration: none;
text-align: center;
line-height: 40px;
height: 100px;
padding: 0 40px;
margin: 0;
width: 100%;
display: inline-block;
appearance: none;
cursor: pointer;
border: none;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-transition-property: all;
transition-property: all;
-webkit-transition-duration: .3s;
transition-duration: .3s;
}
.button-rounded {
border-radius: 4px;
}
.button-uppercase {
text-transform: uppercase;
}
</style>
</head>
<body>
<div class="box">
<form method="post" action="<?php echo $data['url'] ?>">
<input type="hidden" name="<?php echo $data['name'] ?>" value='<?php echo $data['value'] ?>'>
<button type="submit" class="button button-rounded button-uppercase"><?php echo $btnText ?></button>
</form>
</div>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>招商一网通支付demo</title>
</head>
<body>
<ul>
<li><a href="charge.php" target="_blank">一网通支付</a></li>
<li><a href="queryPubKey.php" target="_blank">查询招行公钥</a></li>
<li><a href="bindCard.php" target="_blank">签约招商一网通</a></li>
</ul>
<ul>
<li><a href="queryOrder.php" target="_blank">查询支付订单信息</a></li>
<li><a href="queryRefund.php" target="_blank">查询退款订单信息</a></li>
</ul>
<ul>
<li><a href="refund.php" target="_blank">退款订单</a></li>
</ul>
</body>
</html>
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午2:18
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Config;
use Payment\Client\Query;
date_default_timezone_set('Asia/Shanghai');
$cmbConfig = require_once __DIR__ . '/../cmbconfig.php';
$data = [
'out_trade_no' => '9336161758',
'date' => '20170428',
'transaction_id' => '17242823500000000010',
];
try {
$ret = Query::run(Config::CMB_CHARGE, $cmbConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 招商一网通支付
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 上午11:55
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Config;
use Payment\Client\Helper;
date_default_timezone_set('Asia/Shanghai');
$cmbConfig = require_once __DIR__ . '/../cmbconfig.php';
$channel = 'cmb_pub_key';
try {
$ret = \Payment\Client\Helper::run(Config::CMB_PUB_KEY, $cmbConfig);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午2:29
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Config;
use Payment\Client\Query;
date_default_timezone_set('Asia/Shanghai');
$cmbConfig = require_once __DIR__ . '/../cmbconfig.php';
$data = [
'out_trade_no' => '9354737499',
'refund_no' => '',// 商户退款流水号,长度不超过20位
'date' => '20170430',
'refund_id' => '',// 银行退款流水号,长度不超过20位
];
try {
$ret = Query::run(Config::CMB_REFUND, $cmbConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 招商退款操作
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午6:03
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Config;
use Payment\Client\Refund;
date_default_timezone_set('Asia/Shanghai');
$cmbConfig = require_once __DIR__ . '/../cmbconfig.php';
$refundNo = time() . rand(1000, 9999);
$data = [
'out_trade_no' => '9354737499',
'date' => '20170430',
'refund_no' => $refundNo,
'refund_fee' => 0.01,
'reason' => '测试帐号退款',
'operator_id' => '9999',
];
try {
$ret = Refund::run(Config::CMB_REFUND, $cmbConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 招商一网通配置文件
* Created by PhpStorm.
* User: helei
* Date: 2017/4/27
* Time: 上午11:29
*/
return [
'use_sandbox' => true,// 是否使用 招商测试系统
'branch_no' => 'xxx', // 商户分行号,4位数字
'merchant_no' => 'xxxx',// 商户号,6位数字
'mer_key' => 'xxxxxx',// 秘钥16位,包含大小写字母 数字
// 招商的公钥,建议每天凌晨2:15发起查询招行公钥请求更新公钥。
'cmb_pub_key' => 'xxxxx',
'op_pwd' => 'xxxxx',// 操作员登录密码。
'sign_type' => 'SHA-256',// 签名算法,固定为“SHA-256”
'limit_pay' => [
//'A',
],// 允许支付的卡类型,默认对支付卡种不做限制,储蓄卡和信用卡均可支付 A:储蓄卡支付,即禁止信用卡支付
'notify_url' => 'http://114.215.86.31/__readme/phpinfo.php',// 支付成功的回调
'sign_notify_url' => 'http://114.215.86.31/__readme/phpinfo.php',// 成功签约结果通知地址
'return_url' => 'https://helei112g.github.io/',// 如果是h5支付,可以设置该值,返回到指定页面
'return_raw' => false,// 在处理回调时,是否直接返回原始数据,默认为true
];
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>支付演示demo</title>
</head>
<body>
<ul>
<li><a href="ali/index.html">支付宝支付demo</a></li>
<li><a href="wx/index.html">微信支付demo</a></li>
<li><a href="cmb/index.html">招商一网通支付demo</a></li>
</ul>
</body>
</html>
\ No newline at end of file
<?php
/**
* 第三方支付回调处理
* @author: helei
* @createTime: 2016-07-25 15:57
* @description: 支付通知回调
*/
require_once __DIR__ . '/../autoload.php';
require_once __DIR__ . '/testNotify.php';
use Payment\Common\PayException;
use Payment\Client\Notify;
date_default_timezone_set('Asia/Shanghai');
$aliConfig = require_once __DIR__ . '/aliconfig.php';
$wxConfig = require_once __DIR__ . '/wxconfig.php';
$cmbConfig = require_once __DIR__ . '/cmbconfig.php';
$tlConfig = require_once __DIR__ . '/TLConfig.php';
$callback = new TestNotify();
$type = 'tl_charge';// xx_charge
if (stripos($type, 'ali') !== false) {
$config = $aliConfig;
} elseif (stripos($type, 'wx') !== false) {
$config = $wxConfig;
} elseif (stripos($type, 'cmb') !== false) {
$config = $cmbConfig;
}elseif (stripos($type, 'tl') !== false){
$config = $tlConfig;
}
try {
if (!empty($config)){
// $retData = Notify::getNotifyData($type, $config);// 获取第三方的原始数据,未进行签名检查
// $retData = "{}";
$ret = Notify::run($type, $config, $callback);// 处理回调,内部进行了签名检查
}
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
var_dump($ret);
exit;
<?php
use Payment\Notify\PayNotifyInterface;
use Payment\Config;
/**
* @author: helei
* @createTime: 2016-07-20 18:31
* @description:
*/
/**
* 客户端需要继承该接口,并实现这个方法,在其中实现对应的业务逻辑
* Class TestNotify
* anthor helei
*/
class TestNotify implements PayNotifyInterface
{
public function notifyProcess(array $data)
{
$channel = $data['channel'];
if ($channel === Config::ALI_CHARGE) {// 支付宝支付
} elseif ($channel === Config::WX_CHARGE) {// 微信支付
} elseif ($channel === Config::CMB_CHARGE) {// 招商支付
} elseif ($channel === Config::CMB_BIND) {// 招商签约
} else {
// 其它类型的通知
echo '---';
var_dump($data);
}
// 执行业务逻辑,成功后返回true
return true;
}
}
<?php
/**
* 常量配置
*/
class AppConfig{
const APPID = '00000000';
const CUSID = '990440153996000';
const APPKEY = '43df939f1e7f5c6909b3f4b63f893994';
const APIURL = "https://vsp.allinpay.com/apiweb/unitorder";//生产环境
const APIVERSION = '11';
}
?>
\ No newline at end of file
<?php
class AppUtil{
/**
* 将参数数组签名
*/
public static function SignArray(array $array,$appkey){
$array['key'] = $appkey;// 将key放到数组中一起进行排序和组装
ksort($array);
$blankStr = AppUtil::ToUrlParams($array);
$sign = md5($blankStr);
return $sign;
}
public static function ToUrlParams(array $array)
{
$buff = "";
foreach ($array as $k => $v)
{
if($v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
/**
* 校验签名
* @param array 参数
* @param unknown_type appkey
*/
public static function ValidSign(array $array,$appkey){
$sign = $array['sign'];
unset($array['sign']);
$array['key'] = $appkey;
$mySign = AppUtil::SignArray($array, $appkey);
return strtolower($sign) == strtolower($mySign);
}
}
?>
\ No newline at end of file
<?php
/**
* 公众号支付
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午3:33
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$tlConfig = require_once __DIR__ . '/../TLConfig.php';
$orderNo = 12345678;//time() . rand(1000, 9999);
// 订单信息
$payData = [
'body' => '商品名称',
'reqsn' => $orderNo,
// 'timeout_express' => time() + 600,// 表示必须 600s 内付款
'trxamt' => '1',// 微信沙箱模式,需要金额固定为3.01
'randomstr' => '1450432107647',//md5(uniqid(md5(microtime(true)), true)),
'remark' => '备注信息',
// 如果是服务商,请提供以下参数
'validtime' => 6,//微信分配的子商户公众账号ID
'acct' => 'odNM24283i2wwQPzqy8Fxyax2y8U',// 微信支付分配的子商户号
'limit_pay' => 'no_credit'
];
try {
$ret = Charge::run(Config::TL_CHANNEL_LITE, $tlConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
header("Content-type: text/html; charset=gb2312");
<?php
require_once 'AppConfig.php';
require_once 'AppUtil.php';
$params = array();
foreach($_POST as $key=>$val) {//动态遍历获取所有收到的参数,此步非常关键,因为收银宝以后可能会加字段,动态获取可以兼容由于收银宝加字段而引起的签名异常
$params[$key] = $val;
}
if(count($params)<1){//如果参数为空,则不进行处理
echo "error";
exit();
}
if(AppUtil::ValidSign($params, AppConfig::APPKEY)){//验签成功
//此处进行业务逻辑处理
echo "success";
}
else{
echo "erro";
}
?>
<?php
/**
* 查询支付的订单
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午3:43
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Query;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../TLconfig.php';
$data = [
'randomstr' => '123413',
'reqsn' => '123456',//商户的交易订单号
'trxid' => '123456789123',//支付的收银宝平台流水
];
try {
$ret = Query::run(Config::TL_QUERY, $wxConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 退款处理 金额必须是 3.01
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午3:51
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Refund;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../TLConfig.php';
$data = [
'randomstr' => 'asdasda',
'reqsn' => '14935385689468',
'oldreqsn'=> '123456',
'trxamt' => '100',
'remark' => 'dasd',
];
try {
$ret = Refund::run(Config::TL_REFUND, $wxConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
header("Content-type:text/html;charset=utf-8");
require_once 'AppConfig.php';
require_once 'AppUtil.php';
function pay(){
$params = array();
$params["cusid"] = AppConfig::CUSID;
$params["appid"] = AppConfig::APPID;
$params["version"] = AppConfig::APIVERSION;
$params["trxamt"] = "1";
$params["reqsn"] = "123456";//订单号,自行生成
$params["paytype"] = "W06";
$params["randomstr"] = "1450432107647";//
$params["body"] = "商品名称";
$params["remark"] = "备注信息";
$params["acct"] = "openid";
$params["limit_pay"] = "no_credit";
$params["notify_url"] = "http://172.16.2.46:8080/vo-apidemo/OrderServlet";
$params["sign"] = AppUtil::SignArray($params,AppConfig::APPKEY);//签名
var_dump(json_encode($params));
$paramsStr = AppUtil::ToUrlParams($params);
$url = AppConfig::APIURL . "/pay";
$rsp = request($url, $paramsStr);
echo "请求返回:".$rsp;
echo "<br/>";
$rspArray = json_decode($rsp, true);
if(validSign($rspArray)){
echo "验签正确,进行业务处理";
}
}
//当天交易用撤销
function cancel(){
$params = array();
$params["cusid"] = AppConfig::CUSID;
$params["appid"] = AppConfig::APPID;
$params["version"] = AppConfig::APIVERSION;
$params["trxamt"] = "1";
$params["reqsn"] = "123456788";
$params["oldreqsn"] = "123456";//原来订单号
$params["randomstr"] = "1450432107647";//
$params["sign"] = AppUtil::SignArray($params,AppConfig::APPKEY);//签名
$paramsStr = AppUtil::ToUrlParams($params);
$url = AppConfig::APIURL . "/cancel";
$rsp = request($url, $paramsStr);
echo "请求返回:".$rsp;
echo "<br/>";
$rspArray = json_decode($rsp, true);
if(validSign($rspArray)){
echo "验签正确,进行业务处理";
}
}
//当天交易请用撤销,非当天交易才用此退货接口
function refund(){
$params = array();
$params["cusid"] = AppConfig::CUSID;
$params["appid"] = AppConfig::APPID;
$params["version"] = AppConfig::APIVERSION;
$params["trxamt"] = "1";
$params["reqsn"] = "1234567889";
$params["oldreqsn"] = "123456";//原来订单号
$params["randomstr"] = "1450432107647";//
$params["sign"] = AppUtil::SignArray($params,AppConfig::APPKEY);//签名
$paramsStr = AppUtil::ToUrlParams($params);
$url = AppConfig::APIURL . "/refund";
$rsp = request($url, $paramsStr);
echo "请求返回:".$rsp;
echo "<br/>";
$rspArray = json_decode($rsp, true);
if(validSign($rspArray)){
echo "验签正确,进行业务处理";
}
}
function query(){
$params = array();
$params["cusid"] = AppConfig::CUSID;
$params["appid"] = AppConfig::APPID;
$params["version"] = AppConfig::APIVERSION;
$params["reqsn"] = "123456";
$params["randomstr"] = "1450432107647";//
$params["sign"] = AppUtil::SignArray($params,AppConfig::APPKEY);//签名
$paramsStr = AppUtil::ToUrlParams($params);
$url = AppConfig::APIURL . "/query";
$rsp = request($url, $paramsStr);
echo "请求返回:".$rsp;
echo "<br/>";
$rspArray = json_decode($rsp, true);
if(validSign($rspArray)){
echo "验签正确,进行业务处理";
}
}
//发送请求操作仅供参考,不为最佳实践
function request($url,$params){
$ch = curl_init();
$this_header = array("content-type: application/x-www-form-urlencoded;charset=UTF-8");
curl_setopt($ch,CURLOPT_HTTPHEADER,$this_header);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);//如果不加验证,就设false,商户自行处理
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
//验签
function validSign($array){
if("SUCCESS"==$array["retcode"]){
$signRsp = strtolower($array["sign"]);
$array["sign"] = "";
$sign = strtolower(AppUtil::SignArray($array, AppConfig::APPKEY));
if($sign==$signRsp){
return TRUE;
}
else {
echo "验签失败:".$signRsp."--".$sign;
}
}
else{
echo $array["retmsg"];
}
return FALSE;
}
pay();
//cancel();
//refund();
//query();
?>
\ No newline at end of file
<?php
/**
* app支付
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 上午11:50
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../wxconfig.php';
$orderNo = time() . rand(1000, 9999);
// 订单信息
$payData = [
'body' => 'test body',
'subject' => 'test subject',
'order_no' => $orderNo,
'timeout_express' => time() + 600,// 表示必须 600s 内付款
'amount' => '3.01',// 微信沙箱模式,需要金额固定为3.01
'return_param' => '123',
'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1',// 客户地址
];
try {
$ret = Charge::run(Config::WX_CHANNEL_APP, $wxConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 刷卡支付
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午3:12
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../wxconfig.php';
$orderNo = time() . rand(1000, 9999);
// 订单信息
$payData = [
'body' => 'test body',
'subject' => 'test subject',
'order_no' => $orderNo,
'timeout_express' => time() + 600,// 表示必须 600s 内付款
'amount' => '0.01',// 微信沙箱模式,需要金额固定为0.01
'return_param' => '123',
'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1',// 客户地址
'openid' => '',
'product_id' => '123',
'terminal_id' => 'web',// 终端设备号(门店号或收银设备ID) 默认值 web
'auth_code' => '1231212232323123123',
// 如果是服务商,请提供以下参数
'sub_appid' => '',//微信分配的子商户公众账号ID
'sub_mch_id' => '',// 微信支付分配的子商户号
];
try {
$ret = Charge::run(Config::WX_CHANNEL_BAR, $wxConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>微信支付demo</title>
</head>
<body>
<ul>
<li><a href="appCharge.php" target="_blank">微信手机app支付</a></li>
<li><a href="qrCharge.php" target="_blank">微信扫码支付</a></li>
<li><a href="pubCharge.php" target="_blank">微信公众号支付</a></li>
<li><a href="liteCharge.php" target="_blank">小程序支付</a></li>
<li><a href="barCharge.php" target="_blank">微信刷卡支付</a></li>
<li><a href="wapCharge.php" target="_blank">H5手机网站支付</a></li>
</ul>
<ul>
<li><a href="queryOrder.php" target="_blank">查询支付的订单</a></li>
<li><a href="queryRefund.php" target="_blank">查询退款的订单</a></li>
<li><a href="queryTransfer.php" target="_blank">查询转账的订单(不支持沙箱)</a></li>
</ul>
<ul>
<li><a href="refund.php" target="_blank">退款订单</a></li>
<li><a href="transfer.php" target="_blank">转账操作(不支持沙箱)</a></li>
</ul>
</body>
</html>
\ No newline at end of file
<?php
/**
* 公众号支付
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午3:33
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../wxconfig.php';
$orderNo = time() . rand(1000, 9999);
// 订单信息
$payData = [
'body' => 'test body',
'subject' => 'test subject',
'order_no' => $orderNo,
'timeout_express' => time() + 600,// 表示必须 600s 内付款
'amount' => '3.01',// 微信沙箱模式,需要金额固定为3.01
'return_param' => '123',
'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1',// 客户地址
'openid' => 'o-e_mwTXTaxEhBM8xDoj1ui1f950',
'product_id' => '123',
];
try {
$ret = Charge::run(Config::WX_CHANNEL_LITE, $wxConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 公众号支付
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午3:33
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../wxconfig.php';
$orderNo = time() . rand(1000, 9999);
// 订单信息
$payData = [
'body' => 'test body',
'subject' => 'test subject',
'order_no' => $orderNo,
'timeout_express' => time() + 600,// 表示必须 600s 内付款
'amount' => '3.01',// 微信沙箱模式,需要金额固定为3.01
'return_param' => '123',
'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1',// 客户地址
'openid' => 'o-e_mwTXTaxEhBM8xDoj1ui1f950',
'product_id' => '123',
// 如果是服务商,请提供以下参数
'sub_appid' => '',//微信分配的子商户公众账号ID
'sub_mch_id' => '',// 微信支付分配的子商户号
'sub_openid' => '',// 用户在子商户appid下的唯一标识
];
try {
$ret = Charge::run(Config::WX_CHANNEL_PUB, $wxConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 微信扫码支付
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午2:46
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../wxconfig.php';
$orderNo = time() . rand(1000, 9999);
// 订单信息
$payData = [
'body' => 'test body',
'subject' => 'test subject',
'order_no' => $orderNo,
'timeout_express' => time() + 600,// 表示必须 600s 内付款
'amount' => '3.01',// 微信沙箱模式,需要金额固定为3.01
'return_param' => '123',
'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1',// 客户地址
'openid' => 'ottkCuO1PW1Dnh6PWFffNk-2MPbY',
'product_id' => '123',
// 如果是服务商,请提供以下参数
'sub_appid' => '',//微信分配的子商户公众账号ID
'sub_mch_id' => '',// 微信支付分配的子商户号
];
try {
$ret = Charge::run(Config::WX_CHANNEL_QR, $wxConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo $ret;
\ No newline at end of file
<?php
/**
* 查询支付的订单
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午3:43
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Query;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../wxconfig.php';
$data = [
'out_trade_no' => '14935505602169',
'transaction_id' => '20170430190922203640695',
];
try {
$ret = Query::run(Config::WX_CHARGE, $wxConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 查询退款订单
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午3:43
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Query;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../wxconfig.php';
$data = [
'out_trade_no' => '14935385689468',
'refund_no' => '14935506214648',
'transaction_id' => '12345678920170430191024123337865',
'refund_id' => '1234567892017043019102412333',
];
try {
$ret = Query::run(Config::WX_REFUND, $wxConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 转账查询 没有沙箱模式
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午3:48
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Query;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../wxconfig.php';
$data = [
'trans_no' => '1489852933',
];
try {
$ret = Query::run(Config::WX_CHARGE, $wxConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 退款处理 金额必须是 3.01
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午3:51
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Refund;
use Payment\Config;
use Payment\Common\WxConfig;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../wxconfig.php';
$refundNo = time() . rand(1000, 9999);
$data = [
'out_trade_no' => '14935385689468',
'total_fee' => '3.01',
'refund_fee' => '3.01',
'refund_no' => $refundNo,
'refund_account' => WxConfig::REFUND_RECHARGE,// REFUND_RECHARGE:可用余额退款 REFUND_UNSETTLED:未结算资金退款(默认)
];
try {
$ret = Refund::run(Config::WX_REFUND, $wxConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午4:13
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Transfer;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../wxconfig.php';
$data = [
'trans_no' => time(),
'openid' => 'o-e_mwTXTaxEhBM8xDoj1ui1f950',
'check_name' => 'NO_CHECK',// NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名 OPTION_CHECK:针对已实名认证的用户才校验真实姓名
'payer_real_name' => '何磊',
'amount' => '1',
'desc' => '测试转账',
'spbill_create_ip' => '127.0.0.1',
];
try {
$ret = Transfer::run(Config::WX_TRANSFER, $wxConfig, $data);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
\ No newline at end of file
<?php
/**
* 微信wap支付
* Created by PhpStorm.
* User: helei
* Date: 2017/4/30
* Time: 下午3:40
*/
require_once __DIR__ . '/../../autoload.php';
use Payment\Common\PayException;
use Payment\Client\Charge;
use Payment\Config;
date_default_timezone_set('Asia/Shanghai');
$wxConfig = require_once __DIR__ . '/../wxconfig.php';
$orderNo = time() . rand(1000, 9999);
// 订单信息
$payData = [
'body' => 'test body',
'subject' => 'test subject',
'order_no' => $orderNo,
'timeout_express' => time() + 600,// 表示必须 600s 内付款
'amount' => '3.01',// 微信沙箱模式,需要金额固定为3.01
'return_param' => '123',
'client_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1',// 客户地址
//{"h5_info": {"type":"Wap","wap_url": "https://pay.qq.com","wap_name": "腾讯充值"}}
'scene_info' => [
'type' => 'Wap',// IOS Android Wap 腾讯建议 IOS ANDROID 采用app支付
'wap_url' => 'helei112g.github.io',//自己的 wap 地址
'wap_name' => '测试充值',
],
];
try {
$url = Charge::run(Config::WX_CHANNEL_WAP, $wxConfig, $payData);
} catch (PayException $e) {
echo $e->errorMessage();
exit;
}
echo $url;
\ No newline at end of file
<?php
/**
* @author: helei
* @createTime: 2016-08-01 11:37
* @description: 微信配置文件
*/
return [
'use_sandbox' => true,// 是否使用 微信支付仿真测试系统
'app_id' => 'wxxxxxx', // 公众账号ID
'mch_id' => 'xxxxx',// 商户id
'md5_key' => 'xxxxxxx',// md5 秘钥
'app_cert_pem' => dirname(__FILE__) . DIRECTORY_SEPARATOR . 'wx' . DIRECTORY_SEPARATOR . 'pem' . DIRECTORY_SEPARATOR . 'weixin_app_cert.pem',
'app_key_pem' => dirname(__FILE__) . DIRECTORY_SEPARATOR . 'wx' . DIRECTORY_SEPARATOR . 'pem' . DIRECTORY_SEPARATOR . 'weixin_app_key.pem',
'sign_type' => 'MD5',// MD5 HMAC-SHA256
'limit_pay' => [
//'no_credit',
],// 指定不能使用信用卡支付 不传入,则均可使用
'fee_type' => 'CNY',// 货币类型 当前仅支持该字段
'notify_url' => 'https://helei112g.github.io/v1/notify/wx',
'redirect_url' => 'https://helei112g.github.io/',// 如果是h5支付,可以设置该值,返回到指定页面
'return_raw' => false,// 在处理回调时,是否直接返回原始数据,默认为true
];
\ No newline at end of file
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRA
FljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQE
B/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5Ksi
NG9zpgmLCUYuLkxpLQIDAQAB
-----END PUBLIC KEY-----
\ No newline at end of file
-----BEGIN CERTIFICATE-----
MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
-----END CERTIFICATE-----
\ No newline at end of file
<?php
/**
* @author: yeran
* @createTime: 2018-04-22 17:42
* @description: 交易撤销接口
*/
namespace Payment;
use Payment\Charge\Wx\TLCancel;
use Payment\Common\BaseStrategy;
use Payment\Common\PayException;
/**
* Class CancelContext
* @package Payment
*/
class CancelContext
{
/**
* 退款的渠道
* @var BaseStrategy
*/
protected $cancelHandler;
/**
* 设置对应的退款渠道
* @param string $channel 退款渠道
* - @see Config
*
* @param array $config 配置文件
* @throws PayException
* @author yeran
*/
public function initCancelHandler($channel, array $config)
{
try {
switch ($channel) {
case Config::TL_CANCEL:
$this->cancelHandler = new TLCancel($config);
break;
default:
throw new PayException('当前仅支持:通联支付平台');
}
} catch (PayException $e) {
throw $e;
}
}
/**
* 通过环境类调用交易撤销操作
*
* @param array $data
*
* @return array
* @throws PayException
* @author yeran
*/
public function cancel(array $data)
{
if (! $this->cancelHandler instanceof BaseStrategy) {
throw new PayException('请检查初始化是否正确');
}
try {
return $this->cancelHandler->handle($data);
} catch (PayException $e) {
throw $e;
}
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-14 18:20
* @description: 支付宝移动支付接口
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment\Charge\Ali;
use Payment\Common\Ali\AliBaseStrategy;
use Payment\Common\Ali\Data\Charge\AppChargeData;
use Payment\Common\AliConfig;
use Payment\Utils\ArrayUtil;
use Payment\Utils\StrUtil;
class AliAppCharge extends AliBaseStrategy
{
/**
* 获取支付对应的数据完成类
* @return string
* @author helei
*/
public function getBuildDataClass()
{
$this->config->method = AliConfig::APP_PAY_METHOD;
// 以下两种方式任选一种
return AppChargeData::class;
}
/**
* 返回app 支付数据 sign 在签名内部,已经进行 base64_encode 了
* @param array $data
* @return string
*/
protected function retData(array $data)
{
$sign = $data['sign'];
unset($data['sign']);
$data = ArrayUtil::arraySort($data);// 因为签名时进行了排序,此处返回时也要进行排序,否则支付验证签名无法通过
foreach ($data as &$value) {
$value = StrUtil::characet($value, $this->config->charset);
}
$data['sign'] = $sign;// sign 需要放在末尾
return http_build_query($data);
}
}
<?php
namespace Payment\Charge\Ali;
use Payment\Common\Ali\AliBaseStrategy;
use Payment\Common\Ali\Data\Charge\BarChargeData;
use Payment\Common\AliConfig;
use Payment\Common\PayException;
/**
* 商户扫用户的二维码
*
* Class AliBarCharge
* @package Payment\Charge\Weixin
*
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
class AliBarCharge extends AliBaseStrategy
{
public function getBuildDataClass()
{
$this->config->method = AliConfig::BAR_PAY_METHOD;
return BarChargeData::class;
}
/**
* 处理扫码支付的返回值
* @param array $ret
* $data = [
'code' => 10000,
'msg' => 'Success',
'buyer_logon_id' => 'day***@gmail.com',
'buyer_pay_amount' => '0.01',
'buyer_user_id' => '2088002162809334',
'fund_bill_list' => [
['amount' => '0.01', 'fund_channel' => 'ALIPAYACCOUNT'],
],
'gmt_payment' => '2017-03-05 22:27:46',
'open_id' => '20880008025007264081318860117433',
'out_trade_no' => '14887240631516',
'point_amount' => '0.00',
'receipt_amount' => '0.01',
'total_amount' => '0.01',
'trade_no' => '2017030521001004330274482163',
];
*
* @throws PayException
* @return string 可生产二维码的uri
* @author helei
*/
protected function retData(array $ret)
{
$url = parent::retData($ret);
// 发起网络请求
try {
$data = $this->sendReq($url);
} catch (PayException $e) {
throw $e;
}
return $data;
}
}
<?php
namespace Payment\Charge\Ali;
use Payment\Common\Ali\AliBaseStrategy;
use Payment\Common\Ali\Data\Charge\QrChargeData;
use Payment\Common\AliConfig;
use Payment\Common\PayException;
/**
* 支付宝扫码支付- 用户扫商户生成的二维码完成支付
*
* Class AliQrCharge
* @package Payment\Charge\Weixin
*
* @link https://github.com/helei112g/payment
* @link https://helei112g.github.io/
*/
class AliQrCharge extends AliBaseStrategy
{
public function getBuildDataClass()
{
$this->config->method = AliConfig::QR_PAY_METHOD;
return QrChargeData::class;
}
/**
* 处理扫码支付的返回值
* @param array $ret
*
* @throws PayException
* @return string 可生产二维码的uri
* @author helei
*/
protected function retData(array $ret)
{
$url = parent::retData($ret);
// 发起网络请求
try {
$data = $this->sendReq($url);
} catch (PayException $e) {
throw $e;
}
return $data['qr_code'];
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-14 18:19
* @description: 支付宝 手机网站支付 接口
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment\Charge\Ali;
use Payment\Common\Ali\AliBaseStrategy;
use Payment\Common\Ali\Data\Charge\WapChargeData;
use Payment\Common\AliConfig;
class AliWapCharge extends AliBaseStrategy
{
/**
* 获取支付对应的数据完成类
* @return string
* @author helei
*/
public function getBuildDataClass()
{
$this->config->method = AliConfig::WAP_PAY_METHOD;
// 以下两种方式任选一种
return WapChargeData::class;
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-14 17:56
* @description: 支付宝 即时到账 接口
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment\Charge\Ali;
use Payment\Common\Ali\AliBaseStrategy;
use Payment\Common\Ali\Data\Charge\WebChargeData;
use Payment\Common\AliConfig;
class AliWebCharge extends AliBaseStrategy
{
/**
* 获取支付对应的数据完成类
* @return string
* @author helei
*/
public function getBuildDataClass()
{
$this->config->method = AliConfig::PC_PAY_METHOD;
// 以下两种方式均可以
return WebChargeData::class;
//return 'Payment\Common\Ali\Data\Charge\WebChargeData';
}
}
<?php
namespace Payment\Charge\Cmb;
use Payment\Common\Cmb\CmbBaseStrategy;
use Payment\Common\Cmb\Data\Charge\ChargeData;
/**
* 一网通支付API 接口
* Created by PhpStorm.
* User: helei
* Date: 2017/4/27
* Time: 下午12:36
*/
class CmbCharge extends CmbBaseStrategy
{
public function getBuildDataClass()
{
$this->config->getewayUrl = 'https://netpay.cmbchina.com/netpayment/BaseHttp.dll?MB_EUserPay';
if ($this->config->useSandbox) {// 测试
$this->config->getewayUrl = 'http://121.15.180.66:801/NetPayment/BaseHttp.dll?MB_EUserPay';
}
return ChargeData::class;
}
}
\ No newline at end of file
<?php
/**
* Created by IntelliJ IDEA.
* User: yeran
* Date: 2018/4/23
* Time: 下午5:44
*/
namespace Payment\Charge\Wx;
use Payment\Common\TLConfig;
use Payment\Common\TLpay\Data\Cancel\TLCancelData;
use Payment\Common\TLpay\TLBaseStrategy;
/**
* Class TLCancel
* @package Payment\Charge\Wx
*/
class TLCancel extends TLBaseStrategy{
/**
* 交易撤销 的url
* @return null|string
* @author helei
*/
protected function getReqUrl()
{
return TLConfig::ORDER_CANCEL_URL;
}
/**
* 获取交易退款对应的数据完成类
* @return TLCancelData
* @author helei
*/
public function getBuildDataClass()
{
// TODO: Implement getBuildDataClass() method.
$this->config->paytype = 'W06';
return TLCancelData::class;
}
}
\ No newline at end of file
<?php
/**
* @author: helei
* @createTime: 2016-07-14 18:28
* @description: 微信 公众号 支付接口
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment\Charge\TLpay;
use Payment\Common\TLpay\Data\BackTLChargeData;
use Payment\Common\TLpay\Data\Charge\TLChargeData;
use Payment\Common\TLpay\TLBaseStrategy;
/**
* Class TLLiteCharge
*
* 通联支付-微信小程序支付
*
* @package Payment\Charge\TLpay
* anthor helei
*/
class TLLiteCharge extends TLBaseStrategy
{
public function getBuildDataClass()
{
$this->config->paytype = 'W06';
return TLChargeData::class;
}
/**
* 处理返回值。直接返回与微信小程序文档对应的字段
* @param array $ret
*
* @return array $backData 包含以下键
*
* ```php
* $backData = [
* 'appId' => '', // 小程序id
* 'package' => '', // 订单详情扩展字符串 统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=***
* 'nonceStr' => '', // 随机字符串
* 'timeStamp' => '', // 时间戳
* 'signType' => '', // 签名算法,暂支持MD5
* 'paySign' => '', // 签名
* ];
* ```
* @author helei
*/
protected function retData(array $ret)
{
return json_decode($ret['payinfo'],true);
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-14 17:56
* @description: 微信 app 支付接口
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment\Charge\Wx;
use Payment\Common\Weixin\Data\BackAppChargeData;
use Payment\Common\Weixin\Data\Charge\AppChargeData;
use Payment\Common\Weixin\WxBaseStrategy;
class WxAppCharge extends WxBaseStrategy
{
public function getBuildDataClass()
{
$this->config->tradeType = 'APP';
return AppChargeData::class;
}
/**
* 处理APP支付的返回值。直接返回与微信文档对应的字段
* @param array $ret
*
* @return array $data
*
* ```php
* $data = [
* 'appid' => '', // 应用ID
* 'partnerid' => '', // 商户号
* 'prepayid' => '', // 预支付交易会话ID
* 'package' => '', // 扩展字段 固定值:Sign=WXPay
* 'noncestr' => '', // 随机字符串
* 'timestamp' => '', // 时间戳
* 'sign' => '', // 签名
* ];
* ```
* @author helei
*/
protected function retData(array $ret)
{
$back = new BackAppChargeData($this->config, $ret);
$back->setSign();
$backData = $back->getData();
return $backData;
}
}
<?php
/**
* @author: helei
* @createTime: 2017-03-06 18:29
* @description: 微信 刷卡支付 对应支付宝的条码支付
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment\Charge\Wx;
use Payment\Common\Weixin\Data\Charge\BarChargeData;
use Payment\Common\Weixin\WxBaseStrategy;
use Payment\Common\WxConfig;
class WxBarCharge extends WxBaseStrategy
{
public function getBuildDataClass()
{
return BarChargeData::class;
}
/**
* 刷卡支付 的请求地址是另外一个
* @return string
*/
protected function getReqUrl()
{
return WxConfig::MICROPAY_URL;
}
protected function retData(array $ret)
{
$ret['total_fee'] = bcdiv($ret['total_fee'], 100, 2);
$ret['cash_fee'] = bcdiv($ret['cash_fee'], 100, 2);
if ($this->config->returnRaw) {
return $ret;
}
return $ret;
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-14 18:28
* @description: 微信 公众号 支付接口
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment\Charge\Wx;
use Payment\Common\Weixin\Data\BackPubChargeData;
use Payment\Common\Weixin\Data\Charge\PubChargeData;
use Payment\Common\Weixin\WxBaseStrategy;
/**
* Class WxPubCharge
*
* 微信公众号支付
*
* @package Payment\Charge\Weixin
* anthor helei
*/
class WxPubCharge extends WxBaseStrategy
{
public function getBuildDataClass()
{
$this->config->tradeType = 'JSAPI';
return PubChargeData::class;
}
/**
* 处理公众号支付的返回值。直接返回与微信文档对应的字段
* @param array $ret
*
* @return string $data 包含以下键
*
* ```php
* $data = [
* 'appId' => '', // 公众号id
* 'package' => '', // 订单详情扩展字符串 统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=***
* 'nonceStr' => '', // 随机字符串
* 'timeStamp' => '', // 时间戳
* 'signType' => '', // 签名算法,暂支持MD5
* 'paySign' => '', // 签名
* ];
* ```
* @author helei
*/
protected function retData(array $ret)
{
$back = new BackPubChargeData($this->config, $ret);
$back->setSign();
$backData = $back->getData();
$backData['paySign'] = $backData['sign'];
// 移除sign
unset($backData['sign']);
// 公众号支付返回数组结构
return $backData;
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-14 18:29
* @description: 微信 扫码支付 主要用于网站上
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment\Charge\Wx;
use Payment\Common\Weixin\Data\Charge\QrChargeData;
use Payment\Common\Weixin\WxBaseStrategy;
class WxQrCharge extends WxBaseStrategy
{
public function getBuildDataClass()
{
$this->config->tradeType = 'NATIVE';// 微信文档这里写错了
return QrChargeData::class;
}
/**
* 处理扫码支付的返回值
* @param array $ret
* @return string 可生产二维码的uri
* @author helei
*/
protected function retData(array $ret)
{
if ($this->config->returnRaw) {
return $ret;
}
// 扫码支付,返回链接
return $ret['code_url'];
}
}
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/3/6
* Time: 下午5:44
*/
namespace Payment\Charge\Wx;
use Payment\Common\Weixin\Data\Charge\WapChargeData;
use Payment\Common\Weixin\WxBaseStrategy;
/**
* 微信h5支付
* Class WxWapCharge
* @package Payment\Charge\Weixin
*/
class WxWapCharge extends WxBaseStrategy
{
public function getBuildDataClass()
{
$this->config->tradeType = 'MWEB';
return WapChargeData::class;
}
/**
* 这里由于
* @param array $ret
* @return mixed
*/
protected function retData(array $ret)
{
if ($this->config->returnRaw) {
return $ret;
}
$wabUrl = $ret['mweb_url'];
if ($this->config->returnUrl) {
$wabUrl .= '&redirect_url=' . urlencode($this->config->returnUrl);
}
return $wabUrl;
}
}
\ No newline at end of file
<?php
/**
* @author: helei
* @createTime: 2016-07-14 17:42
* @description: 暴露给客户端调用的接口
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment;
use Payment\Charge\Ali\AliAppCharge;
use Payment\Charge\Ali\AliBarCharge;
use Payment\Charge\Ali\AliWapCharge;
use Payment\Charge\Ali\AliWebCharge;
use Payment\Charge\Ali\AliQrCharge;
use Payment\Charge\Cmb\CmbCharge;
use Payment\Charge\TLpay\TLLiteCharge;
use Payment\Charge\Wx\WxAppCharge;
use Payment\Charge\Wx\WxBarCharge;
use Payment\Charge\Wx\WxPubCharge;
use Payment\Charge\Wx\WxQrCharge;
use Payment\Charge\Wx\WxWapCharge;
use Payment\Common\BaseStrategy;
use Payment\Common\PayException;
/**
* Class ChargeContext
*
* 支付的上下文类
*
* @package Payment
* anthor helei
*/
class ChargeContext
{
/**
* 支付的渠道
* @var BaseStrategy
*/
protected $channel;
/**
* 设置对应的支付渠道
* @param string $channel 支付渠道
* - @see Config
* @param array $config 配置文件
* @throws PayException
* @author helei
*/
public function initCharge($channel, array $config)
{
// 初始化时,可能抛出异常,再次统一再抛出给客户端进行处理
try {
switch ($channel) {
case Config::ALI_CHANNEL_WAP:
$this->channel = new AliWapCharge($config);
break;
case Config::ALI_CHANNEL_APP:
$this->channel = new AliAppCharge($config);
break;
case Config::ALI_CHANNEL_WEB:
$this->channel = new AliWebCharge($config);
break;
case Config::ALI_CHANNEL_QR:
$this->channel = new AliQrCharge($config);
break;
case Config::ALI_CHANNEL_BAR:
$this->channel = new AliBarCharge($config);
break;
case Config::WX_CHANNEL_APP:
$this->channel = new WxAppCharge($config);
break;
case Config::WX_CHANNEL_LITE:// 小程序支付与公众号支付一样,仅仅是客户端的调用方式不同
case Config::WX_CHANNEL_PUB:
$this->channel = new WxPubCharge($config);
break;
case Config::WX_CHANNEL_WAP:
$this->channel = new WxWapCharge($config);
break;
case Config::WX_CHANNEL_QR:
$this->channel = new WxQrCharge($config);
break;
case Config::WX_CHANNEL_BAR:
$this->channel = new WxBarCharge($config);
break;
case Config::CMB_CHANNEL_WAP:
case Config::CMB_CHANNEL_APP:
$this->channel = new CmbCharge($config);
break;
case Config::TL_CHANNEL_LITE:
$this->channel = new TLLiteCharge($config);
break;
default:
throw new PayException('当前支持:支付宝 微信 招商一网通 通联支付');
}
} catch (PayException $e) {
throw $e;
}
}
/**
* 通过环境类调用支付
* @param array $data
*
* ```php
* $payData = [
* "order_no" => createPayid(),
* "amount" => '0.01',// 单位为元 ,最小为0.01
* "client_ip" => '127.0.0.1',
* "subject" => '测试支付',
* "body" => '支付接口测试',
* "extra_param" => '',
* ];
* ```
*
* @return array
* @throws PayException
* @author helei
*/
public function charge(array $data)
{
if (! $this->channel instanceof BaseStrategy) {
throw new PayException('请检查初始化是否正确');
}
try {
return $this->channel->handle($data);
} catch (PayException $e) {
throw $e;
}
}
}
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/3/4
* Time: 下午5:40
*/
namespace Payment\Client;
use Payment\ChargeContext;
use Payment\Common\PayException;
use Payment\Config;
class Charge
{
private static $supportChannel = [
Config::ALI_CHANNEL_APP,// 支付宝 APP 支付
Config::ALI_CHANNEL_WAP, // 支付宝手机网页支付
Config::ALI_CHANNEL_WEB, // 支付宝电脑网站支付
Config::ALI_CHANNEL_QR, // 支付宝当面付-扫码支付
Config::ALI_CHANNEL_BAR,// 支付宝当面付-条码支付
Config::WX_CHANNEL_APP,// 微信 APP 支付
Config::WX_CHANNEL_PUB,// 微信公众号支付
Config::WX_CHANNEL_QR,// 微信公众号扫码支付
Config::WX_CHANNEL_BAR,// 微信刷卡支付
Config::WX_CHANNEL_WAP,// 微信 WAP 支付(此渠道仅针对特定客户开放)
Config::WX_CHANNEL_LITE,// 微信小程序支付
Config::CMB_CHANNEL_APP,// 招行一网通
'applepay_upacp',// Apple Pay
Config::TL_CHANNEL_LITE,
];
/**
* 异步通知类
* @var ChargeContext
*/
protected static $instance;
protected static function getInstance($channel, $config)
{
if (is_null(self::$instance)) {
static::$instance = new ChargeContext();
try {
static::$instance->initCharge($channel, $config);
} catch (PayException $e) {
throw $e;
}
}
return static::$instance;
}
/**
* @param string $channel
* @param array $config
* @param array $metadata
*
* @return mixed
* @throws PayException
*/
public static function run($channel, $config, $metadata)
{
if (! in_array($channel, self::$supportChannel)) {
throw new PayException('sdk当前不支持该支付渠道,当前仅支持:' . implode(',', self::$supportChannel));
}
try {
$instance = self::getInstance($channel, $config);
$ret = $instance->charge($metadata);
} catch (PayException $e) {
throw $e;
}
return $ret;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/4/28
* Time: 上午10:44
*/
namespace Payment\Client;
use Payment\Common\PayException;
use Payment\Config;
use Payment\HelperContext;
/**
* 提供给客户端的辅助类
* Class Helper
* @package Payment\Client
*/
class Helper
{
private static $supportChannel = [
Config::CMB_BIND,// 招商绑卡操作
Config::CMB_PUB_KEY,// 招商公钥查询操作
];
/**
* 异步通知类
* @var HelperContext
*/
protected static $instance;
protected static function getInstance($channel, $config)
{
if (is_null(self::$instance)) {
static::$instance = new HelperContext();
try {
static::$instance->initHelper($channel, $config);
} catch (PayException $e) {
throw $e;
}
}
return static::$instance;
}
/**
* @param string $channel
* @param array $config
* @param array $metadata
*
* @return mixed
* @throws PayException
*/
public static function run($channel, $config, array $metadata = [])
{
if (! in_array($channel, self::$supportChannel)) {
throw new PayException('sdk当前不支持该渠道,当前仅支持:' . implode(',', self::$supportChannel));
}
try {
$instance = self::getInstance($channel, $config);
$ret = $instance->helper($metadata);
} catch (PayException $e) {
throw $e;
}
return $ret;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/3/7
* Time: 下午6:29
*/
namespace Payment\Client;
use Payment\Common\PayException;
use Payment\Config;
use Payment\Notify\PayNotifyInterface;
use Payment\NotifyContext;
class Notify
{
private static $supportChannel = [
Config::ALI_CHARGE,// 支付宝
Config::WX_CHARGE,// 微信
Config::CMB_CHARGE,// 招行一网通
'applepay_upacp',// Apple Pay
Config::TL_CHARGE
];
/**
* 异步通知类
* @var NotifyContext
*/
protected static $instance;
protected static function getInstance($type, $config)
{
if (is_null(self::$instance)) {
static::$instance = new NotifyContext();
try {
static::$instance->initNotify($type, $config);
} catch (PayException $e) {
throw $e;
}
}
return static::$instance;
}
/**
* 执行异步工作
* @param string $type
* @param array $config
* @param PayNotifyInterface $callback
* @return array
* @throws PayException
*/
public static function run($type, $config, $callback)
{
if (! in_array($type, self::$supportChannel)) {
throw new PayException('sdk当前不支持该异步方式,当前仅支持:' . implode(',', self::$supportChannel));
}
try {
$instance = self::getInstance($type, $config);
$ret = $instance->notify($callback);
} catch (PayException $e) {
throw $e;
}
return $ret;
}
/**
* 返回异步通知的结果
* @param $type
* @param $config
* @return array|false
* @throws PayException
*/
public static function getNotifyData($type, $config)
{
try {
$instance = self::getInstance($type, $config);
return $instance->getNotifyData();
} catch (PayException $e) {
throw $e;
}
}
}
\ No newline at end of file
<?php
/**
* Created by IntelliJ IDEA.
* User: yeran
* Date: 2018/4/23
* Time: 下午6:07
*/
namespace Payment\Client;
use Payment\CancelContext;
use Payment\Common\PayException;
use Payment\Config;
class OrderCancel {
private static $supportChannel = [
Config::TL_CHANNEL_LITE,
];
/**
* @var CancelContext
*/
protected static $instance;
protected static function getInstance($channel, $config)
{
if (is_null(self::$instance)) {
static::$instance = new CancelContext();
try {
static::$instance->initCancelHandler($channel, $config);
} catch (PayException $e) {
throw $e;
}
}
return static::$instance;
}
/**
* @param string $channel
* @param array $config
* @param array $metadata
*
* @return mixed
* @throws PayException
*/
public static function run($channel, $config, $metadata)
{
if (! in_array($channel, self::$supportChannel)) {
throw new PayException('sdk当前不支持该支付渠道,当前仅支持:' . implode(',', self::$supportChannel));
}
try {
$instance = self::getInstance($channel, $config);
$ret = $instance->cancel($metadata);
} catch (PayException $e) {
throw $e;
}
return $ret;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/3/6
* Time: 下午9:08
*/
namespace Payment\Client;
use Payment\Common\PayException;
use Payment\Config;
use Payment\QueryContext;
/**
* 查询的客户端类
* Class Query
* @package Payment\Client
*/
class Query
{
protected static $supportType = [
Config::ALI_CHARGE,
Config::ALI_REFUND,
Config::ALI_TRANSFER,
Config::ALI_RED,
Config::WX_CHARGE,
Config::WX_REFUND,
Config::WX_RED,
Config::WX_TRANSFER,
Config::CMB_CHARGE,
Config::CMB_REFUND,
Config::TL_QUERY
];
/**
* 异步通知类
* @var QueryContext
*/
protected static $instance;
protected static function getInstance($queryType, $config)
{
if (is_null(self::$instance)) {
static::$instance = new QueryContext();
try {
static::$instance->initQuery($queryType, $config);
} catch (PayException $e) {
throw $e;
}
}
return static::$instance;
}
/**
* @param string $queryType
* @param array $config
* @param array $metadata
* @return array
* @throws PayException
*/
public static function run($queryType, $config, $metadata)
{
if (! in_array($queryType, self::$supportType)) {
throw new PayException('sdk当前不支持该类型查询,当前仅支持:' . implode(',', self::$supportType) . __LINE__);
}
try {
$instance = self::getInstance($queryType, $config);
$ret = $instance->query($metadata);
} catch (PayException $e) {
throw $e;
}
return $ret;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/3/7
* Time: 上午10:50
*/
namespace Payment\Client;
use Payment\Common\PayException;
use Payment\Config;
use Payment\RefundContext;
/**
* 退款操作客户端接口
* Class Refund
* @package Payment\Client
*/
class Refund
{
private static $supportChannel = [
Config::ALI_REFUND,// 支付宝
Config::WX_REFUND,// 微信
Config::CMB_REFUND,// 招行一网通
'applepay_upacp',// Apple Pay
Config::TL_REFUND
];
/**
* 异步通知类
* @var RefundContext
*/
protected static $instance;
protected static function getInstance($channel, $config)
{
if (is_null(self::$instance)) {
static::$instance = new RefundContext();
try {
static::$instance->initRefund($channel, $config);
} catch (PayException $e) {
throw $e;
}
}
return static::$instance;
}
public static function run($channel, $config, $refundData)
{
if (! in_array($channel, self::$supportChannel)) {
throw new PayException('sdk当前不支持该退款渠道,当前仅支持:' . implode(',', self::$supportChannel));
}
try {
$instance = self::getInstance($channel, $config);
$ret = $instance->refund($refundData);
} catch (PayException $e) {
throw $e;
}
return $ret;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/3/7
* Time: 下午3:16
*/
namespace Payment\Client;
use Payment\Common\PayException;
use Payment\Config;
use Payment\TransferContext;
class Transfer
{
private static $supportChannel = [
Config::ALI_TRANSFER,// 支付宝
Config::WX_TRANSFER,// 微信
'cmb_wallet',// 招行一网通
'applepay_upacp',// Apple Pay
];
/**
* 异步通知类
* @var TransferContext
*/
protected static $instance;
protected static function getInstance($channel, $config)
{
if (is_null(self::$instance)) {
static::$instance = new TransferContext();
try {
static::$instance->initTransfer($channel, $config);
} catch (PayException $e) {
throw $e;
}
}
return static::$instance;
}
/**
* @param $channel
* @param $config
* @param $metadata
*
* @return array
* @throws PayException
*/
public static function run($channel, $config, $metadata)
{
if (! in_array($channel, self::$supportChannel)) {
throw new PayException('sdk当前不支持该退款渠道,当前仅支持:' . implode(',', self::$supportChannel));
}
try {
$instance = self::getInstance($channel, $config);
$ret = $instance->transfer($metadata);
} catch (PayException $e) {
throw $e;
}
return $ret;
}
}
\ No newline at end of file
<?php
/**
* @author: helei
* @createTime: 2016-07-15 17:10
* @description: 支付宝支付接口的基类。
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment\Common\Ali;
use Payment\Common\AliConfig;
use Payment\Common\BaseData;
use Payment\Common\BaseStrategy;
use Payment\Common\PayException;
use Payment\Config;
use Payment\Utils\ArrayUtil;
use Payment\Utils\Curl;
use Payment\Utils\Rsa2Encrypt;
use Payment\Utils\RsaEncrypt;
use Payment\Utils\StrUtil;
abstract class AliBaseStrategy implements BaseStrategy
{
/**
* 支付宝的配置文件
* @var AliConfig $config
*/
protected $config;
/**
* 支付数据
* @var BaseData $reqData
*/
protected $reqData;
/**
* AliBaseStrategy constructor.
* @param array $config
* @throws PayException
*/
public function __construct(array $config)
{
/* 设置内部字符编码为 UTF-8 */
mb_internal_encoding("UTF-8");
try {
$this->config = new AliConfig($config);
} catch (PayException $e) {
throw $e;
}
}
public function handle(array $data)
{
$buildClass = $this->getBuildDataClass();
try {
$this->reqData = new $buildClass($this->config, $data);
} catch (PayException $e) {
throw $e;
}
$this->reqData->setSign();
$data = $this->reqData->getData();
return $this->retData($data);
}
/**
* 支付宝业务发送网络请求,并验证签名
* @param $url
* @return mixed
* @throws PayException
*/
protected function sendReq($url)
{
// 发起网络请求
$curl = new Curl();
$responseTxt = $curl->set([
'CURLOPT_SSL_VERIFYPEER' => true,
'CURLOPT_SSL_VERIFYHOST' => 2,
'CURLOPT_HEADER' => 0,// 为了便于解析,将头信息过滤掉
//'CURLOPT_CAINFO' => $this->config->cacertPath,
])->get($url);
if ($responseTxt['error']) {
throw new PayException('网络发生错误,请稍后再试curl返回码:' . $responseTxt['message']);
}
$body = $responseTxt['body'];
$responseKey = str_ireplace('.', '_', $this->config->method . '.response');
$body = json_decode($body, true);
if ($body[$responseKey]['code'] != 10000) {
throw new PayException($body[$responseKey]['sub_msg']);
}
// 验证签名,检查支付宝返回的数据
$flag = $this->verifySign($body[$responseKey], $body['sign']);
if (! $flag) {
throw new PayException('支付宝返回数据被篡改。请检查网络是否安全!');
}
return $body[$responseKey];
}
/**
* 处理支付宝的返回值并返回给客户端
* @param array $data
* @return string|array
* @author helei
*/
protected function retData(array $data)
{
$sign = $data['sign'];
$data = ArrayUtil::removeKeys($data, ['sign']);
$data = ArrayUtil::arraySort($data);
// 支付宝新版本 需要转码
foreach ($data as &$value) {
$value = StrUtil::characet($value, $this->config->charset);
}
$data['sign'] = $sign;// sign 需要放在末尾
return $this->config->getewayUrl . http_build_query($data);
}
/**
* 返回统一的交易状态 做一些转化,方便处理
* @param $status
* @return string
* @author helei
*/
protected function getTradeStatus($status)
{
switch ($status) {
case 'TRADE_SUCCESS':
//no break
case 'TRADE_FINISHED':
return Config::TRADE_STATUS_SUCC;
case 'WAIT_BUYER_PAY':
case 'TRADE_CLOSED':
default:
return Config::TRADE_STATUS_FAILD;
}
}
/**
* 检查支付宝数据 签名是否被篡改
* @param array $data
* @param string $sign 支付宝返回的签名结果
* @return bool
* @author helei
*/
protected function verifySign(array $data, $sign)
{
$preStr = json_encode($data);
if ($this->config->signType === 'RSA') {// 使用RSA
$rsa = new RsaEncrypt($this->config->rsaAliPubKey);
return $rsa->rsaVerify($preStr, $sign);
} elseif ($this->config->signType === 'RSA2') {// 使用rsa2方式
$rsa = new Rsa2Encrypt($this->config->rsaAliPubKey);
return $rsa->rsaVerify($preStr, $sign);
} else {
return false;
}
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-15 17:28
* @description: 支付宝相关数据的基类
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment\Common\Ali\Data;
use Payment\Common\BaseData;
use Payment\Utils\ArrayUtil;
use Payment\Utils\Rsa2Encrypt;
use Payment\Utils\RsaEncrypt;
/**
* Class BaseData
*
* @property string $getewayUrl 支付宝网关
* @property string $appId 支付宝分配给开发者的应用ID
* @property string $method 接口名称
* @property string $format 仅支持JSON
* @property string $returnUrl HTTP/HTTPS开头字符串
* @property string $charset 请求使用的编码格式,如utf-8,gbk,gb2312等 当前仅支持 utf-8
* @property string $timestamp 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss"
* @property string $version 调用的接口版本,固定为:1.0
* @property string $notifyUrl 支付宝服务器主动通知商户服务器里指定的页面http/https路径
*
* @property string $rsaPrivateKey rsa私钥路径
* @property string $rsaAliPubKey rsa支付宝公钥路径
*
* @property string $partner 合作id
*
* @package Payment\Charge\Ali\Data
* anthor helei
*/
abstract class AliBaseData extends BaseData
{
public function getData()
{
$data = parent::getData();
// 新版需要对数据进行排序
$data = ArrayUtil::arraySort($data);
return $data;
}
/**
* 签名算法实现
* @param string $signStr
* @return string
* @author helei
*/
protected function makeSign($signStr)
{
switch ($this->signType) {
case 'RSA':
$rsa = new RsaEncrypt($this->rsaPrivateKey);
$sign = $rsa->encrypt($signStr);
break;
case 'RSA2':
$rsa = new Rsa2Encrypt($this->rsaPrivateKey);
$sign = $rsa->encrypt($signStr);
break;
default:
$sign = '';
}
return $sign;
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-25 14:49
* @description:
*/
namespace Payment\Common\Ali\Data\Charge;
use Payment\Utils\ArrayUtil;
class AppChargeData extends ChargeBaseData
{
/**
* 业务请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递
*
* @return string
*/
protected function getBizContent()
{
$content = [
'body' => strval($this->body),
'subject' => strval($this->subject),
'out_trade_no' => strval($this->order_no),
'total_amount' => strval($this->amount),
'seller_id' => $this->partner,
// 销售产品码,商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY
'product_code' => 'QUICK_MSECURITY_PAY',
'goods_type' => $this->goods_type,
'passback_params' => $this->return_param,
'disable_pay_channels' => $this->limitPay,
'store_id' => $this->store_id,
];
$timeExpire = $this->timeout_express;
if (! empty($timeExpire)) {
$express = floor(($timeExpire - strtotime($this->timestamp)) / 60);
$express && $content['timeout_express'] = $express . 'm';// 超时时间 统一使用分钟计算
}
$content = ArrayUtil::paraFilter($content);// 过滤掉空值,下面不用在检查是否为空
return json_encode($content, JSON_UNESCAPED_UNICODE);
}
}
<?php
/**
* Created by PhpStorm.
* User: helei <dayugog@gmail.com>
* Date: 2016/12/28
* Time: 20:24
*/
namespace Payment\Common\Ali\Data\Charge;
use Payment\Common\PayException;
/**
* 支付宝 条码支付
* - 扫户扫用户的二维码,完成支付
* Class BarChargeData
*
* @property string $operator_id 商户操作员编号
* @property string $terminal_id 商户机具终端编号
* @property string $alipay_store_id 支付宝店铺的门店ID
* @property string $scene 条码支付,取值:bar_code 声波支付,取值:wave_code
* @property string $auth_code 支付授权码 二维码的数值
*
* @package Payment\Common\Ali\Data\Charge
*/
class BarChargeData extends ChargeBaseData
{
/**
* 业务请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递
*
* @return string
*/
protected function getBizContent()
{
$content = [
'body' => strval($this->body),
'subject' => strval($this->subject),
'out_trade_no' => strval($this->order_no),
'total_amount' => strval($this->amount),
'seller_id' => $this->partner,
'store_id' => $this->store_id,
'operator_id' => $this->operator_id,
'terminal_id' => $this->terminal_id,
'alipay_store_id' => $this->alipay_store_id,
'scene' => $this->scene,
'auth_code' => $this->auth_code,
];
$timeExpire = $this->timeout_express;
if (! empty($timeExpire)) {
$express = floor(($timeExpire - strtotime($this->timestamp)) / 60);
$express && $content['timeout_express'] = $express . 'm';// 超时时间 统一使用分钟计算
}
return json_encode($content, JSON_UNESCAPED_UNICODE);
}
protected function checkDataParam()
{
parent::checkDataParam(); // TODO: Change the autogenerated stub
$scene = $this->scene;
$authCode = $this->auth_code;
if (empty($scene) || ! in_array($scene, ['bar_code', 'wave_code'])) {
throw new PayException('支付场景 scene 必须设置 条码支付:bar_code 声波支付:wave_code');
}
if (empty($authCode)) {
throw new PayException('请提供支付授权码');
}
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-20 14:33
* @description:
*/
namespace Payment\Common\Ali\Data\Charge;
use Payment\Common\Ali\Data\AliBaseData;
use Payment\Common\PayException;
use Payment\Config;
use Payment\Utils\ArrayUtil;
/**
* Class ChargeBaseData
*
* @inheritdoc
*
* @property string $body
* @property string $subject
* @property string $order_no
* @property integer $timeout_express
* @property string $amount
* @property string $goods_type
* @property string $return_param
* @property string $store_id 商户门店编号
*
* @package Payment\Common\Ali\Data\Charge
* anthor helei
*/
abstract class ChargeBaseData extends AliBaseData
{
/**
* 构建 APP支付 加密数据
* @author helei
*/
protected function buildData()
{
$signData = [
// 公共参数
'app_id' => $this->appId,
'method' => $this->method,
'format' => $this->format,
'return_url' => $this->returnUrl,
'charset' => $this->charset,
'sign_type' => $this->signType,
'timestamp' => $this->timestamp,
'version' => $this->version,
'notify_url' => $this->notifyUrl,
// 业务参数
'biz_content' => $this->getBizContent(),
];
// 移除数组中的空值
$this->retData = ArrayUtil::paraFilter($signData);
}
/**
* 支付宝构建请求支付的数据
* @return mixed
*/
abstract protected function getBizContent();
/**
* 检查传入的支付业务参数是否正确
*
* 如果输入参数不符合规范,直接抛出异常
*
* @author helei
*/
protected function checkDataParam()
{
$subject = $this->subject;
$orderNo = $this->order_no;
$amount = $this->amount;
$goodsType = $this->goods_type;
$passBack = $this->return_param;
// 检查订单号是否合法
if (empty($orderNo) || mb_strlen($orderNo) > 64) {
throw new PayException('订单号不能为空,并且长度不能超过64位');
}
// 检查金额不能低于0.01
if (bccomp($amount, Config::PAY_MIN_FEE, 2) === -1) {
throw new PayException('支付金额不能低于 ' . Config::PAY_MIN_FEE . ' 元');
}
// 检查 商品名称 与 商品描述
if (empty($subject)) {
throw new PayException('必须提供 商品的标题/交易标题/订单标题/订单关键字 等');
}
// 检查商品类型
if (empty($goodsType)) {// 默认为实物类商品
$this->goods_type = 1;
} elseif (! in_array($goodsType, [0 ,1])) {
throw new PayException('商品类型可取值为:0-虚拟类商品 1-实物类商品');
}
// 返回参数进行urlencode编码
if (! empty($passBack) && ! is_string($passBack)) {
throw new PayException('回传参数必须是字符串');
}
$this->return_param = urlencode($passBack);
}
}
<?php
/**
* Created by PhpStorm.
* User: helei <dayugog@gmail.com>
* Date: 2016/12/28
* Time: 20:24
*/
namespace Payment\Common\Ali\Data\Charge;
/**
* 支付宝 扫码支付
* Class QrChargeData
*
* @property string $operator_id 商户操作员编号
* @property string $terminal_id 商户机具终端编号
* @property string $alipay_store_id 支付宝店铺的门店ID
*
* @package Payment\Common\Ali\Data\Charge
*/
class QrChargeData extends ChargeBaseData
{
/**
* 业务请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递
*
* @return string
*/
protected function getBizContent()
{
$content = [
'body' => strval($this->body),
'subject' => strval($this->subject),
'out_trade_no' => strval($this->order_no),
'total_amount' => strval($this->amount),
'seller_id' => $this->partner,
'store_id' => $this->store_id,
'operator_id' => $this->operator_id,
'terminal_id' => $this->terminal_id,
'alipay_store_id' => $this->alipay_store_id,
];
$timeExpire = $this->timeout_express;
if (! empty($timeExpire)) {
$express = floor(($timeExpire - strtotime($this->timestamp)) / 60);
$express && $content['timeout_express'] = $express . 'm';// 超时时间 统一使用分钟计算
}
return json_encode($content, JSON_UNESCAPED_UNICODE);
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-22 17:02
* @description:
*/
namespace Payment\Common\Ali\Data\Charge;
use Payment\Utils\ArrayUtil;
class WapChargeData extends ChargeBaseData
{
/**
* 业务请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递
*
* @return string
*/
protected function getBizContent()
{
$content = [
'body' => strval($this->body),
'subject' => strval($this->subject),
'out_trade_no' => strval($this->order_no),
'total_amount' => strval($this->amount),
'seller_id' => $this->partner,
// 销售产品码,商家和支付宝签约的产品码,为固定值QUICK_WAP_PAY
'product_code' => 'QUICK_WAP_PAY',
'goods_type' => $this->goods_type,
'passback_params' => $this->return_param,
'disable_pay_channels' => $this->limitPay,
'store_id' => $this->store_id,
];
$timeExpire = $this->timeout_express;
if (! empty($timeExpire)) {
$express = floor(($timeExpire - strtotime($this->timestamp)) / 60);
$express && $content['timeout_express'] = $express . 'm';// 超时时间 统一使用分钟计算
}
$content = ArrayUtil::paraFilter($content);// 过滤掉空值,下面不用在检查是否为空
return json_encode($content, JSON_UNESCAPED_UNICODE);
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-15 17:28
* @description: 即时到帐 接口的数据处理类
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment\Common\Ali\Data\Charge;
use Payment\Common\PayException;
use Payment\Utils\ArrayUtil;
/**
* Class WebChargeData
*
* @inheritdoc
* @property integer $qr_mod
*
* @package Payment\Charge\Ali\Data
* anthor helei
*/
class WebChargeData extends ChargeBaseData
{
/**
* 业务请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递
*
* @return string
*/
protected function getBizContent()
{
$content = [
'body' => strval($this->body),
'subject' => strval($this->subject),
'out_trade_no' => strval($this->order_no),
'total_amount' => strval($this->amount),
// 销售产品码,商家和支付宝签约的产品码,为固定值QUICK_WAP_PAY
'product_code' => 'FAST_INSTANT_TRADE_PAY',
'goods_type' => $this->goods_type,
'passback_params' => $this->return_param,
'disable_pay_channels' => $this->limitPay,
'store_id' => $this->store_id,
'qr_pay_mode' => $this->qr_mod,
];
$timeExpire = $this->timeout_express;
if (! empty($timeExpire)) {
$express = floor(($timeExpire - strtotime($this->timestamp)) / 60);
$express && $content['timeout_express'] = $express . 'm';// 超时时间 统一使用分钟计算
}
$content = ArrayUtil::paraFilter($content);// 过滤掉空值,下面不用在检查是否为空
return json_encode($content, JSON_UNESCAPED_UNICODE);
}
}
<?php
/**
* @author: helei
* @createTime: 2017-03-06 22:32
* @description:
*/
namespace Payment\Common\Ali\Data\Query;
use Payment\Common\PayException;
use Payment\Utils\ArrayUtil;
/**
* Class ChargeQueryData
*
* @property string $trade_no 支付宝的订单号,优先使用
* @property string $out_trade_no 商户系统内部的订单号
*
* @package Payment\Common\Ali\Data\Query
* anthor helei
*/
class ChargeQueryData extends QueryBaseData
{
/**
* 检查参数
* @author helei
*/
protected function checkDataParam()
{
$tradeNo = $this->trade_no;// 支付宝交易号,查询效率高
$outTradeNo = $this->out_trade_no;// 商户订单号,查询效率低,不建议使用
// 二者不能同时为空
if (empty($outTradeNo) && empty($tradeNo)) {
throw new PayException('必须提供支付宝交易号或者商户网站唯一订单号。建议使用支付宝交易号');
}
}
protected function getBizContent()
{
$content = [
'out_trade_no' => $this->out_trade_no,
'trade_no' => $this->trade_no,
];
$content = ArrayUtil::paraFilter($content);// 过滤掉空值,下面不用在检查是否为空
return json_encode($content, JSON_UNESCAPED_UNICODE);
}
}
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/3/6
* Time: 下午10:37
*/
namespace Payment\Common\Ali\Data\Query;
use Payment\Common\Ali\Data\AliBaseData;
use Payment\Utils\ArrayUtil;
abstract class QueryBaseData extends AliBaseData
{
/**
* 构建 APP支付 加密数据
* @author helei
*/
protected function buildData()
{
$signData = [
// 公共参数
'app_id' => $this->appId,
'method' => $this->method,
'format' => $this->format,
'charset' => $this->charset,
'sign_type' => $this->signType,
'timestamp' => $this->timestamp,
'version' => $this->version,
// 业务参数
'biz_content' => $this->getBizContent(),
];
// 移除数组中的空值
$this->retData = ArrayUtil::paraFilter($signData);
}
/**
* 支付宝构建请求查询的数据
* @return mixed
*/
abstract protected function getBizContent();
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/3/7
* Time: 下午1:45
*/
namespace Payment\Common\Ali\Data\Query;
use Payment\Common\PayException;
use Payment\Utils\ArrayUtil;
/**
* 支付宝退款查询
* Class RefundQueryData
*
* @property string $trade_no 支付宝的订单号,优先使用
* @property string $out_trade_no 商户系统内部的订单号
* @property string $refund_no 请求退款接口时,传入的退款请求号,如果在退款请求时未传入,则该值为创建交易时的外部交易号
*
* @package Payment\Common\Ali\Data\Query
*/
class RefundQueryData extends QueryBaseData
{
protected function getBizContent()
{
$content = [
'out_trade_no' => $this->out_trade_no,
'trade_no' => $this->trade_no,
'out_request_no' => $this->refund_no,
];
$content = ArrayUtil::paraFilter($content);// 过滤掉空值,下面不用在检查是否为空
return json_encode($content, JSON_UNESCAPED_UNICODE);
}
protected function checkDataParam()
{
$tradeNo = $this->trade_no;// 支付宝交易号,查询效率高
$outTradeNo = $this->out_trade_no;// 商户订单号,查询效率低,不建议使用
// 二者不能同时为空
if (empty($outTradeNo) && empty($tradeNo)) {
throw new PayException('必须提供支付宝交易号或者商户网站唯一订单号。建议使用支付宝交易号');
}
$refundNo = $this->refund_no;
if (empty($refundNo)) {
throw new PayException('支付宝查询退款,必须传入提款的请求号。如果在退款请求时未传入,则该值为创建交易时的外部交易号');
}
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: helei
* Date: 2017/3/7
* Time: 下午3:59
*/
namespace Payment\Common\Ali\Data\Query;
use Payment\Common\PayException;
use Payment\Utils\ArrayUtil;
/**
* 构建查询转账情况的数据
*
* @property string $trans_no 商户转账唯一订单号
* @property string $transaction_id 支付宝转账单据号:和商户转账唯一订单号不能同时为空
*
* Class TransferQueryData
* @package Payment\Common\Ali\Data\Query
*/
class TransferQueryData extends QueryBaseData
{
protected function getBizContent()
{
$content = [
'out_biz_no' => $this->trans_no,
'order_id' => $this->transaction_id,
];
$content = ArrayUtil::paraFilter($content);// 过滤掉空值,下面不用在检查是否为空
return json_encode($content, JSON_UNESCAPED_UNICODE);
}
protected function checkDataParam()
{
$transNo = $this->trans_no;
$transactionId = $this->transaction_id;
// 二者不能同时为空
if (empty($transactionId) && empty($transNo)) {
throw new PayException('必须提供支付宝转账单据号或者商户转账单号');
}
}
}
\ No newline at end of file
<?php
/**
* @author: helei
* @createTime: 2016-07-26 18:18
* @description:
*/
namespace Payment\Common\Ali\Data;
use Payment\Common\PayException;
use Payment\Utils\ArrayUtil;
/**
* Class RefundData
*
* @property string $trade_no 支付宝的订单号,优先使用
* @property string $out_trade_no 商户系统内部的订单号
* @property float $refund_fee 退款总金额,订单总金额,只能为整数
* @property string $reason 退款的原因说明
* @property string $refund_no 商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔(3~24位)
* @property string $operator_id 商户的操作员编号
* @property string $terminal_id 商户机具终端编号
* @property string $store_id 商户门店编号
*
* @package Payment\Common\Ali\Data
* anthor helei
*/
class RefundData extends AliBaseData
{
/**
* 检查退款数据是否正常
* @author helei
*/
protected function checkDataParam()
{
$tradeNo = $this->trade_no;// 支付宝交易号,查询效率高
$outTradeNo = $this->out_trade_no;// 商户订单号,查询效率低,不建议使用
$refundAmount = $this->refund_fee;
// 二者不能同时为空
if (empty($outTradeNo) && empty($tradeNo)) {
throw new PayException('必须提供支付宝交易号或者商户网站唯一订单号。建议使用支付宝交易号');
}
if (empty($refundAmount) || ! is_numeric($refundAmount)) {
throw new PayException('refund_fee 退款的金额,该金额不能大于订单金额,单位为元,支持两位小数');
}
}
protected function buildData()
{
$signData = [
// 公共参数
'app_id' => $this->appId,
'method' => $this->method,
'format' => $this->format,
'charset' => $this->charset,
'sign_type' => $this->signType,
'timestamp' => $this->timestamp,
'version' => $this->version,
// 业务参数
'biz_content' => $this->getBizContent(),
];
// 移除数组中的空值
$this->retData = ArrayUtil::paraFilter($signData);
}
/**
* 业务请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递
*
* @return string
*/
private function getBizContent()
{
$content = [
'out_trade_no' => $this->out_trade_no,
'trade_no' => $this->trade_no,
'refund_amount' => $this->refund_fee,
'refund_reason' => $this->reason,
'out_request_no' => $this->refund_no,
'operator_id' => $this->operator_id,
'store_id' => $this->store_id,
'terminal_id' => $this->terminal_id,
];
$content = ArrayUtil::paraFilter($content);// 过滤掉空值,下面不用在检查是否为空
return json_encode($content, JSON_UNESCAPED_UNICODE);
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-27 13:05
* @description:
*/
namespace Payment\Common\Ali\Data;
use Payment\Common\PayException;
use Payment\Config;
use Payment\Utils\ArrayUtil;
/**
* 转账到支付宝帐号
* Class TransData
*
* @property string $trans_no 商户转账唯一订单号
* @property string $payee_type 收款方账户类型。可取值: 1、ALIPAY_USERID:支付宝账号对应的支付宝唯一用户号。以2088开头的16位纯数字组成。 2、ALIPAY_LOGONID:支付宝登录号,支持邮箱和手机号格式。
* @property string $payee_account 收款方账户。与payee_type配合使用。付款方和收款方不能是同一个账户。
* @property string $amount 转账金额,单位:元。 只支持2位小数,小数点前最大支持13位,金额必须大于0。
*
* // 可选参数
* @property string $payer_real_name 付款方真实姓名
* @property string $payee_real_name 收款方真实姓名
* @property string $payer_show_name 默认显示该账户在支付宝登记的实名。收款方可见。
* @property string $remark 转账备注 当付款方为企业账户,且转账金额达到(大于等于)50000元,remark不能为空
*
* @package Payment\Common\Ali\Data
* anthor helei
*/
class TransData extends AliBaseData
{
/**
* 检查参数是否合法
* @author helei
*/
protected function checkDataParam()
{
$transNo = $this->trans_no;
$payeeType = $this->payee_type;
$payeeAccount = $this->payee_account;
$amount = $this->amount;
$remark = $this->remark;
if (empty($transNo)) {
throw new PayException('请传入 商户转账唯一订单号');
}
if (empty($payeeType) || ! in_array($payeeType, ['ALIPAY_USERID', 'ALIPAY_LOGONID'])) {
throw new PayException('请传入收款账户类型');
}
if (empty($payeeAccount)) {
throw new PayException('请传入转账帐号');
}
if (empty($amount) || bccomp($amount, 0, 2) !== 1) {
throw new PayException('请输入转账金额,且大于0');
}
if (bccomp($amount, Config::TRANS_FEE, 2) !== -1 && empty($remark)) {
throw new PayException('转账金额大于等于' . Config::TRANS_FEE , '必须设置 remark');
}
}
protected function buildData()
{
$signData = [
// 公共参数
'app_id' => $this->appId,
'method' => $this->method,
'format' => $this->format,
'charset' => $this->charset,
'sign_type' => $this->signType,
'timestamp' => $this->timestamp,
'version' => $this->version,
// 业务参数
'biz_content' => $this->getBizContent(),
];
// 移除数组中的空值
$this->retData = ArrayUtil::paraFilter($signData);
}
/**
* 业务请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递
*
* @return string
*/
private function getBizContent()
{
$content = [
'out_biz_no' => $this->trans_no,
'payee_type' => strtoupper($this->payee_type),
'payee_account' => $this->payee_account,
'amount' => $this->amount,
'payer_real_name' => $this->payer_real_name,
'payer_show_name' => $this->payer_show_name,
'payee_real_name' => $this->payee_real_name,
'remark' => $this->remark,
];
$content = ArrayUtil::paraFilter($content);// 过滤掉空值,下面不用在检查是否为空
return json_encode($content, JSON_UNESCAPED_UNICODE);
}
}
<?php
/**
* @author: helei
* @createTime: 2016-07-15 14:56
* @description: 支付宝配置文件 所有支付的配置文件,均需要继承 ConfigInterface 这个接口
* @link https://github.com/helei112g/payment/tree/paymentv2
* @link https://helei112g.github.io/
*/
namespace Payment\Common;
use Payment\Utils\ArrayUtil;
use Payment\Utils\StrUtil;
final class AliConfig extends ConfigInterface
{
// 支付宝的网关
public $getewayUrl;
// 支付宝分配给开发者的应用ID
public $appId;
// 接口名称
public $method;// 参考 定义的常量
// 仅支持JSON
public $format = 'JSON';
// 用于同步通知的地址
public $returnUrl;
// 采用的编码
public $charset = 'UTF-8';
// 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss"
public $timestamp;
// 调用的接口版本,固定为:1.0
public $version = '1.0';
// 合作者身份ID
public $partner;
// 用于rsa加密的私钥文件路径
public $rsaPrivateKey;
// 用于rsa解密的支付宝公钥文件路径
public $rsaAliPubKey;
// 支付宝各类method名称
// wap 支付
const WAP_PAY_METHOD = 'alipay.trade.wap.pay';
// app 支付
const APP_PAY_METHOD = 'alipay.trade.app.pay';
// 即时到账 web支付 新版接口
const PC_PAY_METHOD = 'alipay.trade.page.pay';
// 扫码支付 用户扫商户的二维码
const QR_PAY_METHOD = 'alipay.trade.precreate';
// 条码支付 商户扫用户的二维码
const BAR_PAY_METHOD = 'alipay.trade.pay';
// 统一收单线下交易查询
const TRADE_QUERY_METHOD = 'alipay.trade.query';
// 统一收单交易退款查询 未完成
const REFUND_QUERY_METHOD = 'alipay.trade.fastpay.refund.query';
// 转账情况查询
const TRANS_QUERY_METHOD = 'alipay.fund.trans.order.query';
// 统一收单交易退款接口
const TRADE_REFUND_METHOD = 'alipay.trade.refund';
// 单笔转账到支付宝账户接口
const TRANS_TOACCOUNT_METHOD = 'alipay.fund.trans.toaccount.transfer';
public function __construct(array $config)
{
// 初始化配置信息
try {
$this->initConfig($config);
} catch (PayException $e) {
throw $e;
}
}
/**
* 检查传入的配置文件信息是否正确
* @param array $config
* @throws PayException
* @author helei
*/
private function initConfig(array $config)
{
$config = ArrayUtil::paraFilter($config);// 过滤掉空值,下面不用在检查是否为空
// 初始 支付宝网关地址
$this->getewayUrl = 'https://openapi.alipay.com/gateway.do?';
if (isset($config['use_sandbox']) && $config['use_sandbox'] === true) {
$this->getewayUrl = 'https://openapi.alipaydev.com/gateway.do?';
} else {
$this->useSandbox = false;// 不是沙箱模式
}
// 支付宝分配给开发者的应用ID
if (key_exists('app_id', $config) && is_numeric($config['app_id'])) {
$this->appId = $config['app_id'];
} else {
throw new PayException('缺少支付宝分配给开发者的应用ID,请在开发者中心查看');
}
// 初始 支付宝异步通知地址,可为空
if (key_exists('notify_url', $config)) {
$this->notifyUrl = $config['notify_url'];
}
// 初始 支付宝 同步通知地址,可为空
if (key_exists('return_url', $config)) {
$this->returnUrl = $config['return_url'];
}
// 初始 支付宝 签名方式,可为空
if (key_exists('sign_type', $config) && in_array($config['sign_type'], ['RSA', 'RSA2'])) {
$this->signType = $config['sign_type'];
} else {
throw new PayException('目前支付宝仅支持RSA2和RSA,推荐使用RSA2');
}
// 新版本,需要提供独立的公钥信息。每一个应用,公钥都不相同
if (key_exists('ali_public_key', $config) && (file_exists($config['ali_public_key']) || ! empty($config['ali_public_key']))) {
$this->rsaAliPubKey = StrUtil::getRsaKeyValue($config['ali_public_key'], 'public');
} else {
throw new PayException('请提供支付宝对应的rsa公钥');
}
// 初始 RSA私钥文件 需要检查该文件是否存在
if (key_exists('rsa_private_key', $config) && (file_exists($config['rsa_private_key']) || ! empty($config['ali_public_key']))) {
$this->rsaPrivateKey = StrUtil::getRsaKeyValue($config['rsa_private_key'], 'private');
} else {
throw new PayException('请提供商户的rsa私钥文件');
}
// 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" 需要正确设置时区
$this->timestamp = date('Y-m-d H:i:s', time());
// 初始 合作者身份ID 如果该值为空,则默认为商户签约账号对应的支付宝用户ID
if (key_exists('partner', $config)) {
$this->partner = $config['partner'];
}
// 设置禁止使用的支付方式
if (key_exists('limit_pay', $config) && is_array($config['limit_pay'])) {
$this->limitPay = implode(',', $config['limit_pay']);
}
if (key_exists('return_raw', $config)) {
$this->returnRaw = filter_var($config['return_raw'], FILTER_VALIDATE_BOOLEAN);
}
}
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!