您现在的位置是: 网站首页> PHP> Laravel Laravel

Laravel 接入AlipaySDK支付宝支付接口

Smile 2020-12-30 19:07:41 PHP Laravel 阅读:3359

简介使用 Laravel7+ 接入支付宝网站移动支付,初次接入者会遇到各种问题和踩各种坑,本文详细记录接入过程中遇到的问题以及解决方案,避免之后接入再次会遇到

1、下载手机网站支付Demo,传送门

2、配置支付应用信息,个人可以先使用官方提供的沙箱应用环境,要上生产环境时改下支付配置即可,沙箱应用配置请参考官方文档,自行配置好

3、在 Laravel 中导入下载好的Demo,打开根目录下的composer.json文件,找到autoload加入Demo存放路径

"autoload": {
    "psr-4": {
        "App\\": "app/"
    },
    "classmap": [
        "database/seeds",
        "database/factories",
        "app/lib/Alipay"//Demo存放路径
    ]
}

保存好之后在项目更目录下运行 composer dump-autoload 命令

4、在config目录下新建 pay.php 配置文件,根据支付应用信息配置如下支付信息

<?php

return [
    'alipay' => 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",

		//编码格式
		'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、接下来注册 Laravel 路由,如下

Route::get('/alipay', 'AlipayController@index')->name('alipay');
Route::any('/notify', 'AlipayController@notify')->name('notify');
Route::any('/result', 'AlipayController@result')->name('result');

注:这里是个采坑点,为避免采坑用 Route::any方式的路由, 因为支付宝服务端请求你的回调接口时notify异步回调使用的是POST方式,result同步回调时用的是GET方式

6、在App\Http\Middleware\VerifyCsrfToken里,将notify异步回调请求路径去除CSRF TOKEN的保护,如下

<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;

class VerifyCsrfToken extends Middleware
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        'notify',
    ];
}

7、在支付控制器正常调起支付

public function index()
{
	//商户订单号,商户网站订单系统中唯一订单号,必填
    $out_trade_no = $_POST['WIDout_trade_no'];

    //订单名称,必填
    $subject = $_POST['WIDsubject'];

    //付款金额,必填
    $total_amount = $_POST['WIDtotal_amount'];

    //商品描述,可空
    $body = $_POST['WIDbody'];

    //超时时间
    $timeout_express="1m";

    //支付宝配置
	$config = config('pay.alipay');

    $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($config);
    $result=$payResponse->wapPay($payRequestBuilder,$config['return_url'],$config['notify_url']);

    return ;
}

8、到这一步你可能会遇到如下错误

Symfony\Component\ErrorHandler\Error\FatalError: Cannot redeclare decrypt() (previously declared in /vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:372) in file vendor/Alipay/aop/AopEncrypt.php on line 51

报错原因:

alipaySDK中定义的Encrypt()/Decrypt()函数与Laravel中定义的Encrypt()/Decrypt()函数重名了

 

解决办法:

修改alipaySDK中定义的函数名称、修改引用的函数名称

 

修改方案:

在官方给的SDK中,一共有需要修改三个文件中的内容:

 

aop/AopEncrypt.php

aop/AopClient.php

lotusphp_runtime/Cookie/Cookie.php

 

在文件中查找encrypt/decrypt替换为alipayEncrypt/alipayDecrypt即可

9、改好之后,再次发起支付请求,你可能会再次遇到错误如下

The each() function is deprecated. This message will be suppressed on further calls

报错原因:

PHP7.2废除了each函数

 

解决办法:

找到AopClient.php文件中的buildRequestForm函数,修改如下

/**
 * 建立请求,以表单HTML形式构造(默认)
 * @param $para_temp 请求参数数组
 * @return 提交表单HTML文本
 */
protected function buildRequestForm($para_temp) {
	
	$sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='".$this->gatewayUrl."?charset=".trim($this->postCharset)."' method='POST'>";
	foreach ($para_temp as $key => $val) {
		if (false === $this->checkEmpty($val)) {
			//$val = $this->characet($val, $this->postCharset);
			$val = str_replace("'","&apos;",$val);
			//$val = str_replace("\"","&quot;",$val);
			$sHtml.= "<input type='hidden' name='".$key."' value='".$val."'/>";
		}
    }

	//submit按钮控件请不要含有name属性
    $sHtml = $sHtml."<input type='submit' value='ok' style='display:none;''></form>";
	
	$sHtml = $sHtml."<script>document.forms['alipaysubmit'].submit();</script>";
	
	return $sHtml;
}

10、至此,你应该可以正常调起支付了,然后在回调函数处理你的订单业务逻辑,如还有问题请留言

很赞哦! (0)

文章评论

    2021-03-29 20:27:07社会王:

    SDK版本:4.10.12.ALL 没有lotusphp_runtime根本就用不了你这个方法

    2021-03-29 20:28:47 站长回复: 并不要求要有lotusphp_runtime这个目录里面的Cookie.php文件哈,只是SDK包里面使用的Encrypt()/Decrypt()函数名和Laravel框架本身的函数名冲突了而已,你只需要把SDK里面的这两个函数名改一下就OK了

站点信息