java开发微信公众号支付(JSAPI)
https://www.cnblogs.com/gopark/p/9394951.html,这篇文章写的已经很详细了。
下面写一下自己的思路:
1.首先下载demo,地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
2.demo中很多方法对于公众号支付用不到,不需要全都看
3.主要是获取11个参数,放到Map中,用demo里提供WXPayUtil.mapToXml方法转为XML格式,通过post方法请求微信端的统一下单接口,后台收到微信传过来的XML字符串,通过WXPayUtil.xmlToMap方法转为Map,根据key值,获取prepay_id(预支付ID),再把需要的6个参数放到Map中,发送给前台,前台根据prepay_id,唤起微信支付,完成付款。
4.11个参数跟6个参数在controller里面都有写,重点的是:openid
5.查看订单,取消订单等其他功能,后续接触到再进行更新
下面放上自己写的controller
package com.github.wxpay.controller; import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.github.wxpay.util.Constant;
import com.github.wxpay.util.HttpRequestUtil;
import com.github.wxpay.util.OrderUtil;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.RequestMapping;
import com.github.wxpay.sdk.WXPayConstants.SignType; public class WxPayController { /**
*
* @Description 微信浏览器内微信支付/公众号支付(JSAPI)
*/
@RequestMapping(value = "/orders",method = RequestMethod.GET)
@ResponseBody
public Map orders(HttpServletRequest request){
try {
Map<String, String> paramMap = new HashMap<String, String>();
HttpSession session = request.getSession();
String wxopenid = session.getAttribute("openid") == null ? null : session.getAttribute("openid").toString();
//在商户平台的账户中心下:需要用户自行下载证书及安装
String key = Constant.signCustomerKey;
String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
if (ip.indexOf(",") != -1) {
String[] ips = ip.split(",");
ip = ips[0].trim();
}
paramMap.put("appid", Constant.APPIDS[0]);
paramMap.put("mch_id", "");
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
paramMap.put("body", "测试订单XX矿泉水");
paramMap.put("openid", wxopenid);
paramMap.put("out_trade_no", OrderUtil.orderNumber());
paramMap.put("spbill_create_ip", ip);
paramMap.put("total_fee", "0.01");
paramMap.put("notify_url", "http://127.0.0.1:8080/alipay.trade.page.pay-JAVA-UTF-8/notify_url.jsp");// 此路径是微信服务器调用支付结果通知路径
paramMap.put("trade_type", "JSAPI");
String sign = WXPayUtil.generateSignature(paramMap,key,SignType.MD5);
paramMap.put("sign", sign); // 将所有参数(map)转xml格式
String mapToXml = WXPayUtil.mapToXml(paramMap);
System.out.println(mapToXml);
// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
// 发送post请求"统一下单接口"返回预支付id:prepay_id
String xmlStr = HttpRequestUtil.sendPost(unifiedorder_url,mapToXml); Map<String,String> XmlToMap = WXPayUtil.xmlToMap(xmlStr);
// 以下内容是返回前端页面的json数据
String prepay_id = ""; // 预支付ID
if (xmlStr.indexOf("SUCCESS") != -1) {
Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
prepay_id = map.get("prepay_id");
}
Map<String, String> payMap = new HashMap<String, String>();
XmlToMap.put("appId", Constant.APPIDS[0]);
XmlToMap.put("timeStamp", WXPayUtil.getCurrentTimestamp()+"");
XmlToMap.put("nonceStr", WXPayUtil.generateNonceStr());
XmlToMap.put("signType", "MD5");
XmlToMap.put("package", "prepay_id=" + prepay_id);
String paySign = WXPayUtil.generateSignature(payMap, key);
payMap.put("paySign", paySign);
return XmlToMap;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
httpRequest工具:
package com.github.wxpay.util; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URLConnection;
import java.util.List;
import java.net.URL;
import java.util.Map; public class HttpRequestUtil {
/**
* 向指定URL发送GET方法的请求
*
* @param url
* 发送请求的URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return URL 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
System.out.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
} /**
* 向指定 URL 发送POST方法的请求
*
* @param url
* 发送请求的 URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!"+e);
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
}
随机数工具:
package com.github.wxpay.util;
import com.github.wxpay.sdk.WXPayUtil;
public class OrderUtil {
public static String orderNumber(){
int r1 = (int)(Math.random()*10);
int r2 = (int)(Math.random()*10);
long now = WXPayUtil.getCurrentTimestampMs();
String paymentID = String.valueOf(r1)+String.valueOf(r2)+String.valueOf(now);
return paymentID;
}
}
java开发微信公众号支付(JSAPI)的更多相关文章
- Java开发微信公众号(五)---微信开发中如何获取access_token以及缓存access_token
获取access_token是微信api最重要的一个部分,因为调用其他api很多都需要用到access_token.比如自定义菜单接口.客服接口.获取用户信息接口.用户分组接口.群发接口等在请求的时候 ...
- Java开发微信公众号(四)---微信服务器post消息体的接收及消息的处理
在前几节文章中我们讲述了微信公众号环境的搭建.如何接入微信公众平台.以及微信服务器请求消息,响应消息,事件消息以及工具处理类的封装:接下来我们重点说一下-微信服务器post消息体的接收及消息的处理,这 ...
- Java开发微信公众号(三)---微信服务器请求消息,响应消息,事件消息以及工具处理类的封装
在前面几篇文章我们讲了微信公众号环境的配置 和微信公众号服务的接入,接下来我们来说一下微信服务器请求消息,响应消息以及事件消息的相关内容,首先我们来分析一下消息类型和返回xml格式及实体类的封装. ( ...
- Java开发微信公众号(二)---开启开发者模式,接入微信公众平台开发
接入微信公众平台开发,开发者需要按照如下步骤完成: 1.填写服务器配置 2.验证服务器地址的有效性 3.依据接口文档实现业务逻辑 资料准备: 1.一个可以访问的外网,即80的访问端口,因为微信公众号接 ...
- Java开发微信公众号(一)---初识微信公众号以及环境搭建
ps:1.开发语言使用Java springMvc+Mybaits+spring maven实现 2.使用微信接口测试账号进行本地测试 https://mp.weixin.qq.com/debug/c ...
- java版微信公众号支付(H5调微信内置API)
最近需要做微信公众号支付,网上找了大堆的代码,大多都只说了个原理,自己踩了太多坑,所有的坑,都会再下面的文章中标注,代码我也贴上最全的(叫我雷锋)!!! 第一步:配置支付授权目录 你需要有将你公司的微 ...
- 微信公众号支付JSAPI网页,total_fee错误不正确,header重定向参数丢失,无法获取订单号和金额解决
微信公众号支付官方demo错误, 公众号支付只能用在微信里,也就是微信内部浏览器. 1.到WxPayHubHelper.php文件 JsApi_pub()类下createOauthUrlForCode ...
- 用java开发微信公众号:测试公众号与本地测试环境搭建(一)
本文为原创,原始地址为:http://www.cnblogs.com/fengzheng/p/5023678.html 俗话说,工欲善其事,必先利其器.要做微信公众号开发,两样东西不可少,那就是要有一 ...
- Java 关于微信公众号支付总结附代码
很多朋友第一次做微信支付的时候都有蒙,但当你完整的做一次就会发现其实并没有那么难 业务流程和应用场景官网有详细的说明:https://pay.weixin.qq.com/wiki/doc/api/js ...
随机推荐
- utf8 string
https://github.com/BassLC/idUTF8lib Idiot's UTF-8 Library A very (too much really) simple Utf8 libra ...
- 我的Java历程_maven配置的心路历程
从github上download了个maven管理的开源项目,接下来随笔下安装maven的心路历程: 异常尴尬的是import进ide之后一个红色的感叹号!震惊!google一下知道了,maven没配 ...
- 使用IDEA在Maven中创建MyBatis逆向工程以及需要注意的问题(入门)
逆向工程简介: mybatis官方提供逆向工程,可以针对单表自动生成mybatis执行所需要的代码(mapper.java.mapper.xml.pojo…),可以让程序员将更多的精力放在繁杂的业务逻 ...
- SP1487 PT07J - Query on a tree III 主席树+dfs序
Code: #include<iostream> #include<cstdio> #include<algorithm> #include<string&g ...
- C# treeview绑定
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) ...
- c++常见操作的模板
1.统计时间 #include<ctime> clock_t startTime = clock(); code(); clock_t endTime = clock(); cout &l ...
- vuex 基本入门和使用(三)-关于 mutation
vuex 基本入门和使用(三)-关于 mutation vuex 版本为^2.3.1,按照我自己的理解来整理vuex. 关于 mutation 这里应该很好理解. 更改 Vuex 的 store 中的 ...
- IdentityServer4-前后端分离之Vue
原文:IdentityServer4-前后端分离之Vue 前言 之前文章讲到如何使用Node.js+Express构建JavaScript客户端,实现前后端分离.本节将介绍如何使用Vue实现前后端分离 ...
- 【Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) B】 Code For 1
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 把序列生成的过程看成一颗树 会发现最后形成的是一颗二叉树. 每个二叉树上的节点就对应了序列中的一个数字. 如果我们把每个节点都往下投 ...
- centos7.x86_64搭建饥荒服务器
http://blog.ttionya.com/article-1233.html 在centos7下找不到 libcurl-gnutls.so.4,而且必须要安装32位的才行 yum install ...