一、准备工作
公共号支付需要提前在微信公共平台进行业务配置,包括设置支付授权目录、测试支付目录和白名单、设置JS接口安全域名以及设置授权回调页面域名。
1.进行微信公众支付之前,我们需要申请个公众号,以及申请微信支付的功能。
基本参数获取:
APPID 和Appsecret
微信公众平台基本配置里面可以看到
商户号mch_id在微信商户平台里面
API密钥也在商户平台里面
2.支付授权目录:
位置:商户平台–>产品中心–>开发配置
1) 所有使用公众号支付方式发起支付请求的链接地址,都必须在支付授权目录之下;
2) 正式支付授权目录最多设置5个,且域名必须通过ICP备案;
目录示例:
url路径为:http://hbdtty.com/BeautyApp/oauth2controller/oauth2
那么我们需要配置的是:http://hbdtty.com/BeautyApp/oauth2controller/
如果后面带参数的话,省略参数;这个我们不需要考虑参数
url路径为:http://hbdtty.com/BeautyApp/oauth2controller/oauth2 ?user=1
那么我们需要配置的是:http://hbdtty.com/BeautyApp/oauth2controller/
假如没有配对,调用会提示当前url未注册的错误
3.支付类型我们选择jsapi支付
具体的就不多说了,配置的时候百度就可以了记住支付目录配置就可以,我是springmvc项目亲测的。
4、信息填写页面会有防欺诈提示,如何去掉就是在公众号设置里面的功能设置里面设置网页授权域名
二、上面的配置好以后说一下开发代码流程
1.获取授权。获取用户的openid
// oauth2授权时回调controller
public final static String REDIRECT_URI_BASE = "http://www.hbdtty.com/BeautyApp/oauth2controller/oauth2_Base";
// oauth2授权(第一步获取code用到的地址)
public final static String OAUTH2_BASE = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="
+ APPID
+ "&redirect_uri="
+ CommonUtil.urlEncodeUTF8(REDIRECT_URI_BASE)
+ "&response_type=code&scope=snsapi_base&state=pay#wechat_redirect";
// 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";
我们在授权书回调的controller里面获取返回来的openid
@RequestMapping("/oauth2_Base")
public String oauth2_Base(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
// 将请求、响应的编码均设置为UTF-8(防止中文乱码)
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
code = request.getParameter("code");
System.out.println(code+"第一次获取的code");
StringBuffer weiXinOauth2TokenJson = new StringBuffer();
if (!"authdeny".equals(code)) {
weiXinOauth2Token = Oauth2Util.getOauth2AccessToken(code, weiXinOauth2TokenJson);
System.out.println(weiXinOauth2Token.getOpenId());
if(weiXinOauth2Token!=null){
request.getSession().setAttribute("openId", weiXinOauth2Token.getOpenId());//将获取的openid存到缓存,统一下单时要用到
}
}
return "wxpay/pay";
}
2.调统一下单接口
@RequestMapping("/pay")
@ResponseBody
public String pay(HttpServletRequest request,HttpServletResponse response,String total_fee) {
String out_trade_no=CommonUtil.getUUID();
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
parameters.put("appid", ConfigUtil.APPID);
parameters.put("mch_id", ConfigUtil.MCH_ID);
parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());
parameters.put("body", "商品");
parameters.put("out_trade_no", out_trade_no);// 订单号,每次都不能一样
parameters.put("total_fee","1");
parameters.put("spbill_create_ip", IpUtil.getIpAddrByRequest(request));
parameters.put("notify_url", ConfigUtil.NOTIFY_URL);
parameters.put("trade_type", "JSAPI");
parameters.put("openid", request.getSession().getAttribute("openId"));
// 必填————签名
String sign = PayCommonUtil.createSign("UTF-8", parameters);
parameters.put("sign", sign);
String requestXML = PayCommonUtil.getRequestXml(parameters);
String result = CommonUtil.httpsRequest(ConfigUtil.UNIFIED_ORDER_URL, "POST", requestXML);
System.out.println("同一订单接口返回数据:" + result);
String json="";
try {
@SuppressWarnings("unchecked")
Map<String, String> map = XMLUtil.doXMLParse(result);
SortedMap<Object, Object> params = new TreeMap<Object, Object>();
params.put("appId", ConfigUtil.APPID);
params.put("timeStamp", Long.toString(new Date().getTime()));
params.put("nonceStr", PayCommonUtil.CreateNoncestr());
params.put("package", "prepay_id=" + map.get("prepay_id"));
params.put("signType", ConfigUtil.SIGN_TYPE);
String paySign = PayCommonUtil.createSign("UTF-8", params);
params.put("packageValue", "prepay_id=" + map.get("prepay_id")); // 这里用packageValue是预防package是关键字在js获取值出错
params.put("paySign", paySign); // paySign的生成规则和Sign的生成规则一致
params.put("sendUrl", ConfigUtil.SUCCESS_URL); // 付款成功后跳转的页面
System.out.println();
// String userAgent = request.getHeader("user-agent");
// char agent = userAgent.charAt(userAgent.indexOf("MicroMessenger") + 15);
// params.put("agent", new String(new char[] { agent }));// 微信版本号,用于前面提到的判断用户手机微信的版本是否是5.0以上版本。
json = JSONObject.fromObject(params).toString();
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}// 解析微信返回的信息,以Map形式存储便于取值
return json;
}
付款成功后的方法:
@RequestMapping("/paySuccess")
public void paySuccess(HttpServletRequest request,HttpServletResponse response) throws Exception {
InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
System.out.println("~~~~~~~~~~~~~~~~付款成功~~~~~~~~~");
outSteam.close();
inStream.close();
String result = new String(outSteam.toByteArray(), "utf-8");// 获取微信调用我们notify_url的返回信息
@SuppressWarnings("unchecked")
Map<Object, Object> map = XMLUtil.doXMLParse(result);
String orderId = "";
String transactionId = "";
for (Object keyValue : map.keySet()) {
if (keyValue.equals("out_trade_no")) {
orderId = (String) map.get(keyValue);
System.out.println("orderId=--------------"+orderId);
}
if (keyValue.equals("transaction_id")) {
transactionId = (String) map.get(keyValue);
System.out.println("transactionId=--------------"+transactionId);
}
System.out.println(keyValue + "=" + map.get(keyValue));
}
if (map.get("result_code").toString().equalsIgnoreCase("SUCCESS")) {
// TODO 对数据库的操作
response.getWriter().write(PayCommonUtil.setXML("SUCCESS", "")); // 告诉微信服务器,我收到信息了,不要在调用回调action了
System.out.println("-------------" + PayCommonUtil.setXML("SUCCESS", ""));
}
}
3、h5页面根据返回的信息调取支付
<script type="text/javascript">
$("#test").one("click",function(){
$.ajax({
url:"${pageContext.request.contextPath}/wxpay/pay" ,
data:{"total_fee":$("#orderId").val(),
"storename":$("#storename").val(),
"name":$("name").val(),
"phone":$("phone").val()
} //<span style="font-family:微软雅黑;">ajax调用微信统一接口获取prepayId</span>
}).done(function(data){
//alert(data);
var obj = eval('(' + data + ')');
if(parseInt(obj.agent)<5){
alert("您的微信版本低于5.0无法使用微信支付");
return;
}
WeixinJSBridge.invoke('getBrandWCPayRequest',{
"appId" : obj.appId, //公众号名称,由商户传入
"timeStamp":obj.timeStamp, //时间戳,自 1970 年以来的秒数
"nonceStr" : obj.nonceStr, //随机串
"package" : obj.packageValue, //<span style="font-family:微软雅黑;">商品包信息</span>
"signType" : obj.signType, //微信签名方式:
"paySign" : obj.paySign //微信签名
},function(res){
alert(res.err_msg);
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
window.location.href=obj.sendUrl;
//window.location.href="www.baidu.com";
}else{
alert("fail");
window.location.href="http://www.hbdtty.com/BeautyApp/oauth2controller/oauth2";
}
});
});
});
</script>