微信公众号支付开发-JAVA版DEMO

1.准备工作

首先登录微信公众平台,获取并配置以下微信开发配置:

  • 开发者ID【AppID和AppSecret】
  • 服务器配置
    1.url服务器地址设置
    2.Token【自己设置,必须英文或数字】
    3.EncodingAESKey[自己随机生成,用于消息加解密]

然后登录微信商户平台,获取并配置以下微信支付配置:

  • 商户号(mchId)
  • API秘钥(key)
  • API证书(java版主要使用:apiclient_cert.p12)

 PS:需要微信公众号支付银行对私接口,请联系电话/微信17605918869

2.代码展示

提醒:此处粘贴出的代码为方便初学者比较直观的了解、学习微信公众号支付,部分代码并未按照编码规范封装成方法、工具类

将微信支付所有参数定义为 WeChatConfig.java

 
  1. public class WeChatConfig {

  2. /**公众号AppId*/

  3. public static final APP_ID = "";

  4.  
  5. /**公众号AppSecret*/

  6. public static final APP_SECRET = "";

  7.  
  8. /**微信支付商户号*/

  9. public static final String MCH_ID = "";

  10.  
  11. /**微信支付API秘钥*/

  12. public static final String KEY = "";

  13.  
  14. /**微信支付api证书路径*/

  15. public static final String CERT_PATH = "***/apiclient_cert.p12";

  16.  
  17. /**微信统一下单url*/

  18. public static final String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";

  19.  
  20. /**微信申请退款url*/

  21. public static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";

  22.  
  23. /**微信支付通知url*/

  24. public static final String NOTIFY_URL = "此处url用于接收微信服务器发送的支付通知,并处理商家的业务";

  25.  
  26. /**微信交易类型:公众号支付*/

  27. public static final String TRADE_TYPE_JSAPI = "JSAPI";

  28.  
  29. /**微信交易类型:原生扫码支付*/

  30. public static final String TRADE_TYPE_NATIVE = "NATIVE";

  31.  
  32. /**微信甲乙类型:APP支付*/

  33. public static final String TRADE_TYPE_APP = "APP";

  34. }

处理微信公众号支付请求的Controller:WeChatOrderController.java

 
  1. @RequestMapping(value="/m/weChat/")

  2. @Controller("weChatOrderController")

  3. public class WeChatOrderController{

  4.  
  5. @Autowired

  6. private OrderService orderService;

  7. @Autowired

  8. private WechatPayService wechatPayService;

  9. @Autowired

  10. private NotifyReturnService notifyReturnService;

  11.  
  12. @RequestMapping(value = "unifiedOrder")

  13. public String unifiedOrder(HttpServletRequest request,Model model){

  14. //用户同意授权,获得的code

  15. String code = request.getParameter("code");

  16. //请求授权携带的参数【根据自己需要设定值,此处我传的是订单id】

  17. String state = request.getParameter("state");

  18. Order order = orderService.get(state);//订单信息

  19. //通过code获取网页授权access_token

  20. AuthToken authToken = WeChatUtils.getTokenByAuthCode(code);

  21. //构建微信统一下单需要的参数

  22. Map<String,Object> map = Maps.newHashMap();

  23. map.put("openId",authToken.getOpenid());//用户标识openId

  24. map.put("remoteIp",request.getRemoteAddr());//请求Ip地址

  25. //调用统一下单service

  26. Map<String,Object> resultMap = WeChatPayService.unifiedOrder(order,map);

  27. String returnCode = (String) resultMap.get("return_code");//通信标识

  28. String resultCode = (String) resultMap.get("result_code");//交易标识

  29. //只有当returnCode与resultCode均返回“success”,才代表微信支付统一下单成功

  30. if (WeChatConstant.RETURN_SUCCESS.equals(resultCode)&&WeChatConstant.RETURN_SUCCESS.equals(returnCode)){

  31. String appId = (String) resultMap.get("appid");//微信公众号AppId

  32. String timeStamp = WeChatUtils.getTimeStamp();//当前时间戳

  33. String prepayId = "prepay_id="+resultMap.get("prepay_id");//统一下单返回的预支付id

  34. String nonceStr = WeChatUtils.getRandomStr(20);//不长于32位的随机字符串

  35. SortedMap<String,Object> signMap = Maps.newTreeMap();//自然升序map

  36. signMap.put("appId",appId);

  37. signMap.put("package",prepayId);

  38. signMap.put("timeStamp",timeStamp);

  39. signMap.put("nonceStr",nonceStr);

  40. signMap.put("signType","MD5");

  41. model.addAttribute("appId",appId);

  42. model.addAttribute("timeStamp",timeStamp);

  43. model.addAttribute("nonceStr",nonceStr);

  44. model.addAttribute("prepayId",prepayId);

  45. model.addAttribute("paySign",WeChatUtils.getSign(signMap));//获取签名

  46. }else {

  47. logger.error("微信统一下单失败,订单编号:"+order.getOrderNumber()+",失败原因:"+resultMap.get("err_code_des"));

  48. return "redirect:/m/orderList";//支付下单失败,重定向至订单列表

  49. }

  50. //将支付需要参数返回至页面,采用h5方式调用支付接口

  51. return "/mobile/order/h5Pay";

  52. }

  53. }

