整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

个人站点申请接入QQ登录的一波三折

ello呀,我是yangyang.在经历多次qq互联创建网站应用来接入qq快速登录审核不过之后,内心已经难受至极,今天给大家分享下接入qq登录的申请流程的一些细节之处,基本能保证大家通过.


细节点

  1. 创建应用填写的信息最好和个人网站备案填写的一致,尤其是备案号,比写成备案服务号了
  2. 一定要在你的网站登录、注册页面 加入 qq登录的图标(具体官网有说明)


如图

  1. 一定一定要在上面的qq登录图标上做接入代码,如果你只是放了按钮,没有接入的话,结果也是审核不过(下面我给大家分享我拿到的一份代码)

<html>
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>互联登录的demo</title>
    <style>
        html,body {
            margin: 0;
            padding: 0;
            height: 100%;
            width: 100%;
        }
        body {
            font-family: sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        button {
            background-color: transparent;
            width: 150px;
            height: 44px;
            border-radius: 32px;
            border: 1px solid #999;
            cursor: pointer;
            font-family: inherit;
        }
        button:hover {
            background-color: #3abcff;
            border-color: #3abcff;
            color: #fff;
        }
        button i {
            display: inline-block;
            vertical-align: middle;
            width: 18px;
            height: 18px;
            -webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+1pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxNyAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMTYtMTItMjFUMTI6MzM6MjYrMDg6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDE4LTA5LTIxVDEwOjQ1OjQ2KzA4OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDE4LTA5LTIxVDEwOjQ1OjQ2KzA4OjAwIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjcxMzlDMDQwQkQ0ODExRTg4ODFGQTcwMkEwQTAyQTQ5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjcxMzlDMDQxQkQ0ODExRTg4ODFGQTcwMkEwQTAyQTQ5IiBkYzpmb3JtYXQ9ImltYWdlL3BuZyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkQ3RDU2OTAwQjU1QjExRTZCQTZEQUY4MDI2NTY4MUExIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkQ3RDU2OTAxQjU1QjExRTZCQTZEQUY4MDI2NTY4MUExIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+kM01ZAAAA/5JREFUeNrcW01IFVEUvi9Ty8zMNAvJMNIMCZFEK108qFZqpFAQWdugRQVWCNW2TZs2rWonBG1EwaCfRYsWBUVQRGIRSUVZmf1ivbRe3+mdgcdrxLlzZ+478w58zGPmvfvu+eacc885cyeWTCaVicRiMS9fywOagFZgI7AGKAWWANPAZ+A1MArcY/z2MrDp/P8NYIJ5pB64AHygv9LAFHAR2BT6/EMioAYYBP5oKu6Gq8CGKBFwlM06GSASQD95nGQCCoDLASueCbKqIokEkPLXQlbewY10EqQQMGBJeQfDjjtIIOCwZeUdnAyCgJjJOoocYC0Oj4FiZV8oMDZi/mMmgywwnMT5LClPUsg5RnYSIUhzQOu8KeImLmBiAafc1uUsyBmjVN5PDIDvV+EwDiwUQAApUA89ntqMAQeEKK/YCg/aDoK7lSzptuYCMP9yHN4FsIIELeugywsbFtAuUHmSNlsusEXJlG22CGgQSkCDLQLqhRJQZysI/uQ0VKIUQp9foVkAlF8uWHmSyrBdYKmSLaVhE1AinICisAmICScgP2wCyoQTUBI2AQnhBMyETcAO4QTsDC0PwBJI5e9LYLVgAiaBauj0IwwL6BGuPAlVqr1av9DoAd5R2e//ecHDwJ8LqNSj7WSEEA+6KXpMRUuOBBYEEfwqVGrzQkGECJjlDtGrIILgvogpT0IrlqdGqRcCelU0Zb/xKqBSOzOSEcZm0yC4R0Vb9pq6QHfECdjlexVA9F+Jw1slswWuI+uh43M/FtCVA8qTdPh1gU6VG9Kh7QJc+X2MQAvMaw+jDHpO61hAY44oT0Jd7FZdF2hXuSVbdQlodjn3JSLKus2zRZcAt8dMJyJCQJ/LuVqtVFj9v7v7lkq1xJ8JT30neP4jGecTWg0RLiedH1N/rY7PXxJOwBWeJ72P8C3jWpFOLZCX9rk/bQPSkHDzH2Krpj7A8Yxr+TouMMmsjTi5Ap+nvsAboXf/E1CcNldy2UHHinVdYJj9vdzl2mmhBJxzmesy4BFwU5cAeuOjco5rNOh7YcrT0lcxx3zpcV5toLvFIYeEEdBndbs8+9d1IcrfpqBtfbs8CiZ6SkSvt1VlMepTvtICHcb9DuC73sefUrOkJ4spMlV3XSbKz9sU9egObbwE2TR7SnK2BzF/o44P3IBebKQNiqOW7/4YF2xNxiMZ3HUpD0sfkDVYWwW4KpwVtgzSe8Zn07PWUAiAxIUXQ526BOi+9EBp5QD7fY3GKpLgHuMEt9qpWHmiUm+dUOVG+3yrgVUqtQljBbDIqxfzOHeB+9pxzCAPyOOJFnP/0KkgyRy/8ufvjGkff7GYx3Y2Z9LRuWEzaWNPQYdZvzHwrwADAG+u/Wg4e38MAAAAAElFTkSuQmCC);
            -webkit-mask-size: cover;
            background-color: #000;
            
        }
        button span {
            display: inline-block;
            vertical-align: middle;
            font-size: 18px;
            margin-left: 5px;
            letter-spacing: 2px;
        }
        button:hover i {
            background-color: #fff;
        }
        #info {
            text-align: center;
        }
        #avatar {
            width: 100px;
            height: 100px;
            border-radius: 100%;
            object-fit: cover;
        }
        #nick {
            font-size: 18px;
            display: block;
            margin: 15px 0;
        }
    </style>
