基于thinkphp5.0和支付宝面对面扫码支付DEMO制作的扫码支付 今天接口申请下来,下载了官方demo对着调试了一天,终于实现想要的功能,先看图
选择支付宝支付
跳出二维码弹窗
手机支付宝进行扫码支付
支付完成,点击支付完成按钮跳转到订单列表
实现步骤: 1 支付宝接口申请,这个自行申请哦
2 下载官方扫码支付DEMO aopsdkdownload.cn-hangzhou.alipay-pub.aliyun-inc.com/demo/F2FPay… 将其中的f2fpay,aop两个文件夹复制到extend/alipay目录下. 其中的AlipayTradeService.php 我有稍作修改,到时在附件传上来.
3 点击页面的支付按钮后,异步请求二维码
代码语言:javascript复制//发起支付宝支付
public function alipay()
{
if (!request()->isAjax()) {
$this->error('该操作仅支持异步操作');
}
$productId = input('productId',0);
$product = model('Product')->where('id',$productId)->find();
if (empty($product)) {
$this->error('产品不存在');
}
if ($product['status'] != 1) {
$this->error('产品已下架');
}
$outTradeNo = out_trade_no();
$data = [
'notify_url' => url('api/Notify/alipay','',false,true), //回调链接
'return_url' => '',
'out_trade_no' => $outTradeNo, //订单号
'subject' => '爱站SEO '.$product['title'], //产品标题
'total_fee' => $product['cash'],//订单金额,单位为元
'body' => $product['remark'], //产品描述
];
$alipay = new Alipay;
$result = $alipay->qrpay($data);
if(!$result['code']){
return $this->error($result['msg']);
}
//录入订单数据
$orderData = [
'order_num' => $data['out_trade_no'],
// 'prepay_id' => $prepayId,
'product_id' => $productId,
'uid' => session('uid'),
'count' => 1,
'pay_fee' => $data['total_fee'] * 100,
'create_time' => time(),
'paied_time' => 0,
'status' => 1,
];
$res = db('Order')->insert($orderData);
if (!$res) {
$this->error('订单未成功生成');
}
//二维码生成
$qrcodeImg = make_qrcode($result['msg'],$data['out_trade_no']);
return [
'code' => 1,
'msg' => '请用支付宝支付',
'qrcodeImg' => $qrcodeImg, //二维码图片地址
'productInfo' => $product //产品信息
];
}
复制代码
先检查产品是否可用销售,然后生成订单号,调用Alipay支付请求,订单录入后,生成二维码图片,传给前端. Alipay.php 我是放在common/pay/目录下的
代码语言:javascript复制<?php
namespace appcommonpay;
use thinkValidate;
use thinkLog;
/**
* 支付宝扫码支付
*/
class Alipay
{
public function qrpay($data = [])
{
$validate = new Validate([
['out_trade_no','require|alphaNum','订单编号输入错误|订单编号输入错误'],
['total_fee','require|number|gt:0','金额输入错误|金额输入错误|金额输入错误'],
['subject','require','请输入标题'],
['body','require','请输入描述'],
['notify_url','require','异步通知地址不为空'],
]);
if (!$validate->check($data)) {
return ['code'=>0,'msg'=>$validate->getError()];
}
// 支付超时,线下扫码交易定义为5分钟
$timeExpress = "5m";
import('alipay.f2fpay.model.builder.AlipayTradePrecreateContentBuilder', EXTEND_PATH);
import('alipay.f2fpay.service.AlipayTradeService', EXTEND_PATH);
// 创建请求builder,设置请求参数
$qrPayRequestBuilder = new AlipayTradePrecreateContentBuilder();
$qrPayRequestBuilder->setOutTradeNo($data['out_trade_no']);
$qrPayRequestBuilder->setTotalAmount($data['total_fee']);
$qrPayRequestBuilder->setTimeExpress($timeExpress);
$qrPayRequestBuilder->setSubject($data['subject']);
$qrPayRequestBuilder->setBody($data['body']);
// 调用qrPay方法获取当面付应答
$config = config('alipay');
if (!empty($data['notify_url'])) {
$config['notify_url'] = $data['notify_url'];
}
$qrPay = new AlipayTradeService($config);
$qrPayResult = $qrPay->qrPay($qrPayRequestBuilder);
// 根据状态值进行业务处理
switch ($qrPayResult->getTradeStatus()){
case "SUCCESS":
// echo "支付宝创建订单二维码成功:"."<br>---------------------------------------<br>";
$response = $qrPayResult->getResponse();
return ['code'=>1,'msg'=>$response->qr_code];
break;
case "FAILED":
// echo "支付宝创建订单二维码失败!!!"."<br>--------------------------<br>";
return ['code'=>0,'msg'=>'支付宝创建订单二维码失败!!!'];
break;
case "UNKNOWN":
// echo "系统异常,状态未知!!!"."<br>--------------------------<br>";
return ['code'=>0,'msg'=>'系统异常,状态未知!!!'];
break;
default:
return ['code'=>0,'msg'=>'不支持的返回状态,创建订单二维码返回异常!!!'];
break;
}
return ;
}
public function notify_alipay()
{
import('alipay.aop.AopClient');
$config = config('alipay');
$out_trade_no = input('post.out_trade_no');
$transaction_id = input('post.trade_no');
$aop = new AopClient;
$aop->appId = $config['app_id'];
$aop->rsaPrivateKey = $config['merchant_private_key'];
$aop->alipayrsaPublicKey = $config['alipay_public_key'];
$aop->signType = $config['sign_type'];
$result = $aop->rsaCheckV1($_POST,'',$config['sign_type']);
if ($result) {
if(input('trade_status') == 'TRADE_FINISHED' || input('trade_status') == 'TRADE_SUCCESS') {
// 处理支付成功后的逻辑业务
$order = db('Order')->where(['order_num'=>$out_trade_no])->find();
if (!$order) {
Log::write('order not exists');
return 'order not exists';
}
//订单状态错误 1 未付款 其他状态均为已处理的状态
if ($order['status'] != 1) {
Log::write('order is completed:'.$order['status']);
return true;
}
if ($order['pay_fee'] != input('post.total_amount') * 100) {
Log::write('total_amount is error:'.$order['pay_fee'].','.input('post.total_amount'));
return 'total_amount is error';
}
$order['transaction_id'] = $transaction_id;
$order['paied_time'] = time();
$order['status'] = 2;
db('Order')->update($order);
//支付成功的逻辑
return 'success';
}
Log::write('trade_status is error:'.input('trade_status'));
return 'fail';
}
Log::write('sign verify is error:'.var_export($_POST));
return 'fail';
}
}
复制代码
主要有qrpay二维码扫描支付的请求,notify_alipay接收异步通知的处理逻辑 这里用到的接口配置,我是放在/application/extra/alipay.php 下面
代码语言:javascript复制<?php
return [
//签名方式,默认为RSA2(RSA2048)
'sign_type' => "RSA2",
//支付宝公钥
'alipay_public_key' => "",
//商户私钥
'merchant_private_key' => "",
//编码格式
'charset' => "UTF-8",
//支付宝网关
'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
//应用ID
'app_id' => "",
//异步通知地址,只有扫码支付预下单可用
'notify_url' => "http://www.baidu.com",
//最大查询重试次数
'MaxQueryRetry' => "10",
//查询间隔
'QueryDuration' => "3",
//日志文件
'log_file' => RUNTIME_PATH.'/log/'.date('Ym').'/'.date('d').'.log',
];
复制代码