Code Monkey home page Code Monkey logo

alipay-sdk-php's Introduction

Alipay SDK for PHP

🐜 支付宝开放平台(又称:蚂蚁金服开放平台)第三方 PHP SDK,基于官方最新版本。

为什么不用官方

官方 SDK 本 SDK 链接
无 Composer 集成,自动加载依赖第三方 PHP 框架 lotusphp 集成 Packagist
代码不严谨,各种 Warning 持续构建,Notice 也不放过
零单元测试 99% 测试覆盖率
代码风格、命名风格鱼龙混杂 PSR1 + PSR2
几乎零 PHPDoc 持续补充中 对比图
异常和错误处理不统一 所有错误都将以异常的形式抛出,确保返回数据可靠 Exceptions
需手动根据接口名拼接请求类名 请求类工厂,根据 API 名直接创建请求类 AlipayRequestFactory
耦合度高,难以升级或替换 几乎完全解耦,任意替换签名 / 密钥 / 响应 甚至 HTTP 客户端 AopClient

主要目的

  • 集成 Composer。
  • 降低 PHP 依赖至 5.4。
  • 整理代码风格使其符合 PSR-1PSR-2
  • 增加单元测试。
  • 兼容 PHP 7.x。
  • 移除官方 API 文档内 已弃用 特性。
  • 移除难以拓展的调试、日志等特性,以便于集成第三方框架和扩展包。
  • 移除编码转换特性,统一使用 UTF-8
  • 其它优化,持续进行中 ...

小试牛刀

如何使用

  1. Composer 安装。

    composer require abbotton/alipay-sdk
  2. 创建 AlipayKeyPair 实例。

    // 通过密钥文件创建(推荐)
    $keyPair = \Alipay\Key\AlipayKeyPair::create(
        __DIR__ . '/private.pem',
        __DIR__ . '/public.pem'
    );
    
    // 通过密钥字符串创建
    $privateKey = '-----BEGIN RSA PRIVATE KEY-----
    // ......
    kXTZhB4nQqZXWFu8R+RdqC6gTh9k2dDz0NlibYSW9xApWRN572M9/n737110Yxa2
    JZX27eBHLqR8aCZcXkADRpe9+yAL9SqErEOMh26nWFtwP5ZugHRf
    -----END RSA PRIVATE KEY-----';
    $publicKey = '-----BEGIN PUBLIC KEY-----
    // ......
    C9ykBV6BfujeeVQ2wUdpxFtI4gW8A4rgqecMvbL/KngU+aChG+W6SGXD8QY0fC4d
    4QIDAQAB
    -----END PUBLIC KEY-----';
    $keyPair = \Alipay\Key\AlipayKeyPair::create($privateKey, $publicKey);

    AlipayKeyPair 用于存储应用私钥、支付宝公钥;两份密钥将分别用于与支付宝服务器通信时,生成请求签名、验证响应签名等。

  3. 创建 AopClient 实例。

    $aop = new \Alipay\AopClient('APP_ID', $keyPair);

    AopClient 通常情况会贯穿整条业务,除非你须要在同一套代码内处理多个商户号/小程序,否则只需在初始化阶段创建一次即可。

  4. 根据业务需要,创建 AlipayRequest 实例。

    $bizContent = [
        'start_time' => '2021-08-01 00:00:00',
        'end_time' => '2021-08-31 23:59:59',
        'type' => 'TRANSFER',
        'page_no' => 1
    ];
    
    // 通过工厂类创建
    $request = (new \Alipay\AlipayRequestFactory)->create('alipay.data.bill.transfer.query', [
        'biz_content' => $bizContent,
        // ...
    ]);
    
    // 直接创建
    $request = (new \Alipay\Request\AlipayRequest())
        ->setApiMethodName('alipay.data.bill.transfer.query')
        ->setBizContent($bizContent);
  5. 发送请求,获得响应数据。

    $result = $aop->execute($request)->getData();

    所有错误(包括但不限于网络通信异常、数据格式异常、支付宝服务器返回的错误)都会被转换为异常,请注意捕捉。

  6. 更多实例,请移步 examples 目录。

    最后,官方 SDK 内 AopClient::pageExecute() 被分离为 pageExecuteUrlpageExecuteFormAopClient::sdkExecute()AopClient::execute() 方法名保持不变,参数和返回值有所改动。

注意事项

  • 请不要依赖任何在官方 SDK 内被标注为 private 的属性,它们可能已在迭代中被修改或废弃。
  • 请不要依赖任何在官方 API 文档内被标注为 已废弃 的特性,它们可能已在迭代中被废弃或移除。
  • 本 SDK 已移除所有编码转换特性;请确保执行上传文件请求时,文件编码为 UTF-8 而非 GBK

实用工具

可执行文件位于 bin 目录下,点此查看 详细说明

其它资源

已知 Issue

OpenSSL 在 Win32 平台需要配置 openssl.cnf 路径,参见 OpenSSL 安装 - PHP 手册