微信支付前端发起页面: weChatPayTest.jsp

  • 支付按钮href中的redirect_uri= http://自己服务的ip或者域名/m/weChat/unifiedOrder 强调部分需要进行uriEncode
  • 此处代码为在微信公众号内网页调用,故使用的是微信网页授权方式,将订单id通过支付接口中state参数进行传递
  • 微信网页授权说明
 
  1. <!DOCTYPE HTML>

  2. <%@ page contentType="text/html;charset=UTF-8" language="java" %>

  3. <html>

  4. <head>

  5. <meta charset="UTF-8">

  6. <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">

  7. <meta name="screen-orientation" content="portrait">

  8. <meta name="x5-orientation" content="portrait">

  9. <link rel="stylesheet" href="/static/weui/dist/style/weui.min.css">

  10. <title>微信公众号支付测试</title>

  11. </head>

  12. <body>

  13. <div class="container" id="container">

  14. <a href="https://open.weixin.qq.com/connect/oauth2/authorizeappid=wx67e9c91f0bac335d&redirect_uri=http%3a%2f%2f***%2fm%2fweChat%2funifiedOrder&response_type=code&scope=snsapi_base&state=${order.id}#wechat_redirect" class="weui_btn weui_btn_primary">立即支付</a>

  15. </div>

  16. </body>

  17. </html>

  18.  

h5方式调用微信支付接口:h5Pay.jsp

  • WeixinJSBridge为微信公众号内置对象,所以必须在公众号内部网页使用
 
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>

  2. <html>

  3. <head>

  4. <title>确认支付</title>

  5. <script type="text/javascript" src="/static/jquery/jquery-1.11.3.min.js"></script>

  6. <script type="text/javascript" src="/static/jquery-plugin/jquery.form.js"></script>

  7. </head>

  8. <body>

  9. <input type="hidden" name="appId" value="${appId}">

  10. <input type="hidden" name="nonceStr" value="${nonceStr}">

  11. <input type="hidden" name="prepayId" value="${prepayId}">

  12. <input type="hidden" name="paySign" value="${paySign}">

  13. <input type="hidden" name="timeStamp" value="${timeStamp}">

  14. </body>

  15. <script>

  16.  
  17. function onBridgeReady(){

  18. var appId = $("input[name='appId']").val();

  19. var nonceStr = $("input[name='nonceStr']").val();

  20. var prepayId = $("input[name='prepayId']").val();

  21. var paySign = $("input[name='paySign']").val();

  22. var timeStamp = $("input[name='timeStamp']").val();

  23. WeixinJSBridge.invoke(

  24. 'getBrandWCPayRequest', {

  25. "appId":appId,

  26. "timeStamp":timeStamp,

  27. "nonceStr":nonceStr,

  28. "package":prepayId,

  29. "signType":"MD5",

  30. "paySign":paySign

  31. },

  32. function(res){

  33. if(res.err_msg == "get_brand_wcpay_request:ok" ) {

  34. location.href="支付成功返回商家自定义页面";

  35. }else {//这里支付失败和支付取消统一处理

  36. alert("支付取消");

  37. location.href="支付失败返回商家自定义页面";

  38. }

  39. }

  40. );

  41. }

  42.  
  43. $(document).ready(function () {

  44. if (typeof WeixinJSBridge == "undefined"){

  45. if (document.addEventListener){

  46. document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);

  47. }else if (document.attachEvent){

  48. document.attachEvent('WeixinJSBridgeReady', onBridgeReady);

  49. document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);

  50. }

  51. }else {

  52. onBridgeReady();

  53. }

  54. });

  55. </script>

  56. </html>

  57.  
  58.  

