技能拓展springboot

基于spring boot 的 app端微信支付

2021-04-14  本文已影响0人  Raral

基于spring boot 的 app微信支付

微信申请支付平台

  1. 根据需求提供材料,完成账户注册流程


    wx011.jpg
    wx022.jpg
    wx03.png
    wx055.jpg
  1. 在当前账户下申请支付功能

相关所有支付类型


wx_config04.png
  1. 查看对应的支付配置


    wx_config011.jpg
  2. AppId账户管理,核心配置参数

app应用


wx_config022.jpg

小程序应用


wx_config033.jpg
  1. 接入文档
    https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml
  2. 流程图


    wx_pay.png

springboot 接入app支付

controller

@Log4j2
@RequestMapping("/api/ocs/we-chat/pay")
@RestController
public class ApiOcsWeChatPayController extends BaseController {

    @Autowired
    private IApiWeChatPayService apiWeChatPayService;

    /**
     * 微信APP支付 获取预支付id
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @PostMapping("/prepay")
    public AjaxResult prepayOrder(HttpServletRequest request, HttpServletResponse response  )throws Exception{
        TenPayRes tenPayRes = apiWeChatPayService.prepayOrder(request, response);
        if (tenPayRes==null) {
            return AjaxResult.error("失败,请重试");
        }
        return AjaxResult.success("成功",tenPayRes);
    }


    /** app 微信支付校验 */
    @PostMapping("/notify")
    public void notifyRechargeOrder(HttpServletRequest request, HttpServletResponse response)throws Exception{
        boolean b = apiWeChatPayService.notifyRechargeOrder(request, response);
    }

}

//app端需要的参数
public class TenPayRes implements Serializable {

     /** appid */
     private String appId;
     /** 签名 */
     private String sign;
     /** 预支付交易会话标识 */
     private String prepayId;
     /** 商户id */
     private String partnerId;
     /** 随机字符串 */
     private String nonceStr;
     /** 时间戳 */
     private String timeStamp;
     /** 支付方式 */
     private String packageValue;
}

service

@Service
public class ApiWeChatPayServiceImpl implements IApiWeChatPayService {


    @Autowired
    private IOcsRechargeOrderService rechargeOrderService;



    /**
     *  app 微信支付  获取预支付id
     * @param request
     * @param response
     * @return
     */
    @Override
    public TenPayRes prepayOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //1. 微信支付工具类
        PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);
        //2. 获取该业务相关信息
        // 2.1 用户id
        String userId = request.getParameter("userId");
        // 2.2 订单总金额
        String totalFee =request.getParameter("orderAmount");
        BigDecimal total_fees = new BigDecimal(totalFee).multiply(new BigDecimal(100));
        int total_fee = total_fees.intValue();
        // 2.3 订单编号
        String out_trade_no = request.getParameter("orderCode");
        Long aLong = Long.valueOf(out_trade_no);
        QueryWrapper<OcsRechargeOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("code", aLong).eq("user_id", userId);
        //3. 自己业务 可以省略不写
        OcsRechargeOrder one = rechargeOrderService.getOne(wrapper);
        Integer userType = one.getUserType();
        String appId=null;
        String appSecrrt=null;
        if (userType==0){
            appId=WeChatPayStatic.APP_IDS;
            appSecrrt=WeChatPayStatic.APP_SECRETS;
        }else if(userType==1){
            appId=WeChatPayStatic.APP_ID;
            appSecrrt=WeChatPayStatic.APP_SECRET;
        }

        //4.关键 ----------------- 微信支付 参数封装  生成签名-------------
        //微信开发平台应用ID
        prepayReqHandler.setParameter("appid", appId);
        //商品描述
        prepayReqHandler.setParameter("body", WeChatPayStatic.BODY);
        //微信支付商户号
        prepayReqHandler.setParameter("mch_id", WeChatPayStatic.MCH_ID);
        String nonce_str = WXUtil.getNonceStr();
        //随机字符串
        prepayReqHandler.setParameter("nonce_str", nonce_str);
        //微信服务器回调通知url :目的就是微信那边支付成功或者失败后的回调地址,在这里 可以进行自己业务操作(异步的)
        prepayReqHandler.setParameter("notify_url", WeChatPayStatic.NOTIFY_URLS);
        prepayReqHandler.setParameter("out_trade_no", out_trade_no);
        //获取到客户端IP地址
        prepayReqHandler.setParameter("spbill_create_ip", request.getRemoteAddr());
        String timestamp = WXUtil.getTimeStamp();
        //时间戳
        prepayReqHandler.setParameter("time_start", timestamp);
        // System.out.println(String.valueOf(total_fee));
        //订单总金额
        prepayReqHandler.setParameter("total_fee", String.valueOf(total_fee));
        prepayReqHandler.setParameter("trade_type", "APP");

        /**
         * 注意签名(sign)的生成方式,具体见官方文档(传参都要参与生成签名,且参数名按照字典序排序,最后接上APP_KEY,转化成大写)
         */
        String signsss=prepayReqHandler.createMD5Sign(WeChatPayStatic.APP_KEY);
        prepayReqHandler.setParameter("sign", signsss);//签名
        prepayReqHandler.setGateUrl(WeChatPayStatic.GATEURL);//支付入口参数
        //获取prepayid
        String prepayid = prepayReqHandler.sendPrepay().get("prepay_id");

        if (prepayid != null && !prepayid.equals("")) {
            String signs = "appid=" + appId + "&noncestr=" + nonce_str + "&package=Sign=WXPay&partnerid="
                    + WeChatPayStatic.PARTNER_ID + "&prepayid=" + prepayid + "&timestamp=" + timestamp
                    + "&key="+WeChatPayStatic.APP_KEY;

            TenPayRes tenPayRes = new TenPayRes();
            tenPayRes.setAppId(appId);
            tenPayRes.setSign(Md5Encrypt.MD5Encode(signs, "utf8").toUpperCase());
            tenPayRes.setPartnerId(WeChatPayStatic.PARTNER_ID);
            tenPayRes.setPrepayId(prepayid);
            tenPayRes.setNonceStr(nonce_str);
            tenPayRes.setTimeStamp(timestamp);
            tenPayRes.setPackageValue("Sign=WXPay");
            return tenPayRes;
        }

        return null;
    }

    /**
     *  验签
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    public boolean notifyRechargeOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //获取信息流
        response.reset();
        PrintWriter writer = response.getWriter();
        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);
        }
        outSteam.close();
        inStream.close();
        String result = new String(outSteam.toByteArray(), "utf-8");
        Map<String, String> map = null;
        try {
            /**
             * 解析微信通知返回的信息
             */
            map = XMLUtil.doXMLParse(result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        String rnc = map.get("return_code");
        String rtc = map.get("result_code");
        if ("SUCCESS".equals(rnc)) {
            SortedMap<String,String> sort=new TreeMap<String,String>(map);
            String signss=sort.get("sign");
            String signs= XMLUtil.createSign(sort);
            if(!signs.equals(signss)){
                throw new Exception("微信回调参数签名不合法");
            }
            if ("SUCCESS".equals(rtc)){
                //业务校验
                // 订单编号
                String orderCode = map.get("out_trade_no");
                Long orderCodes = Long.valueOf(orderCode);
                // 支付编号
                String payCode = map.get("transaction_id");
                // 支付金额
                String total_fee = map.get("total_fee");
                boolean b = rechargeOrderService.checkRecharge(orderCodes, total_fee, 2);
                if(!b){
                    throw new Exception("金额不符");
                }
                // 支付完成 更新订单状态
                int payType=2;
                BigDecimal money = new BigDecimal(total_fee).divide(new BigDecimal("100"));
                String paymentAmount = money.toString();
                boolean flag = rechargeOrderService.updateRechargeOrder(orderCodes, payType, payCode, paymentAmount,new Date());
                String notifyStr = XMLUtil.setXML("SUCCESS", "OK");
                writer.write(notifyStr);
                writer.flush();
            }

        }

        return false;
    }
}