在本 SDK 内,也可通过自定义 $configargs 参数来自定义此文件路径,而不需要配置环境变量;参见 examples/keys/generate.php

目前已知以下方法依赖于此配置文件:

  • 生成密钥对:AlipayKeyPair::generate()
  • 将私钥资源转换为字符串:AlipayPrivateKey::toString()

感谢

alipay-sdk-php's People

Contributors

abbotton avatar wi1dcard avatar xiashaung avatar yifanes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

alipay-sdk-php's Issues

biz_content根本没有组装给curl发送.

我调用alipay.system.oauth.token也没成功.

抛出异常
Setting unknown property: grant_type

代码:

use Alipay\AlipayRequestFactory;


    public function _initialize()
    {
        parent::_initialize();
        $this->keyPair = \Alipay\Key\AlipayKeyPair::create(
            '../x509/app_private_key.pem',
              '../x509/alipay_public_key.pem'
        );
        $this->miniapp = new \Alipay\AopClient('2021002178607904', $this->keyPair);
    }


    public function test(){
        $request = AlipayRequestFactory::create('alipay.system.oauth.token', [
            'grant_type' => 'authorization_code',
            'code'       => 'db83dc4c505d4c82bce5f6720efePX07',
        ]);
        try {
            $data = $this->miniapp->execute($request)->getData();
            print_r($data);
        } catch (\Exception $ex) {
            http_response_code(500);
            dump($ex);
        }
    }

这个code是小程序上生成的,还没使用过的.

AlipayKeyPair示例密钥与官方提供的示例所需密钥不一致

包文档的,没有private.pem与public.pem,我通过密钥字符串填写应用私钥、支付宝公钥创建也是报错

// 通过密钥文件创建(推荐)
$keyPair = \Alipay\Key\AlipayKeyPair::create(
    __DIR__ . '/private.pem',
    __DIR__ . '/public.pem'
);

官方示例地址(普通调用示例(证书)):https://opendocs.alipay.com/open/54/103419/#%E6%99%AE%E9%80%9A%E8%B0%83%E7%94%A8%E7%A4%BA%E4%BE%8B_3

$appCertPath = "应用证书路径(要确保证书文件可读),例如:/home/admin/cert/appCertPublicKey.crt";
$alipayCertPath = "支付宝公钥证书路径(要确保证书文件可读),例如:/home/admin/cert/alipayCertPublicKey_RSA2.crt";
$rootCertPath = "支付宝根证书路径(要确保证书文件可读),例如:/home/admin/cert/alipayRootCert.crt";

官方所需的这三个文件我都有

大佬,我还是有问题.alipay.system.oauth.token

下面代码在1.3.1是正常的.
2.0.2使用会提示参数缺少.

            $keyPair = \Alipay\Key\AlipayKeyPair::create(
                dirname(__FILE__)  . '/../../../../../x509/app_private_key.pem',
                dirname(__FILE__)  . '/../../../../../x509/alipay_public_key.pem'
            );

            $this->miniapp = new \Alipay\AopClient($appid, $keyPair);

            $request = AlipayRequestFactory::create('alipay.system.oauth.token', [
                'grant_type' => 'authorization_code',
                'code'       => $code,
            ]);

            try {
                $data = $this->miniapp->execute($request)->getData();

            } catch (Exception $e){
                throw new Exception('小程序授权code错误,考虑清小程序缓存.');
            }

然后同样,我拦截了AlipayCurlRequester.php的post函数,给curl发送前
加上了
print_r($url);
print_r($params);exit;


1.3.1使用上面代码这里会打印


https://openapi.alipay.com/gateway.do?charset=UTF-8
Array
(
    [grant_type] => authorization_code
    [code] => 1df1b19648bf4436903668d0f1e0UX07
    [app_id] => 2021002178607904
    [version] => 1.0
    [alipay_sdk] => alipay-sdk-php-20180705
    [charset] => UTF-8
    [format] => JSON
    [sign_type] => RSA2
    [method] => alipay.system.oauth.token
    [timestamp] => 2021-10-10 04:34:16
    [notify_url] => 
    [return_url] => 
    [auth_token] => 
    [app_auth_token] => 
    [sign] => MtkaDEDqchyCwApogioC3sGMAOlM/Ff8ArUdh+6ZoUBgYZghieKCD8xZVsF3PYBfCYSC4SAS1MnVoNL9K1tB0kDCwWDgIczwRoeBArDZZaw2Tc8VNb2WJyB8zX/OKNET+Rr5DLsJmMhFjx/FgQFw5cdxwL/sxn+AhnzYRfJmp1024Itwgb4n/jxP8HfHu/xLDl7nNKRawYzMYppalRg5RsjESM5BskQpS+CF6JiLt+yesxA1MepCLTOWIZ1tC8ea/AgYuXI6Jt4Cw8OwmwjLcHiq6D4LoqPPOo1srzLoKdV8Xb5deUZ3L61ZzV2oUJjsd0Ns7MuC09ECBFyJ4y4fMg==
)

