JAVA移动支付微信和支付宝后台代码

守給你的承諾、 提交于 2019-12-10 01:21:06

前言:之前接APP支付,微信遇到了一点点坑,为了方便以后copy,把之前写的代码粘贴出来。需要的同学可以参考一下,具体参数说明还请详细查看官方文档:

支付宝回调参数说明:https://doc.open.alipay.com/docs/doc.htm?treeId=193&articleId=105301&docType=1

微信支付回调参数:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3

1.微信支付

   1.0 导入xml支持

 <!--XML支持-->
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.7</version>
        </dependency>
        <dependency>
            <groupId>org.jdom</groupId>
            <artifactId>jdom2</artifactId>
            <version>2.0.6</version>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>

    1.1 微信统一下单

 /**
     * 统一下单
     *
     * @param orderSn
     * @param totalFee
     * @param spBillCreateIP
     * @return
     */
    public static Map<Object, Object> sendWxPayRequest(String orderSn, String totalFee, String spBillCreateIP) {
        //签名
        SortedMap<Object, Object> parameters = new TreeMap<>();
        parameters.put("appid", Constant.APPID);
        parameters.put("body", Constant.ORDER_NAME);
        parameters.put("mch_id", Constant.MCH_ID);
        parameters.put("nonce_str", String.valueOf(new Date().getTime()));
        parameters.put("notify_url", Constant.CONFIGMAP.get("weixin.asynchronousNotifyUrl"));
        parameters.put("out_trade_no", orderSn);
        parameters.put("spbill_create_ip", spBillCreateIP);
        parameters.put("total_fee", totalFee);
        parameters.put("trade_type", "APP");
        String sign = createSign("utf-8", parameters);
        //请求xml参数
        StringBuffer requestStr = new StringBuffer("<xml>");
        requestStr.append("<appid><![CDATA[");
        requestStr.append(parameters.get("appid"));
        requestStr.append("]]></appid>");
        requestStr.append("<body><![CDATA[");
        requestStr.append(parameters.get("body"));
        requestStr.append("]]></body>");
        requestStr.append("<mch_id><![CDATA[");
        requestStr.append(parameters.get("mch_id"));
        requestStr.append("]]></mch_id>");
        requestStr.append("<nonce_str><![CDATA[");
        requestStr.append(parameters.get("nonce_str"));
        requestStr.append("]]></nonce_str>");
        requestStr.append("<notify_url><![CDATA[");
        requestStr.append(parameters.get("notify_url"));
        requestStr.append("]]></notify_url>");
        requestStr.append("<out_trade_no><![CDATA[");
        requestStr.append(parameters.get("out_trade_no"));
        requestStr.append("]]></out_trade_no>");
        requestStr.append("<spbill_create_ip><![CDATA[");
        requestStr.append(parameters.get("spbill_create_ip"));
        requestStr.append("]]></spbill_create_ip>");
        requestStr.append("<total_fee><![CDATA[");
        requestStr.append(parameters.get("total_fee"));
        requestStr.append("]]></total_fee>");
        requestStr.append("<trade_type><![CDATA[");
        requestStr.append(parameters.get("trade_type"));
        requestStr.append("]]></trade_type>");
        requestStr.append("<sign><![CDATA[");
        requestStr.append(sign);
        requestStr.append("]]></sign>");
        requestStr.append("</xml>");
        try {
            String body = HttpUtil.post(Constant.ORDER_URL, requestStr.toString());
            String resultStr = new String(body.getBytes("ISO-8859-1"), "utf-8");
            SortedMap<Object, Object> resultMap = XMLUtil.doXMLParse(resultStr);
            logger.info("微信统一下单响应参数= {}", JSON.toJSON(resultMap));
            if (Constant.SUCCESS.equals(resultMap.get("result_code"))) {
                String package1 = "Sign=WXPay";
                SortedMap<Object, Object> payParameters = new TreeMap<>();
                payParameters.put("appid", Constant.APPID);
                payParameters.put("partnerid", Constant.MCH_ID);
                payParameters.put("prepayid", resultMap.get("prepay_id"));
                payParameters.put("package", package1);
                payParameters.put("noncestr", String.valueOf(new Date().getTime()));
                payParameters.put("timestamp", new Date().getTime() / 1000);
                String paySign = SignUtil.createSign("utf-8", payParameters);
                payParameters.put("sign", paySign.toUpperCase());
                return payParameters;
            } else {
                logger.warn("微信统一下单错误:{}", JSON.toJSON(resultMap));
            }
            return null;
        } catch (Exception ex) {
            logger.warn("微信统一下单异常 ex:", ex);
        }
        return null;
    }

    1.2 XmlUtil代码