微信支付订单Service:WeChatPayService.java

 
  1. /**

  2. *微信支付统一下单

  3. **/

  4. public Map<String,Object> unifiedOrder(Order order, Map<String,Object> map){

  5. Map<String,Object> resultMap;

  6. try {

  7. WxPaySendData paySendData = new WxPaySendData();

  8. //构建微信支付请求参数集合

  9. paySendData.setAppId(WeChatConstant.APP_ID);

  10. paySendData.setAttach("微信订单支付:"+order.getOrderNumber());

  11. paySendData.setBody("商品描述");

  12. paySendData.setMchId(WeChatConfig.MCH_ID);

  13. paySendData.setNonceStr(WeChatUtils.getRandomStr(32));

  14. paySendData.setNotifyUrl(WeChatConfig.NOTIFY_URL);

  15. paySendData.setDeviceInfo("WEB");

  16. paySendData.setOutTradeNo(order.getOrderNumber());

  17. paySendData.setTotalFee(order.getSumFee());

  18. paySendData.setTradeType(WeChatConfig.TRADE_TYPE_JSAPI);

  19. paySendData.setSpBillCreateIp((String) map.get("remoteIp"));

  20. paySendData.setOpenId((String) map.get("openId"));

  21. //将参数拼成map,生产签名

  22. SortedMap<String,Object> params = buildParamMap(paySendData);

  23. paySendData.setSign(WeChatUtils.getSign(params));

  24. //将请求参数对象转换成xml

  25. String reqXml = WeChatUtils.sendDataToXml(paySendData);

  26. //发送请求

  27. byte[] xmlData = reqXml.getBytes();

  28. URL url = new URL(WeChatConfig.UNIFIED_ORDER_URL);

  29. HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

  30. urlConnection.setDoOutput(true);

  31. urlConnection.setDoInput(true);

  32. urlConnection.setUseCaches(false);

  33. urlConnection.setRequestProperty("Content_Type","text/xml");

  34. urlConnection.setRequestProperty("Content-length",String.valueOf(xmlData.length));

  35. DataOutputStream outputStream = new DataOutputStream(urlConnection.getOutputStream());

  36. outputStream.write(xmlData);

  37. outputStream.flush();

  38. outputStream.close();

  39. resultMap = WeChatUtils.parseXml(urlConnection.getInputStream());

  40. } catch (Exception e) {

  41. throw new ServiceException("微信支付统一下单异常",e);

  42. }

  43. return resultMap;

  44.  
  45. /**

  46. * 构建统一下单参数map 用于生成签名

  47. * @param data

  48. * @return SortedMap<String,Object>

  49. */

  50. private SortedMap<String,Object> buildParamMap(WxPaySendData data) {

  51. SortedMap<String,Object> paramters = new TreeMap<String, Object>();

  52. if (null != data){

  53. if (StringUtils.isNotEmpty(data.getAppId())){

  54. paramters.put("appid",data.getAppId());

  55. }

  56. if (StringUtils.isNotEmpty(data.getAttach())){

  57. paramters.put("attach",data.getAttach());

  58. }

  59. if (StringUtils.isNotEmpty(data.getBody())){

  60. paramters.put("body",data.getBody());

  61. }

  62. if (StringUtils.isNotEmpty(data.getDetail())){

  63. paramters.put("detail",data.getDetail());

  64. }

  65. if (StringUtils.isNotEmpty(data.getDeviceInfo())){

  66. paramters.put("device_info",data.getDeviceInfo());

  67. }

  68. if (StringUtils.isNotEmpty(data.getFeeType())){

  69. paramters.put("fee_type",data.getFeeType());

  70. }

  71. if (StringUtils.isNotEmpty(data.getGoodsTag())){

  72. paramters.put("goods_tag",data.getGoodsTag());

  73. }

  74. if (StringUtils.isNotEmpty(data.getLimitPay())){

  75. paramters.put("limit_pay",data.getLimitPay());

  76. }

  77. if (StringUtils.isNotEmpty(data.getMchId())){

  78. paramters.put("mch_id",data.getMchId());

  79. }

  80. if (StringUtils.isNotEmpty(data.getNonceStr())){

  81. paramters.put("nonce_str",data.getNonceStr());

  82. }

  83. if (StringUtils.isNotEmpty(data.getNotifyUrl())){

  84. paramters.put("notify_url",data.getNotifyUrl());

  85. }

  86. if (StringUtils.isNotEmpty(data.getOpenId())){

  87. paramters.put("openid",data.getOpenId());

  88. }

  89. if (StringUtils.isNotEmpty(data.getOutTradeNo())){

  90. paramters.put("out_trade_no",data.getOutTradeNo());

  91. }

  92. if (StringUtils.isNotEmpty(data.getSign())){

  93. paramters.put("sign",data.getSign());

  94. }

  95. if (StringUtils.isNotEmpty(data.getSpBillCreateIp())){

  96. paramters.put("spbill_create_ip",data.getSpBillCreateIp());

  97. }

  98. if (StringUtils.isNotEmpty(data.getTimeStart())){

  99. paramters.put("time_start",data.getTimeStart());

  100. }

  101. if (StringUtils.isNotEmpty(data.getTimeExpire())){

  102. paramters.put("time_expire",data.getTimeExpire());

  103. }

  104. if (StringUtils.isNotEmpty(data.getProductId())){

  105. paramters.put("product_id",data.getProductId());

  106. }

  107. if (data.getTotalFee()>0){

  108. paramters.put("total_fee",data.getTotalFee());

  109. }

  110. if (StringUtils.isNotEmpty(data.getTradeType())){

  111. paramters.put("trade_type",data.getTradeType());

  112. }

  113. //申请退款参数

  114. if (StringUtils.isNotEmpty(data.getTransactionId())){

  115. paramters.put("transaction_id",data.getTransactionId());

  116. }

  117. if (StringUtils.isNotEmpty(data.getOutRefundNo())){

  118. paramters.put("out_refund_no",data.getOutRefundNo());

  119. }

  120. if (StringUtils.isNotEmpty(data.getOpUserId())){

  121. paramters.put("op_user_id",data.getOpUserId());

  122. }

  123. if (StringUtils.isNotEmpty(data.getRefundFeeType())){

  124. paramters.put("refund_fee_type",data.getRefundFeeType());

  125. }

  126. if (null != data.getRefundFee() && data.getRefundFee()>0){

  127. paramters.put("refund_fee",data.getRefundFee());

  128. }

  129. }

  130. return paramters;

  131. }

  132. }

