-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit ad4e867
Showing
9 changed files
with
475 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# alipay | ||
一个简单的支付宝sdk,封装了支付宝API,目前只实现了支付相关的以下四个接口: | ||
* alipay.trade.wap.pay | ||
* alipay.trade.page.pay | ||
* alipay.trade.app.pay | ||
* alipay.trade.query | ||
* alipay.trade.refund | ||
|
||
##### 使用方法如下: | ||
``` | ||
$config = [ | ||
// 应用ID,您的APPID(必填) | ||
'app_id' => 'xxxxxxxxxxxx', | ||
// 私钥文件路径(秘钥和秘钥文件路径不能同时为空)( | ||
//'private_key_file_path' => null, | ||
// 公钥文件路径(秘钥和秘钥文件路径不能同时为空) | ||
//'public_key_file_path' => null, | ||
// 商户私钥(秘钥和秘钥文件路径不能同时为空) | ||
'private_key' => 'your-private-key', | ||
// 支付宝公钥(秘钥和秘钥文件路径不能同时为空),查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。 | ||
'public_key' => 'your-public-key', | ||
// 默认异步通知地址(可选配置项:默认为"") | ||
//'notify_url' => 'http://api.test.alipay.net/atinterface/receive_notify.htm', | ||
// 默认同步跳转地址(可选配置项:默认为"") | ||
//'return_url' => '', | ||
// 编码格式(可选配置项,默认为UTF-8) | ||
//'charset' => 'UTF-8', | ||
// 签名方式(可选配置项,默认为RSA2) | ||
//'sign_type'=>'RSA2', | ||
// 支付宝网关(可选配置项,默认为https://openapi.alipay.com/gateway.do) | ||
//'gatewayUrl' => '' | ||
]; | ||
$payment = new Payment($config); | ||
$appOrder = new WebOrder('your-order-number', '1.0', 'order-title', 'order-detail', ''); | ||
$params = $payment->getPayParams($appOrder); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"name": "huangfu/alipay", | ||
"description": "支付宝支付SDK", | ||
"keywords": [ | ||
"alipay", | ||
"alipay-sdk" | ||
], | ||
"require": { | ||
"php":">=5.5.0", | ||
"guzzlehttp/guzzle": "~6.2" | ||
}, | ||
"license": "MIT", | ||
"authors": [ | ||
{ | ||
"name": "huangfu", | ||
"email": "[email protected]" | ||
} | ||
], | ||
"autoload": { | ||
"psr-4": { | ||
"Alipay\\": "src/" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<?php | ||
|
||
namespace Alipay\Payment; | ||
|
||
|
||
class AppOrder extends Order | ||
{ | ||
/** | ||
* AppOrder constructor. | ||
* @param $outTradeNo 商户订单号. | ||
* @param $totalAmount 订单总金额,整形,此处单位为元,精确到小数点后2位,不能超过1亿元 | ||
* @param $subject 订单标题,粗略描述用户的支付目的。 | ||
* @param $body 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元" | ||
* @param $passback_params 公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝只会 | ||
* 在异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝 | ||
*/ | ||
public function __construct($outTradeNo, $totalAmount, $subject, $body, $passback_params) | ||
{ | ||
// 商户订单号. | ||
$this->bizContent['out_trade_no'] = $outTradeNo; | ||
// 订单总金额,整形,此处单位为元,精确到小数点后2位,不能超过1亿元 | ||
$this->bizContent['total_amount'] = $totalAmount; | ||
// 订单标题,粗略描述用户的支付目的。 | ||
$this->bizContent['subject'] = $subject; | ||
// 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元" | ||
$this->bizContent['body'] = $body; | ||
// (推荐使用,相对时间) 该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m | ||
$this->bizContent['timeout_express'] = '1c'; | ||
// 产品标示码,固定值:FAST_INSTANT_TRADE_PAY | ||
$this->bizContent['product_code'] = "FAST_INSTANT_TRADE_PAY"; | ||
/* 公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝只会 | ||
在异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝 */ | ||
$this->bizContent['passback_params'] = json_encode($passback_params); | ||
} | ||
|
||
public function getMethod() | ||
{ | ||
return 'alipay.trade.app.pay'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<?php | ||
/** | ||
* Created by PhpStorm. | ||
* User: huangfu | ||
* Date: 2017/11/13 | ||
* Time: 16:53 | ||
*/ | ||
|
||
namespace Alipay\Payment; | ||
|
||
|
||
abstract class Order | ||
{ | ||
protected $bizContent = []; | ||
|
||
public function getBizContent() | ||
{ | ||
if (!empty($this->bizContent)) { | ||
return json_encode($this->bizContent, JSON_UNESCAPED_UNICODE); | ||
} | ||
return null; | ||
} | ||
|
||
/** | ||
* 获取当前订单的接口名称 | ||
* @return mixed | ||
*/ | ||
public abstract function getMethod(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
<?php | ||
|
||
namespace Alipay\Payment; | ||
|
||
class Payment | ||
{ | ||
//网关 | ||
public $gatewayUrl = "https://openapi.alipay.com/gateway.do"; | ||
//应用ID | ||
public $appId; | ||
//私钥文件路径 | ||
public $rsaPrivateKeyFilePath; | ||
//支付宝公钥文件路径 | ||
public $rsaPublicKeyFilePath; | ||
//app私钥 | ||
public $rsaPrivateKey; | ||
//使用文件读取文件格式,请只传递该值 | ||
public $alipayPublicKey = null; | ||
//支付宝公钥,使用读取字符串格式,请只传递该值 | ||
public $alipayrsaPublicKey; | ||
//api版本 | ||
public $apiVersion = "1.0"; | ||
// 表单提交字符集编码 | ||
public $postCharset = "UTF-8"; | ||
//返回数据格式,仅支持JSON | ||
public $format = "json"; | ||
//签名类型 | ||
public $signType = "RSA2"; | ||
// | ||
public $notifyUrl = ''; | ||
|
||
public $returnUrl = ''; | ||
|
||
public function __construct(array $config) | ||
{ | ||
$this->appId = $config['app_id']; | ||
$this->rsaPrivateKeyFilePath | ||
= isset($config['private_key_file_path']) ? $config['private_key_file_path'] : null; | ||
$this->rsaPublicKeyFilePath | ||
= isset($config['public_key_file_path']) ? $config['public_key_file_path'] : null; | ||
$this->rsaPrivateKey = isset($config['private_key']) ? $config['private_key'] : null; | ||
$this->alipayrsaPublicKey = $config['public_key'] ? $config['public_key'] : null; | ||
$this->notifyUrl = isset($config['notify_url']) ? $config['notify_url'] : ''; | ||
$this->returnUrl = isset($config['return_url']) ? $config['return_url'] : ''; | ||
$this->postCharset = isset($config['charset']) ? $config['charset'] : 'UTF-8'; | ||
$this->signType = isset($config['sign_type']) ? $config['sign_type'] : 'RSA2'; | ||
$this->gatewayUrl = isset($config['gatewayUrl']) ? $config['gatewayUrl'] : "https://openapi.alipay.com/gateway.do"; | ||
} | ||
|
||
/** | ||
* 获取订单支付参数 | ||
* @param $order 订单参数信息 | ||
*/ | ||
public function getPayParams(Order $order) | ||
{ | ||
//组装系统参数 | ||
$sysParams["app_id"] = $this->appId; | ||
$sysParams["version"] = $this->apiVersion; | ||
$sysParams["format"] = $this->format; | ||
$sysParams["sign_type"] = $this->signType; | ||
$sysParams["method"] = $order->getMethod(); | ||
$sysParams["timestamp"] = date("Y-m-d H:i:s"); | ||
$sysParams["terminal_type"] = null; | ||
$sysParams["terminal_info"] = null; | ||
$sysParams["prod_code"] = null; | ||
$sysParams["notify_url"] = $this->notifyUrl; | ||
$sysParams["return_url"] = $this->returnUrl; | ||
$sysParams["charset"] = $this->postCharset; | ||
$sysParams["biz_content"] = $order->getBizContent(); | ||
$sysParams["sign"] = $this->generateSign($sysParams, $this->signType); | ||
return $sysParams; | ||
} | ||
|
||
/** rsaCheckV1 & rsaCheckV2 | ||
* 验证签名 | ||
* 在使用本方法前,必须初始化AopClient且传入公钥参数。 | ||
* 公钥是否是读取字符串还是读取文件,是根据初始化传入的值判断的。 | ||
**/ | ||
public function rsaCheckV1($params, $signType = 'RSA') | ||
{ | ||
$sign = $params['sign']; | ||
$params['sign_type'] = null; | ||
$params['sign'] = null; | ||
return $this->verify($this->getSignContent($params), $sign, $signType); | ||
} | ||
|
||
/** | ||
* 生成待签名字符串 | ||
* @param $params | ||
* @return string | ||
*/ | ||
function getSignContent($params) | ||
{ | ||
ksort($params); | ||
|
||
$stringToBeSigned = ""; | ||
$i = 0; | ||
foreach ($params as $k => $v) { | ||
if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) { | ||
|
||
if ($i == 0) { | ||
$stringToBeSigned .= "$k" . "=" . "$v"; | ||
} else { | ||
$stringToBeSigned .= "&" . "$k" . "=" . "$v"; | ||
} | ||
$i++; | ||
} | ||
} | ||
|
||
unset ($k, $v); | ||
return $stringToBeSigned; | ||
} | ||
|
||
/** | ||
* 生成签名 | ||
* @param $params | ||
* @param string $signType | ||
* @return string | ||
*/ | ||
function generateSign($params, $signType = "RSA") | ||
{ | ||
return $this->sign($this->getSignContent($params), $signType); | ||
} | ||
|
||
function sign($data, $signType = "RSA") | ||
{ | ||
if ($this->checkEmpty($this->rsaPrivateKeyFilePath)) { | ||
$priKey = $this->rsaPrivateKey; | ||
$res = "-----BEGIN RSA PRIVATE KEY-----\n" . | ||
wordwrap($priKey, 64, "\n", true) . | ||
"\n-----END RSA PRIVATE KEY-----"; | ||
} else { | ||
$priKey = file_get_contents($this->rsaPrivateKeyFilePath); | ||
$res = openssl_get_privatekey($priKey); | ||
} | ||
|
||
($res) or die('您使用的私钥格式错误,请检查RSA私钥配置'); | ||
|
||
if ("RSA2" == $signType) { | ||
openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256); | ||
} else { | ||
openssl_sign($data, $sign, $res); | ||
} | ||
|
||
if (!$this->checkEmpty($this->rsaPrivateKeyFilePath)) { | ||
openssl_free_key($res); | ||
} | ||
$sign = base64_encode($sign); | ||
return $sign; | ||
} | ||
|
||
/** | ||
* 校验$value是否非空 | ||
* if not set ,return true; | ||
* if is null , return true; | ||
**/ | ||
function checkEmpty($value) | ||
{ | ||
if (!isset($value)) | ||
return true; | ||
if ($value === null) | ||
return true; | ||
if (trim($value) === "") | ||
return true; | ||
|
||
return false; | ||
} | ||
|
||
|
||
function verify($data, $sign, $signType = 'RSA') | ||
{ | ||
|
||
if ($this->checkEmpty($this->alipayPublicKey)) { | ||
|
||
$pubKey = $this->alipayrsaPublicKey; | ||
$res = "-----BEGIN PUBLIC KEY-----\n" . | ||
wordwrap($pubKey, 64, "\n", true) . | ||
"\n-----END PUBLIC KEY-----"; | ||
} else { | ||
//读取公钥文件 | ||
$pubKey = file_get_contents($this->rsaPublicKeyFilePath); | ||
//转换为openssl格式密钥 | ||
$res = openssl_get_publickey($pubKey); | ||
} | ||
|
||
($res) or die('支付宝RSA公钥错误。请检查公钥文件格式是否正确'); | ||
|
||
//调用openssl内置方法验签,返回bool值 | ||
|
||
if ("RSA2" == $signType) { | ||
$result = (bool)openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256); | ||
} else { | ||
$result = (bool)openssl_verify($data, base64_decode($sign), $res); | ||
} | ||
|
||
if (!$this->checkEmpty($this->alipayPublicKey)) { | ||
//释放资源 | ||
openssl_free_key($res); | ||
} | ||
|
||
return $result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
namespace Alipay\Payment; | ||
|
||
/* 统一收单线下交易查询 */ | ||
class QueryOrder extends Order | ||
{ | ||
/** | ||
* QueryOrder constructor. | ||
* @param $outTradeNo 商户订单号. | ||
*/ | ||
public function __construct($outTradeNo) | ||
{ | ||
// 商户订单号. | ||
$this->bizContentarr['out_trade_no'] = $outTradeNo; | ||
} | ||
|
||
public function getMethod() | ||
{ | ||
// 统一收单线下交易查询 | ||
return 'alipay.trade.query'; | ||
} | ||
} |
Oops, something went wrong.