一、申请微信公众号的微信支付信息
获得微信公众号的APPID
二、申请微信商户平台,并填写相关的信息
获得微信商户平台的商户号ID,并保存自己设置的key
三、下载微信支付的JavaSDK
去这个地址(https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1)下载相应的SDK 四、修改SDK中的内容
修改SDK中的内容:WXPay类中的构造方法,加密方式都改为MD5,如下:
public WXPay(final WXPayConfig config, final String notifyUrl, final boolean autoReport, final boolean useSandbox) throws Exception {
this.config = config;
this.notifyUrl = notifyUrl;
this.autoReport = autoReport;
this.useSandbox = useSandbox;
if (useSandbox) {
this.signType = SignType.MD5; // 沙箱环境
}
else {
this.signType = SignType.MD5;
}
this.wxPayRequest = new WXPayRequest(config);
}
需要自己编写一个IWXPayConfig继承WXPayConfig,如下:
public class IWXPayConfig extends WXPayConfig{
private String app_id;
private String wx_pay_key;
private String wx_pay_mch_id;
public IWXPayConfig() {
}
public IWXPayConfig(String appid,String wxPayKey,String wxPayMchId) {
this.app_id = appid;
this.wx_pay_key = wxPayKey;
this.wx_pay_mch_id = wxPayMchId;
}
@Override
public String getAppID() {
return app_id;
}
@Override
public String getMchID() {
return wx_pay_mch_id;
}
@Override
public String getKey() {
return wx_pay_key;
}
@Override
public InputStream getCertStream() {
// TODO Auto-generated method stub
return null;
}
@Override
public IWXPayDomain getWXPayDomain() {
IWXPayDomain iwxPayDomain = new IWXPayDomain() {
@Override
public void report(String domain, long elapsedTimeMillis, Exception ex) {
}
@Override
public DomainInfo getDomain(WXPayConfig config) {
return new IWXPayDomain.DomainInfo(WXPayConstants.DOMAIN_API, true);
}
};
return iwxPayDomain;
}
}
五、编写微信支付的工具类
package com.forezp.util;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import com.forezp.config.IWXPayConfig;
import com.forezp.wxpay.WXPay;
import com.forezp.wxpay.WXPayUtil;
/**
* @Title WxPayUtil.java
* @Description 微信支付工具类
* Copyright: Copyright (c) 2019
* Company: Guyi Studio
*
* @author zxj
* @date 2019年7月22日 下午2:50:19
*/
@Component
public class WeChatPayUtil {
@Autowired
private GetImage getImage;
/**
*
* @Description 进入到微信支付页面,进行支付
* @param maps
* @return
*
* @author zxj
* @date 2019年7月24日 下午2:16:27
*/
public ModelAndView wxpay(Map<String,String> maps) {
// URL链接
String serverName = maps.get("serverName");
ModelAndView model = new ModelAndView();
IWXPayConfig config = new IWXPayConfig(maps.get("appid"),maps.get("wxPayKey"),maps.get("wxPayMchId"));
WXPay wxpay = null;
try {
wxpay = new WXPay(config);
} catch (Exception e) {
e.printStackTrace();
}
Map<String, String> resp = null;
Map<String, String> data = new HashMap<String, String>();
data.put("body", maps.get("body"));//描述
data.put("out_trade_no", maps.get("out_trade_no"));//订单号
data.put("device_info", "WEB");//web环境
data.put("fee_type", "CNY");//币种
data.put("total_fee", maps.get("total_fee"));//实际应扣除的金额
data.put("spbill_create_ip", maps.get("spbill_create_ip"));//付款IP地址
data.put("notify_url", maps.get("notify_url"));//通知地址 http://localhost:8080/payResult
data.put("trade_type", "JSAPI"); // 此处指定为扫码支付
data.put("openid", maps.get("openid"));//用户的openID
data.put("product_id", maps.get("product_id"));//商品ID
try {
resp = wxpay.unifiedOrder(data);
System.out.println("支付返回的信息是:-----"+resp);
} catch (Exception e) {
e.printStackTrace();
}
if("SUCCESS".equals(resp.get("return_code"))){
String paytimestamp = System.currentTimeMillis()+"";
String paynoncestr = resp.get("nonce_str");
String prepayid = "prepay_id=" + resp.get("prepay_id");
Map<String, String> map = new HashMap<>();
map.put("appId", maps.get("appid"));
map.put("timeStamp", paytimestamp);
map.put("nonceStr", paynoncestr);
map.put("package", prepayid);
map.put("signType", "MD5");
String paySign = null;
try {
paySign = WXPayUtil.generateSignature(map,maps.get("wxPayKey"));
} catch (Exception e) {
e.printStackTrace();
}
model.addObject("appId", maps.get("appid"));
model.addObject("timeStamp", paytimestamp);
model.addObject("nonceStr", paynoncestr);
model.addObject("package", prepayid);
model.addObject("signType", "MD5");
model.addObject("paytimestamp", paytimestamp);
model.addObject("paynoncestr", paynoncestr);
model.addObject("prepayid", prepayid);
model.addObject("paysign", paySign);
//支付成功回调地址
model.addObject("paysuccessurl",serverName+"/paySuccess?total_fee="+maps.get("total_fee")+"out_trade_no="+maps.get("out_trade_no"));
//退出支付,返回的地址
model.addObject("orderhuburl",serverName+"/payCancel");
model.setViewName("payPage");
}else {
model.addObject("content", "您好,很抱歉,无法提交微信支付,请稍后再试!谢谢!");
model.setViewName("result");
}
return model;
}
/**
*
* @Description 生成二维码
* @param maps
* @return
*
* @author zxj
* @date 2019年7月24日 下午2:16:09
*/
public ModelAndView createImage(Map<String,String> maps) {
ModelAndView model = new ModelAndView();
String serverName = maps.get("serverName");
IWXPayConfig config = new IWXPayConfig(maps.get("appid"),maps.get("wxPayKey"),maps.get("wxPayMchId"));
WXPay wxpay = null;
try {
wxpay = new WXPay(config);
} catch (Exception e) {
e.printStackTrace();
}
Map<String, String> resp = null;
Map<String, String> data = new HashMap<String, String>();
data.put("body", maps.get("body"));//描述
data.put("out_trade_no", maps.get("out_trade_no"));//订单号
data.put("device_info", "WEB");
data.put("fee_type", "CNY");
data.put("total_fee", maps.get("total_fee"));//实际应扣除的金额
data.put("spbill_create_ip", maps.get("spbill_create_ip"));
data.put("notify_url", maps.get("notify_url"));//通知地址 http://localhost:8080/payResult
data.put("trade_type", "NATIVE"); // 此处指定为扫码支付
data.put("openid", maps.get("openid"));//用户的openID
data.put("product_id", maps.get("product_id"));//商品ID
try {
resp = wxpay.unifiedOrder(data);
System.out.println("支付返回的信息是:-----"+resp);
} catch (Exception e) {
e.printStackTrace();
}
if("SUCCESS".equals(resp.get("return_code"))){
String paytimestamp = System.currentTimeMillis()+"";
String paynoncestr = resp.get("nonce_str");
String prepayid = "prepay_id=" + resp.get("prepay_id");
String codeurl = resp.get("code_url");
String baseurl = getImage.getImage(codeurl);
Map<String, String> map = new HashMap<>();
map.put("appId", maps.get("appid"));
map.put("timeStamp", paytimestamp);
map.put("nonceStr", paynoncestr);
map.put("package", prepayid);
map.put("signType", "MD5");
String paySign = null;
try {
paySign = WXPayUtil.generateSignature(map,maps.get("wxPayKey"));
} catch (Exception e) {
e.printStackTrace();
}
model.addObject("appId", maps.get("appid"));
model.addObject("timeStamp", paytimestamp);
model.addObject("nonceStr", paynoncestr);
model.addObject("package", prepayid);
model.addObject("signType", "MD5");
model.addObject("paytimestamp", paytimestamp);
model.addObject("paynoncestr", paynoncestr);
model.addObject("prepayid", prepayid);
model.addObject("paysign", paySign);
//支付成功回调地址
model.addObject("paysuccessurl",serverName+"/paySuccess?total_fee="+maps.get("total_fee")+"out_trade_no="+maps.get("out_trade_no"));
//退出支付,返回的地址
model.addObject("orderhuburl",serverName+"/payCancel");
model.addObject("string", "data:image/jpg;base64,"+baseurl);
model.setViewName("newPayPage");
}else {
model.addObject("content", "您好,很抱歉,无法提交微信支付,请稍后再试!谢谢!");
model.setViewName("result");
}
return model;
}
}
六、完成开发,进行验证
package com.forezp.controller;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSONObject;
import com.forezp.model.OrderPayMsg;
import com.forezp.model.PayElement;
import com.forezp.service.PayElementService;
import com.forezp.service.PayService;
import com.forezp.util.TimeUtil;
import com.forezp.util.WeChatPayUtil;
import com.forezp.wxpay.WXPayUtil;
/**
* @Title WxController.java
* @Description 微信支付控制层
* Copyright: Copyright (c) 2019
* Company: Guyi Studio
*
* @author zxj
* @date 2019年7月19日 下午3:58:37
*/
@Controller
public class WxController {
@Autowired
private PayElementService payElementService;
@Autowired
private WeChatPayUtil wxPayUtil;
@Autowired
private PayService payService;
/**
*
* @Description 新增微信支付所需的信息
* @param payElement
* @return
*
* @author zxj
* @date 2019年7月20日 下午4:15:12
*/
@RequestMapping(value = "/addPayElement",method = RequestMethod.POST)
@ResponseBody
public JSONObject addPayElement(@ModelAttribute PayElement payElement) {
JSONObject json = new JSONObject();
System.out.println(payElement.getWxPayKey()+"---"+payElement.getWxPayMchId());
PayElement payele = payElementService.selectByWxPayMchId(payElement.getWxPayMchId());
if(payele==null) {
json.put("Status", 401);
json.put("Message", "新增失败");
return json;
}
try {
//新增微信支付所需信息
payElementService.addPayElement(payElement);
json.put("Status", 200);
json.put("Message", "新增成功");
} catch (Exception e) {
e.printStackTrace();
json.put("Status", 500);
json.put("Message", "产生异常,新增失败");
}
return json;
}
/**
*
* @Description 付款成功页面
* @return
*
* @author zxj
* @date 2019年7月22日 下午3:03:25
*/
@RequestMapping("/paySuccess")
public ModelAndView paySuccess(String total_fee,String out_trade_no) {
ModelAndView model = new ModelAndView();
Integer totalfee = Integer.valueOf(total_fee)/100;
model.addObject("total_fee", totalfee+"");
model.addObject("out_trade_no", out_trade_no);
model.setViewName("success");
return model;
}
/**
*
* @Description 取消付款页面
* @return
*
* @author zxj
* @date 2019年7月24日 下午2:25:16
*/
@RequestMapping("/payCancel")
public String payCancel() {
return "cancel";
}
/**
*
* @Description 微信支付功能
* @param request
* @param orderid
* @param appid
* @return
*
* @author zxj
* @date 2019年7月29日 上午9:50:36
*/
@RequestMapping(value = "/wxpay.do")
public ModelAndView wxpay(HttpServletRequest request,String orderid,String appid,String body) {
// 1、需要根据数据库进行请求 APPID wxPayKey wxPayMchId
// 2、需要根据订单号请求得到订单信息,获得订单付款金额,并且获得openID
ModelAndView model = new ModelAndView();
String serverName = request.getScheme()+"://"+request.getServerName();
System.out.println(serverName);
// OrderPayMsg orderPayMsg = payService.getOrderPayMsg(orderid);
// 根据APPID获取微信支付所需要的信息
PayElement payele = payElementService.selectByAppId(appid);
Map<String,String> map = new HashMap<>();
//微信公众号ID 商城所绑定的微信公众号ID
map.put("appid", appid);
// map.put("appid", "****");
//微信商户号的key
map.put("wxPayKey", payele.getWxPayKey());
// map.put("wxPayKey", "*****");
//微信商户号ID
map.put("wxPayMchId", payele.getWxPayMchId()+"");
// map.put("wxPayMchId", "******");
//描述信息 关于公司名称的简介
map.put("body", "即刻定制");
// map.put("body",body);
//订单编号 唯一
// map.put("out_trade_no", orderPayMsg.getOrderid());
map.put("out_trade_no", "G010987656782836");
//付款金额
// map.put("total_fee", (orderPayMsg.getTotalfee()*100)+"");
map.put("total_fee", "1");
//获取本地IP地址
map.put("spbill_create_ip", getIpAddr(request));
//异步回调的接口
map.put("notify_url", serverName+"/payResult");
//openID 需要根据微信公众号ID来进行获取
// map.put("openid", orderPayMsg.getOpenid());
map.put("openid", "oHb0Z00s3Om59avDnL0_gT_FFMy4");
//产品编号
// map.put("product_id", orderPayMsg.getStyleid());
map.put("product_id", "1523171088");
//域名
map.put("serverName", serverName);
model = wxPayUtil.wxpay(map);
return model;
}
/**
*
* @Description 进入微信支付异步通知
* @param request
* @param response
* @return
* @throws IOException
*
* @author zxj
* @date 2019年7月22日 下午4:46:14
*/
@RequestMapping("/payResult")
@ResponseBody
public String payResult(HttpServletRequest request, HttpServletResponse response) throws IOException{
String resXml="";
try {
InputStream is = request.getInputStream();
//将InputStream转换成String
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
is.close();
}
resXml=sb.toString();
Map<String, String> map = WXPayUtil.xmlToMap(resXml);
if("SUCCESS".equals(map.get("return_code"))&"SUCCESS".equals(map.get("result_code"))){
String orderid = map.get("out_trade_no");
System.out.println("订单号:"+orderid);
//根据订好号修改订单的状态 显示为已经付款
OrderPayMsg pay = payService.getOrderPayMsg(orderid);
System.out.println(pay);
if(1!=pay.getPaystate()){
String openid = map.get("openid");
String totalpay = map.get("total_fee");
String paytime = map.get("time_end");
//实际部署时一定要*100 校验支付金额与订单金额是否相等
if(pay.getTotalfee()*100==Integer.parseInt(totalpay)){
pay.setPaytype(1);
pay.setRealpay(pay.getTotalfee());
pay.setCouponid(0);
pay.setCouponvalue(0);
pay.setPaystate(1);
pay.setPaytime(TimeUtil.getCurrentTime(paytime));
pay.setOrderstate(21);
if(payService.updateOrderPayMsg(pay)>0){
System.out.println("订单:"+orderid+"付款成功,但是未能通知到用户"+openid);
}else{
System.out.println("订单:"+orderid+"付款成功,但是未能通知到用户"+openid+",且未成功跟新订单付款信息");
}
}else{//校验支付金额与订单金额是否相等,不相等则判断积分抵扣情况
System.out.println("支付金额不相等");
}
}
}
System.out.println("异步返回的信息为:"+map);
String wxresult = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
return wxresult;
} catch (Exception e) {
e.printStackTrace();
String result = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
return result;
}
}
/**
* 获取用户端IP
* @param request
* @return
*/
public String getIpAddr(HttpServletRequest request) {
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();
}
return ip;
}
}