</head>
<body>
    <button id="login" style="display:none"><i></i><span>登录</span></button>
    <div id='info' style="display:none;">
        <img id="avatar" src="https://ui.qzone.com/100" alt="">
        <span id="nick">您好,测试用户</span>
        <button id="signOut"><span>注销</span></button>
    </div>
    <script type="text/javascript" src="//qzonestyle.gtimg.cn/qzone/openapi/qc_loader.js"charset="utf-8">
    </script>
<script>

    var options = {
        appId : 101870587, //这个appId 是这个demo的,业务请使用自己的appid
        //s_url 这个参数业务可以自定,目的是让业务在回调页知道怎么回调到发起登录的页面
        // 换成自己的也行
        redirectURI : 'https://qq-web.cdn-go.cn/connect-demo/latest/callback.html?s_url='+encodeURIComponent(location.href)
    }
    //初始化一下sdk
    QC.init(options);


    //未登录,显示登录按钮
    if(!QC.Login.check()){
        document.getElementById('login').style.display='block'
    //登录态检查通过,获取个人信息
    }else{
        QC.Login.getMe(function(openId,accessToken){
            QC.api("get_user_info").success(function (req) {
                document.getElementById('info').style.display='block'
                // document.getElementById('avatar').src = req.data.nickname;
                document.getElementById('nick').innerText = '您好,'+req.data.nickname;
            })
        })
        
    }   


    var loginBtn =document.getElementById('login')
    var signoutBtn  = document.getElementById('signOut')
    if(window.addEventListener){
        var clicked =false
        loginBtn.addEventListener('click',function(){
            if(clicked){
                cosole.log('防止手抖')
                return;
            }
            clicked=true;
            
            setTimeout(function(){clicked=false},500)
            //通过这个方法来打开登录页
            QC.Login.showPopup(options)
        })
        signoutBtn.addEventListener('click',function(){
            QC.Login.signOut();//注销
            location.reload();//页面刷新下
        })
    }else{
        //TODO: 兼容ie老版本
    }

    
</script>
</body>
</html>
  1. 下载sdk本地调试
  2. 一定记得重新提交,如果审核不过,就删除应用再次创建
  3. 如果还有问题,推荐大家腾讯开放平台的客服:腾讯应用开放平台




接入大致流程(以下内容来自官网)

1.注册开发者

1. 在QQ互联开放平台首页 https://connect.qq.com/ ,点击右上角的“登录”按钮,使用QQ账号登录,如下图所示:

重要提示:
开发者QQ号码一旦注册不能变更,
建议使用公司公共QQ号码而不是员工私人号码注册,以免遇到员工离职等情况造成不必要的麻烦。


2. 登录成功后会跳转到开发者注册页面,在注册页面按要求提交公司或个人的基本资料。下图所示的是公司注册页面:


3.按要求提交资料后,审核人员会进行审核,通过审核即可成为开发者。

网站应用及移动应用接入申请


应用接入前,首先需进行申请,获得对应的appid与appkey,以保证后续流程中可正确对网站与用户进行验证与授权。

1.1 创建应用

开发者注册完成后,点击“应用管理”按钮。


跳转到qq互联管理中心页面,点击创建应用。


选择需要创建的应用类型,我们以网站应用为例:


