Java支付宝APP支付-统一收单交易退款

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Jay_1989/article/details/82384315

上一章已经讲述了支付宝服务器异步通知接口的开发,这一章我们讲述一下支付宝统一收单交易退款接口的开发。

1、应用场景

当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,支付宝将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。 交易超过约定时间(签约时设置的可退款时间)的订单无法进行退款 支付宝退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。一笔退款失败后重新提交,要采用原来的退款单号。总退款金额不能超过用户实际支付金额。

2、公共参数

2.1请求地址

环境 HTTPS请求地址
正式环境 https://openapi.alipay.com/gateway.do

2.2公共请求参数

参数 类型 是否必填 最大长度 描述 示例值
app_id String 32 支付宝分配给开发者的应用ID 2014072300007148
method String 128 接口名称 alipay.trade.refund
format String 40 仅支持JSON JSON
charset String 10 请求使用的编码格式,如utf-8,gbk,gb2312等 utf-8
sign_type String 10 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 RSA2
sign String 344 商户请求参数的签名串,详见签名 详见示例
timestamp String 19 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" 2014-07-24 03:07:50
version String 3 调用的接口版本,固定为:1.0 1.0
app_auth_token String 40 详见应用授权概述  
biz_content String   请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档  

3、请求参数

参数 类型 是否必填 最大长度 描述 示例值
out_trade_no String 特殊可选 64 订单支付时传入的商户订单号,不能和 trade_no同时为空。 20150320010101001
trade_no String 特殊可选 64 支付宝交易号,和商户订单号不能同时为空 2014112611001004680073956707
refund_amount Price 必选 9 需要退款的金额,该金额不能大于订单金额,单位为元,支持两位小数 200.12
refund_currency String 可选 8 订单退款币种信息 USD
refund_reason String 可选 256 退款的原因说明 正常退款
out_request_no String 可选 64 标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传。 HZ01RF001
operator_id String 可选 30 商户的操作员编号 OP001
store_id String 可选 32 商户的门店编号 NJ_S_001
terminal_id String 可选 32 商户的终端编号 NJ_T_001
 goods_detail GoodsDetail[] 可选   退款包含的商品列表信息,Json格式。 
其它说明详见:“商品明细说明”
 
refund_royalty_parameters OpenApiRoyaltyDetailInfoPojo[] 可选   退分账明细信息  

4、公共响应参数

参数 类型 是否必填 最大长度 描述 示例值
code String - 网关返回码,详见文档 40004
msg String - 网关返回码描述,详见文档 Business Failed
sub_code String - 业务返回码,参见具体的API接口文档 ACQ.TRADE_HAS_SUCCESS
sub_msg String - 业务返回码描述,参见具体的API接口文档 交易已被支付
sign String - 签名,详见文档 DZXh8eeTuAHoYE3w1J+POiPhfDxOYBfUNn1lkeT/V7P4zJdyojWEa6IZs6Hz0yDW5Cp/viufUb5I0/V5WENS3OYR8zRedqo6D+fUTdLHdc+EFyCkiQhBxIzgngPdPdfp1PIS7BdhhzrsZHbRqb7o4k3Dxc+AAnFauu4V6Zdwczo=

5、响应参数

参数 类型 是否必填 最大长度 描述 示例值
trade_no String 必填 64 2013112011001004330000121536 支付宝交易号
out_trade_no String 必填 64 商户订单号 6823789339978248
buyer_logon_id String 必填 100 用户的登录id 159****5620
fund_change String 必填 1 本次退款是否发生了资金变化 Y
refund_fee Price 必填 11 退款总金额 88.88
refund_currency String 选填 8 退款币种信息 USD
gmt_refund_pay Date 必填 32 退款支付时间 2014-11-27 15:45:57
refund_detail_item_list TradeFundBill 选填   退款使用的资金渠道  
store_name String 选填 512 交易在支付时候的门店名称 望湘园联洋店
buyer_user_id String 必填 28 买家在支付宝的用户id 2088101117955611
present_refund_buyer_amount String 选填 11 本次退款金额中买家退款金额 88.88
present_refund_discount_amount String 选填 11 本次退款金额中平台优惠退款金额 88.88
present_refund_mdiscount_amount String 选填 11 本次退款金额中商家优惠退款金额 88.88

6、请求示例

AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
request.setBizContent("{" +
"\"out_trade_no\":\"20150320010101001\"," +
"\"trade_no\":\"2014112611001004680073956707\"," +
"\"refund_amount\":200.12," +
"\"refund_currency\":\"USD\"," +
"\"refund_reason\":\"正常退款\"," +
"\"out_request_no\":\"HZ01RF001\"," +
"\"operator_id\":\"OP001\"," +
"\"store_id\":\"NJ_S_001\"," +
"\"terminal_id\":\"NJ_T_001\"," +
"      \"goods_detail\":[{" +
"        \"goods_id\":\"apple-01\"," +
"\"alipay_goods_id\":\"20010001\"," +
"\"goods_name\":\"ipad\"," +
"\"quantity\":1," +
"\"price\":2000," +
"\"goods_category\":\"34543238\"," +
"\"body\":\"特价手机\"," +
"\"show_url\":\"http://www.alipay.com/xxx.jpg\"" +
"        }]," +
"      \"refund_royalty_parameters\":[{" +
"        \"royalty_type\":\"transfer\"," +
"\"trans_out\":\"2088101126765726\"," +
"\"trans_out_type\":\"userId\"," +
"\"trans_in_type\":\"userId\"," +
"\"trans_in\":\"2088101126708402\"," +
"\"amount\":0.1," +
"\"amount_percentage\":100," +
"\"desc\":\"分账给2088101126708402\"" +
"        }]" +
"  }");
AlipayTradeRefundResponse response = alipayClient.execute(request);
if(response.isSuccess()){
System.out.println("调用成功");
} else {
System.out.println("调用失败");
}

7、响应示例