微信工具类 WeChatUtils.java

 
  1. public class WeChatUtils {

  2.  
  3. /**

  4. * 根据code获取微信授权access_token

  5. * @param request

  6. */

  7. public static AuthToken getTokenByAuthCode(String code){

  8. AuthToken authToken;

  9. StringBuilder json = new StringBuilder();

  10. try {

  11. URL url = new URL(WeChatConstant.GET_AUTHTOKEN_URL+"appid="+ WeChatConstant.APP_ID+"&secret="+ WeChatConstant.APP_SECRET+"&code="+code+"&grant_type=authorization_code");

  12. URLConnection uc = url.openConnection();

  13. BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));

  14. String inputLine ;

  15. while((inputLine=in.readLine())!=null){

  16. json.append(inputLine);

  17. }

  18. in.close();

  19. //将json字符串转成javaBean

  20. ObjectMapper om = new ObjectMapper();

  21. authToken = readValue(json.toString(),AuthToken.class);

  22. } catch (Exception e) {

  23. throw new ServiceException("微信工具类:根据授权code获取access_token异常",e);

  24. }

  25. return authToken;

  26. }

  27.  
  28. /**

  29. * 获取微信签名

  30. * @param map 请求参数集合

  31. * @return 微信请求签名串

  32. */

  33. public static String getSign(SortedMap<String,Object> map){

  34. StringBuffer sb = new StringBuffer();

  35. Set set = map.entrySet();

  36. Iterator iterator = set.iterator();

  37. while (iterator.hasNext()){

  38. Map.Entry entry = (Map.Entry) iterator.next();

  39. String k = (String) entry.getKey();

  40. Object v = entry.getValue();

  41. //参数中sign、key不参与签名加密

  42. if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)){

  43. sb.append(k + "=" + v + "&");

  44. }

  45. }

  46. sb.append("key=" + WeChatPayConfig.KEY);

  47. String sign = MD5.MD5Encode(sb.toString()).toUpperCase();

  48. return sign;

  49. }

  50.  
  51. /**

  52. * 解析微信服务器发来的请求

  53. * @param inputStream

  54. * @return 微信返回的参数集合

  55. */

  56. public static SortedMap<String,Object> parseXml(InputStream inputStream) {

  57. SortedMap<String,Object> map = Maps.newTreeMap();

  58. try {

  59. //获取request输入流

  60. SAXReader reader = new SAXReader();

  61. Document document = reader.read(inputStream);

  62. //得到xml根元素

  63. Element root = document.getRootElement();

  64. //得到根元素所有节点

  65. List<Element> elementList = root.elements();

  66. //遍历所有子节点

  67. for (Element element:elementList){

  68. map.put(element.getName(),element.getText());

  69. }

  70. //释放资源

  71. inputStream.close();

  72. } catch (Exception e) {

  73. throw new ServiceException("微信工具类:解析xml异常",e);

  74. }

  75. return map;

  76. }

  77.  
  78. /**

  79. * 扩展xstream,使其支持name带有"_"的节点

  80. */

  81. public static XStream xStream = new XStream(new DomDriver("UTF-8",new XmlFriendlyNameCoder("-_","_")));

  82.  
  83. /**

  84. * 请求参数转换成xml

  85. * @param data

  86. * @return xml字符串

  87. */

  88. public static String sendDataToXml(WxPaySendData data){

  89. xStream.autodetectAnnotations(true);

  90. xStream.alias("xml", WxPaySendData.class);

  91. return xStream.toXML(data);

  92. }

  93.  
  94. /**

  95. * 获取当前时间戳

  96. * @return 当前时间戳字符串

  97. */

  98. public static String getTimeStamp(){

  99. return String.valueOf(System.currentTimeMillis()/1000);

  100. }

  101.  
  102. /**

  103. * 获取指定长度的随机字符串

  104. * @param length

  105. * @return 随机字符串

  106. */

  107. public static String getRandomStr(int length){

  108. String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

  109. Random random = new Random();

  110. StringBuffer sb = new StringBuffer();

  111. for (int i = 0; i < length; i++) {

  112. int number = random.nextInt(base.length());

  113. sb.append(base.charAt(number));

  114. }

  115. return sb.toString();

  116. }

  117. }

