diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java index cf5bb8c3..45973443 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java @@ -1,19 +1,11 @@ package me.chanjar.weixin.mp.api; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.bean.pay.*; + import java.io.File; import java.util.Map; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.mp.bean.pay.WxEntPayRequest; -import me.chanjar.weixin.mp.bean.pay.WxEntPayResult; -import me.chanjar.weixin.mp.bean.pay.WxMpPayCallback; -import me.chanjar.weixin.mp.bean.pay.WxMpPayRefundResult; -import me.chanjar.weixin.mp.bean.pay.WxMpPayResult; -import me.chanjar.weixin.mp.bean.pay.WxRedpackResult; -import me.chanjar.weixin.mp.bean.pay.WxSendRedpackRequest; -import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderRequest; -import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderResult; - /** * 微信支付相关接口 * Created by Binary Wang on 2016/7/28. @@ -25,7 +17,7 @@ public interface WxMpPayService { * 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1) * 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识" * 接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder - * @throws WxErrorException + * @throws WxErrorException * */ WxUnifiedOrderResult unifiedOrder(WxUnifiedOrderRequest request) @@ -42,7 +34,7 @@ public interface WxMpPayService { /** * 该接口提供所有微信支付订单的查询,当支付通知处理异常戒丢失的情冴,商户可以通过该接口查询订单支付状态。 * 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2 - * @throws WxErrorException + * @throws WxErrorException * */ WxMpPayResult getJSSDKPayResult(String transactionId, String outTradeNo) @@ -56,18 +48,15 @@ public interface WxMpPayService { WxMpPayCallback getJSSDKCallbackData(String xmlData); /** + *
* 微信支付-申请退款 * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4 - * - * @param parameters 需要传入的退款参数的Map。以下几项为参数的必须项:transaction_id - * out_trade_no (仅在上述transaction_id为空时是必须项) - * out_refund_no - * total_fee - * refund_fee + * 接口链接:https://api.mch.weixin.qq.com/secapi/pay/refund + * + * @param keyFile 证书文件对象 * @return 退款操作结果 */ - WxMpPayRefundResult refundPay(Map
- *
@@ -80,7 +69,7 @@ public interface WxMpPayService { /** * 发送微信红包给个人用户 - *+ ** 文档详见: * 发送普通红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3 * 发送裂变红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4 @@ -89,7 +78,7 @@ public interface WxMpPayService { WxRedpackResult sendRedpack(WxSendRedpackRequest request) throws WxErrorException; /** - *+ ** 企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,提供通过API完成企业付款的功能。 * 比如目前的保险行业向客户退保、给付、理赔。 * 企业付款将使用商户的可用余额,需确保可用余额充足。查看可用余额、充值、提现请登录商户平台“资金管理”https://pay.weixin.qq.com/进行操作。 diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java index 79e2c312..a8d5dc3f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java @@ -1,19 +1,18 @@ package me.chanjar.weixin.mp.api.impl; -import java.io.File; -import java.io.FileInputStream; -import java.lang.reflect.Field; -import java.security.KeyStore; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.SortedMap; -import java.util.TreeMap; - -import javax.net.ssl.SSLContext; - +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.annotations.XStreamAlias; +import me.chanjar.weixin.common.annotation.Required; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.xml.XStreamInitializer; +import me.chanjar.weixin.mp.api.WxMpPayService; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.pay.*; import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; @@ -26,26 +25,13 @@ import org.apache.http.ssl.SSLContexts; import org.apache.http.util.EntityUtils; import org.joor.Reflect; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.thoughtworks.xstream.XStream; -import com.thoughtworks.xstream.annotations.XStreamAlias; - -import me.chanjar.weixin.common.annotation.Required; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.xml.XStreamInitializer; -import me.chanjar.weixin.mp.api.WxMpPayService; -import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.bean.pay.WxEntPayRequest; -import me.chanjar.weixin.mp.bean.pay.WxEntPayResult; -import me.chanjar.weixin.mp.bean.pay.WxMpPayCallback; -import me.chanjar.weixin.mp.bean.pay.WxMpPayRefundResult; -import me.chanjar.weixin.mp.bean.pay.WxMpPayResult; -import me.chanjar.weixin.mp.bean.pay.WxRedpackResult; -import me.chanjar.weixin.mp.bean.pay.WxSendRedpackRequest; -import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderRequest; -import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderResult; +import javax.net.ssl.SSLContext; +import java.io.File; +import java.io.FileInputStream; +import java.lang.reflect.Field; +import java.security.KeyStore; +import java.util.*; +import java.util.Map.Entry; /** * Created by Binary Wang on 2016/7/28. @@ -55,8 +41,10 @@ import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderResult; public class WxMpPayServiceImpl implements WxMpPayService { private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com"; - private static final List+ * + * @author binarywang(https://github.com/binarywang) + * Created by Binary Wang on 2016-10-08. + */ +@XStreamAlias("xml") +public class WxMpPayRefundRequest { + /** + *TRADE_TYPES = Lists.newArrayList("JSAPI", - "NATIVE", "APP"); + private static final String[] TRADE_TYPES = new String[]{"JSAPI","NATIVE", "APP"}; + private static final String[] REFUND_ACCOUNT = new String[]{"REFUND_SOURCE_RECHARGE_FUNDS", + "REFUND_SOURCE_UNSETTLED_FUNDS"}; + private WxMpService wxMpService; public WxMpPayServiceImpl(WxMpService wxMpService) { @@ -115,33 +103,25 @@ public class WxMpPayServiceImpl implements WxMpPayService { } @Override - public WxMpPayRefundResult refundPay(Map parameters) + public WxMpPayRefundResult refund(WxMpPayRefundRequest request, File keyFile) throws WxErrorException { - SortedMap refundParams = new TreeMap<>(parameters); - refundParams.put("appid", - this.wxMpService.getWxMpConfigStorage().getAppId()); - refundParams.put("mch_id", - this.wxMpService.getWxMpConfigStorage().getPartnerId()); - refundParams.put("nonce_str", System.currentTimeMillis() + ""); - refundParams.put("op_user_id", - this.wxMpService.getWxMpConfigStorage().getPartnerId()); - String sign = this.createSign(refundParams, - this.wxMpService.getWxMpConfigStorage().getPartnerKey()); - refundParams.put("sign", sign); - - StringBuilder request = new StringBuilder(" "); - for (Map.Entry "); + checkParameters(request); - String url = PAY_BASE_URL + "/secapi/pay/refund"; - String responseContent = this.wxMpService.post(url, request.toString()); XStream xstream = XStreamInitializer.getInstance(); xstream.processAnnotations(WxMpPayRefundResult.class); - WxMpPayRefundResult wxMpPayRefundResult = (WxMpPayRefundResult) xstream - .fromXML(responseContent); + xstream.processAnnotations(WxMpPayRefundRequest.class); + + request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); + String partnerId = this.wxMpService.getWxMpConfigStorage().getPartnerId(); + request.setMchId(partnerId); + request.setNonceStr( System.currentTimeMillis() + ""); + request.setOpUserId(partnerId); + String sign = this.createSign(this.xmlBean2Map(request), this.wxMpService.getWxMpConfigStorage().getPartnerKey()); + request.setSign(sign); + + String url = PAY_BASE_URL + "/secapi/pay/refund"; + String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request), keyFile, partnerId); + WxMpPayRefundResult wxMpPayRefundResult = (WxMpPayRefundResult) xstream.fromXML(responseContent); if (!"SUCCESS".equalsIgnoreCase(wxMpPayRefundResult.getResultCode()) || !"SUCCESS".equalsIgnoreCase(wxMpPayRefundResult.getReturnCode())) { @@ -158,6 +138,20 @@ public class WxMpPayServiceImpl implements WxMpPayService { return wxMpPayRefundResult; } + private void checkParameters(WxMpPayRefundRequest request) { + checkNotNullParams(request); + + if (StringUtils.isNotBlank(request.getRefundAccount())) { + if(!ArrayUtils.contains(REFUND_ACCOUNT, request.getRefundAccount())){ + throw new IllegalArgumentException("refund_account目前必须为" + Arrays.toString(REFUND_ACCOUNT) + "其中之一"); + } + } + + if (StringUtils.isBlank(request.getOutTradeNo()) && StringUtils.isBlank(request.getTransactionId())) { + throw new IllegalArgumentException("transaction_id 和 out_trade_no 不能同时为空,必须提供一个"); + } + } + @Override public boolean checkJSSDKCallbackDataSignature(Mappara : refundParams.entrySet()) { - request.append(String.format("<%s>%s%s>", para.getKey(), - para.getValue(), para.getKey())); - } - request.append(" kvm, String signature) { @@ -176,7 +170,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); request.setNonceStr(System.currentTimeMillis() + ""); - String sign = this.createSign(xmlBean2Map(request), + String sign = this.createSign(this.xmlBean2Map(request), this.wxMpService.getWxMpConfigStorage().getPartnerKey()); request.setSign(sign); @@ -258,7 +252,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); request.setNonceStr(System.currentTimeMillis() + ""); - String sign = this.createSign(xmlBean2Map(request), + String sign = this.createSign(this.xmlBean2Map(request), this.wxMpService.getWxMpConfigStorage().getPartnerKey()); request.setSign(sign); @@ -274,16 +268,13 @@ public class WxMpPayServiceImpl implements WxMpPayService { } return result; - } private void checkParameters(WxUnifiedOrderRequest request) { - checkNotNullParams(request); - if (!TRADE_TYPES.contains(request.getTradeType())) { - throw new IllegalArgumentException("trade_type目前必须为" + TRADE_TYPES + "其中之一"); - + if (! ArrayUtils.contains(TRADE_TYPES, request.getTradeType())) { + throw new IllegalArgumentException("trade_type目前必须为" + Arrays.toString(TRADE_TYPES) + "其中之一"); } if ("JSAPI".equals(request.getTradeType()) && request.getOpenid() == null) { @@ -368,10 +359,19 @@ public class WxMpPayServiceImpl implements WxMpPayService { String url = PAY_BASE_URL + "/mmpaymkttransfers/promotion/transfers"; - try (FileInputStream instream = new FileInputStream(keyFile)) { - String mchId = request.getMchId(); + String responseContent = this.executeRequestWithKeyFile(xstream.toXML(request), url, keyFile, request.getMchId()); + WxEntPayResult result = (WxEntPayResult) xstream.fromXML(responseContent); + if ("FAIL".equals(result.getResultCode())) { + throw new WxErrorException( + WxError.newBuilder().setErrorMsg(result.getErrCode() + ":" + result.getErrCodeDes()).build()); + } + return result; + } + + private String executeRequestWithKeyFile( String requestStr, String url, File keyFile, String mchId) throws WxErrorException { + try (FileInputStream inputStream = new FileInputStream(keyFile)) { KeyStore keyStore = KeyStore.getInstance("PKCS12"); - keyStore.load(instream, mchId.toCharArray()); + keyStore.load(inputStream, mchId.toCharArray()); SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, @@ -379,17 +379,10 @@ public class WxMpPayServiceImpl implements WxMpPayService { try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build()) { HttpPost httpPost = new HttpPost(url); - httpPost.setEntity(new StringEntity(new String(xstream.toXML(request).getBytes("UTF-8"), "ISO-8859-1"))); + httpPost.setEntity(new StringEntity(new String(requestStr.getBytes("UTF-8"), "ISO-8859-1"))); try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = EntityUtils.toString(response.getEntity()); - WxEntPayResult result = (WxEntPayResult) xstream.fromXML(responseContent); - if ("FAIL".equals(result.getResultCode())) { - throw new WxErrorException( - WxError.newBuilder().setErrorMsg(result.getErrCode() + ":" + result.getErrCodeDes()).build()); - } - - return result; + return EntityUtils.toString(response.getEntity()); } } } catch (Exception e) { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java index 1a7ffe84..4cd26894 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java @@ -1,23 +1,9 @@ package me.chanjar.weixin.mp.api.impl; -import java.io.IOException; - -import org.apache.http.HttpHost; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.conn.ssl.DefaultHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.client.BasicResponseHandler; -import org.apache.http.impl.client.CloseableHttpClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; - import me.chanjar.weixin.common.bean.WxAccessToken; import me.chanjar.weixin.common.bean.WxJsapiSignature; import me.chanjar.weixin.common.bean.result.WxError; @@ -26,38 +12,22 @@ import me.chanjar.weixin.common.session.StandardSessionManager; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.common.util.RandomUtils; import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; -import me.chanjar.weixin.common.util.http.DefaultApacheHttpClientBuilder; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; -import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; -import me.chanjar.weixin.common.util.http.URIUtil; -import me.chanjar.weixin.mp.api.WxMpCardService; -import me.chanjar.weixin.mp.api.WxMpConfigStorage; -import me.chanjar.weixin.mp.api.WxMpDataCubeService; -import me.chanjar.weixin.mp.api.WxMpKefuService; -import me.chanjar.weixin.mp.api.WxMpMaterialService; -import me.chanjar.weixin.mp.api.WxMpMenuService; -import me.chanjar.weixin.mp.api.WxMpPayService; -import me.chanjar.weixin.mp.api.WxMpQrcodeService; -import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.api.WxMpStoreService; -import me.chanjar.weixin.mp.api.WxMpUserBlacklistService; -import me.chanjar.weixin.mp.api.WxMpUserService; -import me.chanjar.weixin.mp.api.WxMpUserTagService; -import me.chanjar.weixin.mp.bean.WxMpIndustry; -import me.chanjar.weixin.mp.bean.WxMpMassNews; -import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; -import me.chanjar.weixin.mp.bean.WxMpMassPreviewMessage; -import me.chanjar.weixin.mp.bean.WxMpMassTagMessage; -import me.chanjar.weixin.mp.bean.WxMpMassVideo; -import me.chanjar.weixin.mp.bean.WxMpSemanticQuery; -import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; -import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; -import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; -import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; -import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult; -import me.chanjar.weixin.mp.bean.result.WxMpUser; +import me.chanjar.weixin.common.util.http.*; +import me.chanjar.weixin.mp.api.*; +import me.chanjar.weixin.mp.bean.*; +import me.chanjar.weixin.mp.bean.result.*; +import org.apache.http.HttpHost; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.impl.client.CloseableHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; public class WxMpServiceImpl implements WxMpService { @@ -477,6 +447,7 @@ public class WxMpServiceImpl implements WxMpService { } return null; } catch (IOException e) { + this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXECEPTION]: {}", uri, data, e.getMessage()); throw new RuntimeException(e); } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxMpPayRefundRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxMpPayRefundRequest.java new file mode 100644 index 00000000..e375d64e --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxMpPayRefundRequest.java @@ -0,0 +1,301 @@ +package me.chanjar.weixin.mp.bean.pay; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import me.chanjar.weixin.common.annotation.Required; + +/** + * + * 微信支付-申请退款请求参数 + * 注释中各行每个字段描述对应如下: + *字段名 + * 变量名 + * 是否必填 + * 类型 + * 示例值 + * 描述 + * + * 公众账号ID + * appid + * 是 + * String(32) + * wx8888888888888888 + * 微信分配的公众账号ID(企业号corpid即为此appId) + *+ */ + @XStreamAlias("appid") + private String appid; + + /** + *+ * 商户号 + * mch_id + * 是 + * String(32) + * 1900000109 + * 微信支付分配的商户号 + *+ */ + @XStreamAlias("mch_id") + private String mchId; + + /** + *+ * 设备号 + * device_info + * 否 + * String(32) + * 13467007045764 + * 终端设备号 + *+ */ + @XStreamAlias("device_info") + private String deviceInfo; + + /** + *+ * 随机字符串 + * nonce_str + * 是 + * String(32) + * 5K8264ILTKCH16CQ2502SI8ZNMTM67VS + * 随机字符串,不长于32位。推荐随机数生成算法 + *+ */ + @XStreamAlias("nonce_str") + private String nonceStr; + + /** + *+ * 签名 + * sign + * 是 + * String(32) + * C380BEC2BFD727A4B6845133519F3AD6 + * 签名,详见签名生成算法 + *+ */ + @XStreamAlias("sign") + private String sign; + + /** + *+ * 微信订单号 + * transaction_id + * 跟out_trade_no二选一 + * String(28) + * 1217752501201400000000000000 + * 微信生成的订单号,在支付通知中有返回 + *+ */ + @XStreamAlias("transaction_id") + private String transactionId; + + /** + *+ * 商户订单号 + * out_trade_no + * 跟transaction_id二选一 + * String(32) + * 1217752501201400000000000000 + * 商户侧传给微信的订单号 + *+ */ + @XStreamAlias("out_trade_no") + private String outTradeNo; + + /** + *+ * 商户退款单号 + * out_refund_no + * 是 + * String(32) + * 1217752501201400000000000000 + * 商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔 + *+ */ + @Required + @XStreamAlias("out_refund_no") + private String outRefundNo; + + /** + *+ * 订单金额 + * total_fee + * 是 + * Int + * 100 + * 订单总金额,单位为分,只能为整数,详见支付金额 + *+ */ + @Required + @XStreamAlias("total_fee") + private Integer totalFee; + + /** + *+ * 退款金额 + * refund_fee + * 是 + * Int + * 100 + * 退款总金额,订单总金额,单位为分,只能为整数,详见支付金额 + *+ */ + @Required + @XStreamAlias("refund_fee") + private Integer refundFee; + + /** + *+ * 货币种类 + * refund_fee_type + * 否 + * String(8) + * CNY + * 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型 + *+ */ + @XStreamAlias("refund_fee_type") + private String refundFeeType; + + /** + *+ * 操作员 + * op_user_id + * 是 + * String(32) + * 1900000109 + * 操作员帐号, 默认为商户号 + *+ */ + //@Required + @XStreamAlias("op_user_id") + private String opUserId; + + /** + *+ * 退款资金来源 + * refund_account + * 否 + * String(30) + * REFUND_SOURCE_RECHARGE_FUNDS + * 仅针对老资金流商户使用, + *