PHP使用 yansongda/pay 实现支付宝-网页支付功能,转账提现功能

8 篇文章 0 订阅

PHP使用 yansongda/pay 实现支付宝-网页支付功能,转账提现功能

官方文档

https://pay.yansongda.cn/

安装

注意PHP对应版本
composer require yansongda/pay

代码

这里的获取配置方式跟文档有些差别,因为证书地址需要动态配置获取存在一些问题

<?php
/**
 * 支付宝网关
 */

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 需要使用支付宝登录获取

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值