package com.wangnian.util.wechat.pay;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

public class XmlUtil {
    /**
     * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
     *
     * @param strxml
     * @return
     * @throws JDOMException
     * @throws IOException
     */
    public static SortedMap<Object, Object> doXMLParse(String strxml) throws JDOMException, IOException {
        if (null == strxml || "".equals(strxml)) {
            return null;
        }
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        InputStream in = String2Inputstream(strxml);
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Element e = (Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if (children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
                v = XMLUtil.getChildrenText(children);
            }
            parameters.put(k, v);
        }
        //关闭流
        in.close();
        return parameters;
    }

    /**
     * 获取子结点的xml
     *
     * @param children
     * @return String
     */
    public static String getChildrenText(List children) {
        StringBuffer sb = new StringBuffer();
        if (!children.isEmpty()) {
            Iterator it = children.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String name = e.getName();
                String value = e.getTextNormalize();
                List list = e.getChildren();
                sb.append("<" + name + ">");
                if (!list.isEmpty()) {
                    sb.append(XMLUtil.getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }
        return sb.toString();
    }

    /**
     * 获取xml编码字符集
     *
     * @param strxml
     * @return
     * @throws IOException
     * @throws JDOMException
     */
    public static String getXMLEncoding(String strxml) throws JDOMException, IOException {
        InputStream in = String2Inputstream(strxml);
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        in.close();
        return (String) doc.getProperty("encoding");
    }

    public static InputStream String2Inputstream(String str) {
        return new ByteArrayInputStream(str.getBytes());
    }
}

   1.3 SignUtil代码

package com.wangnian.util.wechat.pay;

import com.wangnian.api.config.Constant;

import java.security.MessageDigest;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.logging.Logger;

/**
 * Created by http://my.oschina.net/wangnian on 2016/7/27.
 */
public class SignUtil {

    /**
     * 微信支付签名算法sign
     *
     * @param characterEncoding
     * @param parameters
     * @return
     */
    public static String createSign(String characterEncoding, SortedMap<Object, Object> parameters) {
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + Constant.WEIXIN_KEY);

        String sign = MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }

    private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));

        return resultSb.toString();
    }

    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname))
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes()));
            else
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes(charsetname)));
        } catch (Exception exception) {
        }
        return resultString;
    }

    private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

    public static String resultSuccess() {
        return "<xml>\n" +
                "  <return_code><![CDATA[SUCCESS]]></return_code>\n" +
                "  <return_msg><![CDATA[OK]]></return_msg>\n" +
                "</xml>";
    }
}

1.4 微信通知回调

 /**
     * 微信回调地址
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/weixin/asynchronousNotify", method = RequestMethod.POST)
    public String wexinNotify(HttpServletRequest request) {
        try {
            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 resultStr = new String(outSteam.toByteArray(), "utf-8");
            SortedMap<String, String> resultMap = XmlUtil.doXMLParse(resultStr);//将xml转成排序之后的map
            logger.info("微信支付回调地址请求参数=requst:{}", JSON.toJSON(resultMap));
            String result_code = resultMap.get("result_code");//业务结果
            String is_subscribe = resultMap.get("is_subscribe");//是否关注了微信公众号
            String out_trade_no = resultMap.get("out_trade_no");//订单号
            String transaction_id = resultMap.get("transaction_id");//微信支付订单号  类似于支付宝的交易号
            String sign = resultMap.get("sign");//签名
            String total_fee = resultMap.get("total_fee");//订单总金额  单位为 分
            String openid = resultMap.get("openid");//用户在商户appid下的唯一标识
            String time_end = resultMap.get("time_end");
            String bank_type = resultMap.get("bank_type");
            //签名验证
            String signStr = SignUtil.createSign("UTF-8", resultMap);
            logger.warn("验证= signStr:{},sign:{}", signStr, sign);
            if (!signStr.equals(sign)) {
                logger.warn("微信支付回调地址请求参数签名验证失败= signStr:{},sign:{}", signStr, sign);
                mailTools.SendMail("微信支付回调地址请求参数签名验证失败", "signStr:" + signStr + ",sign:" + sign, null);
                return "error";
            }
            if (result_code.equals("SUCCESS")) {
                logger.info("支付成功= 订单号:{},交易号:{}", out_trade_no, transaction_id);
                BigDecimal bigDecimal_total_fee = new BigDecimal(total_fee);
                BigDecimal bigDecimal = bigDecimal_total_fee.divide(new BigDecimal(100));
                //TODO 
                支付成功处理业务逻辑
            }
            //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
            return WeixinUtil.resultSuccess();
        } catch (Exception ex) {
            logger.warn("微信支付回调地址处理异常:{}", ex);
            mailTools.SendMail("环境异常,微信支付回调地址处理异常", "异常", ex);
            ex.printStackTrace();
        }
        return "success";
    }

1.5 httpUtil代码

package com.wangnian.util.net;

import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Http工具类
 * Created by wangnian on 2016/6/2.
 */
