Java实现 微信支付 NATIVE 方式 网页二维码的形式显示

具体代码位置

mqd66/wechat-pay (github.com)

1、配置类

package vip.xiaonuo.modular.weChatPay.config;

public class WeChatConfig {

	/**
	* 微信服务号APPID
	*/
	public static String APPID="111111111111111111111";
	/**
	* 微信支付的商户号
	*/
	public static String MCHID="11111111111111111111";
	/**
	* 微信支付的API密钥
	*/
	public static String APIKEY="1111111111111111111111111";
	/**
	* 微信支付成功之后的回调地址【注意:当前回调地址必须是公网能够访问的地址】
      内网穿透去实现
	*/
	public static String WECHAT_NOTIFY_URL_PC="111111111111111111111";
//	public static String WECHAT_NOTIFY_URL_PC="http://hspay.hbhy.com.cn";
	/**
	* 微信统一下单API地址
	*/
	public static String UFDODER_URL="11111111111111111111111";
    /**
	* 应用对应的凭证
	*/
	public static String APP_SECRET="111111111111111111111";
}

2、具体核心代码

package vip.xiaonuo.modular.weChatPay.service.impl;

import cn.hutool.core.util.XmlUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.http.HttpUtil;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import vip.xiaonuo.modular.sqlcurrency.mapper.SqlMapper;
import vip.xiaonuo.modular.weChatPay.config.WeChatConfig;
import vip.xiaonuo.modular.weChatPay.entity.weChatOrg;
import vip.xiaonuo.modular.weChatPay.service.WeChatPayService;
import vip.xiaonuo.modular.weChatPay.util.PayForUtil;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;

