微信Navicat(二维码扫码)支付(Java开发)完整版

一:准备工作

1:先去微信公众平台注册一个公众号,选择服务号

2:去微信商户平台注册一个商户号,用于收款

3:在商户号中配置对应的公众号的APPID

4:支付结果异步通知(需要重点注意)

注意:请先详细查看官方文档按步骤开发,一切以官方文档为主 微信Navicat支付官方文档

5:测试的时候一定要使用内网穿透软件,否则回调时会报错

二:开发代码

WeChatPayConfig:

public class WeChatPayConfig {
    //公众号APPID
    private String APPID = "";

    //商户号KEY
    private String KEY = "";

    //商户号ID
    private String MCHID = "";

    //支付完成后微信回调地址,需要外网能访问要是域名,不能是127.0.0.1跟localhost
    private String NOTIFY_URL = "";
}

WeChatPayServcie:
public interface WeChatPayServcie {

    //微信支付下单
    public Map<String,String> getWxpayUrl(Map<String, String> sourceMap);

    //订单查询
    public String orderQuery(String out_trade_no);
}

@Service
public class WeChatPayServiceImpl implements WeChatPayServcie {
   
    /**
     * 微信支付请求
     * @param sourceMap
     * @return
     */
    public Map<String,String> getWxpayUrl(Map<String, String> sourceMap) {
        SortedMap<String, Object> signParams = new TreeMap<String, Object>();
        String nonce_str = UUID.randomUUID().toString().trim().replaceAll("-", "");
        signParams.put("appid", PayConfig.APPID);
        signParams.put("mch_id",PayConfig.MCHID);
        signParams.put("nonce_str",sourceMap.get("nonce_str"));
        signParams.put("product_id",sourceMap.get("prod_id"));
        signParams.put("body",sourceMap.get("body"));
        signParams.put("out_trade_no",sourceMap.get("out_trade_no"));
        signParams.put("total_fee",sourceMap.get("total_fee"));
        signParams.put("spbill_create_ip", WxUtil.getIp());
        signParams.put("notify_url",PayConfig.NOTYFLY_URL);
        signParams.put("trade_type","NATIVE");
        String sign = WxUtil.createSign(signParams,PayConfig.KEY);
        signParams.put("sign",sign);
        String xmlPackage = WxUtil.parseMapXML(signParams);
        Map<String, Object> resultMap = new HashMap();
        try {
            String result = HttpUtil.post("https://api.mch.weixin.qq.com/pay/unifiedorder",xmlPackage);
            resultMap = WxUtil.parseXmlMap(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String returnCode = (String) resultMap.get("return_code");
        String returnMsg = (String) resultMap.get("return_msg");
        if (returnCode.equalsIgnoreCase("FAIL")) {
            throw new RuntimeException(returnMsg);
        }
        String result_code = (String) resultMap.get("result_code");
        if (result_code.equalsIgnoreCase("FAIL")) {
            throw new RuntimeException(resultMap.get("err_code_des"));
        }
        String code_url = (String) resultMap.get("code_url");
        Map<String,String> map = new HashMap<>();
        map.put("code_url",code_url);
        map.put("out_trade_no",sourceMap.get("out_trade_no"));
        return map;
    }


    /**
     * 微信支付订单查询
     * @param out_trade_no
     * @return
     */
    public String orderQuery(String out_trade_no) {
        String nonce_str = UUID.randomUUID().toString().trim().replaceAll("-", "");
        SortedMap<String, Object> signParams = new TreeMap<>();
        signParams.put("appid", payConfig.getWeChatPorpetties().getAppId());
        signParams.put("mch_id",payConfig.getWeChatPorpetties().getMchId());
        signParams.put("out_trade_no",out_trade_no);
        signParams.put("nonce_str",nonce_str);
        String sign = WxUtil.createSign(signParams,payConfig.getWeChatPorpetties().getApiKey());
        signParams.put("sign",sign);
        String xmlPackage = WxUtil.parseMapXML(signParams);
        Map<String, Object> resultMap = new HashMap();
        try {
            String result = HttpUtil.post("https://api.mch.weixin.qq.com/pay/orderquery",xmlPackage);
            resultMap = WxUtil.parseXmlMap(result);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("渠道网络异常");
        }
        String returnCode = (String) resultMap.get("return_code");
        String returnMsg = (String) resultMap.get("return_msg");
        if (returnCode.equalsIgnoreCase(PayContants.FAIL)) {
            throw new RuntimeException(returnMsg);
        }
        String result_code = (String) resultMap.get("result_code");
        if (result_code.equalsIgnoreCase(PayContants.FAIL)) {
            throw new RuntimeException(resultMap.get("err_code_des"));
        }
        String trade_state = (String) resultMap.get("trade_state");
        return trade_state;
    }
}

WeChatPayController:
/**
 * 微信支付接口
 */
@Controller
public class WxPayController {

    @Autowired
    WeChatPayServcie weChatPayServcie;

   /**
    * 微信支付下单
    * payID可以不用传自己生成32位以内的随机数就好,要保证不重复
    * totalFee金额一定要做判断,判断这笔支付金额与数据库是否一致
    */
    @RequestMapping("pay")
    @ResponseBody
    public Map<String ,String> toWxpay(HttpServletRequest httpRequest,String payId, String totalFee, String body){
        System.out.println("开始微信支付...");
        Map<String, String> map = new HashMap<>();
        String nonce_str = UUID.randomUUID().toString().trim().replaceAll("-", "");

        //生成一笔支付记录


        //拼接支付参数
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("nonce_str", nonce_str);
        paramMap.put("prod_id", payId);
        paramMap.put("body", body);
        paramMap.put("total_fee", totalFee);
        paramMap.put("out_trade_no", payId);

        //发送支付请求并获取返回参数与二维码,用于支付与调用查询接口
        Map<String, String> returnMap = weChatPayServcie.getWxpayUrl(paramMap);
        httpRequest.setAttribute("out_trade_no", payId);
        httpRequest.setAttribute("total_fee", totalFee);
        
        //code_url就是二维码URL,可以把这个URL放到草料二维码中生成微信二维码
        httpRequest.setAttribute("code_url", returnMap.get("code_url"));

        map.put("out_trade_no", payId);
        map.put("total_fee", String.valueOf(bigDecimal));
        map.put("code_url", returnMap.get("code_url"));
        return map;
    }

    /**
    * 查询微信订单
    * ot_trade_no是支付
    */
    @RequestMapping("query")
    @ResponseBody
    public Root<String> orderQuery(String out_trade_no){
        return weixinPayServcie.orderQuery(queryCallbackForm.getOut_trade_no());
    }

    /**
    * 微信支付回调,这个地址就是Config中的NOTYFLY_URL
    */
    @RequestMapping("callback")
    public void notify_url(HttpServletRequest request, HttpServletResponse response) throws DocumentException, ServletException, IOException,Throwable {
        System.out.print("微信支付回调获取数据开始...");
        String inputLine;
        String notityXml = "";
        try {
            while ((inputLine = request.getReader().readLine()) != null) {
                notityXml += inputLine;
            }
            request.getReader().close();
        } catch (Exception e) {
            WxUtil.sendXmlMessage(request,response, PayContants.FAIL);
            throw new RuntimeException("回调数据xml获取失败!");
        }
        if(StringUtils.isEmpty(notityXml)){
            WxUtil.sendXmlMessage(request,response, PayContants.FAIL);
            throw new RuntimeException("回调数据xml为空!");
        }
        Map<String ,Object> resultMap = XMLParse.parseXmlMap(notityXml);
        String returnCode = (String) resultMap.get("return_code");
        String returnMsg = (String) resultMap.get("return_msg");
        if (returnCode.equalsIgnoreCase(PayContants.FAIL)) {
            WxUtil.sendXmlMessage(request,response, PayContants.FAIL);
            throw new RuntimeException(returnMsg);
        }
        String resultCode = (String) resultMap.get("result_code");
        if (resultCode.equalsIgnoreCase(PayContants.FAIL)) {
            WxUtil.sendXmlMessage(request,response, PayContants.FAIL);
            throw new RuntimeException(resultMap.get("err_code_des"));
        }

        SortedMap<String ,Object> paramMap = new TreeMap<>();
        paramMap.put("appid",resultMap.get("appid"));
        paramMap.put("mch_id",resultMap.get("mch_id"));
        paramMap.put("nonce_str",resultMap.get("nonce_str"));
        paramMap.put("body",resultMap.get("body"));
        paramMap.put("openid", resultMap.get("openid"));
        paramMap.put("is_subscribe",resultMap.get("is_subscribe"));
        paramMap.put("trade_type",resultMap.get("trade_type"));
        paramMap.put("bank_type",resultMap.get("bank_type"));
        paramMap.put("total_fee",resultMap.get("total_fee"));
        paramMap.put("fee_type",resultMap.get("fee_type"));
        paramMap.put("cash_fee",resultMap.get("cash_fee"));
        paramMap.put("transaction_id",resultMap.get("transaction_id"));
        paramMap.put("out_trade_no",resultMap.get("out_trade_no"));
        paramMap.put("time_end",resultMap.get("time_end"));
        paramMap.put("return_code",resultMap.get("return_code"));
        paramMap.put("return_msg",resultMap.get("return_msg"));
        paramMap.put("result_code",resultMap.get("result_code"));

        String out_trade_no = (String) resultMap.get("out_trade_no");
        String sign = SignUtil.createSign(paramMap,WxPayConfig.KEY);
        String mySign =(String) resultMap.get("sign");

        //回调一定要验证签名以防数据被篡改
        if(sign.equals(mySign)){
            System.out.println("回调签名验证成功!");
            
                //修改业务逻辑,将那笔支付状态改为已支付
            }
            WxUtil.sendXmlMessage(request,response, PayContants.SUCCESS);
        }else{
            WxUtil.sendXmlMessage(request,response, PayContants.FAIL);
            throw new RuntimeException("签名不一致!");
        }
    }

}

WxUtil:
package com.ys.commons.utils.pay;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//微信工具类
public class WxUtil {