而2.0.2同样,这里打印.

https://openapi.alipay.com/gateway.do?charset=UTF-8
Array
(
    [app_id] => 2021002178607904
    [version] => 1.0
    [alipay_sdk] => alipay-sdk-PHP-4.11.14.ALL
    [charset] => UTF-8
    [format] => JSON
    [sign_type] => RSA2
    [method] => alipay.system.oauth.token
    [timestamp] => 2021-10-10 04:28:13
    [notify_url] => 
    [return_url] => 
    [terminal_type] => 
    [terminal_info] => 
    [prod_code] => 
    [auth_token] => 
    [app_auth_token] => 
    [biz_content] => 
    [sign] => EW61o91IdadmXKw/e/CvHt7KioT6SRvW4huZR58hPX756mCroPmCKoYPM8U14es8cgw53iHbWqR+FQNmxfHUIwDbGXTxPVXIa8uCYkZ50CdFuGv522BJ66uGafVfcFvsdKMlSAcxoSyTl42tnzOYpxxMKHsec0D60z9Fom/s/pFJsblR5zQLLyASfnfquDPcuLLzhZ4t40t17ga/ZTR+y/XnNaLJ6FWETqQ7/Gqmx3je1+3R2C3XV2MjQMvRdI+yE9clJ3ZBMU0F099uR9+6ZBmjrUN/S72Zq88V5cvaklzbrmFxJ9YZrsKTq1xrRf2h7VTEa9SLzd6ujIlrjsLPeA==
)

2.0.2参数组装后丢失了,关键的code和grant_type两个参数.

静态方法中是不能调用$this的

AlipayRequestFactory这个工厂类中create是静态方法不能调用$this

 public static function create($classOrApi, $config = [])
    {
        $factory = isset($this) ? $this : new self();  
        if (strpos($classOrApi, '.')) {
            return $factory->createByApi($classOrApi, $config);
        } else {
            return $factory->createByClass($classOrApi, $config);
        }
    }

bizContent未加入到请求参数中

代码:

$aop = new \Alipay\AopClient($appId, $keyPair);
$bizContent = [
    'url_param' => 'pages/goodsDetail/goodsDetail',
    'query_param' => $scene,
    'describe' => 'test',
];
$request = (new \Alipay\Request\AlipayRequest())
    ->setApiMethodName('alipay.open.app.qrcode.create')
    ->setBizContent($bizContent);
$result = $aop->execute($request)->getData();

结果一直报错参数不合法
image
我看了源码发现bizContent未加入请求参数中,之后我手动在alipay-sdk\aop\AopClient.phpbuild 方法里加上bizContent参数,如下

/**
     * 拼接请求参数并签名.
     *
     * @param AlipayRequest $request
     *
     * @return array
     */
    public function build(AlipayRequest $request)
    {
        // 组装系统参数
        $sysParams = [];
        $sysParams['app_id'] = $this->appId;
        $sysParams['version'] = static::API_VERSION;
        $sysParams['alipay_sdk'] = static::SDK_VERSION;

        $sysParams['charset'] = $this->requester->getCharset();
        $sysParams['format'] = $this->parser->getFormat();
        $sysParams['sign_type'] = $this->signer->getSignType();

        $sysParams['method'] = $request->getApiMethodName();
        $sysParams['timestamp'] = $request->getTimestamp();
        $sysParams['notify_url'] = $request->getNotifyUrl();
        $sysParams['return_url'] = $request->getReturnUrl();

        $sysParams['terminal_type'] = $request->getTerminalType();
        $sysParams['terminal_info'] = $request->getTerminalInfo();
        $sysParams['prod_code'] = $request->getProdCode();

        $sysParams['auth_token'] = $request->getAuthToken();
        $sysParams['app_auth_token'] = $request->getAppAuthToken();
        $sysParams['biz_content'] = $request->getBizContent(); // 这里是我加的

        // 转换可能是数组的参数
        if ($request->arrayAsJson) {
            foreach ($sysParams as &$param) {
                if (is_array($param) || is_object($param)) {
                    $param = json_encode($param, JSON_UNESCAPED_UNICODE);
                }
            }
            unset($param);
        }

        // 签名
        $sysParams['sign'] = $this->signer->generateByParams(
            $sysParams,
            $this->keyPair->getPrivateKey()->asResource()
        );

        return $sysParams;
    }

然后就可以正常运行了
image

关于证书问题:error:0906D06C:PEM routines:PEM_read_bio:no start line

解决办法:

$privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" .
    wordwrap($company_pay_account['private_key'], 64, "\n", true) .
    "\n-----END RSA PRIVATE KEY-----";
$publicKey = "-----BEGIN PUBLIC KEY-----\n" .
    wordwrap($company_pay_account['public_key'], 64, "\n", true) .
    "\n-----END PUBLIC KEY-----";

php8.1兼容问题

Alipay\Key\AlipayPrivateKey implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary)

大佬有空更新下.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.