点击创建网站应用后,按要求完善信息:


  1. 网站回调地址填写规范:https://wiki.connect.qq.com/%E5%9B%9E%E8%B0%83%E5%9C%B0%E5%9D%80%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%8F%8A%E4%BF%AE%E6%94%B9%E6%96%B9%E6%B3%95
  2. 备案信息填写规范:http://www.miitbeian.gov.cn/publish/query/indexFirst.action


网站信息填写完成,点击“创建应用”后,网站应用创建完成,点击“应用管理”,进入管理中心,在管理中心可以查看到网站获取的appid和appkey,如下图所示:


备注:创建移动应用与网站应用步骤方法一致,在此不赘述。

1.2 网站信息完善

点击“应用中心”,应用右侧的“查看”,进入应用详情页面。


应用详情页面可点击“修改”来编辑应用“基本信息”和“平台信息”。



点击“应用接口”可查看已获取的接口,使用QQ登录功能。

客户需求在h5调用扫一扫来识别二维码,经调研发现使用微信sdk是最好的方式。官网的文档(https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html)写的很好,就是太伤肝,坑太多。下面我给大家详细描述一下实现过程。

步骤

1、绑定域名

先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。ip白名单记得也需要配置,不然后端会报错,无法调用接口。

2、引入JS文件

npm方式安装,npm install jweixin-module --save ,uniapp需要建立package.json

var jWeixin = require('jweixin-module')


3、通过config接口注入权限验证配置

wx.config({
 debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
 appId: '', // 必填,公众号的唯一标识
 timestamp: , // 必填,生成签名的时间戳,与后端保持一致
 nonceStr: '', // 必填,生成签名的随机串,与后端保持一致
 signature: '',// 必填,签名,后端返回的值,需要把当前页面的url传递到后端,不然签名会无效
 jsApiList: [] // 必填,需要使用的JS接口列表
});

4、java获取token,ticket,签名

下面的三步一个参数都不能错,不然就很难搞,token和ticket需要缓存起来,有访问次数限制。

  • 获取token
String tokenData =
   "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
       + APPID
       + "&secret="
       + SECRET;
String resp = HttpUtils.sendGet(tokenData);
  • 获取ticket
String ticketUrl =
   "https://api.weixin.qq.com/cgi-bin/ticket/getticket?"
       + "access_token="
       + accessToken
       + "&type=jsapi";
String resp = HttpUtils.sendGet(ticketUrl);
  • 获取签名
String url = ??? // 前端的请求页面
String ticket = String.valueOf(jsonObject.get("ticket"));
String nonceStr = UUID.randomUUID().toString();
String timestamp = Long.toString(System.currentTimeMillis() / 1000);
String string1 =
   new StringBuilder("jsapi_ticket=")
       .append(ticket)
       .append("&noncestr=")
       .append(nonceStr)
       .append("×tamp=")
       .append(timestamp)
       .append("&url=")
       .append(url)
       .toString();
// 得到签名
String signature = encryptSHA(string1);

 /**
 * sha
 */
 private static String encryptSHA(String signStr) {
  StringBuffer hexValue = new StringBuffer();
  try {
  MessageDigest sha = MessageDigest.getInstance("SHA-1");
  byte[] byteArray = signStr.getBytes("UTF-8");
  byte[] md5Bytes = sha.digest(byteArray);
  for (int i = 0; i < md5Bytes.length; i++) {
  int val = ((int) md5Bytes[i]) & 0xff;
  if (val < 16) {
  hexValue.append("0");
  }
  hexValue.append(Integer.toHexString(val));
  }
  } catch (Exception e) {
  e.printStackTrace();
  return "";
  }
  return hexValue.toString();
 }

5、调用扫码

