laravel реализует платежную функцию Alipay

PHP Laravel Alipay

причина

Некоторое время назад, поскольку в проекте необходимо реализовать функцию оплаты мобильного веб-сайта Alipay, я написал эту статью для протокола.

 

 

Бэкенд-фреймворк: Laravel 5.5

 

 

Бизнес-функции

Продавцам удобно интегрировать платежную функцию Alipay в мобильное веб-приложение. Продавец вызывает интерфейс веб-платежей, предоставленный Alipay на веб-странице, чтобы активировать платежный модуль в клиенте Alipay, веб-страница продавца переходит к Alipay для завершения платежа, а после завершения платежа возвращается к веб-страницу продавца и, наконец, отобразить результат платежа. Если клиент Alipay не может быть запущен, он автоматически войдет в процесс оплаты на веб-странице через определенный период времени.

 

1. Создайте приложение

Ссылка на сайт:Финансовая открытая платформа Alipay Ant

Уведомление:

  1. Требуется подтвержденная учетная запись Alipay с настоящим именем.
  2. Предприятия или отдельные промышленные и торговые домохозяйства могут подать заявку
  3. Требуется реальная и действующая бизнес-лицензия, а веб-сайт должен быть зарегистрирован через ICP.

Перейдите на открытую платформу Ant Financial -> Центр разработчиков -> Веб-приложение и мобильное приложение. Создавайте приложения по запросу, здесь я создаюВеб/мобильные приложения.

После того, как создание будет завершено, отправьте его для рассмотрения. Большинство приложений необходимо подписать до того, как они могут быть использованы, и договор требует бизнес-лицензии.

 

2. Настройте среду приложения

    

        

После завершения настройки ее можно отправить на проверку. После того, как разработчик нажмет «Отправить на проверку», проверка займет один рабочий день. После того, как приложение успешно переходит в онлайн, состояние становится онлайн, и приложение в этом состоянии может вызывать интерфейс производственной среды.

 

3. Конфигурация вызова интерфейса

В настоящее время существует множество платежных интерфейсов, интегрированных с alipay SDK в laravel. Обычно используются следующие:

OmniPay-laravel:ссылка на github OmniPay-laravel

latrell/alipay:ссылка на github latrell/alipay

...

Из-за нужд проекта здесь я использую родной пакет SDK от alipay.

Сначала загрузите демонстрационную версию PHP:Демо-версия PHP для мобильных платежей на веб-сайте Alipay

Из index.php видно, что демо поддерживает следующие функции

手机网站2.0支付(接口名:alipay.trade.wap.pay)
手机网站2.0订单查询 (接口名:alipay.trade.query)
手机网站2.0订单退款  (接口名:alipay.trade.refund)
手机网站2.0订单退款查询(接口名:alipay.trade.fastpay.refund.query)
手机网站2.0账单下载(接口名:alipay.data.dataservice.bill.downloadurl.query)

Где config.php — файл конфигурации:

<?php
$config = array (    
        //应用ID,您的APPID。
        'app_id' => "",

        //商户私钥,您的原始格式RSA私钥
        'merchant_private_key' => "",
        
        //异步通知地址
        'notify_url' => "",
        //http://工程公网访问地址/alipay.trade.wap.pay-PHP-UTF-8/notify_url.php

        //同步跳转
        'return_url' => "",
        //http://mitsein.com/alipay.trade.wap.pay-PHP-UTF-8/return_url.php
        // jk.mrwangqi.com

        //编码格式
        'charset' => "UTF-8",

        //签名方式
        'sign_type'=>"RSA2",

        //支付宝网关
        'gatewayUrl' => "https://openapi.alipay.com/gateway.do",

        //支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
        'alipay_public_key' => "",
);

配置完成后,修改demo权限
sudo chmod -R 777 alipayDemo

 

Посетите index.php в демо-версии

Таким образом, демо может быть запущено.

 

 

конкретное развитие

Загрузите SDK прямо сейчас:Мобильный сайт Alipay для оплаты PHP SDK

 

1. Знакомство с пакетом SDK

Шаги по внедрению пакета SDK в laravel:

  1. Создайте новую папку libs в app/ и поместите пакет SDK в этот каталог.

2. Найдите файл composer.json в корневом каталоге и добавьте следующую конфигурацию:

"autoload": {  
        "classmap": [  
            "database",  
            "app/libs/alipay" //这里是自定义包的文件位置,我将我项目中的该SDK包命名为alipay 
        ],  
        "psr-4": {  
            "App\\": "app/"  
        }  
    },  

 

3. Выполните следующую команду

composer dump-autoload     //当在包中加入新的类,需要更新autoloader  

 

2. Переместить/Новый файл

Создайте новый каталог wappay в каталоге alipay и создайте два новых каталога, buildermodel и service, в каталоге wappay. Скопируйте файлы wappay/buildermodel/AlipayTradeWapPayContentBuilder.php и wappay/service/AlipayTradeService.php из демонстрационного каталога выше в соответствующие каталоги во вновь созданном wappay в пакете SDK вашего собственного проекта.

