【SpringBoot2微信支付实例】
1、 POM添加微信开发支持
<parent> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
2、yml配置
weixin: #正式环境
wxpay:
useSandbox: true
app_id: adfasfasdfsdf //公众账号ID
mch_id: 134dddddd4901// 商户号
key: 13579246800987654321abcdefssssghijkl// 商户密钥
certPath: src/weixin/apiclient_cert.p12//从微信商户平台下载的安全证书存放的路径
spbill_create_ip: 114.55.200.128 //APP和网页支付提交用户端ip, Native支付填调用微信支付API的机器IP, 即:服务器ip地址
notify_url: // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。(需要配置)
trade_type: NATIVE
placeanorder_url: https://api.mch.weixin.qq.com/pay/unifiedorder
return_url_html: // 微信支付 - 统一下单地址
sandboxSignKeyurl: https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey
attach: 教育
3、wechatConfig配置文件获取yml配置
@Data@Configuration
public class WeChatConfig {
@Value("${weixin.wxpay.useSandbox}")
private boolean useSandbox;//是否沙箱环境
@Value("${weixin.wxpay.app_id}")
public String app_id; // 公众账号ID
@Value("${weixin.wxpay.mch_id}")
public String mch_id ; // 商户号
@Value("${weixin.wxpay.key}")
public String key; // 商户密钥
@Value("${weixin.wxpay.certPath}")
public String certPath =
ClassUtils.getDefaultClassLoader().getResource("").getPath()+"/weixin/apiclient_cert.p12";
//从微信商户平台下载的安全证书存放的路径
// APP和网页支付提交用户端ip, Native支付填调用微信支付API的机器IP, 即:服务器ip地址
@Value("${weixin.wxpay.spbill_create_ip}")
public String spbill_create_ip;
// 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。(需要配置)
@Value("${weixin.wxpay.notify_url}")
public String notify_url;
// 支付方式,取值如下:JSAPI,NATIVE,APP
@Value("${weixin.wxpay.trade_type}")
public String trade_type;
@Value("${weixin.wxpay.placeanorder_url}")
// 微信支付 - 统一下单地址
public String placeanorder_url;
@Value("${weixin.wxpay.attach}")
public String attach;
}
4、支付代码处理文件
controller层
/** * 正式使用环境
* @param id
* @param req
* @param response
* @return
* @throws Exception
*/
@RequestMapping(value = "/pay", method = {RequestMethod.GET, RequestMethod.POST})
public BaseResponse orderPay(@RequestParam Integer id,@RequestParam(required = false) Integer acuId,
HttpServletRequest req, HttpServletResponse response) throws Exception {
log.info("进入微信支付申请");
DlOrder dlOrder = idlOrderService.get(id);
String out_trade_no=dlOrder.getOdUuid(); // 需要前端给的参数
//获取金额,根据业务逻辑获取
String total_fee = idlOrderService.useOrNotCoupon(dlOrder,acuId); //微信支付钱的单位为分
log.info("支付金额:",total_fee);
//String user_id= dlOrder.getCreateUser(); //
String attach=weChatConfig.getAttach();
String spbill_create_ip= weChatConfig.getSpbill_create_ip();//IP地址
log.info(spbill_create_ip);
//生成订单
Map<String,String> result = wxOrderService.dounifiedOrder(id,attach,out_trade_no,total_fee,spbill_create_ip,1);
if (null != result)
{
String code_url = result.get("code_url");
log.info("返回图片地址:{}",code_url);
BufferedImage image = PayUtil.getQRCodeImge(code_url);
response.setContentType("image/jpeg");
response.setHeader("Pragma","no-cache");
response.setHeader("Cache-Control","no-cache");
response.setIntHeader("Expires",-1);
ImageIO.write(image, "JPEG", response.getOutputStream());
return successToJson(result,"获取微信支付订单成功");
}else {
return fail("获取微信支付订单失败");
}
//return resultString; //给前端app返回此字符串,再调用前端的微信sdk引起微信支付
}
service层:
//生成订单
@Override
public Map<String, String> dounifiedOrder(Integer id,String attach, String out_trade_no,
String total_fee, String spbill_create_ip, int type) throws Exception {
//第一步、查询微信服务器是否有订单
//第二步、有,则关闭先前的订单
//第三步、生成新订单
WXPay wxpay = new WXPay(config, WXPayConstants.SignType.HMACSHA256,false);
//微信生成订单参数
Map<String, String> data = convertToWXData(attach,out_trade_no,total_fee,spbill_create_ip,type);
StringBuffer url= new StringBuffer();
Map<String,String> existsresp = getExistOrder(wxpay,out_trade_no);
String existsresp_return_code = existsresp.get("return_code");
String existsresp_trade_state= existsresp.get("trade_state");
String existsresp_result_code= existsresp.get("result_code");
log.info("查询订单:{}",JSON.toJSONString(existsresp));
log.info("更新前out_trade_no:{}",out_trade_no);
if ("SUCCESS".equals(existsresp_return_code))
{
log.info("关闭已有订单,订单existsresp_return_code:{},existsresp_result_code:{},existsresp_trade_state:{}",
existsresp_return_code,existsresp_result_code,existsresp_trade_state);
if ("SUCCESS".equals(existsresp_result_code)
&& ("NOTPAY".equals(existsresp_trade_state)||"CLOSED".equals(existsresp_trade_state)))
{
log.info("关闭已有订单,订单existsresp_result_code:{}",existsresp_result_code);
closeOrder(wxpay,out_trade_no);
//更改订单UUID
out_trade_no = StringUtil.getOrderID();
data.put("out_trade_no",out_trade_no);
DlOrder dlOrder = new DlOrder();
dlOrder.setId(id);
dlOrder.setOdUuid(out_trade_no);
int i = dlOrderMapper.updateByID(dlOrder);
log.info("更新后out_trade_no:{}",out_trade_no);
}
}
try {
Map<String, String> resp = wxpay.unifiedOrder(data);
String returnCode = resp.get("return_code"); //获取返回码
String returnMsg = resp.get("return_msg");
//String nonce_str = resp.get("nonce_str");//微信返回的随机字符串
log.info("生成订单的结果:{}",JSON.toJSONString(resp));
if("SUCCESS".equals(returnCode)){ //若返回码为SUCCESS,则会返回一个result_code,再对该result_code进行判断
String resultCode = resp.get("result_code");
String errCodeDes = resp.get("err_code_des");
log.info(resultCode);
if("SUCCESS".equals(resultCode)){
//获取预支付交易回话标志
return convertToWXRst(resp,data);
}else {
//订单已经生成的情况下,直接查询订单返回
Map<String,String> existsresp2 = getExistOrder(wxpay,out_trade_no);
log.info("已经存在的订单1:{}",JSON.toJSONString(existsresp2));
log.info("订单号:{},错误信息:{}",out_trade_no,errCodeDes);
return convertToWXRst(existsresp2,data);
}
}else {
//订单已经生成的情况下,直接查询订单返回
Map<String,String> existsresp2 = getExistOrder(wxpay,out_trade_no);
log.info("已经存在的订单2:{}",JSON.toJSONString(existsresp2));
log.info("订单号:{},错误信息:{}",out_trade_no,returnMsg);
}
} catch (Exception e) {
log.info(e.getMessage());
}
return null;
}
/**
* 微信生成订单参数
* @param attach
* @param out_trade_no
* @param total_fee
* @param spbill_create_ip
* @param type
* @return
* @throws Exception
*/
private Map<String, String> convertToWXData(String attach, String out_trade_no,
String total_fee, String spbill_create_ip, int type) throws Exception {
Map<String, String> data = new HashMap<String, String>();
String body="订单支付";
data.put("appid",weChatConfig.getApp_id());
data.put("mch_id",weChatConfig.getMch_id());
data.put("nonce_str",WXPayUtil.generateNonceStr());
data.put("body", body);
data.put("out_trade_no", out_trade_no);
data.put("total_fee", total_fee);
data.put("spbill_create_ip",spbill_create_ip);
//异步通知地址(请注意必须是外网)
data.put("notify_url", weChatConfig.getNotify_url());
data.put("trade_type", weChatConfig.getTrade_type());
data.put("attach", attach);
String signtmp = WXPayUtil.generateSignature(data, config.getKey(), WXPayConstants.SignType.HMACSHA256);
data.put("sign", signtmp);
log.info("微信环境类型:{}",config.isUseSandbox());
return data;
}
/**
* 查询已有订单
* @param wxpay
* @param out_trade_no
* @return
* @throws Exception
*/
@Override
public Map<String,String> getExistOrder(WXPay wxpay, String out_trade_no) throws Exception {
Map<String,String> data = new HashMap<>();
data.put("out_trade_no",out_trade_no);
data.put("mch_id",weChatConfig.getMch_id());
Map<String, String> existsresp = wxpay.orderQuery(data);
log.info("查看是否有存在的订单:{}",JSON.toJSONString(existsresp));
return existsresp;
}
/**
* 获取订单返回值
* @param resp
* @param data
* @return
* @throws Exception
*/
private Map<String,String> convertToWXRst(Map<String, String> resp,Map<String, String> data) throws Exception {
Map<String,String> map = new HashMap<>();
String prepay_id = resp.get("prepay_id");
map.put("appid",weChatConfig.getApp_id());
map.put("mch_id",weChatConfig.getMch_id());
map.put("prepayid",prepay_id);
map.put("package","Sign=WXPay");
map.put("noncestr",resp.get("nonce_str"));
map.put("timestamp",String.valueOf(System.currentTimeMillis()/1000));
String sign = WXPayUtil.generateSignature(data, config.getKey(), WXPayConstants.SignType.HMACSHA256);
map.put("sign",sign);
map.put("timestamp",resp.get("timestamp"));
map.put("package","WXPay");
map.put("code_url",resp.get("code_url"));
map.put("return_code",resp.get("return_code"));
map.put("result_code",resp.get("result_code"));
if (null != resp.get("trade_state") && "SUCCESS".equals(resp.get("trade_state"))) {
//对于已经支付成功的订单,直接修改订单的状态
//需要判断是否已经支付,只有未支付才需要修改
String out_trade_no = resp.get("out_trade_no");
DlOrder order = dlOrderMapper.getOrderByUUID(out_trade_no);
if(null !=order.getOdStatusCode()
&& "O2".equals(order.getOdStatusCode())) {
DlOrder dlOrder = new DlOrder();
dlOrder.setOdUuid(resp.get("out_trade_no"));
dlOrder.setOdStatusCode("O3");
dlOrder.setOdStatusName("已支付");
dlOrder.setModifyTime(new Date());
dlOrder.setModifyUser("admin@qq.com");
BigDecimal total_fee = new BigDecimal(resp.get("total_fee"));
dlOrder.setOdOutOfPocket(total_fee.multiply(new BigDecimal("100")));
int update = dlOrderMapper.update(dlOrder);
//插入一条支付成功的记录
this.insertPaymentLog(resp,out_trade_no,resp.get("nonce_str"));
}
}
return map;
}
5、微信服务同步通知页面
/** * 订单支付异步通知
*/
@ApiOperation(value = "手机订单支付完成后回调")
@RequestMapping(value = "/notify",method = {RequestMethod.GET, RequestMethod.POST})
public String WXPayBack(HttpServletRequest request,HttpServletResponse response){
String resXml="";
log.info("======================>>>微信支付回调<<======================");
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 + "
");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
resXml=sb.toString();
//实例测试代码
/* resXml = "<xml><appid><![CDATA[wx7a5088333e7a7234]]></appid>
" +
"<attach><![CDATA[82569575@qq.com,7]]></attach>
" +
"<bank_type><![CDATA[CFT]]></bank_type>
" +
"<cash_fee><![CDATA[1]]></cash_fee>
" +
"<fee_type><![CDATA[CNY]]></fee_type>
" +
"<is_subscribe><![CDATA[N]]></is_subscribe>
" +
"<mch_id><![CDATA[1348674901]]></mch_id>
" +
"<nonce_str><![CDATA[51eec4509f68473da0a660baabaab8a9]]></nonce_str>
" +
"<openid><![CDATA[owyu2v00-fp62nZa-fRvEl2doR1w]]></openid>
" +
"<out_trade_no><![CDATA[2019081211264961401245689]]></out_trade_no>
" +
"<result_code><![CDATA[SUCCESS]]></result_code>
" +
"<return_code><![CDATA[SUCCESS]]></return_code>
" +
"<sign><![CDATA[BDA7CBAA80954C531F5E100559A34992]]></sign>
" +
"<time_end><![CDATA[20190813100643]]></time_end>
" +
"<total_fee>1</total_fee>
" +
"<trade_type><![CDATA[NATIVE]]></trade_type>
" +
"<transaction_id><![CDATA[4200000398201908134997424507]]></transaction_id>
" +
"</xml>";*/
//log.info("回调返回的xml结果值:{}",resXml);
String out_trade_no = wxOrderService.payBack(resXml);
if (null != out_trade_no) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
//发送邮件
log.info("启动一个线程,微信发送下单邮件。线程编号:{}",Thread.currentThread().getName());
sendPlaceOrderMail(out_trade_no);
}
});
t.start();
}
log.info("支付成功,回调结果:{}",out_trade_no);
return toPaySuccess(out_trade_no);
//return result;
}catch (Exception e){
log.error("手机支付回调通知失败",e);
String result = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
return result;
}
}
/***
* 查看支付状态
* @param id
* @param req
* @param response
* @return
*/
@ApiOperation(value = "微信手机订单支付状态")
@RequestMapping(value = "/getWXPayStatus",method = {RequestMethod.GET, RequestMethod.POST})
public BaseResponse getWXPayStatus(@RequestParam Integer id,
HttpServletRequest req, HttpServletResponse response){
try {
DlOrder dlOrder = idlOrderService.get(id);
Map<String, String> wxPayStatus = wxOrderService.getWXPayStatus(dlOrder.getOdUuid());
if (null != wxPayStatus)
{
/*{"transaction_id":"4200000376201908143196470846","nonce_str":"GNAGvXoqGWHocktm","trade_state":"SUCCESS",
"bank_type":"CFT","openid":"owyu2v00-fp62nZa-fRvEl2doR1w",
"sign":"06334CB9CFB0C65C5D09488AEA20A0E32BB323A3D095FAD46EAC843AD430C6B8",
"return_msg":"OK","fee_type":"CNY","mch_id":"1348674901",
"cash_fee":"1","out_trade_no":"2019081411420931412345679",
"appid":"wx7a5088333e7a7234","total_fee":"1",
"trade_state_desc":"支付成功","trade_type":"NATIVE","result_code":"SUCCESS",
"attach":"点教点育","time_end":"20190814114313","is_subscribe":"N","return_code":"SUCCESS"}*/
if ("SUCCESS".equals(wxPayStatus.get("return_code"))
&&"SUCCESS".equals(wxPayStatus.get("result_code"))
&&"SUCCESS".equals(wxPayStatus.get("trade_state")))
{
return successToJson("支付成功");
}
}
} catch (Exception e) {
log.info("---------------获取微信支付状态失败------------------");
e.printStackTrace();
}
return fail("支付中");
}
/**
* 成功业务处理
* @param out_trade_no 订单ID,本地业务订
* @return
*/
private String toPaySuccess(String out_trade_no){
String return_url_html = alipayConfig.getReturn_url_html();
//前后分离形式 直接返回页面 记得加上注解@Response http://login.calidray.com你要返回的网址,再页面初始化时候让前端调用你其他接口,返回信息
StringBuilder sbd = new StringBuilder();
sbd.append("<form action="");
sbd.append(return_url_html);
sbd.append("#/payForSuccess?odUuid=");
sbd.append(out_trade_no);
sbd.append("" method="get" name="form1">
");
sbd.append("</form>
");
sbd.append("<script>document.forms[0].submit();</script>");
// 如果使用优惠券,更新优惠券已经使用
DlOrder order = idlOrderService.getByUUID(out_trade_no);
dlActiveCouponUserService.setAcuIsUsed(order);
log.info("跳转页面:{}",sbd.toString());
return sbd.toString();
}
集成成功,请测试!
以上是 【SpringBoot2微信支付实例】 的全部内容, 来源链接: utcz.com/z/513991.html