    //获取当前IP
    public static String getIp() {
        try {
            String spbill_create_ip = InetAddress.getLocalHost().getHostAddress();
            return spbill_create_ip;
        } catch (UnknownHostException var2) {
            var2.printStackTrace();
            return "获取IP失败...";
        }
    }

    //输出xml格式
    public static void sendXmlMessage(HttpServletRequest request, HttpServletResponse response, String content) {
        try {
            String contentXml = "<xml><return_code><![CDATA[" + content + "]]></return_code></xml>";
            OutputStream os = response.getOutputStream();
            BufferedWriter resBr = new BufferedWriter(new OutputStreamWriter(os));
            resBr.write(contentXml);
            resBr.flush();
            resBr.close();
        } catch (IOException var6) {
            var6.printStackTrace();
        }

    }
    
    //生成sign签名
    public static String createSign(SortedMap<String, Object> packageParams, String KEY) {
        StringBuffer sb = new StringBuffer();
        Set<Entry<String, Object>> es = packageParams.entrySet();
        Iterator it = es.iterator();

        while(it.hasNext()) {
            Entry<String, Object> entry = (Entry)it.next();
            String k = (String)entry.getKey();
            String v = (String)entry.getValue();
            if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }

        sb.append("key=" + KEY);
        String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
        return sign;
    }

