java-微信支付-app

袁良弼
2023-12-01

操作之前建议查看官方文档熟悉名词解释
链接: 微信支付app官方文档
坐标–>

        <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>

微信配置参数–>
(小插曲,安卓接wx_package的时候使用’='号切割 但是由于这个字段的特殊性 最后采用的是安卓写死…)

 //appId
    private String appId = "123456";
    //商户id
    private String mchId = "123456";
    //商户密钥
    private String key = "123456";
    // AppSecret
    private String appSecret = "123456";
    //证书存放地址
    private String certPath = "";
    //HTTP链接超时时间
    private int httpConnectTimeoutMs = 8000;
    //HTTP读取数据超时时间
    private int httpReadTimeoutMs = 10000;
    //微信支付异步通知地址
    private String payNotifyUrl = "123456";
	
    private String wx_package ="Sign=WXPay";

支付下单–>
下单接口是个大坑,参数必须保持顺序否则会报出签名异常
链接: 微信检测签名.
还需要注意的是:再请求完下单接口后,需要进行二次签名才能返给app调起支付,否则一直会报参数异常

//1.参数封装
public String create(PayElementVO vo) throws Exception {
        Map data = new HashMap();
        data.put("appid", weixinConfig.getAppId());//公众账号ID
        if (StringUtils.isNotEmpty(vo.getSubject())) {
            data.put("body", vo.getSubject());
        }
        data.put("mch_id", weixinConfig.getMchId());//商户
        data.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
        data.put("notify_url", weixinConfig.getPayNotifyUrl());
        data.put("out_trade_no", vo.getOrderId());//交易订单号
        data.put("spbill_create_ip", "111,111,1,1");//服务器IP
        data.put("total_fee", yuan.toString());//金额(分)
        data.put("trade_type", "APP");//交易类型
        try {
            String xmlParam = WXPayUtil.generateSignedXml(data, weixinConfig.getKey());
            System.out.println("请求的参数:" + xmlParam);
            Map<String, String> stringMap = WXPayUtil.xmlToMap(xmlParam);
            //2.发送请求
            String xmlResult = HttpClientUtil.postXML(WXPayConstants.UNIFIEDORDER_URL, xmlParam);
            Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
			//3.组装返回给安卓的数据 需要二次签名
            Map map = new LinkedHashMap<String, String>();
            map.put("appid", mapResult.get("appid"));
            map.put("partnerid", mapResult.get("mch_id"));
            map.put("prepayid", mapResult.get("prepay_id"));
            map.put("noncestr", mapResult.get("nonce_str"));
            map.put("timestamp", String.valueOf(new Date().getTime()).substring(0, 10));
            map.put("package", "Sign=WXPay");
            String signature = WXPayUtil.generateSignature(map, weixinConfig.getKey());
            String resultString = "{\"appid\":\"" + mapResult.get("appid") + "\",\"partnerid\":\"" + mapResult.get("mch_id") + "\",\"package\":\"Sign=WXPay\"," +
                    "\"noncestr\":\"" + mapResult.get("nonce_str") + "\",\"timestamp\":" + map.get("timestamp") + "," +
                    "\"prepayid\":\"" + mapResult.get("prepay_id") + "\",\"sign\":\"" + signature + "\"}";
            return resultString;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "";
        }
 }

查询订单交易情况

链接: 微信查询订单状态.

    /**
     * 查询订单消费情况
     */
    public Map queryPayStatus(String transactionId) {
//        Order order = orderMapper.selectById(orderId);
//        BigDecimal amount = order.getAmount();
        //1.封装参数
        Map param = new HashMap();
        param.put("appid", weixinConfig.getAppId());
        param.put("mch_id", weixinConfig.getMchId());
        param.put("nonce_str", WXPayUtil.generateNonceStr());
        param.put("transaction_id", transactionId);
        try {
            String xmlParam = WXPayUtil.generateSignedXml(param, weixinConfig.getKey());
            //2.发送请求
            String xmlResult = HttpClientUtil.postXML(WXPayConstants.ORDERQUERY_URL, xmlParam);
            Map<String, String> map = WXPayUtil.xmlToMap(xmlResult);
//            if (amount.compareTo(new BigDecimal(map.get("settlement_total_fee"))) != 0) {
//                return new HashMap();
//            }
            log.info("【微信查詢訂單】xmlParam={}", xmlParam);
            return map;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

微信回调

由于业务问题,使用的回调 没使用查单进行操作
需要额外注意的是回调接口必须外网可访问
可以使用公司服务器 或者使用小工具ngrok内网穿透 本地调试起来不要太方便!

 /**
     * 微信回调
     */
    public void WXPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
      	Map<String, String> params = getRequestMap(request, params);
        String orderId = params.get("out_trade_no");
   
        boolean signatureValid = false;
        try {
            signatureValid = WXPayUtil.isSignatureValid(params, weixinConfig.getKey());
        } catch (Exception e) {
			log.error("【微信异步通知】微信回调通知失败 e={} params={}", e, params);
            responseBody(response, "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![回调通知失败]></return_msg></xml>");
            return;
        }
        if (signatureValid == false) {
            log.error("【微信异步通知】验证签名错误 params={}",params);
            responseBody(response, "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![验证签名错误]></return_msg></xml>");
            return;
        }
        //向微信发送成功接收通知
        responseBody(response, "<xml><return_code><![CDATA[SUEECSS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
        return;
    }
     private Map<String, String> getRequestMap(HttpServletRequest request, Map<String, String> params) {
        String inputLine = null;
        // 接收到的数据
        StringBuffer recieveData = new StringBuffer();
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(
                    request.getInputStream(), "UTF-8"));
            while ((inputLine = in.readLine()) != null) {
                recieveData.append(inputLine);
            }
        } catch (IOException e) {
        } finally {
            try {
                if (null != in) {
                    in.close();
                }
            } catch (IOException e) {
            }
        }
        try {
            params= WXPayUtil.xmlToMap(recieveData.toString());//微信jdk 中一个XML转MAP的工具
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return params;
    }

httpClient工具类–>

package com.ftsino.huntingalliance.common.utils;

import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

@Component
public class httpClientUtils{
    private static final Log logger = LogFactory.getLog(httpClientUtils.class);
    private static final int timeout = 5000;
    public static final String DEFAULT_CHARSET = "UTF-8";

    /**
     * 获取一个HttpClient对象
     *
     * @return
     */
    public static HttpClient getHttpClient() {
        HttpClient client = new HttpClient();
        client.getHttpConnectionManager().getParams().setConnectionTimeout(timeout);
        client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, DEFAULT_CHARSET);
        return client;
    }

    /**
     * 提交xml
     *
     * @param url     地址
     * @param xmlFile xml文件
     * @return
     */
    public static String postXML(String url, String xmlFile) {
        return postXML(url, xmlFile, getHttpClient());
    }

    /**
     * 提交xml
     *
     * @param url    地址
     * @param xml    xml内容
     * @param client
     * @return
     */
    public static String postXML(String url, String xml, HttpClient client) {
        String resp = null;
        PostMethod post = new PostMethod(url);
        try {
            RequestEntity requestEntity = new StringRequestEntity(xml, "text/xml", DEFAULT_CHARSET);
            post.setRequestEntity(requestEntity);
            // 指定请求内容的类型
            post.setRequestHeader("Content-type", "application/xml; charset=" + DEFAULT_CHARSET);
            client.executeMethod(post);
            resp = post.getResponseBodyAsString();
        } catch (Exception e) {
            logger.error("提交xml失败", e);
            throw new RuntimeException("提交xml失败");
        } finally {
            post.releaseConnection();
        }
        return resp;
    }
}

使用微信中遇到的问题(支付以及回调)
请参考 微信支付以及回调问题.

.

 类似资料: