实现思路

  • 生成一个二维码,加入要处理的url连接
  • 在用户扫完码后,在对应的脚本中,判断扫码终端,调用相应的支付
  • 若能够扫码之后能唤起相应app,支付宝要用手机网站支付方式微信要使用jsapi支付方式

效果展示



提示: 因为项目即将上线,所以上面的支付二维码连接被我替换了(注意在生成二维码时加入的连接,要带上http协议)

实现步骤

  • 生成二维码

//我的url指向了checkTerrace方法
$url = self::ADMIN_URL . 'params=' . $params;
//ADMIN_URL是生成二维码的url,请替换成自己
  • 处理用户扫码操作(checkTerrace方法)

public function checkTerrace()
{
$pay_type = $this->getPayType(); //该方法使用来判断用户扫码终端的
$params = $this->request->get('params'); //生成二维码url带的参数(看个人需求,我的项目需要额外参数)
$params = $this->desDecode($params); //这里是因为我对参数进行了desc加密,看个人需求
if ($pay_type === 'alipay') { //如果用户是通过支付宝扫码,进行支付宝相关操作
if ($params === false) {
echo "系统错误!,请稍后重试";
exit;
}
$res = $this->createOrder($pay_type, $params);
if (!$res) {
echo "系统错误,请稍后重试";
exit;
}
$this->aliPay($res);
} elseif ($pay_type === 'wechat') { //如果用户是通过微信扫码,进行微信相关操作
if ($params === false) {
echo "系统错误,请稍后重试";
exit;
}
$prepare = $this->wechat($pay_type, $params);
$this->assign('json', $prepare);
return $this->display('wpay.html');
} elseif ($pay_type === false) {
echo "请使用支付宝或微信进行扫码";
exit;
}
}
  • 判断扫码终端