public class HttpUtil {

    private static Logger logger = LoggerFactory.getLogger(HttpUtil.class);

    /**
     * get请求
     *
     * @param url
     * @return
     */
    public static String get(String url) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpget = new HttpGet(url);
        try {
            CloseableHttpResponse response = httpClient.execute(httpget);
            HttpEntity httpEntity = response.getEntity();
            String strResult = EntityUtils.toString(httpEntity);
            logger.debug("url:{},response:{}", url, strResult);
            return strResult;
        } catch (Exception ex) {
            logger.warn("excption:{}", ex);
        } finally {
            httpget.releaseConnection();
            try {
                httpClient.close();
            } catch (IOException e) {
                logger.error("httpclient.close() Failure :{} " + e);
            }
        }
        return null;
    }

    /**
     * 带参数的get请求
     *
     * @param url
     * @param parMap
     * @return
     */
    public static String get(String url, Map<String, String> parMap) {
        String body = null;
        HttpClientBuilder httpclientBuilder = HttpClientBuilder.create();
        CloseableHttpClient httpclient = httpclientBuilder.build();
        HttpGet httpget = new HttpGet(url);
        List<NameValuePair> nvps = new ArrayList<>();
        Set<Map.Entry<String, String>> paramsEntry = parMap.entrySet();
        for (Map.Entry<String, String> paramEntry : paramsEntry) {
            nvps.add(new BasicNameValuePair(paramEntry.getKey(), paramEntry.getValue()));
        }
        try {
            String str = EntityUtils.toString(new UrlEncodedFormEntity(nvps, "UTF-8"));
            httpget.setURI(new URI(httpget.getURI().toString() + "?" + str));
            CloseableHttpResponse response = httpclient.execute(httpget);
            try {
                logger.debug("http get status is : {}", response.getStatusLine());//状态码,一般状态码为200时,为正常状态
                HttpEntity entity = response.getEntity();
                body = EntityUtils.toString(entity, "UTF-8");
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } catch (Exception e) {
            logger.info("Http Get Method Failure : {}", e);
        } finally {
            httpget.releaseConnection();
            try {
                httpclient.close();
            } catch (IOException e) {
                logger.error("httpclient.close() Failure :{} " + e);
            }
        }
        logger.info("response body : {}", body);
        return body;
    }

    /**
     * 带参数post请求
     *
     * @param url
     * @return
     */
    public static String post(String url, Map<String, String> map) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpost = new HttpPost(url);
        if (map != null) {
            List<NameValuePair> nvps = new ArrayList<>();
            for (String key : map.keySet()) {
                nvps.add(new BasicNameValuePair(key, map.get(key)));
            }
            httpost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
        }
        try {
            CloseableHttpResponse response = httpClient.execute(httpost);
            String strResult = EntityUtils.toString(response.getEntity());
            logger.debug("url:{} ,map:{},response:{}", url, map, strResult);
            return strResult;
        } catch (Exception ex) {
            logger.warn("excption:{}", ex);
        } finally {
            httpost.releaseConnection();
            try {
                httpClient.close();
            } catch (IOException e) {
                logger.error("httpclient.close() Failure :{} " + e);
            }
        }
        return null;
    }


    /**
     * RAW Post请求
     *
     * @param url
     * @param Body
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String post(String url, String Body) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpost = new HttpPost(url);
        httpost.setEntity(new StringEntity(Body, Consts.UTF_8));
        try {
            CloseableHttpResponse response = httpClient.execute(httpost);
            String strResult = EntityUtils.toString(response.getEntity());
            logger.debug("url:{} ,Body:{},response:{}", url, Body, strResult);
            return strResult;
        } catch (Exception ex) {
            logger.warn("excption:{}", ex);
        } finally {
            httpost.releaseConnection();
            try {
                httpClient.close();
            } catch (IOException e) {
                logger.error("httpclient.close() Failure :{} " + e);
            }
        }
        return null;
    }


    /**
     * 微信API请求  (带证书)
     *
     * @param url
     * @param Body
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String weixinApipost(String url, String Body) {
        HttpPost httpost = null;
        CloseableHttpClient httpClient = null;
        try {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            FileInputStream instream = new FileInputStream(new File("C:/Users/Administrator/Desktop/apiclient_cert.p12"));
            try {
                keyStore.load(instream, "1370249302".toCharArray());
            } finally {
                instream.close();
            }
            SSLContext sslcontext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, "1370249302".toCharArray())
                    .build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[]{"TLSv1"},
                    null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

            httpClient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .build();
            httpost = new HttpPost(url);
            httpost.setEntity(new StringEntity(Body, Consts.UTF_8));
            CloseableHttpResponse response = httpClient.execute(httpost);
            String strResult = EntityUtils.toString(response.getEntity());
            logger.debug("url:{} ,Body:{},response:{}", url, Body, strResult);
            return strResult;
        } catch (Exception ex) {
            logger.warn("excption:{}", ex);
        } finally {
            httpost.releaseConnection();
            try {
                httpClient.close();
            } catch (IOException e) {
                logger.error("httpclient.close() Failure :{} " + e);
            }
        }
        return null;
    }

}

 

2.支付宝支付

 2.0 导入支付宝的jar包

        <!--阿里支付-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>alipay</artifactId>
            <version>20160828220058</version>
        </dependency>

注意公共的maven里是没有这个jar包的,需要自己导入到自己的私服maven里,或者直接依赖jar包

2.1生成支付宝请求签名

        Map<String, String> map = new HashMap<>();
        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", alipay_app_id, APP_PRIVATE_KEY, "json", CHARSET_UTF8, ALIPAY_PUBLIC_KEY, "RSA2");
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody("");
        model.setSubject("");
        model.setOutTradeNo(orderNo);
        model.setTimeoutExpress("30m");
        model.setTotalAmount(orderPrice);
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        request.setNotifyUrl(alipayNotifyUrl);
        try {
            //这里和普通的接口调用不同,使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            map.put("orderString", response.getBody());//就是orderString 可以直接给客户端请求,无需再做处理。
        } catch (AlipayApiException e) {
            throw new BusinessException("获取支付宝参数错误");
        }
        return map;

2.2 支付宝通知回调

 /**
     * 支付宝异步的通知
     */
    @RequestMapping(value = "/alipay/asynchronousNotify", method = RequestMethod.POST)
    public String alipayNotify(HttpServletRequest request) throws UnsupportedEncodingException, AlipayApiException {
        logger.info("支付宝回调地址请求参数=requst:{}", JSON.toJSON(request.getParameterMap()));
        //获取支付宝POST过来反馈信息)
        Map requestParams = request.getParameterMap();
        Map<String, String> params = MapConverter.requestParameterMapToHashMap(requestParams);
        //获取支付宝POST过来反馈信息)
        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ali_public_key, AlipayConfig.input_charset) //调用SDK验证签名
        if (signVerified) {
            //按照支付结果异步通知中的描述,对支付结果中的业务内容进行1\2\3\4二次校验,校验成功后在response中返回success,校验失败返回failure
            //商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
            //支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
            //交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
            //支付账号
            String buyer_email = new String(request.getParameter("buyer_email").getBytes("ISO-8859-1"), "UTF-8");
            //支付的金额
            BigDecimal total_fee = new BigDecimal(request.getParameter("total_fee"));//支付宝原样返回  1.00
            String refund_status = request.getParameter("refund_status");//支付宝退款字段
            //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
            if (trade_status.equals("TRADE_FINISHED")) {
                logger.info("支付失败= 订单号:{},支付宝交易号:{}", out_trade_no, trade_no);
            } else if (trade_status.equals("TRADE_SUCCESS")) {
                if (refund_status != null) {
                    logger.info("退款成功= 订单号:{},支付宝交易号:{}", out_trade_no, trade_no);
                    return "success";
                }
                logger.info("支付成功= 订单号:{},支付宝交易号:{}", out_trade_no, trade_no);
                //TODO 支付成功处理业务逻辑,需要注意避免重复处理
            }

        } else {
            // TODO 验签失败则记录异常日志,并在response中返回failure.
        }
        return "success";
    }

 

