Laravel5.5 支付宝支付

laravel5.5 支付—— 支付宝

配置

商家账号服务申请很麻烦, 为了快速测试 可以用 沙箱测试版app, 不过目前 只支持 安卓手机

测试的服务,也要实名认证和身份扩展后才可以,也就填写一些个人信息,很简单,这里不做详细介绍

蚂蚁金服开放平台

蚂蚁金服沙箱测试版

说明


private_key 私钥

private_key 是商家应用私钥,获取方法说明,我是下载 Mac版的(RSA签名工具下载地址),生成秘钥的格式应该选 PKCS1(非JAVA使用) ,但我这里一直生成失败,不知道 是不是因为黑苹果的原因T_T,所以这里我是这样处理的:

1.秘钥格式 先选,PKCS8(JAVA适用),点击生成秘钥

2.复制 商户应用私钥,点击标签栏的格式装换, 粘贴,点击 转PKCS1(非JAVA使用)私钥,生成内容则为 下方配置中private_key的值

image
image

ali_public_key 公钥

千万要注意 ali_public_key不是RSA签名工具 生成的公钥,而是 支付宝后台应用中的 RSA2(SHA256)密钥支付宝公钥

获取方法:

1.RSA签名验签工具格式转换中 点击生成公钥文件 复制内容

image

2.进入后台,设置RSA2(SHS256)秘钥应用公钥,粘贴上刚才复制的内容

image

image

3.保存成功后, 点击查看支付宝公钥, 就能获取到支付宝公钥了

image

image

秘钥调试工具


配置文件

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;
        }
    }
}

我的博客

我的掘金

我的简书

Laravel China

我的微信公众号

本作品采用《CC 协议》,转载必须注明作者和本文链接
安静的美男子
本帖由系统于 5年前 自动加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 16
mengdodo

给你个赞

5年前 评论

file

这个我一开始也弄错,博主做个记录挺好的。还有支付宝通知是否要考虑重复通知
public function aliPayNtify(Request $request, OrderService $orderService)

5年前 评论

@lovecn 嗯嗯,这里确实挺坑的

5年前 评论

@lovecn 访问失败后才会重复通知吧,这里我写的只是个大概,细节没有做还

5年前 评论

大神,你的文章对我启发很大,感谢,希望您多出一些精品文章,给我们学习!

5年前 评论

点赞,不错的文章

5年前 评论

不错

大神,学习了

5年前 评论

沙箱环境支付后无法收到服务器通知吗

4年前 评论
猪猪

退款时 'out_request_no' => Common::getUuid() // 同一笔交易多次退款标识(部分退款标识)这个可以不要吗?
而且为什么会报错 Common 未找到呢?

4年前 评论

在这里我说一下我的问题及解决方法,这个坑了我很久,$config['notify_url'] = $config['notify_url'].'?id='.$request->id;在这里我加入id后会导致验签失败,我去除掉后面的id后验签通过,我搞了好久这个问题,但是还是不明白为什么这样会出错吧

4年前 评论

$request->order_guid请问这个是什么

4年前 评论

错误代码 invalid-signature 错误原因: 验签出错,请确认charset参数放在了URL查询字符串中且各参数值使用charset参数指示的字符集编码

4年前 评论
jasonjiang123

支持公钥证书模式吗

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!