JAVA实现的微信扫描二维码支付
吐槽一下
支付项目采用springMvc+Dubbo架构实现,只对外提供接口。
话说,为什么微信支付比支付宝来的晚了那么一点,一句话,那一阵挺忙的,然后就没有时间整理,最近做完支付宝支付,顺便也把微信支付的也整理一下。
这里再吐槽一下,微信支付的DEMO基本为零,很多代码都是从网上查找的(也可能我么有仔细找API)。
前期酝酿准备
扫码支付,目前来说个人是不可以申请的,包括现在支付宝的即时到帐个人相关业务也取消了。所以这里必须有一个微信支付商户平台,具体怎么申请的,我也不清楚,只是拿来用的。
商户平台是要配合绑定微信公众账号使用的,具体操作申请下来已经绑定了,这里你也只管用就是了。
什么是扫码支付?
场景介绍
用户扫描商户展示在各种场景的二维码进行支付。
步骤1:商户根据微信支付的规则,为不同商品生成不同的二维码(如图6.1),展示在各种场景,用于用户扫描购买。
步骤2:用户使用微信“扫一扫”(如图6.2)扫描二维码后,获取商品支付信息,引导用户完成支付(如图6.3)。


支付二维码
图6.1 支付二维码
打开微信扫一扫二维码
图6.2 打开微信扫一扫二维码
确认支付页面
图6.3 确认支付页面
步骤(3):用户确认支付,输入支付密码(如图6.4)。
步骤(4):支付完成后会提示用户支付成功(如图6.5),商户后台得到支付成功的通知,然后进行发货处理。
用户确认支付,输入密码
图6.4 用户确认支付,输入密码
支付成功提示
图6.5 支付成功提示