3 支付宝退款

需要导入jar包

package com.wangnian;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;

import static com.fengchao.api.config.Constant.RSA_PRIVATE;

public class Test {


    public static void main(String[] args) throws AlipayApiException {
        // 支付宝的公钥,调用接口
        String ali_public_key = "WIGfMA0GCSqGSIb3DQECAQUAA4GNADCBiQKBGQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB";
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
                "2016062701558376",
                RSA_PRIVATE,
                "json",
                "GBK",
                ali_public_key);
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        request.setBizContent("{" +
                "    \"out_trade_no\":\"147254841304887\"," + //订单号
                "    \"trade_no\":\"2016083021001004360293292481\"," +//交易号
                "    \"refund_amount\":0.01," +//推荐金额
                "    \"refund_reason\":\"正常退款\"," +//退款备注
                "    \"out_request_no\":\"HZ01RF0023\"" +//标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传。
                "  }");
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        if ("10000".equals(response.getCode())) {//退款成功
              @TODO 处理业务
        } else {
            //失败
            response.getCode();
            response.getSubCode();
            response.getSubMsg();

        }

    }

}

4.微信退款

package com.wangnian;

import com.wangnian.api.config.Constant;
import com.wangnian.util.net.HttpUtil;
import com.wangnian.util.wechat.pay.XmlUtil;