/**
* 判断扫码终端
*
* @return string|boolean
* @date 2021-02-04
*/
private function getPayType()
{
if (strstr($_SERVER['HTTP_USER_AGENT'], 'AlipayClient')) {
return "alipay";
} elseif (strstr($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger')) {
return "wechat";
} else {
return false;
}
}
  • 生成订单
     /**
* 生成订单
*
* @param string $pay_type
* @param json $params
* @return void
* @date 2021-02-04
*/
//这个逻辑就不贴代码了
private function createOrder($pay_type, $params)
{
/*生成订单相关逻辑代码*/
}
  • 支付宝支付
/**
* 唤起支付宝app
*
* @param array $api_params
* @return void
* @date 2021-02-04
*/
private function aliPay($api_params)
{
$config = [
'notify_url' => '异步回调地址',
'is_open_certificate' => true
];
$domain = urlencode($api_params['domain']);
$api = [
'out_trade_no' => $api_params['trade_no'],
'total_amount' => '0.01',
'subject' => '商品标题',
'passback_params' => $domain
];
$pay = new Pay($config);
$res = $pay->driver('alipay')->gateway('wap')->pay($api); //调用支付宝手机网站支付
echo $res;
}
  • 微信支付
/**
* 唤起微信app
*
* @return void
* @date 2021-02-04
*/
public function wechat($pay_type, $params)
{
$opend_id = $this->getOpenId(); //处理微信jsapi支付之前,要先获取用户的openID
if (!$opend_id) {
echo "微信授权失败...";
exit;
}
$api_params = $this->createOrder($pay_type, $params); //用户openID获取成功后才进行订单生产操作
if (!$api_params) {
echo "系统错误,请稍后重试";
exit;
}
$config = ['notify_url' => '微信异步回调地址'];
$api = [
'body' => '我是标题',
'out_trade_no' => $api_params['trade_no'],
'total_fee' => 1,
'openid' => $opend_id,
'attach' => $api_params['domain']
];
$pay = new Pay($config);
$res = $pay->driver('wechat')->gateway('mp')->pay($api); //调用微信jsapi支付
return $res;
}
  • 静默获取openID
/**
* 获取用户的openid
*
* @return void
* @date 2021-02-04
*/
public function getOpenId()
{
if (isset($_SESSION['open_id']) && $_SESSION['open_id']) {
return $_SESSION['open_id'];
}
if (!$this->request->get('code')) {
$redirect_uri = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; //这里授权后微信跳转的地址,要写在订单处理处,否则会造成因为程序跳转到微信授权页面,导致脚本逻辑终止
$redirect_uri = urlencode($redirect_uri);
$url = $this->codeUrl . 'redirect_uri=' . $redirect_uri . '&appid=' . $this->appId . '&scope=snsapi_base&response_type=code&state=STATE#wechat_redirect'; //使用用户静默授权模式(因为我不需要获取用户信息所有就没采用用户手段授权模式)
header("location:{$url}"); //跳转到微信授权页面
} else {
$openidurl = $this->openidUrl . 'appid=' . $this->appId . '&secret=' . $this->appSecret . '&code=' . $this->request->get('code') . '&grant_type=authorization_code';
$data = Http::get($openidurl);
$data = json_decode($data, true);
if ($data['openid']) {
$_SESSION['open_id'] = $data['openid']; //获取到的用户openID存储到session中
} else {
$_SESSION['open_id'] = false;
}
return $_SESSION['open_id'];
}
}
  • 前端轮询判断监听订单支付状态

$(function() {

            $("#code").qrcode({
//jQuery生成二维码
width: 165, //宽度
height: 167, //高度
text: $('input[name="url"]').val()
});
var startTime = Date.parse(new Date())/1000;
//设置定时器
var poll_request = setInterval( function() {
$.ajax({
url: '/company/StoreSetting/checkStatus',
data:{time:startTime},
dataType:'json',
type:'get',
success:function(res) {
if (res.code == 400) {
var result = clearTimer(poll_request, startTime);
if (result) {
var html = `<img src="/Static/images/paybg.png">`+
`<div class="notify" id="notify">`+
`<img src="/Static/images/pay_time_out.png" alt="">`+
`<span class="pay_tip">点击重新获取</span>`+
`</div>`;
$('.qrcode-img').empty();
$('.qrcode-img').append(html);
}
} else if(res.code == 500) {
var html = `<img src="/Static/images/paybg.png">`+
`<div class="notify">`+
`<img src="/Static/images/pay_error.png" alt="">`+
`<span class="pay_tip">已扫码<br>请在手机端操作</span>`+
`</div>`;
$('.qrcode-img').empty();
$('.qrcode-img').append(html);
clearTimer(poll_request, startTime);
} else if(res.code == 200) {
clearInterval(poll_request)
layer.msg("支付成功", {icon:6}, function() {
window.location.reload()
})
// layer.msg("支付成功", {icon:6}, function() { // })
}
}
})
}, 2000);
})
function clearTimer(index, startTime) {
if (((Date.parse(new Date())/1000) - startTime) > 60) {
clearInterval(index)
return 'reload';
}
return false;
}
//刷新二维码
$('.qrcode-img').on("click", '#notify', function() {
$('.qrcode-img').empty()
$("#code").qrcode({
width: 165, //宽度
height: 167, //高度
text: $('input[name="url"]').val()
});
var startTime = Date.parse(new Date())/1000;
var poll_request = setInterval( function() {
$.ajax({
url: '/company/StoreSetting/checkStatus',
data:{time:startTime},
dataType:'json',
type:'get',
success:function(res) {
if (res.code == 400) {
var result = clearTimer(poll_request, startTime);
if (result) {
var html = `<img src="/Static/images/paybg.png">`+
`<div class="notify" id="notify">`+
`<img src="/Static/images/pay_time_out.png" alt="">`+
`<span class="pay_tip">点击重新获取</span>`+
`</div>`;
$('.qrcode-img').empty();
$('.qrcode-img').append(html);
}
} else if(res.code == 500) {
var html = `<img src="/Static/images/paybg.png">`+
`<div class="notify">`+
`<img src="/Static/images/pay_error.png" alt="">`+
`<span class="pay_tip">已扫码<br>请在手机端操作</span>`+
`</div>`;
$('.qrcode-img').empty();
$('.qrcode-img').append(html);
clearTimer(poll_request, startTime);
} else if(res.code == 200) {
clearInterval(poll_request)
layer.msg("支付成功", {icon:6}, function() {
window.location.reload()
})
// layer.msg("支付成功", {icon:6}, function() { // })
}
}
})
}, 2000);
})

前端效果:

  • 用户进入支付页面但是一直为扫码,超过一定时间

  • 用户扫码后一直未进行支付,超过一定时间

只是给大家提供了一个思路,希望能够对需要的人有些帮助

PHP实现一个二维码同时支持支付宝和微信支付的更多相关文章

  1. 公司开发的APP,如何生成一个二维码,供客户下载使用

    1.其实和简单,因为一般的用户使用扫一扫,大多数都是用微信自带的扫一扫工具 而,微信打开的二维码页面,会自动屏蔽apk文件,所以显然把apk的url生成一个二维码,让用户扫一扫就能直接下载,这样是行不 ...

  2. 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码

    详解C#泛型(二)   一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...

  3. 二维码合成,将苹果和安卓(ios和android)合成一个二维码,让用户扫描一个二维码就可以分别下载苹果和安卓的应用

    因为公司推广的原因,没有合适的将苹果和安卓(ios和android)合成一个二维码的工具. 因为这个不难,主要是根据浏览器的UA进行判断,所以就自己开发了一个网站 网站名称叫:好推二维码  https ...

  4. 用Arduino制作一个二维码显示器

    先上图 场景是这样的, 这几天给CS系统做一个微信支付的功能,  但是生成的二维码是在前台的电脑上..不可能让用户跑到前台的电脑上去扫描...然后拿出了N年前买的Arduino 做了一个二维码显示器. ...

  5. 一个二维码如何自动识别是安卓(Android)还是苹果(IOS)

    思考问题: 通常,我们开发一个APP,有Android版本.IOS版本. 但是只有一个二维码?怎么办呢? 怎么让IOS用户扫描二维码下载IOS版本,Android用户扫描二维码下载到Android版本 ...

  6. 用一个二维码做下载地址,自动区分是 ios 还是 android

    用一个二维码做下载地址,自动区分是 ios 还是 android, 甚至区分 iphone  和 ipad. <html> <head> <meta http-equiv ...

  7. 用lua nginx module搭建一个二维码

    用lua nginx module搭建一个二维码(qr code)生成器 作者 vinoca 發布於 2014年10月31日 如果有VPS,或者开源的路由器,安装一个nginx,添加lua-nginx ...

  8. 安卓app和苹果app共用一个二维码

    应项目要求,现在安卓app和苹果app共用一个二维码,对外提供下载: <html> <head> <meta http-equiv="Content-Type& ...

  9. react页面内嵌微信二维码 和 自定义样式 以及 微信网页共用unionId问题

    在react页面内嵌“微信二维码”,实现PC端通过微信扫码进行登录.首先去微信开放平台注册一个账号,创建一个网站应用,提交网站备案审核,获取appid和appsecret:其他开发流程根据微信文档来进 ...

随机推荐

  1. Idea里面远程提交spark任务到yarn集群

    Idea里面远程提交spark任务到yarn集群 1.本地idea远程提交到yarn集群 2.运行过程中可能会遇到的问题 2.1首先需要把yarn-site.xml,core-site.xml,hdf ...

  2. OpenStack (haproxy)

    openstack部署脚本 链接:<https://pan.baidu.com/s/1BTp_tGNC6ZWwVmKkhwivgw > 提取码:jxuz haproxy 官网:< h ...

  3. Cisco动态路由(rip)

    接Cisco静态路由,讨论一下Cisco动态路由. 实验环境布置 命令布置动态路由 Router0: Router>enable Router#configure terminal Router ...

  4. jvm系列五-java内存模型初览(1)

    本文转载自:再有人问你Java内存模型是什么,就把这篇文章发给他. 网上有很多关于Java内存模型的文章,在<深入理解Java虚拟机>和<Java并发编程的艺术>等书中也都有关 ...

  5. NodeMCU学习笔记

    NodeMCU学习笔记 引脚连通 引脚 连通 D3 FLASH按键 D0 模组上的LED D4 芯片的LED FLASH按键 D3引脚已经与开发板上的FLASH按键开关连接 我们可以通过NodeMCU ...

  6. A - 欧拉回路

    欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路.现给定一个图,问是否存在欧拉回路? Input测试输入包含若干测试用例.每个测试用例的第1行给出两个正整数,分别是节点数N ...

  7. [ZJOI2007]仓库建设(斜率dp优化)

    前言 纪念一下我做的第二道斜率优化$dp$题,终于自己能把代码敲出来了,然而有很智障的$bug$,把$i$写成$q[i]$,找了半天QAQ.然后写$dp$公式并优化的能力稍微强了一点(自我感觉良好), ...

  8. POJ 2594 Treasure Exploration 最小可相交路径覆盖

    最小路径覆盖 DAG的最小可相交路径覆盖: 算法:先用floyd求出原图的传递闭包,即如果a到b有路径,那么就加边a->b.然后就转化成了最小不相交路径覆盖问题. 这里解释一下floyd的作用如 ...

  9. poj2923 Relocation

    Description Emma and Eric are moving to their new house they bought after returning from their honey ...

  10. hutool学习总结

    1. 为什么要学习Hutool的使用 Hutool官网 中文写的已经很清楚了 Hutool是一款强力的工具类.封装了工作开发中一些常见的功能操作.避免重复造轮子,使用它大大提高的开发效率. 2. Hu ...