微信:微信扫码支付、调用统一下单接口、网站支付 + springmvc

news/2024/5/17 15:20:18/文章来源:https://blog.csdn.net/u010246789/article/details/51554021

一、场景:公司需要在网站上进行微信支付。

二、API:使用微信开放平台的接入微信支付


-扫码支付。微信支付开发者平台链接

三、分析:

  1. 接入扫码支付(包含PC网站支付)包含三个阶段,问这里只讲使用,也就是第2阶段的《启动设计和开发》。
  2. 点击查看开发者文档(扫码支付)后,这里感觉微信的文档没有支付宝好理解(稍微吐槽下~~~),不过我们忽略一切,直接进入模式二:模式二最简单直接,不需要在商户后台进行配置,推荐大家使用,微信也说流程更为简单,我这里也讲的是模式二,模式一大家有兴趣可以自行研究下。
  3. 如上图,总流程有14步,主要流程是生成订单、调统一下单API、将返回的支付交易链接生成二维码展示;我这边主要就是将这三步结合springmvc后,成功生儿二维码之后,用户就可以扫码支付了。后面的回调跟跟我的另一篇博文基本类似,大家借鉴下就行了:支付宝:web页面扫码支付、网站支付、支付宝即时到账 + springmvc

四、实现:

  1. 准备:根据统一下单接口API我先定义了三个对象:UnifiedOrderRequest(统一下单请求参数(必填))、UnifiedOrderRequestExt(统一下单请求参数(非必填))、UnifiedOrderRespose(统一下单返回参数);具体如下代码,get、set方法可自行生产,太占篇幅。

    UnifiedOrderRequest.class
    /*** 统一下单请求参数(必填)* @author Y**/
    public class UnifiedOrderRequest {private String appid;				//公众账号IDprivate String mch_id;				//商户号private String nonce_str;			//随机字符串private String sign;				//签名private String body;				//商品描述private String out_trade_no;		<span style="white-space:pre">	</span>//商户订单号private String total_fee;			//总金额private String spbill_create_ip;	<span style="white-space:pre">	</span>//终端IPprivate String notify_url;			//通知地址private String trade_type;			//交易类型
    }
    UnifiedOrderRequestExt.class
    /*** 统一下单请求参数(非必填)* @author Y**/
    public class UnifiedOrderRequestExt extends UnifiedOrderRequest{private String device_info;			//设备号private String detail;				//商品详情private String attach;				//附加数据private String fee_type;			//货币类型private String time_start;			//交易起始时间private String time_expire;			//交易结束时间private String goods_tag;			//商品标记private String product_id;			//商品IDprivate String limit_pay;			//指定支付方式private String openid;				//用户标识
    }
    UnifiedOrderRespose.class
    /*** 统一下单返回参数* @author Y**/
    public class UnifiedOrderRespose {private String return_code;				//返回状态码private String return_msg;				//返回信息private String appid;					//公众账号IDprivate String mch_id;					//商户号private String device_info;				//设备号private String nonce_str;				//随机字符串private String sign;					//签名private String result_code;				//业务结果private String err_code;				//错误代码private String err_code_des;			<span style="white-space:pre">	</span>//错误代码描述private String trade_type;				//交易类型private String prepay_id;				//预支付交易会话标识private String code_url;				//二维码链接
    }
  2. Controller主入口:
    	/*** 创建二维码*/@RequestMapping("createQRCode")public void createQRCode(String orderId, HttpServletResponse response) {//生成订单String orderInfo = createOrderInfo(orderId);//调统一下单APIString code_url = httpOrder(orderInfo);//将返回预支付交易链接(code_url)生成二维码图片//这里使用的是zxing   <span style="color:#ff0000;"><strong>说明1(见文末)</strong></span>try {int width = 200;int height = 200;String format = "png";Hashtable hints = new Hashtable();hints.put(EncodeHintType.CHARACTER_SET, "utf-8");BitMatrix bitMatrix = new MultiFormatWriter().encode(code_url, BarcodeFormat.QR_CODE, width, height, hints);OutputStream out = null;out = response.getOutputStream();MatrixToImageWriter.writeToStream(bitMatrix, format, out);out.flush();out.close();} catch (Exception e) {}}

  3. 生成订单:分两部分:一部分是业务需求的订单信息,就是发起支付前的订单信息,业务系统自行创建存储;另一部分是满足统一下单API要求的订单信息(也是我们这里要讲的)。“xxxxxx”:是你需要自己填写的对应信息:
    	/*** 生成订单* @param orderId* @return*/private String createOrderInfo(String orderId) {//生成订单对象UnifiedOrderRequest unifiedOrderRequest = new UnifiedOrderRequest();unifiedOrderRequest.setAppid("xxxxxxxxxxxxx");//公众账号IDunifiedOrderRequest.setMch_id("xxxxxxxxx");//商户号unifiedOrderRequest.setNonce_str(StringUtil.makeUUID());//随机字符串       <span style="color:#ff0000;"><strong>说明2(见文末)</strong></span>unifiedOrderRequest.setBody("xxxxxx");//商品描述unifiedOrderRequest.setOut_trade_no(orderId);//商户订单号unifiedOrderRequest.setTotal_fee("x");	//金额需要扩大100倍:1代表支付时是0.01unifiedOrderRequest.setSpbill_create_ip("xxxxxxxxxxxxx");//终端IPunifiedOrderRequest.setNotify_url("xxxxxxxxxxxxxx");//通知地址unifiedOrderRequest.setTrade_type("NATIVE");//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付unifiedOrderRequest.setSign(createSign(unifiedOrderRequest));//签名<span style="color:#ff0000;"><strong>说明5(见文末,签名方法一并给出)</strong></span>//将订单对象转为xml格式XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_"))); //<span style="color:#ff0000;"><strong>说明3(见文末)</strong></span>xStream.alias("xml", UnifiedOrderRequest.class);//根元素名需要是xmlreturn xStream.toXML(unifiedOrderRequest);}

  4. 调统一下单API:根据要求将生成订单中返回的xml向微信给定的统一下单URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder,发送请求,成功并获得二维码。
    	/*** 调统一下单API* @param orderInfo* @return*/private String httpOrder(String orderInfo) {String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";try {HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();//加入数据  conn.setRequestMethod("POST");  conn.setDoOutput(true);  BufferedOutputStream buffOutStr = new BufferedOutputStream(conn.getOutputStream());  buffOutStr.write(orderInfo.getBytes());buffOutStr.flush();  buffOutStr.close();  //获取输入流  BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));  String line = null;  StringBuffer sb = new StringBuffer();  while((line = reader.readLine())!= null){  sb.append(line);  }  XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));//说明3(见文末)//将请求返回的内容通过xStream转换为UnifiedOrderRespose对象xStream.alias("xml", UnifiedOrderRespose.class);UnifiedOrderRespose unifiedOrderRespose = (UnifiedOrderRespose) xStream.fromXML(sb.toString());//根据微信文档return_code 和result_code都为SUCCESS的时候才会返回code_url//<span style="color:#ff0000;"><strong>说明4(见文末)</strong></span>if(null!=unifiedOrderRespose && "SUCCESS".equals(unifiedOrderRespose.getReturn_code()) && "SUCCESS".equals(unifiedOrderRespose.getResult_code())){return unifiedOrderRespose.getCode_url();}else{return null;}} catch (Exception e) {e.printStackTrace();}return null;}

  5. 将返回的支付交易链接生成二维码展示:没有异常的情况下,在页面中使用<img>标签接收就行。实际使用时,结合前端和业务的需求放置二维码。可以在扫码支付/案例及规范中找到部分素材和界面规范来设计微信风格的支付页面。
    <img src="${ctx}/wxPay/createQRCode?orderId=1111" width="174px">

  6. 用户可以通过维系客户端进行扫码支付。支付完成后回调我们notify_url设置的url,通过成功的回调来更改业务系统中的订单状态或者一些业务需求。这里回调没有写出可以参考支付宝:web页面扫码支付、网站支付、支付宝即时到账 + springmvc中的回调。

五、说明:

  1. 二维码可以查看zxing实现二维码生成和解析;微信这边也提供了二维码的学习,大家有兴趣可以看看:http://www.thonky.com/qr-code-tutorial/ 和http://coolshell.cn/articles/10590.html

  2. 随机字符串:微信对随机字符串的要求是不超过32位。我这边是这样生成的,用时间戳。
    	/*** 创建UUID* @return*/public static synchronized String makeUUID() {Date date = new Date();StringBuffer s = new StringBuffer(DateUtil.formatYmdhmsm(date));return s.append((new Random().nextInt(900) + 100)).toString();}



  3. 使用Xstream时,由于微信定义的变量名大部分使用了“_”,但是在Xstream中它是关键字,所以会自动变为“__”,引起报错。详情请看:XStream异常:对象转为XML时,会把"_"转成"__";报错:(Lcom/thoughtworks/xstream/io/naming/NameCoder;)V

  4. 获取二维码链接时,只有在return_code 和result_code都为SUCCESS的时候有返回;这里我就简单的满足时返回,不满足返回null,您写的时候需要结合业务考虑下,是否需要增加判断,从而满足不同的业务场景。统一下单API

  5. 签名在上面一直没有详细说明,首先查看微信的安全规范中签名算法。key值,需要自己填写
    	/*** 生成签名* * @param appid_value* @param mch_id_value* @param productId* @param nonce_str_value* @param trade_type * @param notify_url * @param spbill_create_ip * @param total_fee * @param out_trade_no * @return*/private String createSign(UnifiedOrderRequest unifiedOrderRequest) {//根据规则创建可排序的map集合SortedMap<String, String> packageParams = new TreeMap<String, String>();packageParams.put("appid", unifiedOrderRequest.getAppid());packageParams.put("body", unifiedOrderRequest.getBody());packageParams.put("mch_id", unifiedOrderRequest.getMch_id());packageParams.put("nonce_str", unifiedOrderRequest.getNonce_str());packageParams.put("notify_url", unifiedOrderRequest.getNotify_url());packageParams.put("out_trade_no", unifiedOrderRequest.getOut_trade_no());packageParams.put("spbill_create_ip", unifiedOrderRequest.getSpbill_create_ip());packageParams.put("trade_type", unifiedOrderRequest.getTrade_type());packageParams.put("total_fee", unifiedOrderRequest.getTotal_fee());StringBuffer sb = new StringBuffer();Set es = packageParams.entrySet();//字典序Iterator it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = (String) entry.getValue();//为空不参与签名、参数名区分大小写if (null != v && !"".equals(v) && !"sign".equals(k)&& !"key".equals(k)) {sb.append(k + "=" + v + "&");}}//第二步拼接key,key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置sb.append("key=" +"xxxxxxxxxxxxxxxxx");String sign = MD5Util.MD5Encode(sb.toString(), "utf-8").toUpperCase();//MD5加密return sign;}


相关文章:支付宝:web页面扫码支付、网站支付、支付宝即时到账 + springmvc













本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_855482.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA 模拟网站注册登录功能,用文件代替数据库

JAVA 模拟网站注册登录功能 代码太长&#xff0c;粘不上去&#xff0c;只能截图了&#xff0c;看起来可能会比较困难&#xff0c;抱歉~ 操作过程注释写的很清楚&#xff0c;我就不多说了

ASP.NET网站管理工具无法连接SQLamp;n…

所遇问题&#xff1a;进入Visual Studio 2010的“网站”菜单的“ASP.NET 配置”后&#xff0c;点击“安全”后&#xff0c;出现如下的出错信息&#xff1a; 测试“AspNetSqlProvider”&#xff0c;出现如下的出错信息&#xff1a;未能建立数据库连接。如果尚未创建 SQL Server …

Java 爬虫遇到需要登录的网站,该怎么办?(三)

这是 Java 网络爬虫系列博文的第二篇&#xff0c;在上一篇 Java 网络爬虫&#xff0c;就是这么的简单 中&#xff0c;我们简单的学习了一下如何利用 Java 进行网络爬虫。在这一篇中我们将简单的聊一聊在网络爬虫时&#xff0c;遇到需要登录的网站&#xff0c;我们该怎么办&…

(10)基于Python模拟网站的登录

最近利用工作之余&#xff0c;把之前研究的东西又翻看了一遍&#xff0c;发现其中一个数据表格的导出&#xff0c;并没有对网站的登录进行模拟。本着打破砂锅问到底的精神&#xff0c;再一次打开该网站&#xff0c;研究了该网站的登录是怎么一回事的。 首先&#xff0c;打开抓包…

基于struts1.2的网站源码组织结构

结合自己弄的一个小项目,总结一下在MyEclipse下&#xff0c;使用Strut1.2框架开发网站的源码组织结构 &#xff08;stuts1.2的架构基本上是这样的了~&#xff09; 下图左边是源码组织结构,右边为相应的说明

数据库有用网站

分享下常用的数据库网站&#xff0c;希望对大家有用 数据库SQL基础知识&#xff1a;http://www.w3school.com.cn/sql/index.asp ChinaUnix: http://www.chinaunix.net/ itpub网站&#xff1a; http://www.itpub.net/ MySQL中文社区&#xff1a;http://www.mysqlpub.com/fo…

个人创业楷模:一个人,一个网站,5.75亿美元卖掉

个人创业楷模&#xff1a;一个人&#xff0c;一个网站&#xff0c;5.75亿美元卖掉&#xff08;转&#xff09; 一个人&#xff0c;24岁时写了一个网站&#xff0c;每天只工作2小时&#xff0c;他还嫌工作量太大。他每天从谷歌广告赚好几万美元&#xff0c;不用合伙人&#xff…

Apache网站服务器

Apache网站服务基础 Apache简介 Apache HTTP Server 是开源软件项目的杰出代表&#xff0c;基于标准的HTPP网络协议提供网页浏览服务&#xff0c;在Web服务器领域中长期保持着超过半数的份额。Apache服务器可以运行在Linux、UNIX、Windows等多种操作系统平台中。 Apache的主…

网站架构常识

1、DNS域名解析&#xff08;步骤&#xff09; 2、网站架构演变过程 &#xff08;1&#xff09;传统架构 传统项目分为三层架构&#xff0c;将业务逻辑层、数据库访问层、控制层放入在一个项目中 使用SSH或者SSM技术。 优点:适合于个人或者小团队开发&#xff0c;不适合大团队…

不修改代码就能优化ASP.NET网站性能的一些方法

阅读目录 开始配置OutputCache启用内容过期解决资源文件升级问题启用压缩删除无用的HttpModule其它优化选项本文将介绍一些方法用于优化ASP.NET网站性能&#xff0c;这些方法都是不需要修改程序代码的。它们主要分为二个方面&#xff1a;1. 利用ASP.NET自身的扩展性进行优化。2…

IIS日志-网站运维的好帮手

阅读目录 开始IIS日志包含了哪些信息IIS日志的配置如何分析IIS日志推荐的IIS日志分析方法IIS日志中的异常记录再谈 scwin32status64寻找性能问题寻找可改进的目标程序架构对IIS日志分析过程的影响对于一个需要长期维护的网站来说&#xff0c;如何让网站长久稳定运行是件很有意义…

【Python成长之路】Python爬虫 --requests库爬取网站乱码(\xe4\xb8\xb0\xe5\xaf\x8c\xe7\x9)的解决方法

【写在前面】 在用requests库对自己的CSDN个人博客&#xff08;https://blog.csdn.net/yuzipeng&#xff09;进行爬取时&#xff0c;发现乱码报错&#xff08;\xe4\xb8\xb0\xe5\xaf\x8c\xe7\x9&#xff09;&#xff0c;如下图所示&#xff1a; 网上 查找了一些方法&#xff0c…

【Python成长之路】破解Boss直聘网站滑块验证

哈喽大家好&#xff0c;我是鹏哥。 今天要记录的内容是 —— 破解Boss直聘网站的滑块验证。 …… 上 课 铃…… TuesdayBurak Yeter;Danelle Sandoval - Tuesday 1 写在前面 最近领导安排我投入公司招聘工作&#xff0c;然后自然就需要不停地在boss直聘网上进行人才搜索。搞了…

【Python成长之路】基于Flask开发网站--利用复选框进行批量操作

哈喽大家好&#xff0c;我是鹏哥。 今天我想写的内容是 —— 基于Flask实现网页表格的批量删除。 ~~~上课铃~~~ LiberatorsEpic Score - Vengeance - ES033 1 写在前面 由于近期有同事在工作中向我求助网页可视化怎么做&#xff0c;对于从来没有学过html/vue/javascript等框架开…

【Python成长之路】基于Flask开发网站 -- 基于重定向实现搜索功能

哈喽大家好&#xff0c;我是鹏哥。 今天继续上周的内容&#xff0c;仍然讲基于Flask开发网站&#xff0c;不过这次的控件是 ——基于重定向实现搜索功能。 ~~~上课铃~~~ Silver Scrapes(As Featured In the ESPN "This Is College GameDay" Spot)Danny McCarthy - Si…

【Python成长之路】从 零做网站开发 -- 下拉选择项的实现

哈喽大家好&#xff0c;我是鹏哥。 今天继续之前的html组件开发话题是 —— 下拉选择项。 ~~~上课铃~~~ 卡农变奏曲K.Williams - 终极钢琴测试王 1 写在前面 上次的搜索功能&#xff0c;有粉丝提到&#xff0c;能不能设置成可选的搜索条件。答案自然是可以的&#xff0c;所以我…

手把手教你用 Docker 部署网站[Docker 系列-8]

大家好&#xff0c;我是本周的值班编辑 江南一点雨 &#xff0c;本周将由我为大家排版并送出技术干货&#xff0c;大家可以在公众号后台回复“java”&#xff0c;获得作者 Java 知识体系/面试必看资料。在实际的开发环境或者生产环境&#xff0c;容器往往都不是独立运行的&…

推荐几个不错第 Java 学习网站

这是Java极客技术的第313篇原创文章粉粉昨天晚上做梦&#xff0c;梦见自己想好好学习一下 Java&#xff0c;因为平常总是 CRUD 导致自己根本没有时间学习&#xff0c;所以第二天粉粉怀着激动的心情不到5点就起床整理&#xff0c;从而给大家推荐几个不错的网站。LearnJava 在线这…

阿粉带你从零搭建一个属于自己的个人网站

每天早上七点三十分&#xff0c;准时推送干货很多小伙伴私信我&#xff0c;问我怎么弄一个个人博客系统&#xff0c;之前其实也聊过&#xff0c;不过没关系&#xff0c;今天我们再来详细的说一说。对于已经上线的项目&#xff0c;我们知道后期的迭代主要集中在线上发布这个环节…

面试官:假如说我们现在要做一个千万级用户量网站,你怎么设计高并发架构?...

每天早上七点三十&#xff0c;准时推送干货之前的时候&#xff0c;阿粉一直在看同事面试&#xff0c;但是呢&#xff0c;阿粉并没有自己去面试&#xff0c;而无意间打开Boss的时候&#xff0c;发现一家公司私聊了我&#xff0c;我回复了一下之后&#xff0c;竟然说我可以去面试…