import java.util.Date;
import java.util.SortedMap;
import java.util.TreeMap;

import static com.fengchao.util.wechat.pay.SignUtil.createSign;

/**
 * Created by http://my.oschina.net/wangnian on 2016/8/30.
 */
public class Test1 {
    public static void main(String[] args) {
        //签名
        SortedMap<Object, Object> parameters = new TreeMap<>();
        parameters.put("appid", Constant.APPID);
        parameters.put("mch_id", Constant.MCH_ID);
        parameters.put("nonce_str", String.valueOf(new Date().getTime()));
        parameters.put("out_trade_no", "147201368144688");//订单号
        parameters.put("out_refund_no", "1");//退款ID
        parameters.put("total_fee", "1");//订单总金额
        parameters.put("refund_fee", "1");//订单退款金额
        parameters.put("op_user_id", Constant.MCH_ID);//操作员帐号, 默认为商户号
        String sign = createSign("utf-8", parameters);
        //请求xml参数
        StringBuffer requestStr = new StringBuffer("<xml>");
        requestStr.append("<appid><![CDATA[");
        requestStr.append(parameters.get("appid"));
        requestStr.append("]]></appid>");

        requestStr.append("<mch_id><![CDATA[");
        requestStr.append(parameters.get("mch_id"));
        requestStr.append("]]></mch_id>");

        requestStr.append("<nonce_str><![CDATA[");
        requestStr.append(parameters.get("nonce_str"));
        requestStr.append("]]></nonce_str>");

        requestStr.append("<out_trade_no><![CDATA[");
        requestStr.append(parameters.get("out_trade_no"));
        requestStr.append("]]></out_trade_no>");

        requestStr.append("<out_refund_no><![CDATA[");
        requestStr.append(parameters.get("out_refund_no"));
        requestStr.append("]]></out_refund_no>");

        requestStr.append("<total_fee><![CDATA[");
        requestStr.append(parameters.get("total_fee"));
        requestStr.append("]]></total_fee>");

        requestStr.append("<refund_fee><![CDATA[");
        requestStr.append(parameters.get("refund_fee"));
        requestStr.append("]]></refund_fee>");

        requestStr.append("<op_user_id><![CDATA[");
        requestStr.append(parameters.get("op_user_id"));
        requestStr.append("]]></op_user_id>");

        requestStr.append("<sign><![CDATA[");
        requestStr.append(sign);
        requestStr.append("]]></sign>");
        requestStr.append("</xml>");
        try {
            String body = HttpUtil.weixinApipost(Constant.REFUND_URL, requestStr.toString());
            String resultStr = new String(body.getBytes("ISO-8859-1"), "utf-8");
            SortedMap<Object, Object> resultMap = XmlUtil.doXMLParse(resultStr);
            if ("SUCCESS".equals(resultMap.get("return_code")) && "SUCCESS".equals(resultMap.get("result_code"))) {
                 @TODO 处理业务逻辑
            } else {
                resultMap.get("return_msg");
                resultMap.get("err_code_des");
            }

        } catch (Exception ex) {

        }

    }

}

 

博客地址:https://my.oschina.net/wangnian

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!