springboot 整合微信 APP支付

  • Post author:
  • Post category:其他


最近搞了个团油的项目,还是一个星期就干出来的项目,其中的事情就不多说了,过来人都知道。在这里介绍一下微信的APP支付吧

首先第一步,从网上找到微信的开发文档,看看你是哪种支付,是哪种支付就点哪种支付。我是APP支付就演示这个了。

到了这里  我建议开发者先去把业务流程仔细看一遍,知道我们后台要干啥,前台要干啥。(其实方便甩锅)

这里我就不再上业务流程的图了,直接说

API

我没有做退款功能,只有支付功能,但是后台其实只用到了统一下单这个接口,让我们看一下需要哪些必填参数

微信后台可以直接给我们的有3个必填的参数,也是最重要的3个参数

应用id(APP_ID),商户号(MCH_ID),应用对应的秘钥(APP_KEY)

这3个参数可以从微信的商户平台取,我自己没有就不演示了

在这里上代码

我的配置类,涉及隐私的地方,我用*代替

package com.thundersdata.backend.basic.configure;
 
import com.github.wxpay.sdk.WXPayConfig;
import org.apache.poi.util.IOUtils;
 
import java.io.InputStream;
 
/**
 * @Author: wrc
 * @Classname MyWxpayConfig
 * @Description TODO
 * @Date 2020/5/28 13:38
 * @Created wrc
 */
public class MyWxpayConfig  implements WXPayConfig {
    private byte [] certData;
 
    public MyWxpayConfig() throws  Exception{
        InputStream certStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("cert/apiclient_cert.p12");
        this.certData = IOUtils.toByteArray(certStream);
        certStream.close();
    }
    /**
     * 微信开发平台应用ID, 从微信商户取
     */
    public static final String APP_ID = "****";
    /**
     * 应用对应的凭证
     */
//    public static final String APP_SECRET = "";
    /**
     * 应用对应的密钥, 从微信商户取
     */
    public static final String APP_KEY = "****";
    /**
     * 微信支付商户号, 从微信商户取
     */
    public static final String MCH_ID = "*****";
    /**
     * 商品描述
     */
    public static final String BODY = "付款";
    /**
     * 商户号对应的密钥
     */
//    public static final String PARTNER_key = "";
 
    /**
     * 商户id 非必填
     */
    public static final String PARTNER_ID = "*******";
    /**
     * 常量固定值
     */
    public static final String GRANT_TYPE = "client_credential";
    /**
     * 获取预支付id的接口url 写死的地址
     */
    public static String GATEURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
 
    /**
     * 微信服务器回调通知url  自己的回调接口,一定要是是域名访问才行,建议搞个nginx反向代理一下,在nginx上配置一下可以获取真实的IP地址
     */
    public static String NOTIFY_URL = "https://****.com/Pay/wx_back"; //可以访问的url
    /**
     * 微信服务器查询订单url  写死的地址
     */
    public static String ORDER_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery";
 
    @Override
    public String getAppID() {
        return APP_ID;
    }
 
    @Override
    public String getMchID() {
        return MCH_ID;
    }
 
    @Override
    public String getKey() {
        return APP_KEY;
    }
 
    @Override
    public InputStream getCertStream() {
        return null;
    }
 
    @Override
    public int getHttpConnectTimeoutMs() {
        return 8000;
    }
 
    @Override
    public int getHttpReadTimeoutMs() {
        return 10000;
    }
}

接口类

OllOrder是我自己封装的订单类,里面有我想要的具体参数,比如金额,下单用户id…

package com.thundersdata.backend.basic.controller;
 
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.thundersdata.backend.basic.configure.MyWxpayConfig;
import com.thundersdata.backend.basic.model.OllOrder;
import com.thundersdata.backend.basic.service.WxPayService;
import com.thundersdata.backend.basic.utils.AESUtil2;
import com.thundersdata.backend.basic.utils.HttpResult;
import com.thundersdata.backend.basic.utils.IPUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
 
/**
 * @Author: wrc
 * @Classname PayController
 * @Description TODO
 * @Date 2020/5/28 14:34
 * @Created wrc
 */
@Api(tags = "支付")
@RestController
@RequestMapping("/Pay")
public class PayController {
 
 
 