如何集成到项目中去?
ConfigUtil参数配置:
import java.util.Map;import java.util.ResourceBundle;import java.util.SortedMap;import java.util.TreeMap;/*** 相关配置参数* 创建者 张志朋* 创建时间 2016年9月28日**/public class ConfigUtil {/*** 服务号相关信息*/public final static String APP_ID = "2016";//服务号的应用IDpublic final static String APP_SECRET = "2016";//服务号的应用密钥public final static String TOKEN = "weixinCourse";//服务号的配置tokenpublic final static String MCH_ID = "2016";//商户号public final static String API_KEY = "2016";//API密钥public final static String SIGN_TYPE = "MD5";//签名加密方式public final static String CERT_PATH = "apiclient_cert.p12";//微信支付证书存放路径地址static ResourceBundle resource = ResourceBundle.getBundle("config");//微信支付统一接口的回调actionpublic final static String NOTIFY_URL = resource.getString("WEIXIN_NOTIFY_URL");/*** 微信基础接口地址*///获取token接口(GET)public final static String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";//oauth2授权接口(GET)public final static String OAUTH2_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";//刷新access_token接口(GET)public final static String REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";// 菜单创建接口(POST)public final static String MENU_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";// 菜单查询(GET)public final static String MENU_GET_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";// 菜单删除(GET)public final static String MENU_DELETE_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";/*** 微信支付接口地址*///微信支付统一接口(POST)public final static String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信退款接口(POST)public final static String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";//订单查询接口(POST)public final static String CHECK_ORDER_URL = "https://api.mch.weixin.qq.com/pay/orderquery";//关闭订单接口(POST)public final static String CLOSE_ORDER_URL = "https://api.mch.weixin.qq.com/pay/closeorder";//退款查询接口(POST)public final static String CHECK_REFUND_URL = "https://api.mch.weixin.qq.com/pay/refundquery";//对账单接口(POST)public final static String DOWNLOAD_BILL_URL = "https://api.mch.weixin.qq.com/pay/downloadbill";//短链接转换接口(POST)public final static String SHORT_URL = "https://api.mch.weixin.qq.com/tools/shorturl";//接口调用上报接口(POST)public final static String REPORT_URL = "https://api.mch.weixin.qq.com/payitil/report";public static void commonParams(SortedMap<Object, Object> packageParams){// 账号信息String appid = ConfigUtil.APP_ID; // appidString mch_id = ConfigUtil.MCH_ID; // 商业号// 生成随机字符串String currTime = PayCommonUtil.getCurrTime();String strTime = currTime.substring(8, currTime.length());String strRandom = PayCommonUtil.buildRandom(4) + "";String nonce_str = strTime + strRandom;packageParams.put("appid", appid);// 公众账号IDpackageParams.put("mch_id", mch_id);// 商户号packageParams.put("nonce_str", nonce_str);// 随机字符串}/*** 该接口主要用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),减小二维码数据量,提升扫描速度和精确度。* @Author 张志朋* @param urlCode void* @Date 2016年10月26日* 更新日志* 2016年10月26日 张志朋 首次创建**/@SuppressWarnings("rawtypes")public static void shorturl(String urlCode){try {String key = ConfigUtil.API_KEY; // keySortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();ConfigUtil.commonParams(packageParams);packageParams.put("long_url", urlCode);// URL链接String sign = PayCommonUtil.createSign("UTF-8", packageParams, key);packageParams.put("sign", sign);// 签名String requestXML = PayCommonUtil.getRequestXml(packageParams);String resXml = HttpUtil.postData(ConfigUtil.SHORT_URL, requestXML);Map map = XMLUtil.doXMLParse(resXml);String returnCode = (String) map.get("return_code");if("SUCCESS".equals(returnCode)){String resultCode = (String) map.get("return_code");if("SUCCESS".equals(resultCode)){urlCode = (String) map.get("short_url");}}} catch (Exception e) {e.printStackTrace();}}
参数必填项 APP_ID 和APP_SECRET 是从微信公众号里面获取的,而MCH_ID和API_KEY是从商户平台获取的。CERT_PATH 证书可选,但是如果做退款接口必须要使用证书。NOTIFY_URL 为回调地址,自定义路径,但是一定要微信平台可以调用到你的url。
如何生成二维码订单?
文档有详细的参数说明,具体生成需要xml解析,这里就不放了,好多的说,有需要的可以留言。
支付回调:
/*** 二维码支付* 创建者 张志朋* 创建时间 2016年10月31日**/@Controller@RequestMapping(value = "weixin")public class WeixinPayController {@Autowiredprivate IWeixinPayService weixinpayBack;/*** 微信支付回调* @Author 张志朋* @param request* @param response* @throws Exception void* @Date 2016年9月28日* 更新日志* 2016年9月28日 张志朋 首次创建**/@SuppressWarnings({ "unchecked", "rawtypes" })@RequestMapping(value = "pay")public void weixin_notify(HttpServletRequest request, HttpServletResponse response) throws Exception {LogUtil.info("支付成功回调");// 读取参数InputStream inputStream = request.getInputStream();StringBuffer sb = new StringBuffer();String s;BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));while ((s = in.readLine()) != null) {sb.append(s);}in.close();inputStream.close();// 解析xml成mapMap<String, String> m = new HashMap<String, String>();m = XMLUtil.doXMLParse(sb.toString());// 过滤空 设置 TreeMapSortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();Iterator it = m.keySet().iterator();while (it.hasNext()) {String parameter = (String) it.next();String parameterValue = m.get(parameter);String v = "";if (null != parameterValue) {v = parameterValue.trim();}packageParams.put(parameter, v);}// 账号信息String key = ConfigUtil.API_KEY; // key// 判断签名是否正确if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) {// ------------------------------// 处理业务开始// ------------------------------String resXml = "";if ("SUCCESS".equals((String) packageParams.get("result_code"))) {// 这里是支付成功String orderNo = (String) packageParams.get("out_trade_no");String attach = (String) packageParams.get("attach");//回调K12LogUtil.info(attach+"(订单号:"+orderNo+"付款成功)");// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";weixinpayBack.updateAccOrder(orderNo);} else {LogUtil.info("支付失败,错误信息:" + packageParams.get("err_code"));resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";}// ------------------------------// 处理业务完毕// ------------------------------BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());out.write(resXml.getBytes());out.flush();out.close();} else {LogUtil.info("通知签名验证失败");}}}
大体就这个样子,后续的可能就是安全优化了。涉及到钱可不是小问题。
原文地址:http://blog.52itstyle.com/archives/180
JAVA实现的微信扫描二维码支付的更多相关文章
- 微信连WiFi关注公众号流程更新 解决ios微信扫描二维码不关注就能上网的问题
前几天鼓捣了一下微信连WiFi功能,设置还蛮简单的,但ytkah发现如果是ios版微信扫描微信连WiFi生成的二维码不用关注公众号就可以直接上网了,而安卓版需要关注公众号才能上网,这样就少了很多ios ...
- 关于微信扫描二维码下载apk文件的细节设计
微信使用的人数越来越多,渐渐的用户形成了一种习惯,扫描二维码的时候,也会打开微信去扫描,但是微信不支持第三方的链接下载,有些厂商已经发现了这一特点,所以在使用二维码下载自家的app时,会做一个提示,引 ...
- 微信扫描二维码安卓弹出默认浏览器(苹果打开App Store)打开下载链接
使用微信推广的用户经常都会遇到推广链接被拦截导致无法下载app的情况,此时用户在微信中打开会提示“ 已停止访问该网页 ”.这对于使用微信营销的商家来说就很不友好且损失非常大,因为用户是不知道为什么打不 ...
- 微信扫描二维码跳转手机默认浏览器打开下载app的链接是怎么实现的
此方法可以实现微信内置浏览器跳转到手机其它浏览器,现在网上其它的方法都只是一个页面,让访问者自己手动点右上角浏览器打开,而这个不同,是可以直接自动跳转的. <?php error_reporti ...
- 实现手机扫描二维码页面登录,类似web微信-第一篇,业务分析
转自:http://www.cnblogs.com/fengyun99/p/3541249.html 关于XMPP组件的文章,先休息两天,好歹已经完整的写了一份. 这两天,先实现一套关于web微信扫描 ...
- 手机扫描二维码下载APP,根据操作系统不同自动下载
Android和IOS手机扫描二维码下载APP,根据OS不同,自动处理相应下载操作.IOS自动跳转至AppStore应用下载页,Android自动下载应用的apk包. <script type= ...
- java实现微信支付宝等多个支付平台合一的二维码支付(maven+spring springmvc mybatis框架)
首先申明,本人实现微信支付宝等支付平台合多为一的二维码支付,并且实现有效时间内支付有效,本人采用的框架是spring springmvc mybatis 框架,maven管理.其实如果支付,不需要my ...
- 用c#开发微信 (20) 微信登录网站 - 扫描二维码登录
像京东,一号店等网站都实现了用微信来登录的功能,就是用手机上的微信扫一扫网站上的二维码,微信上确认后,即可自动用微信的帐号登录网站. 1 创建网站应用 在微信开放平台创建一个网站应用 https:// ...
- 实现手机扫描二维码页面登录,类似web微信-第二篇,关于二维码的自动生成
转自:http://www.cnblogs.com/fengyun99/p/3541251.html 接上一章,我们已经基本把业务逻辑分析清楚了 下面我们第一步,实现二维码的web动态生成. 页面的二 ...
随机推荐
- MyBatis学习总结(六)——调用存储过程
一.提出需求 查询得到男性或女性的数量, 如果传入的是0就女性否则是男性 二.准备数据库表和存储过程 1 create table p_user( 2 id int primary key auto_ ...
- SQLServer清空数据库中所有的表并且ID自动归0
exec sp_MSforeachtable 'Truncate Table ?'
- CAS原子锁 高效自旋无锁的正确用法
"atomic_lock.h" #pragma once #ifndef _atomic_lock_h_include_ #define _atomic_lock_h_includ ...
- @@IDENTITY与SCOPE_IDENTITY()
在一条 INSERT.SELECT INTO 或大容量复制语句完成后,@@IDENTITY 中包含语句生成的最后一个标识值.如果语句未影响任何包含标识列的表,则 @@IDENTITY 返回 NULL. ...
- 使用SQL Server Audit记录数据库变更
最近工作中有一个需求,就是某一个比较重要的业务表经常被莫名其妙的变更.在SQL Server中这类工作如果不事前捕获记录的话,无法做到.对于捕获变更来说,可以考虑的选择包括Trace,CDC. ...
- jQuery事件流的顺序
<div id="aaron"> <div id='test'> <ul> <p>点击p被委托,ul被阻止了,因为内部重写了事件对象 ...
- 深入理解line-height与vertical-align
前面的话 line-height.font-size.vertical-align是设置行内元素布局的关键属性.这三个属性是相互依赖的关系,改变行间距离.设置垂直对齐等都需要它们的通力合作.在CSS字 ...
- 一套后台管理html模版
最近自己需要一套后台管理的模版,然后去网上查找,模版的确很多,但是适合我的并不多.我需要的模版是不会很大,我能够控制代码,样式不要太古朴,最好有点CSS3的效果.最后终于找到一张主页,然后再根据这个主 ...
- 推荐20款基于 jQuery & CSS 的文本效果插件
jQuery 和 CSS 可以说是设计和开发行业的一次革命.这一切如此简单,快捷的一站式服务.jQuery 允许你在你的网页中添加一些真正令人惊叹的东西而不用付出很大的努力,要感谢那些优秀的 jQue ...
- Hadoop入门学习笔记---part1
随着毕业设计的进行,大学四年正式进入尾声.任你玩四年的大学的最后一次作业最后在激烈的选题中尘埃落定.无论选择了怎样的选题,无论最后的结果是怎样的,对于大学里面的这最后一份作业,也希望自己能够尽心尽力, ...