微信常量类 WeChatConstant.java

 
  1. public class WeChatConstant {

  2. /**Token*/

  3. public static final String TOKEN = "";

  4. /**EncodingAESKey*/

  5. public static final String AES_KEY = "";

  6. /**消息类型:文本消息*/

  7. public static final String MESSAGE_TYPE_TEXT = "text";

  8. /**消息类型:音乐*/

  9. public static final String MESSAGE_TYPE_MUSIC = "music";

  10. /**消息类型:图文*/

  11. public static final String MESSAGE_TYPE_NEWS = "news";

  12. /**消息类型:图片*/

  13. public static final String MESSAGE_TYPE_IMAGE = "image";

  14. /**消息类型:视频*/

  15. public static final String MESSAGE_TYPE_VIDEO = "video";

  16. /**消息类型:小视频*/

  17. public static final String MESSAGE_TYPE_SHORTVIDEO = "shortvideo";

  18. /**消息类型:链接*/

  19. public static final String MESSAGE_TYPE_LINK = "link";

  20. /**消息类型:地理位置*/

  21. public static final String MESSAGE_TYPE_LOCATION = "location";

  22. /**消息类型:音频*/

  23. public static final String MESSAGE_TYPE_VOICE = "voice";

  24. /**消息类型:事件推送*/

  25. public static final String MESSAGE_TYPE_EVENT = "event";

  26. /**事件类型:subscribe(订阅)*/

  27. public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";

  28. /**事件类型:unsubscribe(取消订阅)*/

  29. public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";

  30. /**事件类型:CLICK(自定义菜单点击事件)*/

  31. public static final String EVENT_TYPE_CLICK = "CLICK";

  32. /**返回消息类型:转发客服*/

  33. public static final String TRANSFER_CUSTOMER_SERVICE="transfer_customer_service";

  34. /**ACCESS_TOKEN*/

  35. public static final String ACCESS_TOKEN_ENAME = "access_token";

  36. /**返回成功字符串*/

  37. public static final String RETURN_SUCCESS = "SUCCESS";

  38. /**主动发送消息url*/

  39. public static final String SEND_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=";

  40. /**通过code获取授权access_token的URL*/

  41. public static final String GET_AUTHTOKEN_URL = " https://api.weixin.qq.com/sns/oauth2/access_token?";

  42. }