this.$wx.scanQRCode((res) => {this.$u.route('pages/my/device', {serialNo:res.resultStr});

避坑指南

1、通过后端同学获取调用微信sdk所需的签名过程中,需要注意跨域问题;

2、用微信sdk前提必须是微信容器,换句话说就是微信浏览器打开,才能使用微信sdk;

3、如何在开发本地环境去测试微信sdk的调用情况,可以做内网穿透,使用微信开发者工具调试;

4、在微信容器使用微信sdk报错,config报错:config:invalid signature,这一步卡了我很久,严格执行步骤4,可以少走很多弯路;如果你是IOS,请记住SPA不会即时改变url,需要全局缓存页面地址;

5、报错config:fail,invalid url domain,微信公众号接口提前配置好;

最后,祝你好运。

如若转载,请注明出处:开源字节 https://sourcebyte.vip/article/349.html

、支付宝环境准备

1、注册支付宝开放平台

https://open.alipay.com/platform/home.htm 选择支付宝登录就好

2、创建支付应用

这里以网页应用为例

开发者中心-->网页&移动应用-->支付接入 根据要求填写信息




创建完成



注:正式使用是要提交审核通过上线了 才能使用。测试,支付宝为我们提供了沙箱环境。后面演示 使用沙箱环境。

3、开发项设置。

设置加签方式,私钥与支付宝公钥。(私钥公钥很重要)

这里支付宝为我们提供了生成私钥公钥的工具。下载下来使用即可。




这里一定要保存好你的私钥。将公钥复制进去 生成支付宝公钥。



二、开发环境准备

1、沙箱环境

支付宝为方便我们在应用审核过程中进行开发,为大家提供了沙箱测试环境。进入沙箱,系统会默认生成沙箱环境应用,供我们使用。

开发者中心-->研发服务-->沙箱



同样我们需要设置一下秘钥。注意这里的网关是https://openapi.alipaydev.com/gateway.do,和正式环境是有区别的 。

下载一个沙箱环境的支付宝钱包,供开发使用,使用沙箱环境测试,正式的支付宝是操作不了的

2、新建springboot项目

过程省略

3、添加支付宝maven依赖

<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java -->
<dependency>
 <groupId>com.alipay.sdk</groupId>
 <artifactId>alipay-sdk-java</artifactId>
 <version>3.7.110.ALL</version>
</dependency>
​

4、根据文档中心提供的sdk书写支付代码

阿里SDK 项目结构如下,下面我将其整合成了HTML方式。


1>新建阿里配置类文件AlipayConig

packagecom.szz.alipay.config;
​
importjava.io.FileWriter;
importjava.io.IOException;
​
/* *
*类名:AlipayConfig
*功能:基础配置类
*详细:设置帐户有关信息及返回路径
*修改日期:2017-04-05
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
​
publicclassAlipayConfig{
​
//请在这里配置您的基本信息
​
 // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
 publicstaticStringapp_id="2018070560544403";
​
 // 商户私钥,您的PKCS8格式RSA2私钥
 publicstaticStringmerchant_private_key="";
​
 // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
 publicstaticStringalipay_public_key="";
​
 // 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
 publicstaticStringnotify_url="http://工程公网访问地址/alipay.trade.page.pay-JAVA-UTF-8/notify_url.jsp";
​
 // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
 publicstaticStringreturn_url="http://kcjvsv.natappfree.cc/auth";//"http://工程公网访问地址/alipay.trade.page.pay-JAVA-UTF-8/return_url.jsp";
​
 // 签名方式
 publicstaticStringsign_type="RSA2";
​
 // 字符编码格式
 publicstaticStringcharset="utf-8";
​
 // 支付宝网关
 publicstaticStringgatewayUrl="https://openapi.alipay.com/gateway.do";
​
 // 支付宝网关
 publicstaticStringlog_path="C:\\";
​
​
​
 /**
 * 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
 *
 * @param sWord 要写入日志里的文本内容
 */
 publicstaticvoidlogResult(StringsWord) {
 FileWriterwriter=null;
 try{
 writer=newFileWriter(log_path+"alipay_log_"+System.currentTimeMillis() +".txt");
 writer.write(sWord);
 } catch(Exceptione) {
 e.printStackTrace();
 } finally{
 if(writer!=null) {
 try{
 writer.close();
 } catch(IOExceptione) {
 e.printStackTrace();
 }
 }
 }
 }
}
​

2>测试主页面

<!DOCTYPE html>
<htmllang="en">
<head>
 <metacharset="UTF-8">
 <title>支付宝电脑网站支付</title>
 <style>
 * {
 margin: 0;
 padding: 0;
 }
​
 ul, ol{
 list-style: none;
 }
​
 body{
 font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
 sans-serif;
 }
​
 .tab-head{
 margin-left: 120px;
 margin-bottom: 10px;
 }
​
 .tab-content{
 clear: left;
 display: none;
 }
​
 h2{
 border-bottom: solid#02aaf12px;
 width: 200px;
 height: 25px;
 margin: 0;
 float: left;
 text-align: center;
 font-size: 16px;
 }
​
 .selected{
 color: #FFFFFF;
 background-color: #02aaf1;
 }
​
 .show{
 clear: left;
 display: block;
 }
​
 .hidden{
 display: none;
 }
​
 .new-btn-login-sp{
 padding: 1px;
 display: inline-block;
 width: 75%;
 }
​
 .new-btn-login{
 background-color: #02aaf1;
 color: #FFFFFF;
 font-weight: bold;
 border: none;
 width: 100%;
 height: 30px;
 border-radius: 5px;
 font-size: 16px;
 }
​
 #main{
 width: 100%;
 margin: 0auto;
 font-size: 14px;
 }