    //将map转为xml
    public static String parseMapXML(SortedMap<String, Object> map) {
        String xmlResult = "";
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Iterator var3 = map.keySet().iterator();

        while(var3.hasNext()) {
            String key = (String)var3.next();
            String value = "<![CDATA[" + map.get(key) + "]]>";
            sb.append("<" + key + ">" + value + "</" + key + ">");
            System.out.println();
        }

        sb.append("</xml>");
        xmlResult = sb.toString();
        return xmlResult;
    }

    //将xml转为map
    public static Map<String, Object> parseXmlMap(String xml) throws DocumentException {
        Document document = DocumentHelper.parseText(xml);
        Element root = document.getRootElement();
        List<Element> elementList = root.elements();
        Map<String, Object> map = new HashMap();
        Iterator var5 = elementList.iterator();

        while(var5.hasNext()) {
            Element e = (Element)var5.next();
            map.put(e.getName(), e.getText());
        }

        return map;
    }
}

发送请求需要推荐一个非常好用的工具,里面各种常用的工具都封装好了hutool,如果想直接复制代码使用也需要引入此工具的maven库

注意:此工具只支持JDK 1.7以上

至此代码已经完成,有意见建议的都可以留言,后续会更新最完整最新版的PayPal支付,同时有需要的也可以看看博主的支付宝PC支付

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值