{
    "alipay_trade_refund_response": {
        "code": "10000",
        "msg": "Success",
        "trade_no": "支付宝交易号",
        "out_trade_no": "6823789339978248",
        "buyer_logon_id": "159****5620",
        "fund_change": "Y",
        "refund_fee": 88.88,
        "refund_currency": "USD",
        "gmt_refund_pay": "2014-11-27 15:45:57",
        "refund_detail_item_list": [
            {
                "fund_channel": "ALIPAYACCOUNT",
                "amount": 10,
                "real_amount": 11.21,
                "fund_type": "DEBIT_CARD"
            }
        ],
        "store_name": "望湘园联洋店",
        "buyer_user_id": "2088101117955611",
        "present_refund_buyer_amount": "88.88",
        "present_refund_discount_amount": "88.88",
        "present_refund_mdiscount_amount": "88.88"
    },
    "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}

8、异常示例

{
    "alipay_trade_refund_response": {
        "code": "20000",
        "msg": "Service Currently Unavailable",
        "sub_code": "isp.unknow-error",
        "sub_msg": "系统繁忙"
    },
    "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}

9、代码实现 

9.1基础类

AlipayConfig配置类,主要包含支付宝的配置信息

package com.hisap.xql.api.common.ali;
 
/**
 * @Author: QijieLiu
 * @Description: 支付宝配置信息
 * @Date: Created in 10:39 2018/8/20
 */
public class AlipayConfig {
	public static String APP_ID = "xxxxxx";
	public static String APP_PRIVATE_KEY = "xxxxxx";//APP私钥
	public static String APP_PUBLIC_KEY = "xxxxxx";//APP公钥
	public static String ALIPAY_PUBLIC_KEY = "xxxxxx";//支付宝公钥
	public static String UNIFIEDORDER_URL = "https://openapi.alipay.com/gateway.do";
        public static String NOTIFY_URL = "http://xxx.xxx.xxx.xxx/XqlApi/xxx/paynotify";
	public static String CHARSET = "UTF-8";
	public static String FORMAT = "json";
	public static String SIGNTYPE = "RSA2";
	public static String TIMEOUT_EXPRESS = "30m";
}

AlipayRefund支付宝退款实体类

package com.hisap.xql.api.common.ali;

/**
 * @Author: QijieLiu
 * @Description: 支付宝退款类
 * @Date: Created in 18:57 2018/8/20
 */
public class AlipayRefund {
    private String out_trade_no;//必须 商户订单号
    private String trade_no;//必须 支付宝交易号
    private String refund_amount;//必须 退款金额
    private String refund_reason;//可选 代表 退款的原因说明
    private String out_request_no;//可选 标识一次退款请求,同一笔交易多次退款需要保证唯一(就是out_request_no在2次退款一笔交易时,要不一样),如需部分退款,则此参数必传
    private String operator_id;//可选 代表 商户的操作员编号
    private String store_id;//可选 代表 商户的门店编号
    private String terminal_id;//可选 代表 商户的终端编号

    public String getOut_trade_no() {
        return out_trade_no;
    }

    public void setOut_trade_no(String out_trade_no) {
        this.out_trade_no = out_trade_no;
    }

    public String getTrade_no() {
        return trade_no;
    }

    public void setTrade_no(String trade_no) {
        this.trade_no = trade_no;
    }

    public String getRefund_amount() {
        return refund_amount;
    }

    public void setRefund_amount(String refund_amount) {
        this.refund_amount = refund_amount;
    }

    public String getRefund_reason() {
        return refund_reason;
    }

    public void setRefund_reason(String refund_reason) {
        this.refund_reason = refund_reason;
    }

    public String getOut_request_no() {
        return out_request_no;
    }

    public void setOut_request_no(String out_request_no) {
        this.out_request_no = out_request_no;
    }

    public String getOperator_id() {
        return operator_id;
    }

    public void setOperator_id(String operator_id) {
        this.operator_id = operator_id;
    }

    public String getStore_id() {
        return store_id;
    }

    public void setStore_id(String store_id) {
        this.store_id = store_id;
    }

    public String getTerminal_id() {
        return terminal_id;
    }

    public void setTerminal_id(String terminal_id) {
        this.terminal_id = terminal_id;
    }
}

ResponseJson基础类,主要与APP前端进行交互

package com.hisap.xql.api.common.bean;
 
public class ResponseJson {
	// 结果码
	private String code;
	// 结果说明
	private String message;
	// 内容
	private Object data;
 
	public String getCode() {
		return code;
	}
 
	public void setCode(String code) {
		this.code = code;
	}
 
	public String getMessage() {
		return message;
	}
 
	public void setMessage(String message) {
		this.message = message;
	}
 
	public Object getData() {
		return data;
	}
 
	public void setData(Object data) {
		this.data = data;
	}
 
}

9.1业务类

这里我就只贴出Service层代码,其余代码都类似,参数这里只需要两个,一个是支付宝交易号,还有一个是退款金额,注意一下这里的退款金额单位是元,而微信是分。当然这里也可以添加对应的业务逻辑,我们这里不需要。

package com.hisap.xql.api.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.hisap.xql.api.common.ali.AlipayConfig;
import com.hisap.xql.api.common.ali.AlipayRefund;
import com.hisap.xql.api.common.bean.ResponseJson;
import com.hisap.xql.api.common.constant.CodeMsg;
import com.hisap.xql.api.common.utils.Collections3;
import com.hisap.xql.api.common.utils.CommonUtil;
import com.hisap.xql.api.common.utils.StringUtil;
import com.hisap.xql.api.common.utils.VersionUtil;
import com.hisap.xql.api.dao.XqlOrderGoodsMapper;
import com.hisap.xql.api.model.XqlOrder;
import com.hisap.xql.api.model.XqlOrderGoods;
import com.hisap.xql.api.model.XqlOrderGoodsExample;
import com.hisap.xql.api.model.XqlVersion;
import com.hisap.xql.api.service.AliPayService;
import com.hisap.xql.api.service.CommonService;
import com.hisap.xql.api.service.ErpInterfaceService;
import com.hisap.xql.api.service.WeChatPayService;
import com.hisap.xql.api.service.XqlOrderService;

@Service
public class AliPayServiceImpl implements AliPayService {
	private static final Logger logger = LoggerFactory
			.getLogger(AliPayServiceImpl.class);
	
	@Autowired
	CommonService commonService;

	@Autowired
	XqlOrderService xqlOrderServiceImpl;

	@Autowired
	XqlOrderGoodsMapper xqlOrderGoodsMapper;

	@Autowired
	WeChatPayService weChatPayServiceImpl;
	
	@Autowired
	ErpInterfaceService erpInterfaceServiceImpl;


	@Override
	public ResponseJson refund(String trade_no, BigDecimal refund_amount)
			throws Exception {
		ResponseJson responseJson = new ResponseJson();
		try{
			// 实例化客户端
			AlipayClient alipayClient = new DefaultAlipayClient(
					AlipayConfig.UNIFIEDORDER_URL, AlipayConfig.APP_ID,
					AlipayConfig.APP_PRIVATE_KEY, AlipayConfig.FORMAT,
					AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY,
					AlipayConfig.SIGNTYPE);
			AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
			AlipayRefund alipayRefund = new AlipayRefund();
			alipayRefund.setTrade_no(trade_no);
			alipayRefund.setRefund_amount(refund_amount.toString());
			request.setBizContent(JSONObject.toJSONString(alipayRefund));
			AlipayTradeRefundResponse response = alipayClient.execute(request);
			if(response.getCode().equals("10000")){
				responseJson = CommonUtil.createResponseJson(
						CodeMsg.SUCCESS_CODE, CodeMsg.SUCCESS_MSG, response);
			}else{
				responseJson = CommonUtil.createResponseJson(
						response.getSubCode(), response.getSubMsg(), response);
			}
		}catch(Exception e){
			e.printStackTrace();
			logger.error("支付宝退款接口服务端异常,异常信息---" + e.getMessage(), e);
			return CommonUtil.createResponseJson(
					CodeMsg.SERVER_ERROR_CODE, CodeMsg.SERVER_ERROR_MSG, new JSONObject());
		}
		
		return responseJson;
	}
	
	public static void main(String[] args) throws Exception {
		String trade_no = "2018083021001004540585684766";
		BigDecimal refund_amount = new BigDecimal("0.01");
		ResponseJson responseJson = new ResponseJson();
		
		AliPayServiceImpl aa = new AliPayServiceImpl();
		responseJson = aa.refund(trade_no,refund_amount);
		System.out.println(JSON.toJSONString(responseJson, SerializerFeature.WriteNullStringAsEmpty));
	}

}

支付宝的统一收单交易退款就讲到这里,有什么问题大家可以私我。

猜你喜欢

转载自blog.csdn.net/Jay_1989/article/details/82384315