    @Autowired
    private WxPayService wxPayService;
 
    private Logger logger = LoggerFactory.getLogger(PayController.class);
 
    @ApiOperation(value = "微信支付")
    @PostMapping("/wxOrder")
    public HttpResult orderPay(@RequestBody @Valid OllOrder data, HttpServletRequest request) throws Exception {
        try {
            System.err.println("进入微信支付申请");
            System.out.println(data);
            String spbill_create_ip = IPUtils.getIpAddr(request);
            String key = MyWxpayConfig.APP_KEY;
            System.err.println(spbill_create_ip);
            Map<String, String> resultMap = wxPayService.dounifiedOrder(data, spbill_create_ip);
            HttpResult result=HttpResult.ok("订单生成");
            result.setData(resultMap);
            return result; //给前端app返回此字符串,再调用前端的微信sdk引起微信支付
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            return HttpResult.error("服务器繁忙,请稍后");
        }
    }
 
 
    /**
     * 微信订单回执信息接口
     * @param request
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "微信订单回执信息接口")
    @PostMapping("wx_back")
    public String test(HttpServletRequest request) throws Exception {
        String result=null;
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            reader.close();
            System.out.println("==="+sb.toString());
            result=wxPayService.payBack(sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("服务器繁忙,请稍后");
        } finally {
            return result;
        }
    }
 
 
 
 
}

Service类

package com.thundersdata.backend.basic.service;
 
import com.alibaba.fastjson.JSONObject;
import com.thundersdata.backend.basic.model.OllOrder;
 
import java.util.Map;
 
/**
 * @Author: wrc
 * @Classname WxPayService
 * @Description TODO
 * @Date 2020/5/28 14:36
 * @Created wrc
 */
public interface WxPayService {
 
 
    Map<String, String> dounifiedOrder(OllOrder ollOrder, String spbill_create_ip) throws Exception;
 
 
    String payBack(String notifyData) throws Exception;
}

ServiceImpl类

package com.thundersdata.backend.basic.service.impl;
 
import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.thundersdata.backend.basic.configure.MyWxpayConfig;
import com.thundersdata.backend.basic.model.OllOrder;
import com.thundersdata.backend.basic.service.OllOrderService;
import com.thundersdata.backend.basic.service.WxPayService;
import com.thundersdata.backend.basic.vo.OllOrderOne;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
 
/**
 * @Author: wrc
 * @Classname WxPayServiceImpl
 * @Description TODO
 * @Date 2020/5/28 14:36
 * @Created wrc
 */
@Service
public class WxPayServiceImpl  implements WxPayService {
 
 
    private static Logger logger = LoggerFactory.getLogger(WxPayServiceImpl.class);
    @Autowired
    OllOrderService OllOrderService;
 
 
 