AlipayTradeWapPayContentBuilder.php — это инкапсуляция бизнес-параметров демоверсии Alipay платежного интерфейса мобильного веб-сайта Alipay. AlipayTradeService.php — это инкапсуляция бизнес-функции платежного интерфейса демо-версии Alipay мобильного веб-сайта Alipay.

Создайте файл log.txt в каталоге SDK. Хранить файлы как журналы платежей Alipay

 

3. Настроить/ввести пространство имен

Установите пространство имен AlipayTradeWapPayContentBuilder.php и AlipayTradeService.php, я установил

namespace App\libs\alipay\wappay\buildermodel;
namespace App\libs\alipay\wappay\buildermodel;

 

Установите пространства имен для alipay/aop/request/AlipayTradeWapPayRequest.php и alipay/aop/AopClient.php, что я установил:

namespace App\libs\alipay\aop\request;
namespace App\libs\alipay\aop;

 

Внесите два вышеуказанных пространства имен в AlipayTradeWapPayContentBuilder.php:

use App\libs\alipay\aop\request\AlipayTradeWapPayRequest;
use App\libs\alipay\aop\AopClient;

 

Прокомментируйте следующий код в AlipayTradeService.php:

// require_once dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'./../../AopSdk.php';
// require dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'./../../config.php';

 

4. Настроить конфиг (alipay.php)

В приведенной выше демонстрации alipay в качестве файла конфигурации присутствует файл config.php.Здесь этот файл нам не нужен.Мы используем возможности laravel для создания нового alipay.php в каталоге config в каталоге проекта laravel:

return [

            //应用ID,您的APPID。
        'app_id' => "",

        //商户私钥,您的原始格式RSA私钥
        'merchant_private_key' => "",
        
        //异步通知地址
        'notify_url' => "",
        //http://工程公网访问地址/alipay.trade.wap.pay-PHP-UTF-8/notify_url.php

        //同步跳转
        'return_url' => "",
        //http://mitsein.com/alipay.trade.wap.pay-PHP-UTF-8/return_url.php
        // jk.mrwangqi.com

        //编码格式
        'charset' => "UTF-8",

        //签名方式
        'sign_type'=>"RSA2",

        //支付宝网关
        'gatewayUrl' => "https://openapi.alipay.com/gateway.do",

        //支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
        'alipay_public_key' => "",
];

 

5. Соответствует функции модификации конфигурации

Настройте необходимые параметры платежного интерфейса в alipay.php. Ниже мы модифицируем alipay/wappay/service/AlipayTradeService.php:

class AlipayTradeService {

    //支付宝网关地址
    public $gateway_url = "https://openapi.alipay.com/gateway.do";

    //支付宝公钥
    public $alipay_public_key;

    //商户私钥
    public $private_key;

    //应用id
    public $appid;

    //编码格式
    public $charset = "UTF-8";

    public $token = NULL;
    
    //返回数据格式
    public $format = "json";

    //签名方式
    public $signtype = "RSA";

    function __construct(){
        $this->gateway_url = config('alipay.gatewayUrl'); //获得config文件夹下的alipay.php中的gatewayUrl参数,下同。
        $this->appid = config('alipay.app_id');
        $this->private_key = config('alipay.merchant_private_key');
        $this->alipay_public_key = config('alipay.alipay_public_key');
        $this->charset = config('alipay.charset');
        $this->signtype= config('alipay.sign_type');

        if(empty($this->appid)||trim($this->appid)==""){
            throw new Exception("appid should not be NULL!");
        }
        if(empty($this->private_key)||trim($this->private_key)==""){
            throw new Exception("private_key should not be NULL!");
        }
        if(empty($this->alipay_public_key)||trim($this->alipay_public_key)==""){
            throw new Exception("alipay_public_key should not be NULL!");
        }
        if(empty($this->charset)||trim($this->charset)==""){
            throw new Exception("charset should not be NULL!");
        }
        if(empty($this->gateway_url)||trim($this->gateway_url)==""){
            throw new Exception("gateway_url should not be NULL!");
        }

    }
    function AlipayWapPayService($alipay_config) {
        $this->__construct($alipay_config);
    }

    /**
     * alipay.trade.wap.pay
     * @param $builder 业务参数,使用buildmodel中的对象生成。
     * @param $return_url 同步跳转地址,公网可访问
     * @param $notify_url 异步通知地址,公网可以访问
     * @return $response 支付宝返回的信息
     */
    function wapPay($builder,$return_url,$notify_url) {
    
        $biz_content=$builder->getBizContent();
        //打印业务参数
        $this->writeLog($biz_content);
    
        $request = new AlipayTradeWapPayRequest();
    
        $request->setNotifyUrl($notify_url);
        $request->setReturnUrl($return_url);
        $request->setBizContent ( $biz_content );
    
        // 首先调用支付api
        $response = $this->aopclientRequestExecute ($request,true);
        // $response = $response->alipay_trade_wap_pay_response;
        return $response;
    }

