https://pay.yansongda.cn/
注意PHP对应版本
composer require yansongda/pay
这里的获取配置方式跟文档有些差别,因为证书地址需要动态配置获取存在一些问题
/**
* 支付宝网关
*/
use App\Exceptions\ApiException;
use Illuminate\Container\Container;
use Psr\Http\Message\ResponseInterface;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\InvalidParamsException;
use Yansongda\Pay\Pay;
use Yansongda\Pay\Plugin\Alipay\Fund\AccountQueryPlugin;
class AlipayGateway
{
/**
* @return array
*/
public function getConfig(): array
{
return [
'alipay' => [
'default' => [
// 必填-支付宝分配的 app_id
'app_id' => 'xxx',
// 必填-应用私钥 字符串或路径
// 在 https://open.alipay.com/develop/manage 《应用详情->开发设置->接口加签方式》中设置
'app_secret_cert' => 'xxx',
// 必填-应用公钥证书 路径
// 设置应用私钥后,即可下载得到以下3个证书
'app_public_cert_path' => storage_path('app/certificate/alipay/appCertPublicKey_2021004115668591.crt'),
// 必填-支付宝公钥证书 路径
'alipay_public_cert_path' => storage_path('app/certificate/alipay/alipayCertPublicKey_RSA2.crt'),
// 必填-支付宝根证书 路径
'alipay_root_cert_path' => storage_path('app/certificate/alipay/alipayRootCert.crt'),
// 回调地址
'return_url' => 'https://xxx.cn/api/pay/alipay/return',
// 通知地址
'notify_url' => 'https://xxx.cn/api/pay/alipay/notify',
// 选填-第三方应用授权token
'app_auth_token' => '',
// 选填-服务商模式下的服务商 id,当 mode 为 Pay::MODE_SERVICE 时使用该参数
'service_provider_id' => '',
// 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
'mode' => Pay::MODE_NORMAL,
]
],
];
}
/**
* 创建交易(Web端)
*/
public function web($orderNo, $totalAmount, $subject): string
{
$result = Pay::alipay($this->getConfig())->web([
'out_trade_no' => $orderNo,
'total_amount' => $totalAmount,
'subject' => $subject,
]);
return $result->getBody();
}
/**
* 转账/提现
* @param string $orderNo 订单编号
* @param string $totalAmount 总金额
* @param string $payeeIdentity OpenID
* @return array
* @throws ApiException
*/
public function transfer(string $orderNo, string $totalAmount, string $payeeIdentity): array
{
$container = Container::getInstance();
$response = Pay::alipay($this->getConfig(), $container)->transfer([
'out_biz_no' => $orderNo,
'trans_amount' => $totalAmount,
'product_code' => 'TRANS_ACCOUNT_NO_PWD',
'biz_scene' => 'DIRECT_TRANSFER',
'payee_info' => [
'identity' => $payeeIdentity,
'identity_type' => 'ALIPAY_OPEN_ID',
// 'name' => '沙箱环境'
],
]);
// 转换获取数组结果
$result = $response->toArray();
if ($this->success($result)) {
return $result;
}
logger('transfer->', $result);
throw new ApiException(1001, $result['sub_msg']);
}
/**
* 账户查询余额(商家)
* @throws ApiException
*/
public function accountQueryBalance()
{
try {
$params = [
'alipay_user_id' => 'xxx', // 支付宝会员ID (这里填写商家号)
'account_type' => 'ACCTRANS_ACCOUNT', // 查询的账号类型
];
$allPlugins = Pay::alipay($this->getConfig())->mergeCommonPlugins([AccountQueryPlugin::class]);
$response = Pay::alipay($this->getConfig())->pay($allPlugins, $params);
$result = $response->toArray();
if ($this->success($result)) {
return $result['available_amount'];
} else {
throw new ApiException(1001, '账户查询余额错误');
}
} catch (ContainerException | InvalidParamsException $e) {
throw new ApiException(1001, '账户查询余额->错误码: ' . $e->getCode() . '提示: ' . $e->getMessage());
}
}
/**
* 回调处理
* @throws InvalidParamsException
* @throws ContainerException
*/
public function returnCallback(): array
{
$data = Pay::alipay($this->getConfig())->callback(); // 是的,验签就这么简单!
// 信息处理
// 订单号:$data->out_trade_no
// 支付宝交易号:$data->trade_no
// 订单总金额:$data->total_amount
return $data->toArray();
}
/**
* 通知处理
* @return ResponseInterface
*/
public function notifyCallback(): ResponseInterface
{
$alipay = Pay::alipay($this->getConfig());
try {
$data = $alipay->callback(); // 是的,验签就这么简单!
logger('alipay->notifyCallback', $data->toArray());
// 订单逻辑处理
// 请自行对 trade_status 进行判断及其它逻辑进行判断,在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时,支付宝才会认定为买家付款成功。
// 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号;
// 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额);
// 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email);
// 4、验证app_id是否为该商户本身。
// 5、其它业务逻辑情况
} catch (\Exception $e) {
// $e->getMessage();
logger('alipay->notifyCallback:错误提示' . $e->getMessage());
}
return $alipay->success();
}
/**
* 判断结果是否成功
* @param array $response
* @return bool
*/
public function success(array $response): bool
{
if (!empty($response['code']) && $response['code'] == 10000) {
return true;
}
if (empty($response['code']) && empty($response['sub_code'])) {
return true;
}
return false;
}
}
/**
* 支付示例-网页重定向付款
*/
public function pay(Request $request): string
{
// 订单号
$orderNo = '001' . time();
// 金额
$totalAmount = '0.1';
$alipay = new AlipayGateway();
// 网页重定向付款
$result = $alipay->web($orderNo, $totalAmount, '商品001');
return view('pay', ['data' => $result]);
}
/**
* 支付示例-提现/转账
* @throws ApiException
*/
public function transfer(Request $request): array
{
// 订单号
$orderNo = '001' . time();
// 金额(最小金额 0.1)
$totalAmount = '0.1';
$alipay = new AlipayGateway();
$balance = $alipay->accountQueryBalance();
// 余额相等或者 余额大于总金额 则可以转账
if (bccomp($balance, $totalAmount, 1) !== -1) {
// 转账 (自行获取OpenId)
$payeeIdentity = 'xxx'; // openid
return $alipay->transfer($orderNo, $totalAmount, $payeeIdentity);
}
return [
'msg' => '商户账户余额不足, 请联系商家'
];
}
注意1: web 方法需要页面承载返回结果的
form
代码
注意2: OpenId 需要使用支付宝登录获取