return [ //应用ID,您的APPID。 'app_id' => "", //商户私钥 'merchant_private_key' =>' //异步通知地址,$_SERVER["REQUEST_SCHEME"] => string(4) "http";$_SERVER["HTTP_HOST"] => string(16) "ktgpt.itulan.com"; 'notify_url' => $_SERVER['REQUEST_SCHEME']."://".$_SERVER['HTTP_HOST']."/common/alipay/notify_url", //同步页面跳转 'return_url' => "https://".$_SERVER['HTTP_HOST']."/common/alipay/return_url", //编码格式 支付宝默认UTF-8。 import('alipay.pagepay.service.AlipayTradeService')中查看 'charset' => "UTF-8", //签名方式 默认RSA2。 import('alipay.pagepay.service.AlipayTradeService')中查看 'sign_type'=>"RSA2", //支付宝网关 默认。 import('alipay.pagepay.service.AlipayTradeService')中查看 'gatewayUrl' => "https://openapi.alipay.com/gateway.do", // 'gatewayUrl' => "https://openapi.alipaydev.com/gateway.do",//沙箱模式 //支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。 'alipay_public_key' => "", ]在common模块中写一个alipay类写一个类把支付、退款、查询都放在一起。
<?php
namespace app\common\controller;
use think\Controller;
use think\Db;
use think\Request;
use think\Loader;
use think\Log;
/**
* 支付宝
*/
class Alipay extends Controller{
//生成唯一订单号
public function build_order_no(){
return date('Ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}
//支付宝电脑支付退款 退款用支付宝公钥
//支付宝电脑支付付款 ,显示付款页面
public function payOrder($request){
import('alipay.pagepay.buildermodel.AlipayTradePagePayContentBuilder');
import('alipay.pagepay.service.AlipayTradeService');
$config=config('zhifubao');
//商户订单号,商户网站订单系统中唯一订单号,必填
$out_trade_no = trim($request['out_trade_no']);
//订单名称,必填
$subject = trim($request['trade_name']);
//付款金额,必填
$total_amount = trim($request['total_amount']);
//商品描述,可空
// $body = trim($request->WIDbody);
//构造参数
$payRequestBuilder = new \AlipayTradePagePayContentBuilder();
// $payRequestBuilder->setBody($body);
$payRequestBuilder->setSubject($subject);
$payRequestBuilder->setTotalAmount($total_amount);
$payRequestBuilder->setOutTradeNo($out_trade_no);
$aop = new \AlipayTradeService($config);//加反斜杠
/**
* pagePay 电脑网站支付请求
* @param $builder 业务参数,使用buildmodel中的对象生成。
* @param $return_url 同步跳转地址,公网可以访问
* @param $notify_url 异步通知地址,公网可以访问
* @return $response 支付宝返回的信息
*/
$response = $aop->pagePay($payRequestBuilder,$config['return_url'],$config['notify_url']);
$product_id=$request['cproduct_id'];
if(empty($request['cproduct_id'])){
$product_id=$request['tola_product_id'];
}
if($response){
Log::info('进入支付宝二维码付款页面');
$data['out_trade_no']=$out_trade_no;
$data['money']=$total_amount;
$data['product_id']=$product_id;
$data['status']=-1;
// 客户点击购买进入支付页面后把数据存入数据库
Db::name('statis')->insert($data);
echo json_encode(['status'=>1,'msg'=>'success','data'=>$response]);
}else{
echo json_encode(['status'=>0,'msg'=>'false','orderid'=>$orderid]);
}
}
//同步页面跳转
public function return_url(Request $request){
Log::info('同步页面跳转');
import('alipay.pagepay.service.AlipayTradeService');
$config=config('zhifubao');
$arr=$request->get();//同步是get方式返回数据
$alipaySevice = new \AlipayTradeService($config);//加反斜杠
$result = $alipaySevice->check($arr);
Log::info("同步回调通知返回信息:".json_encode($arr,true));
/* 实际验证过程建议商户添加以下校验。
1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
4、验证app_id是否为该商户本身。
*/
if($result) {
//验证成功
//请在这里加上商户的业务逻辑程序代码
Log::info('同步验证成功');
//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表
//商户订单号
$out_trade_no = htmlspecialchars($arr['out_trade_no']);
//支付宝交易号
$trade_no = htmlspecialchars($arr['trade_no']);
$this->redirect('first/paymentResult');
//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
} else {
//验证失败
echo "验证失败";
}
}
//支付宝支付成功之后异步回调处理,保存数据到数据库,交易号,交易金额,公共参数:授权appid,签名
public function notify_url(Request $request){
import('alipay.pagepay.service.AlipayTradeService');
Log::info('进入notify_url异步回调函数中');
$config=config('zhifubao');
$arr=$request->post();
$arr['fund_bill_list']=htmlspecialchars_decode($arr['fund_bill_list']);
$alipaySevice = new \AlipayTradeService($config);
$result = $alipaySevice->check($arr);
/* 实际验证过程建议商户添加以下校验。
1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
4、验证app_id是否为该商户本身。
*/
if($result) {//验证成功
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//请在这里加上商户的业务逻辑程序代
Log::info('notify_url异步回调处理验证成功');
//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
//获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表
//商户订单号
$out_trade_no = $arr['out_trade_no'];
//支付宝交易号
$trade_no = $arr['trade_no'];
//交易状态
$trade_status = $arr['trade_status'];
//交易金额
$total_amount = $arr['total_amount'];
if($arr['trade_status'] == 'TRADE_SUCCESS') {
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//请务必判断请求时的total_amount与通知时获取的total_fee为一致的
//如果有做过处理,不执行商户的业务程序
//注意:
//退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
// 1,充值消费明细statistics表
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//请务必判断请求时的total_amount与通知时获取的total_fee为一致的
//如果有做过处理,不执行商户的业务程序
//注意:
//付款完成后,支付宝系统发送该交易状态通知
}
//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
echo "success"; //请不要修改或删除
}else {
//验证失败
echo "fail";
Log::info('异步回调处理验证失败');
}
}
//退款
public function refund($request){
import('alipay.pagepay.buildermodel.AlipayTradeRefundContentBuilder');
import('alipay.pagepay.service.AlipayTradeService');
$config=config('zhifubao');
//商户订单号,商户网站订单系统中唯一订单号
$out_trade_no = trim($request['WIDTRout_trade_no']);
//需要退款的金额,该金额不能大于订单金额,必填
$refund_amount = trim($request['WIDTRrefund_amount']);
//退款的原因说明
$refund_reason = trim($request['WIDTRrefund_reason']);
//标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传
// $out_request_no = trim($arr['WIDTRout_request_no']);
//构造参数
$RequestBuilder=new \AlipayTradeRefundContentBuilder();//加反斜杠
$RequestBuilder->setOutTradeNo($out_trade_no);
$RequestBuilder->setRefundAmount($refund_amount);
// $RequestBuilder->setOutRequestNo($out_request_no);
$RequestBuilder->setRefundReason($refund_reason);
$aop = new \AlipayTradeService($config);//加反斜杠
/**
* alipay.trade.refund (统一收单交易退款接口)
* @param $builder 业务参数,使用buildmodel中的对象生成。
* @return $response 支付宝返回的信息
*/
$response = $aop->Refund($RequestBuilder);
//$response返回值 失败,object(stdClass)#19 (6) ["code"] => string(5) "40004" ["msg"] => string(15) "Business Failed" ["sub_code"] => string(19) "ACQ.TRADE_NOT_EXIST" ["sub_msg"] =>string(15) "交易不存在" ["refund_fee"] => string(4) "0.00" ["send_back_fee"] => string(4) "0.00"
//$response返回值,退款成功 ["code"] => string(5) "10000"
// ["msg"] => string(7) "Success"
// ["buyer_logon_id"] => string(14) "lij***@163.com"
// ["buyer_user_id"] => string(16) "2088102616669786"
// ["fund_change"] => string(1) "N"
// ["gmt_refund_pay"] => string(19) "2021-05-11 17:14:11"
// ["out_trade_no"] => string(16) "2021051010210050"
// ["refund_fee"] => string(4) "0.01"
// ["send_back_fee"] => string(4) "0.00"
// ["trade_no"] => string(28) "2021051022001469781454012273"
// }
$res['code']=$response->code;
$res['msg']=$response->msg;
return json_encode($res);
}
}
?>
支付宝支付的时候遇到的,因为php7+以上版本抛弃了each函数导致,找到extend\alipay\aop\AopClient.php:
while (list ($key, $val) = each ($para_temp)) {
改为
foreach ($para_temp as $key => $val) {
1.需http://或者https://格式的完整路径
例:https://您的域名/notify_url.php ,支持ip地址方式。(推荐使用域名)
2.不能加?id=123这类自定义参数
错误示例:https://您的域名/notify_url.php?id=123&test=abc
3.必须外网可以正常访问,这个不难理解,在您的异步地址没有代码逻辑的情况下,直接访问应该是一个空白页面并且http状态是200(不支持http200以外的状态),即不能在本机电脑测试,要到服务器上做测试,同时也要确保外部可以访问该页面。
4,首先支付宝Notify_url 调用的这个控制器Controller,不能有访问权限的问题。我把它继承了Allow控制器,这个控制器必须登录后才能访问,所以肯定是不行的。
1、notify_url:通过 POST 请求的形式将支付结果作为参数通知到商户系统,使用$_POST获取数据
2、return_url:通过 GET 请求的形式,使用$_GET获取数据
3、notify_url是异步通知,异步无法使用Cookie和Session保存数据。return_url是同步页面跳转;
4,notify_url回调地址,支付宝服务器通知商户服务器是否支付成功。支付宝在支付成功后,会带参(比如业务参数类:交易号,交易金额,公共参数:授权appid,签名)来请求你这个地址,服务器告诉你,这一单,我们支付宝收到款了,然后这里肯定有可能会有第三方的恶意请求(伪造请求)。所以你对这些进行验证,然后识别出是支付宝的回调,然后进行业务处理。比如修改订单支付状态。