     function aopclientRequestExecute($request,$ispage=false) {

        $aop = new AopClient ();
        $aop->gatewayUrl = $this->gateway_url;
        $aop->appId = $this->appid;
        $aop->rsaPrivateKey =  $this->private_key;
        $aop->alipayrsaPublicKey = $this->alipay_public_key;
        $aop->apiVersion ="1.0";
        $aop->postCharset = $this->charset;
        $aop->format= $this->format;
        $aop->signType=$this->signtype;
        // 开启页面信息输出
        $aop->debugInfo=true;
        if($ispage)
        {
            $result = $aop->pageExecute($request,"post");
            echo $result;
        }
        else 
        {
            $result = $aop->Execute($request);
        }
        
        //打开后,将报文写入log文件
        $this->writeLog("response: ".var_export($result,true));
        return $result;
    }
    //请确保项目文件有可写权限,不然打印不了日志。
    function writeLog($text) {
        // $text=iconv("GBK", "UTF-8//IGNORE", $text);
        //$text = characet ( $text );
        file_put_contents ( dirname ( __FILE__ ).DIRECTORY_SEPARATOR."./../../log.txt", date ( "Y-m-d H:i:s" ) . "  " . $text . "\r\n", FILE_APPEND );
    }
}

?>

Другие интерфейсы временно недоступны, поэтому я их спрячу здесь.

 

6. Создайте новый контроллер (AlipayController)

php artisan make:controller AlipayController

 

Поскольку необходимо реализовать оплату через мобильный веб-сайт, необходимо определить платежный интерфейс:

<?php

namespace App\Http\Controllers\User\Alipay;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

use App\libs\alipay\wappay\buildermodel\AlipayTradeWapPayContentBuilder;
use App\libs\alipay\wappay\service\AlipayTradeService;

class AlipayWapController extends Controller {

     /**
      *支付接口
     */
    public function alipayWapPay(Request $request) {
        $out_trade_no = getTradeNOString();          //公共方法生成唯一订单号
        $subject = 'test';                           //数据仅供测试,下同
        $total_amount = 0.01;
        $body = 'test test!';
        $timeout_express="1m";

        $payRequestBuilder = new AlipayTradeWapPayContentBuilder();
        $payRequestBuilder->setBody($body);
        
        $payRequestBuilder->setSubject($subject);
        $payRequestBuilder->setOutTradeNo($out_trade_no);
        $payRequestBuilder->setTotalAmount($total_amount);
       
        $payRequestBuilder->setTimeExpress($timeout_express);
        

        $payResponse = new AlipayTradeService();

        $result=$payResponse->wapPay($payRequestBuilder,config('alipay.return_url'),config('alipay.notify_url'));


    }

     /**
     *支付同步回调接口,在config/alipay.php的return_url参数进行配置

     */
    public function alipayReturn() {
        
    }

    /**
     *支付异步回调接口,在config/alipay.php的notify_url参数进行配置
     */
    public function alipayNotify() {

    }
}

 

7. Определите маршрут

Определение маршрутов платежей и синхронных и асинхронных маршрутов обратного вызова

    Route::group(['prefix' => 'alipay'],function() {
        Route::get('wappay','AlipayWapController@alipayWapPay');
        Route::get('return','AlipayWapController@alipayReturn');
        Route::get('notify','AlipayWapController@alipayNotify');
    });

 

Следует отметить, что синхронная маршрутизация вызывается в форме GET, а асинхронная маршрутизация вызывается в форме POST. При вызове платежного интерфейса будут возникать ошибки CSRF. Теперь проще всего использовать промежуточное ПО laravel, чтобы избежать CSRF, в app/Http. /Добавить маршрутизацию в Middleware/VerifyCsrfToken.php

    protected $except = [
        //
        'alipay/pay',
        'alipay/return',
        'alipay/notify'
    ];

 

8. Изменение конфликтов

В это время платежный интерфейс можно вызвать, указав маршрут, но при вызове будет сообщено о следующей ошибке:

Cannot redeclare Encrypt() (previously declared in .../vendor/laravel/lumen-framework/src/helpers.php:126)
//或:
Cannot redeclare Decrypt() (previously declared in .../vendor/laravel/lumen-framework/src/helpers.php:126)

 

Это связано с тем, что когда Laravel 5 использует Alipay SDK, имена функций шифрования и дешифрования в Laravel и функций шифрования и дешифрования в Alipay SDK, Encrypt()/Decrypt() конфликтуют.

Решение. Просто измените имя функции, определенное в Alipay SDK, и измените имя указанной функции.

Шаги модификации:

Всего в Alipay SDK необходимо изменить три файла:

aop/AopEncrypt.php

aop/AopClient.php

lotusphp_runtime/Cookie/Cookie.php

 

Найдите в файле encrypt/decrypt и замените его на alipayEncrypt/alipayDecrypt.

Примечание: Если сервер находится под Linux, может появиться сообщение об ошибке без разрешения, потому что мы создали новый файл log.txt в пакете SDK и функцию writeLog() в alipay/wappay/service/AlipayTradeService.php. нет разрешения на запись при записи журнала платежей в этот файл, просто дайте ему разрешение.

 

 

Заканчивать

На данный момент реализована функция оплаты мобильного веб-сайта Alipay в Laravel.Если есть какие-либо недостатки, обращайтесь.