​
 .red-star{
 color: #f00;
 width: 10px;
 display: inline-block;
 }
​
 .null-star{
 color: #fff;
 }
​
 .content{
 margin-top: 5px;
 }
​
 .contentdt{
 width: 100px;
 display: inline-block;
 float: left;
 margin-left: 20px;
 color: #666;
 font-size: 13px;
 margin-top: 8px;
 }
​
 .contentdd{
 margin-left: 120px;
 margin-bottom: 5px;
 }
​
 .contentddinput{
 width: 85%;
 height: 28px;
 border: 0;
 -webkit-border-radius: 0;
 -webkit-appearance: none;
 }
​
 #foot{
 margin-top: 10px;
 position: absolute;
 bottom: 15px;
 width: 100%;
 }
​
 .foot-ul{
 width: 100%;
 }
​
 .foot-ulli{
 width: 100%;
 text-align: center;
 color: #666;
 }
​
 .note-help{
 color: #999999;
 font-size: 12px;
 line-height: 130%;
 margin-top: 5px;
 width: 100%;
 display: block;
 }
​
 #btn-dd{
 margin: 20px;
 text-align: center;
 }
​
 .foot-ul{
 width: 100%;
 }
​
 .one_line{
 display: block;
 height: 1px;
 border: 0;
 border-top: 1pxsolid#eeeeee;
 width: 100%;
 margin-left: 20px;
 }
​
 .am-header{
 display: -webkit-box;
 display: -ms-flexbox;
 display: box;
 width: 100%;
 position: relative;
 padding: 7px0;
 -webkit-box-sizing: border-box;
 -ms-box-sizing: border-box;
 box-sizing: border-box;
 background: #1D222D;
 height: 50px;
 text-align: center;
 -webkit-box-pack: center;
 -ms-flex-pack: center;
 box-pack: center;
 -webkit-box-align: center;
 -ms-flex-align: center;
 box-align: center;
 }
​
 .am-headerh1{
 -webkit-box-flex: 1;
 -ms-flex: 1;
 box-flex: 1;
 line-height: 18px;
 text-align: center;
 font-size: 18px;
 font-weight: 300;
 color: #fff;
 }
 </style>
</head>
<bodytext=#000000bgColor="#ffffff"leftMargin=0topMargin=4>
<headerclass="am-header">
 <h1>支付宝电脑网站支付体验入口页</h1>
