配置
商家账号服务申请很麻烦,为了快速测试 可以用 沙箱测试版 app, 不过目前 只支持 安卓手机
测试的服务,也要实名认证和身份扩展后才可以,也就填写一些个人信息,很简单,这里不做详细介绍
说明
private_key 私钥
private_key 是商家应用私钥,获取方法说明,我是下载 Mac 版的(RSA 签名工具下载地址),生成秘钥的格式应该选 PKCS1 (非 JAVA 使用) , 但我这里一直生成失败,不知道 是不是因为黑苹果的原因 T_T,所以这里我是这样处理的:
-
秘钥格式 先选,PKCS8 (JAVA 适用),点击生成秘钥
-
复制 商户应用私钥,点击标签栏的格式装换,粘贴,点击 转 PKCS1 (非 JAVA 使用) 私钥,生成内容则为 下方配置中 private_key 的值
ali_public_key 公钥
千万要注意 ali_public_key 不是 RSA 签名工具 生成的公钥,而是 支付宝后台应用中的 RSA2 (SHA256) 密钥支付宝公钥
获取方法:
配置文件
config 目录下新建 alipay.php 文件 配置以下内容
<?php
return [
'pay' => [
// APPID
'app_id' => '************',
// 支付宝 支付成功后 主动通知商户服务器地址 注意 是post请求
'notify_url' => 'http://192.168.0.110:9555/api/home/ali_pay_ntify',
// 支付宝 支付成功后 回调页面 get
'return_url' => 'http://192.168.0.110:9528/#/pay_success',
// 公钥(注意是支付宝的公钥,不是商家应用公钥)
'ali_public_key' => '********',
// 加密方式: **RSA2** 私钥 商家应用私钥
'private_key' => '********',
'log' => [ // optional
'file' => '../storage/logs/alipay.log',
'level' => 'info', // 建议生产环境等级调整为 info,开发环境为 debug
'type' => 'single', // optional, 可选 daily.
'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
],
'http' => [
'timeout' => 5.0,
'connect_timeout' => 5.0,
// 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
],
'mode' => 'dev', // optional,设置此参数,将进入沙箱模式
]
];
支付组件
composer require yansongda/pay
二维码生成器
composer require simplesoftwareio/simple-qrcode
控制器
本例 中只简单介绍常用的,手机网站支付、app 支付、扫码支付、退款,更多功能请参考
use Yansongda\Pay\Pay;
use App\Services\OrderService;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
class AliPayController extends Controller
{
// 手机网页支付接口
public function aliPay(Request $request)
{
$aliPayOrder = [
'out_trade_no' => time(),
'total_amount' => $order->total_amount, // 支付金额
'subject' => $request->subject ?? '支付宝手机网页支付' // 备注
];
$config = config('alipay.pay');
$config['return_url'] = $config['return_url'].'?id='.$request->id;
$config['notify_url'] = $config['notify_url'].'?id='.$request->id;
return Pay::alipay($config)->wap($aliPayOrder);
}
// app支付接口
public function aliPayApp(Request $request)
{
$aliPayOrder = [
'out_trade_no' => time(),
'total_amount' => $order->total_amount, // 支付金额
'subject' => $request->subject ?? '默认' // 备注
];
$config = config('alipay.pay');
$config['return_url'] = $config['return_url'].'?id='.$request->id;
return Pay::alipay($config)->app($aliPayOrder);
}
// 支付宝扫码 支付
public function aliPayScan(Request $request)
{
$aliPayOrder = [
'out_trade_no' => time(),
'total_amount' => $order->total_amount, // 支付金额
'subject' => $request->subject ?? '扫码支付' // 备注
];
$config = config('alipay.pay');
$config['return_url'] = $config['return_url'].'?order_guid='.$request->order_guid;
$scan = Pay::alipay($config)->scan($aliPayOrder);
if(empty($scan->code) || $scan->code !== '10000') return false;
$url = $scan->code.'?order_guid='.$request->order_guid;
// 生成二维码
return QrCode::encoding('UTF-8')->size(300)->generate($url);
}
// 支付成功后 支付宝服务通知本项目服务器
// post 请求
// 这里只是大概写一下逻辑,具体的安全防护 自己再去做限制
public function aliPayNtify(Request $request, OrderService $orderService)
{
$order = Order::find($request->id);
// 更新自己项目 订单状态
if(!empty($order)) $orderService->payOrder($order);
}
// 支付宝退款
public function aliPayRefund(Request $request)
{
try {
$payOrder = [
'out_trade_no' => $order->out_trade_no, // 商家订单号
'refund_amount' => $order->total_amount, // 退款金额 不得超过该订单总金额
'out_request_no' => Common::getUuid() // 同一笔交易多次退款标识(部分退款标识)
];
$config = config('alipay.pay');
// 返回状态码 code 10000 成功
$result = Pay::alipay($config)->refund($payOrder);
if (empty($result->code) || $result->code !== '10000') throw new \Exception('请求支付宝退款接口失败');
// 订单改为 已退款状态
// ~~自己商城的订单状态修改逻辑
} catch (\Exception $exception) {
\Log::error($exception->getMessage());
return false;
}
}
}