    @Override
    public Map<String, String> dounifiedOrder(OllOrder ollOrder, String spbill_create_ip) throws Exception {
 
        //用户id
        String userId = String.valueOf(ollOrder.getCreateUserId());
        //金额
        String amount = ollOrder.getActualAmount();
        Map<String, String> fail = new HashMap<>();
        MyWxpayConfig config = new MyWxpayConfig();
        WXPay wxpay = new WXPay(config);
        Map<String, String> data = new HashMap<String, String>();
        //应用ID
        data.put("appid", MyWxpayConfig.APP_ID);
        //商户号
        data.put("mch_id", MyWxpayConfig.MCH_ID);
        //随机字符串
        data.put("nonce_str", WXPayUtil.generateNonceStr());
//        data.put("nonce_str", "test");
        //根据订单的种类不同充值类型不同
        String  body="全民乐享-加油";
        data.put("body", body);
        //商户订单号
        String outTradeNo= UUID.randomUUID().toString().replaceAll("-", "");
        ollOrder.setNumber(outTradeNo);
        data.put("out_trade_no", outTradeNo);
        System.out.println("====="+amount);
        String total = String.format("%.0f", Double.valueOf(amount) * 100);
        //总金额
        data.put("total_fee", total);
        //终端IP
        data.put("spbill_create_ip", spbill_create_ip);
        //异步通知地址(请注意必须是外网)
        data.put("notify_url", MyWxpayConfig.NOTIFY_URL);
//        data.put("openid",openId);
        //交易类型
        data.put("trade_type", "APP");
//        data.put("attach", attach);
//        data.put("sign", MD5Util.getSign(data));
        //应用对应的密钥
        String sign11 = WXPayUtil.generateSignature(data, MyWxpayConfig.APP_KEY);
 
        System.out.println("sign:" + sign11);
        //签名
        data.put("sign", WXPayUtil.generateSignature(data, MyWxpayConfig.APP_KEY));
        System.out.println(data);
        StringBuffer url = new StringBuffer();
        Map<String,String>dataMap=new HashMap<String,String>();
        Map<String,String> map = new HashMap<>();
        try {
            //下单
            Map<String, String> resp = wxpay.unifiedOrder(data);
            if("SUCCESS".equals(resp.get("result_code"))){
                String nonce_str = (String)resp.get("nonce_str");
                //预支付交易会话标识
                String prepay_id = (String)resp.get("prepay_id");
                Long time =System.currentTimeMillis()/1000;
                //吊起支付接口
                map.put("appid",config.getAppID());
                map.put("partnerid",config.getMchID());
                map.put("package","Sign=WXPay");
                map.put("noncestr",nonce_str);
                map.put("timestamp",time+"");
                map.put("prepayid",prepay_id);
                String sign=WXPayUtil.generateSignature(map, MyWxpayConfig.APP_KEY);
                map.put("sign",sign);
                System.out.println(resp);
                //map.put("time",System.currentTimeMillis()/1000+"");
 
                ollOrder.setStatus(0);
                OllOrderService.insertSelective( ollOrder);
            }
            resp.put("time",System.currentTimeMillis()/1000+"");
            return map;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            logger.info(e.getMessage());
        }
        return fail;
    }
 
 
 
    /**
     * 回调
     * @param notifyData
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public String payBack(String notifyData) throws Exception {
        Map<String,String> notifyMap=WXPayUtil.xmlToMap(notifyData);
        MyWxpayConfig config = new MyWxpayConfig();
        WXPay wxpay = new WXPay(config);
        Map<String,String> resultMap=new HashMap<String,String>();
 
        resultMap.put("return_code","SUCCESS");
        resultMap.put("return_msg","OK");
        //验证
        if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
            //签名正确
            //状态码SUCCESS或者FALL
            System.out.println(1);
            String result_code=notifyMap.get("result_code").toUpperCase();
            //订单号
            String out_trade_no = notifyMap.get("out_trade_no");
            OllOrder order = OllOrderService.selectOne(out_trade_no);
            System.out.println(order);
            OllOrder ordered = new OllOrder();
            if("SUCCESS".equals(result_code)) {
                System.out.println(2);
                System.out.println(notifyMap);
                //总金额,微信返回的金额是分为单位的,转化为元为单位的
                Double total_fee = Double.valueOf(notifyMap.get("total_fee")) / 100;
                System.out.println(String.format("%.0f", total_fee));
                if(order.getStatus()==0){
                    //所有验证结束后 进行订单状态的修改
                    System.out.println("修改订单状态");
                    order.setStatus(1);
                    OllOrderService.updateByPrimaryKeySelective(order);
                    ordered.setId(order.getId());
                    ordered.setStatus(1);
                    ordered.setUpdateTime(new Date());
                    System.out.println("支付===="+ordered);
                    OllOrderService.updateByPrimaryKeySelective(ordered);
                }
            }else {
                //微信返回支付失败信息修改支付状态为失败
                //String out_trade_no=notifyMap.get("out_trade_no");
                ordered.setId(order.getId());
                //状态码4为支付失败
                order.setStatus(4);
                OllOrderService.updateByPrimaryKeySelective(order);
                ordered.setStatus(4);
                ordered.setUpdateTime(new Date());
                System.out.println("支付===="+ordered);
                OllOrderService.updateByPrimaryKeySelective(ordered);
            }
        }else {
            System.out.println("签名错误");
            logger.info("签名错误");
            new RuntimeException("签名错误");
        }
        notifyMap.remove("sign");
        String sign11 = WXPayUtil.generateSignature(notifyMap, MyWxpayConfig.APP_KEY);
        System.out.println("=========|||"+sign11);
        return WXPayUtil.mapToXml(resultMap);
    }
 
 
 
}



版权声明:本文为weixin_50185313原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。