步骤一.首先 你要有一个微信公众号 和公众号对应的微信商户号
1) 先申请一个微信公众号
https://kf.qq.com/faq/120911VrYVrA151013MfYvYV.html
官网教程 做微信支付 我们要的是服务号。 订阅号不能做微信支付
2) 申请微信商户号
https://jingyan.baidu.com/article/15622f24d389b3fdfcbea5d1.html
步骤二.配置信息
1)配置信息 设置网页授权域名 和 JS接口安全域名
微信公众平台-->公众号设置-->功能设置
先把这个文件下载过来 放到 你要设置的域名 根目录下 这样才会设置成功 不要带http
2)配置支付目录
商户平台-->产品中心-->开发配置(传送门:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3),且最多可以同时设置5个目录
好 到这一步 配置信息就完成了
步骤三.开发要提供的参数
公众APPID:wx15*********a8 (开发需要的)
开发者密码APPSECEPT : c210***************892d7 (开发需要的)
商户ID:14******42 (开发需要的)
API密钥:5d5************b35b (开发需要的)
微信公众平台-->基本设置
公众APPID 和 APPSECEPT 我们就有了
商户平台-->账号中心-->商户信息
商户ID 也有了 我们还差一个 API密钥
商户平台-->账号中心-->API安全
好了 现在 配置 和参数 我们已经全部都有了 想在开始代码了
步骤四:开发流程:
微信支付 (说白了就是调用官方文档的“统一下单”接口,之后将微信服务器返回的参数做个加工后,返回到前台(JSP页面)) 文档地址
https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1
文档主要讲 请求地址是
https://api.mch.weixin.qq.com/pay/unifiedorder
入参有很多 其中的必填参数有:
1. appid APPID (已有)
2. mch_id 商户ID (已有)
3. nonce_str 随机字符串(可以用UUID生成)
4. sign 签名
5. body 所支付的名称
6. out_trade_no 咱们自己所提供的订单号,需要唯一(可以是时间戳)
7. total_fee 支付金额
8. spbill_create_ip IP地址(获取ip地址)
9. notify_url 回调地址(支付成功后的通知地址)
10. trade_type 支付类型(默认写 咱们是公众号支付此处给“JSAPI”)
11. openid 支付人的微信公众号对应的唯一标识
好 我们先获取 openid
1.获取OpenID 时 要先获取 code 也是去请求微信的地址
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
入参
APPID: 公众号 APPID
redirect_uri: 回调地址 就是访问这个链接后跳转到哪个地址去
response_type:就直接写 code
scope:应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
state:重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
#wechat_redirect:必填不用管
回参
code:返回的 code参数
state:上面传的 state参数
2.获取OpenID 也是请求地址
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
入参
APPID: 公众号 APPID
secret:开发者密码 APPSECEPT
code:上面获取的code 参数
grant_type:直接写 authorization_code
回参
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE"
}
OpenID 就是我们要
1. appid APPID (已有)
2. mch_id 商户ID (已有)
3. nonce_str 随机字符串(可以用UUID生成)
4. sign 签名
5. body 所支付的名称
6. out_trade_no 咱们自己所提供的订单号,需要唯一(可以是时间戳)
7. total_fee 支付金额 1 为1分钱
8. spbill_create_ip IP地址(获取ip地址)
9. notify_url 回调地址(支付成功后的通知地址)
10. trade_type 支付类型 咱们是公众号支付此处给“JSAPI”
11. openid 支付人的微信公众号对应的唯一标识 (openid 我们也有了)
现在 我们只差 sing了
用WXPayUtil中的
generateSignature(Map 方法,data是将除了sign外,其他10个参数放到map中,key是四大配置参数中的API秘钥&#xff08;paternerKey&#xff09; sign_type 也可以通过 WXPayUtil 中的方法获取 主要是表明 加密方式 WXPayConstants.SignType sign_type &#61; WXPayConstants.SignType.MD5; String sign &#61; WXPayUtil.generateSignature(map, AppMchKey, sign_type); String reqestHtml &#61;WXPayUtil.mapToXml(map); String xmlStr &#61; sendPost(url,reqestHtml); <xml><return_code>SUCCESS]]>return_code><return_msg>OK]]>return_msg><appid>wx2421b1c4370ec43b]]>appid><mch_id>10000100]]>mch_id><nonce_str>IITRi8Iabbblz1Jc]]>nonce_str><openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]>openid><sign>7921E432F65EB8ED0CE9755F0E86D72F]]>sign><result_code>SUCCESS]]>result_code><prepay_id>wx201411101639507cbf6ffd8b0779950874]]>prepay_id><trade_type>JSAPI]]>trade_type>xml> 调用 WXPayUtil.xmlToMap(respondResult) 把 xml 转换成 map Map 其中 只有 prepay_id 是我们要的 我们要放回个前端的参数是 1. appId&#xff1a;四大参数之一的APPID&#xff1b; 2. timestamp&#xff1a;时间戳&#xff08;newDate()即可&#xff09; 3. nonceStr&#xff1a;随机字符串,再次用WXPayUtil中的generateNonceStr()即可&#xff1b; 4. package&#xff1a;就tm是它用到了prepay_id,但是还不是直接取值,还非要固定格式的,值的格式例如&#xff1a;”prepay_id&#61; wx2018…250…9981…666” 5. signType&#xff1a;写MD5就好 6. paySign&#xff1a;签名 if (xmlStr.indexOf("SUCCESS") !&#61; -1) {Map payMap.put("paySign", paySign); 这就完成了 代码 后端代码 有一些方法 可以自己写 package com.wizrole.hospital.wechat.controller;import com.github.wxpay.sdk.WXPayUtil; String code&#61; request.getParameter("code"); //页面获取openId接口String getopenid_url &#61; https://api.weixin.qq.com/sns/oauth2/access_token;String param&#61;"appid&#61;"&#43;你appid&#43;"&secret&#61;"&#43;你secret&#43;"&code&#61;"&#43;code&#43;"&grant_type&#61;authorization_code";//向微信服务器发送get请求获取openIdStrString openIdStr &#61; HttpRequest.sendGet(getopenid_url, param);JSONObject json &#61; JSONObject.parseObject(openIdStr);//转成Json格式String openId &#61; json.getString("openid");//获取openId /*** 获取客户端IP地址* &#64;param request* &#64;return*/public static String getIpAddr(HttpServletRequest request) {String ip &#61; request.getHeader("x-forwarded-for");if (ip &#61;&#61; null || ip.length() &#61;&#61; 0 || "unknown".equalsIgnoreCase(ip)) {ip &#61; request.getHeader("Proxy-Client-IP");}if (ip &#61;&#61; null || ip.length() &#61;&#61; 0 || "unknown".equalsIgnoreCase(ip)) {ip &#61; request.getHeader("WL-Proxy-Client-IP");}if (ip &#61;&#61; null || ip.length() &#61;&#61; 0 || "unknown".equalsIgnoreCase(ip)) {ip &#61; request.getRemoteAddr();}return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;} package com.wizrole.hospital.healthCard.util;import org.slf4j.Logger; 前端代码 var a &#61; "https://open.weixin.qq.com/connect/oauth2/authorize?appid&#61;appid&redirect_uri&#61;http://wizrole.natapp1.cc/index.html&response_type&#61;code&scope&#61;snsapi_base&state&#61;STATE#wechat_redirect";location.href &#61; a; 在index.html 页面写 下面这段js function getQueryString(name) { //调取微信支付
这些方法都在 wxpay-sdk-0.0.3.jar 这个jar包里
这就生成了 sing 了 把 sing 也 加到 data 里去
调用 mapToXml(Map
会把 map 转换成 xml
post请求 https://api.mch.weixin.qq.com/pay/unifiedorder
成功放回的数据
return payMap;
import com.wizrole.hospital.healthCard.util.HttpRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;import static com.wizrole.hospital.wechat.service.WechatService.*;
import static com.wizrole.hospital.wechat.util.XmlUtil.getCurrentTimestamp;
import static com.wizrole.hospital.wechat.util.XmlUtil.getIpAddr;public class Test {&#64;RequestMapping(value &#61; "testPay" , method &#61; {RequestMethod.POST, RequestMethod.GET})&#64;ResponseBodypublic Map orders(HttpServletRequest request) {
try {Map
//获取请求ip地址String ip &#61; getIpAddr(request);String body &#61; request.getParameter("body");String total_fee &#61; request.getParameter("total_fee");//支付金额String out_trade_no &#61; String.valueOf(getCurrentTimestamp()); //订单号
paraMap.put("appid",appID);//公众号ID
paraMap.put("body", "尧舜商城-订单结算");paraMap.put("mch_id",AppMchId);//商户号 ID
paraMap.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
paraMap.put("openid", openid);//OpenID
paraMap.put("out_trade_no", out_trade_no);//订单号
paraMap.put("spbill_create_ip", ip);paraMap.put("total_fee","1");paraMap.put("trade_type", "JSAPI");paraMap.put("notify_url","http://wizrole.natapp1.cc/Wechat/notifyUrl.do");// 此路径是微信服务器调用支付结果通知路径随意写
String sign &#61; WXPayUtil.generateSignature(paraMap, AppMchKey);paraMap.put("sign", sign);String xml &#61; WXPayUtil.mapToXml(paraMap);//将所有参数(map)转xml格式// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
String unifiedorder_url &#61; "https://api.mch.weixin.qq.com/pay/unifiedorder";String xmlStr &#61; HttpRequest.sendPost(unifiedorder_url, xml);//发送post请求"统一下单接口"返回预支付id:prepay_id//以下内容是返回前端页面的json数据
String prepay_id &#61; "";//预支付idif (xmlStr.indexOf("SUCCESS") !&#61; -1) {Map
}
import org.slf4j.LoggerFactory;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;public class HttpRequest {private static final Logger log &#61; LoggerFactory.getLogger(HttpRequest.class);/*** 发送GET请求* &#64;param url* &#64;param param* &#64;return*/public static String sendGet(String url , String param){String result &#61; "";BufferedReader in &#61; null;HttpURLConnection connection &#61; null;try {log.info("发起请求 URL为[" &#43; url &#43; "], 请求方式 [GET], 参数为: " &#43; param);String urlNameString &#61; url &#43; "?" &#43; param;URL realUrl &#61; new URL(urlNameString.replaceAll(" ",""));connection &#61; (HttpURLConnection)realUrl.openConnection();connection.setRequestProperty("accept" , "*/*");connection.setRequestProperty("connection" , "Keep-Alive");connection.setRequestProperty("user-agent" , "Mozilla/4.0(compatible; MSIE 6.0; Windows NT5.1:SV1");connection.connect();Map
// Map
conn.connect();
// for (String key : map1.keySet()){
// System.out.println("----------------------------> " &#43; key &#43; "--->" &#43; map1.get(key));
// }Map
var reg &#61; new RegExp("(^|&)" &#43; name &#43; "&#61;([^&]*)(&|$)", "i");
var r &#61; window.location.search.substr(1).match(reg);
if (r !&#61; null) return unescape(r[2]);
return null;
}
var code &#61; getQueryString("code");
function pay(){openid &#61; $("#openId").text();$.ajax({url:"/testPay",type:"POST",dataType: &#39;json&#39;,data:{code:code,body:"测试",total_fee:"1"},success: function (data) {if (data.return_msg &#61;&#61; "OK") {WeixinJSBridge.invoke(&#39;getBrandWCPayRequest&#39;, {"appId": data.appid, //公众号名称&#xff0c;由商户传入"timeStamp": data.timeStamp, //时间戳&#xff0c;自1970年以来的秒数"nonceStr": data.nonce_str, //随机串"package": "prepay_id&#61;" &#43; data.prepay_id,"signType": "MD5", //微信签名方式&#xff1a;"paySign": data.sign //微信签名},function (res) {if (res.err_msg &#61;&#61; "get_brand_wcpay_request:ok") {alert("支付成功,订单受理中");} else if (res.err_msg &#61;&#61; "get_brand_wcpay_request:cancel") {//取消订单self.cancelOrder(orderdata.order_no, function (status) {if (status &#61;&#61; 1) {alert("支付已取消");} else if (status &#61;&#61; 2) {alert("订单取消失败&#xff0c;请联系管理员")}});} else if (res.err_msg &#61;&#61; "get_brand_wcpay_request:fail") {//取消订单self.cancelOrder(orderdata.order_no, function (status) {if (status &#61;&#61; 1) {alert("支付失败");} else if (status &#61;&#61; 2) {alert("订单取消失败&#xff0c;请联系管理员")}});}});}}})}