@Service
public class WeChatPayServiceImpl implements WeChatPayService {
    @Resource
    private SqlMapper sqlMapper;
    @Override
    public void codePay(String money,HttpServletRequest request, HttpServletResponse response) {
        // 支付的商品名称
        String body="嘴巴香大辣条";
        //支付金额(单位:分)
        if("".equals(money)){
            throw new RuntimeException("出错了");
        }
//       这里转换为分
        int amountInCents = (int) (Double.parseDouble(money) * 100);
        String amountInCentsStr = String.valueOf(amountInCents);
        //获取二维码内容urlCode
        String resXml = null;
        try {
            resXml = getNative( body, amountInCentsStr);
            Map<String, Object> data= XmlUtil.xmlToMap(resXml);
            String urlCode = data.get("code_url").toString();
            //生成二维码到输出流
            response.setContentType("image/jpeg");
            ServletOutputStream out = response.getOutputStream();
            QrCodeUtil.generate(urlCode, 300, 300,"jpg" ,out);
            out.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * @Description 支付回调
     */
    @Override
    public void wxnotify(HttpServletRequest request, HttpServletResponse response) {
        // 读取回调数据
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        try {
            inputStream = request.getInputStream();
            String s;
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            while ((s = in.readLine()) != null) {
                sb.append(s);
            }
            in.close();
            inputStream.close();
            // 解析xml成map
            Map<String, Object> m=XmlUtil.xmlToMap(sb.toString());
            // 过滤空 设置 TreeMap
            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
            Iterator<String> it = m.keySet().iterator();
            while (it.hasNext()) {
                String parameter = it.next();
                Object parameterValue = m.get(parameter);
                String v = "";
                if (null != parameterValue) {
                    v = parameterValue.toString().trim();
                }
                packageParams.put(parameter, v);
            }
            // 微信支付的API密钥
            String key = WeChatConfig.APIKEY;
            // 判断签名是否正确
            if (PayForUtil.isTenpaySign(packageParams, key)) {
                String resXml = "";
                if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
                    System.err.println("--------------------------------------------");
                    System.err.println("支付回调成功。。。可在此处执行业务逻辑。。。");
                    System.err.println("--------------------------------------------");
                    // 支付成功,执行自己的业务逻辑开始
                    String app_id = (String) packageParams.get("appid");
                    String mch_id = (String) packageParams.get("mch_id");
                    String openid = (String) packageParams.get("openid");
                    // 是否关注公众号
                    String is_subscribe = (String) packageParams.get("is_subscribe");
                    // 附加参数【商标申请_0bda32824db44d6f9611f1047829fa3b_15460】--【业务类型_会员ID_订单号】
                    String attach = (String) packageParams.get("attach");
                    String out_trade_no = (String) packageParams.get("out_trade_no");
                    String total_fee = (String) packageParams.get("total_fee");
                    // 微信支付订单号
                    String transaction_id = (String) packageParams.get("transaction_id");
                    // 支付完成时间
                    String time_end = (String) packageParams.get("time_end");
                    System.out.println(packageParams);
                    // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                    resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                } else {
                    System.err.println("支付失败,错误信息:" + packageParams.get("err_code"));

                    resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                            + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                }
                response.getWriter().write(resXml);
            } else {
                System.err.println("通知签名验证失败");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }


    /**
     * @Description NATIVE支付模式(二维码网页扫码支付)
     */
    public static String getNative(String body,String totalFee) throws Exception {
        //账号信息
        String appid = WeChatConfig.APPID;
        String mch_id = WeChatConfig.MCHID;
        String key = WeChatConfig.APIKEY;

        //微信支付成功之后的回调地址【注意:当前回调地址必须是公网能够访问的地址】
        String notify_url = WeChatConfig.WECHAT_NOTIFY_URL_PC;
        String ufdoder_url = WeChatConfig.UFDODER_URL;
        String trade_type = "NATIVE";
        String out_trade_no = PayForUtil.getOrderNo();

        //请求参数封装
        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        // 随机字符串
        packageParams.put("nonce_str", "nonce"+out_trade_no);
        // 支付的商品名称
        packageParams.put("body", body);
        // 商户订单号【备注:每次发起请求都需要随机的字符串,否则失败。】
        packageParams.put("out_trade_no",out_trade_no);
        // 支付金额
        packageParams.put("total_fee", totalFee);
        // 客户端主机
        packageParams.put("spbill_create_ip", PayForUtil.localIp());
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);
        // 获取签名
        String sign = PayForUtil.createSign(packageParams, key);
        packageParams.put("sign", sign);
        // 将请求参数转换成String类型
        String requestXML = XmlUtil.mapToXmlStr(packageParams, "xml");
        // 解析请求之后的xml参数并且转换成String类型
        String resXml= HttpUtil.post(ufdoder_url, requestXML);
        return resXml;
    }
}

3、工具类

package vip.xiaonuo.modular.weChatPay.util;

import cn.hutool.crypto.digest.DigestUtil;

import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;

public class PayForUtil {
 
    /**
     * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
     * @return boolean
     */
    public static boolean isTenpaySign(SortedMap<Object, Object> packageParams, String API_KEY) {
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.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();
            if(!"sign".equals(k) && null != v && !"".equals(v)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + API_KEY);
 
        //算出摘要
        String mysign = DigestUtil.md5Hex(sb.toString()).toLowerCase();
        String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();
 
        return tenpaySign.equals(mysign);
    }
 
    /**
     * sign签名
     * @return String
     */
    public static String createSign( SortedMap<Object, Object> packageParams, String API_KEY) {
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = entry.getValue().toString();
            if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + API_KEY);
        String sign = DigestUtil.md5Hex(sb.toString());
        return sign;
    }
 
    /**
     * 获取本机IP地址
     * @return String
     */
    public static String localIp(){
        String ip = null;
        Enumeration allNetInterfaces;
        try {
            allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                List<InterfaceAddress> InterfaceAddress = netInterface.getInterfaceAddresses();
                for (InterfaceAddress add : InterfaceAddress) {
                    InetAddress Ip = add.getAddress();
                    if (Ip != null && Ip instanceof Inet4Address) {
                        ip = Ip.getHostAddress();
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return ip;
    }
 /**
     * 生成订单号
     * @return
     */
    public static String getOrderNo() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String newDate = sdf.format(new Date());
        String result = "";
        Random random = new Random();
        for (int i = 0; i < 3; i++) {
            result += random.nextInt(10);
        }
        return newDate + result;
    }
    /**
     * 元转换成分
     * @param amount
     * @return
     */
    public static String getMoney(String amount) {
        if(amount==null){
            return "";
        }
        // 金额转化为分为单位
        // 处理包含, ¥ 或者$的金额
        String currency =  amount.replaceAll("\\$|\\¥|\\,", "");
        int index = currency.indexOf(".");
        int length = currency.length();
        Long amLong = 0l;
        if(index == -1){
            amLong = Long.valueOf(currency+"00");
        }else if(length - index >= 3){
            amLong = Long.valueOf((currency.substring(0, index+3)).replace(".", ""));
        }else if(length - index == 2){
            amLong = Long.valueOf((currency.substring(0, index+2)).replace(".", "")+0);
        }else{
            amLong = Long.valueOf((currency.substring(0, index+1)).replace(".", "")+"00");
        }
        return amLong.toString();
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值