其他微信对象:

封装微信授权返回的信息,此处属性均为小写【微信返回的是小写很不友好】

 
  1. public class AuthToken implements Serializable {

  2. /**授权access_token*/

  3. private String access_token;

  4. /**有效期*/

  5. private String expires_in;

  6. /**刷新access_token*/

  7. private String refresh_token;

  8. /**用户OPENID*/

  9. private String openid;

  10. /**授权方式Scope*/

  11. private String scope;

  12. /**错误码*/

  13. private String errcode;

  14. /**错误消息*/

  15. private String errmsg;

  16. /**getter() and setter()*/

  17. }

微信请求参数对象【下单与退款均可使用此对象】

 
  1. public class WxPaySendData {

  2.  
  3. /**公众账号ID 必须*/

  4. @XStreamAlias("appid")

  5. private String appId;

  6.  
  7. /**商户号 必须*/

  8. @XStreamAlias("mch_id")

  9. private String mchId;

  10.  
  11. /**设备号*/

  12. @XStreamAlias("device_info")

  13. private String deviceInfo;

  14.  
  15. /**随机字符串 必须*/

  16. @XStreamAlias("nonce_str")

  17. private String nonceStr;

  18.  
  19. /**签名 必须*/

  20. @XStreamAlias("sign")

  21. private String sign;

  22.  
  23. /**商品描述 必须*/

  24. @XStreamAlias("body")

  25. private String body;

  26.  
  27. /**商品详情*/

  28. @XStreamAlias("detail")

  29. private String detail;

  30.  
  31. /**附加数据*/

  32. @XStreamAlias("attach")

  33. private String attach;

  34.  
  35. /**商户订单号 必须*/

  36. @XStreamAlias("out_trade_no")

  37. private String outTradeNo;

  38.  
  39. /**货币类型*/

  40. @XStreamAlias("fee_type")

  41. private String feeType;

  42.  
  43. /**交易金额 必须[JSAPI,NATIVE,APP]*/

  44. @XStreamAlias("total_fee")

  45. private int totalFee;

  46.  
  47. /**交易类型 [必须]*/

  48. @XStreamAlias("trade_type")

  49. private String tradeType;

  50.  
  51. /**通知地址 [必须]*/

  52. @XStreamAlias("notify_url")

  53. private String notifyUrl;

  54.  
  55. /**终端Ip [必须]*/

  56. @XStreamAlias("spbill_create_ip")

  57. private String spBillCreateIp;

  58.  
  59. /**订单生成时间yyyyMMddHHmmss*/

  60. @XStreamAlias("time_start")

  61. private String timeStart;

  62.  
  63. /**订单失效时间yyyyMMddHHmmss 间隔>5min*/

  64. @XStreamAlias("time_expire")

  65. private String timeExpire;

  66.  
  67. /**用户标识 tradeType=JSAPI时必须*/

  68. @XStreamAlias("openid")

  69. private String openId;

  70.  
  71. /**商品标记*/

  72. @XStreamAlias("goods_tag")

  73. private String goodsTag;

  74.  
  75. /**商品ID tradeType=NATIVE时必须*/

  76. @XStreamAlias("product_id")

  77. private String productId;

  78.  
  79. /**指定支付方式*/

  80. @XStreamAlias("limit_pay")

  81. private String limitPay;

  82.  
  83.  
  84. /**

  85. *以下属性为申请退款参数

  86. */

  87. /**微信订单号 [商户订单号二选一]*/

  88. @XStreamAlias("transaction_id")

  89. private String transactionId;

  90.  
  91. /**商户退款单号 [必须]*/

  92. @XStreamAlias("out_refund_no")

  93. private String outRefundNo;

  94.  
  95. /**退款金额 [必须]*/

  96. @XStreamAlias("refund_fee")

  97. private Integer refundFee;

  98.  
  99. /**货币种类*/

  100. @XStreamAlias("refund_fee_type")

  101. private String refundFeeType;

  102.  
  103. /**操作员账号:默认为商户号 [必须]*/

  104. @XStreamAlias("op_user_id")

  105. private String opUserId;

  106.  
  107. /**getter() and setter()*/

  108. }

猜你喜欢

转载自blog.csdn.net/xinzi11243094/article/details/81978218