dao

utils



public class PrepayIdRequestHandler extends RequestHandler {

    public PrepayIdRequestHandler(HttpServletRequest request,
                                  HttpServletResponse response) {
        super( request, response );
    }


    public String createMD5Sign(String Appkeys) {


        StringBuffer sb = new StringBuffer();
        Set es = super.getAllParameters().entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            sb.append( k + "=" + v + "&" );
        }
        String params = sb.append( "key=" + Appkeys ).substring( 0 );
        String sign = Md5Encrypt.MD5Encode( params, "utf8" );
        return sign.toUpperCase();
    }

    /**
     * 提交预支付
     *
     * @return
     * @throws Exception
     */
    public Map<String,String> sendPrepay() throws Exception {
        TenpayHttpClient httpClient = this.callHP();
        Map<String, String> map = new HashMap<>();
        String prepayid = "";
        String resContent = "";
        if (httpClient != null) {
            resContent = httpClient.getResContent();
            System.out.println( "获取prepayid的返回值:" + resContent );
            map= XMLUtil.doXMLParse( resContent );

        }
        return map;
    }

    //获取沙箱密钥


    public String getShaKey() throws Exception {
        TenpayHttpClient httpClient = this.callHP();
        String SignKey = "";
        String resContent = "";
        if (httpClient != null) {
            resContent = httpClient.getResContent();
            System.out.println( "获取SignKey的返回值:" + resContent );
            Map<String, String> map = XMLUtil.doXMLParse( resContent );
            if (map.containsKey( "sandbox_signkey" )) {
                SignKey = map.get( "sandbox_signkey" );
            }
        }
        return SignKey;
    }

    public TenpayHttpClient callHP() {
        String SignKey = "";
        Set es = super.getAllParameters().entrySet();
        Iterator it = es.iterator();
        StringBuffer sb = new StringBuffer( "<xml>" );
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            sb.append( "<" + k + ">" + v + "</" + k + ">" );
        }
        sb.append( "</xml>" );
        String params = sb.substring( 0 );//截取字符串

        System.out.println( "请求参数:" + params );
        String requestUrl = super.getGateUrl();
        System.out.println( "请求url:" + requestUrl );
        TenpayHttpClient httpClient = new TenpayHttpClient();
        httpClient.setReqContent( requestUrl );
        Boolean b = httpClient.callHttpPost( requestUrl, params );
        if (b) {
            return httpClient;
        } else {
            return null;
        }
    }

}

参考文献

https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_5_2.shtml
https://blog.csdn.net/xiaxl/article/details/108851372

上一篇 下一篇

猜你喜欢

热点阅读