微信退款------API操作


这个是微信退款api 可以直接复制去测试。如果没有问题可以直接封装自己的方法


package com.huanuan.zl.order.weixin;

import java.io.InputStream;
import java.security.KeyStore;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.commons.collections4.map.HashedMap;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.core.io.ClassPathResource;

import com.github.wxpay.sdk.WXPayUtil;
import com.huanuan.zl.order.weixin.util.WeiXinUtil;

public class weixin {
	
	
	
	
	
	
	
	public static void main(String[] args) {
        try {
        //构建参数
        	Map<String, String>  dataMap = new HashedMap<String, String>();
        dataMap.put("appid","");
        dataMap.put("mch_id","");
        //自行实现该随机串
        dataMap.put("nonce_str","");
        dataMap.put("out_trade_no","P190808170038402889c5318502");
        dataMap.put("out_refund_no","P190808170038402889c5318502");
        dataMap.put("total_fee","1");
        dataMap.put("refund_fee","1");
        dataMap.put("refund_desc","退款");
        //生成签名
        String sign = WXPayUtil.generateSignature(dataMap,"65b20e102f369c75c169aef14d2fb9f6");
        dataMap.put("sign", sign);
        //map数据转xml
        String xmlString = WeiXinUtil.MapToXml(dataMap);
        //发起退款
        String doRefund = doRefund("mch_id(你的商户id)", "https://api.mch.weixin.qq.com/secapi/pay/refund", xmlString);
        System.out.println("=================="+doRefund);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 *
 * @param mchId 商户ID
 * @param url 请求URL
 * @param data 退款参数
 * @return
 * @throws Exception
 */
public static String doRefund(String mchId, String url, String data) throws Exception {
    /**
     * 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的
     */
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    

//  this.getClass().getClassLoader().getResource("apiclient_cert.p12").getFile()
  //File file = new File("classpath:WX_FILE/apiclient_cert.p12");
  ClassPathResource classPathResource = new ClassPathResource("cert/apiclient_cert.p12");
  
  InputStream fileInputStream = classPathResource.getInputStream();

  //FileInputStream fileInputStream = new FileInputStream(file);1578564831
  char[] password = "你的商户id".toCharArray();
    
    //这里自行实现我是使用数据库配置将证书上传到了服务器可以使用 FileInputStream读取本地文件
//    ByteArrayInputStream inputStream = FileUtil.getInputStream("https://############################.p12");
    try {
        //这里写密码..默认是你的MCHID
        keyStore.load(fileInputStream, password);
    } finally {
    	fileInputStream.close();
    } 
    SSLContext sslcontext = SSLContexts.custom()
            //这里也是写密码的
            .loadKeyMaterial(keyStore, mchId.toCharArray())
            .build(); 
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext,
            SSLConnectionSocketFactory.getDefaultHostnameVerifier());
    CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .build();
    try {
        HttpPost httpost = new HttpPost(url);  
        httpost.setEntity(new StringEntity(data, "UTF-8"));
        CloseableHttpResponse response = httpclient.execute(httpost);
        try {
            HttpEntity entity = response.getEntity(); 
            //接受到返回信息
            String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
            EntityUtils.consume(entity);
            return jsonStr;
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }
}
	
}


使用的工具类
里面有生成签名和解析Map
组装Map的方法,验签。。。。

package com.huanuan.zl.order.weixin.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.commons.codec.digest.DigestUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.xml.sax.InputSource;



public class WeiXinUtil {


    private static int number = 10;
    private static Random random = new Random();
    @Value("${huanuan.pay.key}")
    private String key;
    



    public String getKey() {
		return key;
	}




	public void setKey(String key) {
		this.key = key;
	}




	/**
     * 组装xml
     * @param dataMap
     * @return
     */
    public static String MapToXml(Map<String, String> dataMap) {
        StringBuilder newxml = new StringBuilder();
        newxml.append("<xml>");
        for(String s : dataMap.keySet()){
            newxml.append("<").append(s).append(">");
            newxml.append(dataMap.get(s));
            newxml.append("</").append(s).append(">");
        }
        newxml.append("</xml>");
        System.out.println(newxml);
        return newxml.toString();
    }

  


    /**
     * POST请求,字符串形式数据
     * @param url 请求地址
     * @param param 请求数据
     * @param
     */
    public static String sendPostUrl(String url, String param) {

        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(),"UTF-8"));
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常!" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }


    /**
     * 验证签名
     * @param
     * @return
     */
    public static boolean checkSign(LinkedHashMap<String, Object> map) {

        String signFromAPIResponse = map.get("sign").toString();

        if (signFromAPIResponse == "" || signFromAPIResponse == null) {

            System.out.println("API返回的数据签名数据不存在,有可能被第三方篡改!!!");

            return false;

        }
        System.out.println("服务器回包里面的签名是:" + signFromAPIResponse);

        //清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名

        map.put("sign", "");

        //将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较

        String signForAPIResponse = new WeiXinUtil().creatsign(map);

        if (!signForAPIResponse.equals(signFromAPIResponse)) {

            //签名验不过,表示这个API返回的数据有可能已经被篡改了

            System.out.println("API返回的数据签名验证不通过,有可能被第三方篡改!!! signForAPIResponse生成的签名为" + signForAPIResponse);

            return false;

        }

        System.out.println("恭喜,API返回的数据签名验证通过!!!");

        return true;

    }


    /**
     * 把数组装换map
     * @param result
     * @return
     */
    public static LinkedHashMap<String, Object> XmlToMap(String result) throws DocumentException {

    	LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
        InputSource in = new InputSource (new StringReader(result));
        in.setEncoding("utf-8");
        SAXReader sax = new SAXReader();
        Document document = sax.read(in);
        Element el = document.getRootElement();
        List<Element> list = el.elements();
        for(Element element:list) {
            map.put(element.getName(), element.getTextTrim());
            System.out.println(element.getName()+"============"+element.getTextTrim());
        }
        return map;
    }

    /**
     * 签名生成
     * @return
     */
    public  String creatsign(LinkedHashMap<String, Object> linkedHashMap){
        StringBuilder xml = new StringBuilder();
        for(String s : linkedHashMap.keySet()){
            xml.append(s).append("=").append(linkedHashMap.get(s)).append("&");
        }
        xml.append("key="+key);
        String sign = DigestUtils.md5Hex(xml.toString()).toString().toUpperCase();
        System.out.println("你的签名为==="+sign);
        return sign;
    }

    /**
     * 随机生成数
     * @return
     */
    public static String strcode(){
        StringBuilder code = new StringBuilder();
        for(int i = 0 ; i < 10 ; i++){
            code.append(random.nextInt(10));
        }
        code.append(System.currentTimeMillis());
        return code.toString();
    }

    public static void main(String[] args) throws IOException {
        
        ClassPathResource classPathResource = new ClassPathResource("p12/apiclient_cert.p12");
        //InputStream inputStream = classPathResource.getInputStream();

        System.out.println(classPathResource.contentLength());
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在调用微信支付的退款接口https://api.mch.weixin.qq.com/secapi/pay/refund时,您需要传递以下参数: 1. appid:公众账号ID或应用ID。 2. mch_id:商户号。 3. nonce_str:随机字符串,不长于32位。 4. sign_type:签名类型,目前支持HMAC-SHA256和MD5,默认为MD5。 5. sign:签名,详见下面的签名生成算法。 6. transaction_id:微信订单号,与商户订单号二选一。 7. out_trade_no:商户订单号,与微信订单号二选一。 8. out_refund_no:商户退款单号。 9. total_fee:订单金额,单位为分。 10. refund_fee:退款金额,单位为分。 11. refund_fee_type:退款货币种类,可选,默认为CNY。 12. refund_desc:退款原因。 13. refund_account:退款资金来源。 签名方法根据sign_type参数来决定: 1. 若sign_type为MD5,则按照以下方法计算签名: - 将所有发送给微信支付API的数据按照参数名ASCII码从小到大排序(字典序); - 使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA; - 在stringA最后拼接上"&key=商户密钥"得到stringSignTemp字符串; - 对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,即得到sign值。 2. 若sign_type为HMAC-SHA256,则按照以下方法计算签名: - 将所有发送给微信支付API的数据按照参数名ASCII码从小到大排序(字典序); - 使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA; - 在stringA最后拼接上"&key=商户密钥"得到stringSignTemp字符串; - 对stringSignTemp进行HMAC-SHA256运算,再将得到的字符串进行Base64编码,即得到sign值。 请确保传递的参数和签名方法正确,以确保接口调用成功。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜空繁星vv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值