</header>
<divid="main">
 <divid="tabhead"class="tab-head">
 <h2id="tab1"class="selected"name="tab">付 款</h2>
 <h2id="tab2"name="tab">交 易 查 询</h2>
 <h2id="tab3"name="tab">退 款</h2>
 <h2id="tab4"name="tab">退 款 查 询</h2>
 <h2id="tab5"name="tab">交 易 关 闭</h2>
 </div>
 <formname=alipaymentaction=/paymethod=post
 target="_blank">
 <divid="body1"class="show"name="divcontent">
 <dlclass="content">
 <dt>商户订单号 :</dt>
 <dd>
 <inputid="WIDout_trade_no"name="WIDout_trade_no"/>
 </dd>
 <hrclass="one_line">
 <dt>订单名称 :</dt>
 <dd>
 <inputid="WIDsubject"name="WIDsubject"/>
 </dd>
 <hrclass="one_line">
 <dt>付款金额 :</dt>
 <dd>
 <inputid="WIDtotal_amount"name="WIDtotal_amount"/>
 </dd>
 <hrclass="one_line">
 <dt>商品描述:</dt>
 <dd>
 <inputid="WIDbody"name="WIDbody"/>
 </dd>
 <hrclass="one_line">
 <dt></dt>
 <ddid="btn-dd">
 <spanclass="new-btn-login-sp">
 <buttonclass="new-btn-login"type="submit"
 style="text-align: center;">付 款</button>
 </span><spanclass="note-help">如果您点击“付款”按钮,即表示您同意该次的执行操作。</span>
 </dd>
 </dl>
 </div>
 </form>
 <formname=tradequeryaction=/querymethod=post
 target="_blank">
 <divid="body2"class="tab-content"name="divcontent">
 <dlclass="content">
 <dt>商户订单号 :</dt>
 <dd>
 <inputid="WIDTQout_trade_no"name="WIDTQout_trade_no"/>
 </dd>
 <hrclass="one_line">
 <dt>支付宝交易号 :</dt>
 <dd>
 <inputid="WIDTQtrade_no"name="WIDTQtrade_no"/>
 </dd>
 <hrclass="one_line">
 <dt></dt>
 <ddid="btn-dd">
 <spanclass="new-btn-login-sp">
 <buttonclass="new-btn-login"type="submit"
 style="text-align: center;">交 易 查 询</button>
 </span><spanclass="note-help">商户订单号与支付宝交易号二选一,如果您点击“交易查询”按钮,即表示您同意该次的执行操作。</span>
 </dd>
 </dl>
 </div>
 </form>
 <formname=traderefundaction=alipay.trade.refund.jspmethod=post
 target="_blank">
 <divid="body3"class="tab-content"name="divcontent">
 <dlclass="content">
 <dt>商户订单号 :</dt>
 <dd>
 <inputid="WIDTRout_trade_no"name="WIDTRout_trade_no"/>
 </dd>
 <hrclass="one_line">
 <dt>支付宝交易号 :</dt>
 <dd>
 <inputid="WIDTRtrade_no"name="WIDTRtrade_no"/>
 </dd>
 <hrclass="one_line">
 <dt>退款金额 :</dt>
 <dd>
 <inputid="WIDTRrefund_amount"name="WIDTRrefund_amount"/>
 </dd>
 <hrclass="one_line">
 <dt>退款原因 :</dt>
 <dd>
 <inputid="WIDTRrefund_reason"name="WIDTRrefund_reason"/>
 </dd>
 <hrclass="one_line">
 <dt>退款请求号 :</dt>
 <dd>
 <inputid="WIDTRout_request_no"name="WIDTRout_request_no"/>
 </dd>
 <hrclass="one_line">
 <dt></dt>
 <ddid="btn-dd">
 <spanclass="new-btn-login-sp">
 <buttonclass="new-btn-login"type="submit"
 style="text-align: center;">退 款</button>
 </span><spanclass="note-help">商户订单号与支付宝交易号二选一,如果您点击“退款”按钮,即表示您同意该次的执行操作。</span>
 </dd>
 </dl>
 </div>
 </form>
 <formname=traderefundquery
 action=alipay.trade.fastpay.refund.query.jspmethod=post
 target="_blank">
 <divid="body4"class="tab-content"name="divcontent">
 <dlclass="content">
 <dt>商户订单号 :</dt>
 <dd>
 <inputid="WIDRQout_trade_no"name="WIDRQout_trade_no"/>
 </dd>
 <hrclass="one_line">
 <dt>支付宝交易号 :</dt>
 <dd>
 <inputid="WIDRQtrade_no"name="WIDRQtrade_no"/>
 </dd>
 <hrclass="one_line">
 <dt>退款请求号 :</dt>
 <dd>
 <inputid="WIDRQout_request_no"name="WIDRQout_request_no"/>
 </dd>
 <hrclass="one_line">
 <dt></dt>
 <ddid="btn-dd">
 <spanclass="new-btn-login-sp">
 <buttonclass="new-btn-login"type="submit"
 style="text-align: center;">退 款 查 询</button>
 </span><spanclass="note-help">商户订单号与支付宝交易号二选一,如果您点击“退款查询”按钮,即表示您同意该次的执行操作。</span>
 </dd>
 </dl>
 </div>
 </form>
 <formname=tradecloseaction=alipay.trade.close.jspmethod=post
 target="_blank">
 <divid="body5"class="tab-content"name="divcontent">
 <dlclass="content">
 <dt>商户订单号 :</dt>
 <dd>
 <inputid="WIDTCout_trade_no"name="WIDTCout_trade_no"/>
 </dd>
 <hrclass="one_line">
 <dt>支付宝交易号 :</dt>
 <dd>
 <inputid="WIDTCtrade_no"name="WIDTCtrade_no"/>
 </dd>
 <hrclass="one_line">
 <dt></dt>
 <ddid="btn-dd">
 <spanclass="new-btn-login-sp">
 <buttonclass="new-btn-login"type="submit"
 style="text-align: center;">交 易 关 闭</button>
 </span><spanclass="note-help">商户订单号与支付宝交易号二选一,如果您点击“交易关闭”按钮,即表示您同意该次的执行操作。</span>
 </dd>
 </dl>
 </div>
 </form>
 <divid="foot">
 <ulclass="foot-ul">
 <li>支付宝版权所有 2015-2018 ALIPAY.COM</li>
 </ul>
 </div>
</div>
</body>
<scriptlanguage="javascript">
 vartabs=document.getElementsByName('tab');
 varcontents=document.getElementsByName('divcontent');
​
 (functionchangeTab(tab) {
 for(vari=0, len=tabs.length; i<len; i++) {
 tabs[i].onmouseover=showTab;
 }
 })();
​
 functionshowTab() {
 for(vari=0, len=tabs.length; i<len; i++) {
 if(tabs[i] ===this) {
 tabs[i].className='selected';
 contents[i].className='show';
 } else{
 tabs[i].className='';
 contents[i].className='tab-content';
 }
 }
 }
​
 functionGetDateNow() {
 varvNow=newDate();
 varsNow="";
 sNow+=String(vNow.getFullYear());
 sNow+=String(vNow.getMonth() +1);
 sNow+=String(vNow.getDate());
 sNow+=String(vNow.getHours());
 sNow+=String(vNow.getMinutes());
 sNow+=String(vNow.getSeconds());
 sNow+=String(vNow.getMilliseconds());
 document.getElementById("WIDout_trade_no").value= sNow;
 document.getElementById("WIDsubject").value="测试";
 document.getElementById("WIDtotal_amount").value="0.01";
 }
 GetDateNow();
</script>
</html>

3>支付,查询,验签接口

packagecom.szz.alipay.ali;
​
importcom.alipay.api.AlipayApiException;
importcom.alipay.api.request.AlipayTradePagePayRequest;
importcom.alipay.api.request.AlipayTradeQueryRequest;
importcom.szz.alipay.config.AlipayConfig;
importcom.szz.alipay.service.AlipayTradeService;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RestController;
​
importjavax.servlet.http.HttpServletRequest;
importjava.io.UnsupportedEncodingException;
​
/**
* @program admin
* @description: 交易
* @author: szz
* @create: 2019/11/25 16:15
*/
@RestController
publicclassAlipayTrede{
​
 @Autowired
 privateAlipayTradeServicealipayTradeService;
​
 @RequestMapping("/pay")
 publicStringtrade(HttpServletRequestrequest) throwsAlipayApiException, UnsupportedEncodingException{
​
 //设置请求参数
 AlipayTradePagePayRequestalipayRequest=newAlipayTradePagePayRequest();
 alipayRequest.setReturnUrl(AlipayConfig.return_url);
 alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
​
 //商户订单号,商户网站订单系统中唯一订单号,必填
 Stringout_trade_no=request.getParameter("WIDout_trade_no");
 //付款金额,必填
 Stringtotal_amount=request.getParameter("WIDtotal_amount");
 //订单名称,必填
 Stringsubject=request.getParameter("WIDsubject");
 //商品描述,可空
 Stringbody=request.getParameter("WIDbody");
​
 //输出
// out.println(result);
 returnalipayTradeService.pay(out_trade_no,total_amount,subject,body);
 }
​
 @RequestMapping("/query")
 publicStringquery(HttpServletRequestrequest) throwsAlipayApiException, UnsupportedEncodingException{
 //设置请求参数
 AlipayTradeQueryRequestalipayRequest=newAlipayTradeQueryRequest();
​
 //商户订单号,商户网站订单系统中唯一订单号
 Stringout_trade_no=request.getParameter("WIDTQout_trade_no");
 //支付宝交易号
 Stringtrade_no=request.getParameter("WIDTQtrade_no");
 //请二选一设置
​
 alipayRequest.setBizContent("{\"out_trade_no\":\""+out_trade_no+"\","+"\"trade_no\":\""+trade_no+"\"}");
​
​
 returnalipayTradeService.query(out_trade_no,trade_no);
 }
​
 @RequestMapping("/auth")
 publicStringauth(HttpServletRequestrequest) throwsAlipayApiException, UnsupportedEncodingException{
 returnalipayTradeService.auth(request);
 }
}
packagecom.szz.alipay.service;
​
importcom.alipay.api.AlipayApiException;
importcom.alipay.api.AlipayClient;
importcom.alipay.api.DefaultAlipayClient;
importcom.alipay.api.internal.util.AlipaySignature;
importcom.alipay.api.request.AlipayTradePagePayRequest;
importcom.alipay.api.request.AlipayTradeQueryRequest;
importcom.szz.alipay.config.AlipayConfig;
importorg.springframework.stereotype.Service;
​
importjavax.servlet.http.HttpServletRequest;
importjava.io.UnsupportedEncodingException;
importjava.util.HashMap;
importjava.util.Iterator;
importjava.util.Map;
​
/**
* @program admin
* @description: 支付宝支付
* @author: szz
* @create: 2019/11/26 15:23
*/
@Service
publicclassAlipayTradeServiceImplimplementsAlipayTradeService{
​
 /**
 * 获得初始化的AlipayClient
 */
 privatefinalAlipayClientalipayClient=newDefaultAlipayClient(AlipayConfig.gatewayUrl,
 AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json",
 AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
​
​
 /**
 * 订单支付
 *
 * @param outTradeNo 商户订单号,商户网站订单系统中唯一订单号,必填
 * @param totalAmount 付款金额,必填
 * @param subject 订单名称,必填
 * @param desc 商品描述,可空
 * @return
 */
 @Override
 publicStringpay(StringoutTradeNo, StringtotalAmount, Stringsubject, Stringdesc) {
​
 //设置请求参数
 AlipayTradePagePayRequestalipayRequest=newAlipayTradePagePayRequest();
 alipayRequest.setReturnUrl(AlipayConfig.return_url);
 alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
​
​
 alipayRequest.setBizContent("{\"out_trade_no\":\""+outTradeNo+"\","
 +"\"total_amount\":\""+totalAmount+"\","
 +"\"subject\":\""+subject+"\","
 +"\"body\":\""+desc+"\","
 +"\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
​
 //请求
 Stringresult=null;
 try{
 result=alipayClient.pageExecute(alipayRequest).getBody();
 } catch(AlipayApiExceptione) {
 e.printStackTrace();
 }
​
​
 returnresult;
 }
​
 /**
 * 订单查询
 *
 * @param outTradeNo 商户订单号,商户网站订单系统中唯一订单号
 * @param tradeNo 支付宝交易号
 * 请二选一设置
 * @return
 */
 @Override
 publicStringquery(StringoutTradeNo, StringtradeNo) {
​
 //设置请求参数
 AlipayTradeQueryRequestalipayRequest=newAlipayTradeQueryRequest();
​
 alipayRequest.setBizContent("{\"out_trade_no\":\""+outTradeNo+"\","+"\"trade_no\":\""+tradeNo+"\"}");
​
 //请求
 Stringresult=null;
 try{
 result=alipayClient.execute(alipayRequest).getBody();
 } catch(AlipayApiExceptione) {
 e.printStackTrace();
 }
​
 returnresult;
 }
​
 /**
 * 同步验证
 * @param request
 * @return
 */
 publicStringauth(HttpServletRequestrequest) {
​
 //获取支付宝GET过来反馈信息
 Map<String, String>params=newHashMap<String, String>();
 Map<String, String[]>requestParams=request.getParameterMap();
 for(Iterator<String>iter=requestParams.keySet().iterator(); iter.hasNext(); ) {
 Stringname=(String) iter.next();
 String[] values=(String[]) requestParams.get(name);
 StringvalueStr="";
 for(inti=0; i<values.length; i++) {
 valueStr=(i==values.length-1) ?valueStr+values[i]
 : valueStr+values[i] +",";
 }
 //乱码解决,这段代码在出现乱码时使用
 try{
 valueStr=newString(valueStr.getBytes("ISO-8859-1"), "utf-8");
 } catch(UnsupportedEncodingExceptione) {
 e.printStackTrace();
 }
 params.put(name, valueStr);
 }
​
 booleansignVerified=false; //调用SDK验证签名
 try{
 signVerified=AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type);
 } catch(AlipayApiExceptione) {
 e.printStackTrace();
 }
​
 //——请在这里编写您的程序(以下代码仅作参考)——
 if(signVerified) {
 //商户订单号
 Stringout_trade_no=null;
 try{
 out_trade_no=newString(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
 } catch(UnsupportedEncodingExceptione) {
 e.printStackTrace();
 }
​
 //支付宝交易号
 Stringtrade_no=null;
 try{
 trade_no=newString(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
 } catch(UnsupportedEncodingExceptione) {
 e.printStackTrace();
 }
​
 //付款金额
 Stringtotal_amount=null;
 try{
 total_amount=newString(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
 } catch(UnsupportedEncodingExceptione) {
 e.printStackTrace();
 }
​
 System.out.println("trade_no:"+trade_no+"<br/>out_trade_no:"+out_trade_no+"<br/>total_amount:"+total_amount);
 return"trade_no:"+trade_no+"<br/>out_trade_no:"+out_trade_no+"<br/>total_amount:"+total_amount;
 } else{
 System.out.println("验签失败");
 return"验签失败";
 }
 }
}

注:return_url支付成功返回页面,这里必须是外网可以正常访问的页面。

3>运行代码,如下界面



付款




这里我的外网地址访问失效了。

支付宝说明:一切交易以查询结果为准,所以建议回调的地址设置成交易查询结果。交易查询可根据订单号及支付宝订单号查询

可以看到我刚才的支付结果是成功的。