java服务器端微信、支付宝支付和退款功能

工作需要,写了服务器端的支付和退款功能,包含微信和支付宝,网上也有很多demo可以借鉴,我把我的代码放出来,写的比较简单,有问题的欢迎指正,大家一起学习。

微信支付需要调用微信的统一下单接口,而支付宝不用。

我写的时候微信和支付宝都单独写了一个工具类,来调用支付,给前端返回需要的数据。

ps:支付是可以不需要服务器端的,不过为了安全一点点,所以前端需要调起支付的字段都直接从服务器端返回,前端拿到字段直接调起支付就可以了。

Map<String,String> map = new HashMap<String,String>();
switch (record.getCheckType()) {
 case 10:
 map = Alipay.prePay(record.getAmount(),out_trade_no);
 return ResponseData.ok(map);
 case 20:
 map = WXPay.prePay(record.getAmount(),out_trade_no);
 return ResponseData.ok(map);
}

10是支付宝支付,20是微信支付,map里存放前端需要的字段,直接返回给手机端

其中out_trade_no这个是商户自己生成的唯一订单号

public class WXPay {

 private static String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");

 //统一下单
 public static Map<String,String> prePay(BigDecimal amount,String out_trade_no){
 String entity = genProductArgs(amount,out_trade_no); 

 byte[] buf = Util.httpPost(url, entity);

 String content = new String(buf);
 Map<String,String> xml=decodeXml(content);
 return getRep(xml);
 }

 private static Map<String, String> getRep(Map<String, String> xml) {
 Random random = new Random();
 List<NameValuePair> signParams = new LinkedList<NameValuePair>();
 signParams.add(new BasicNameValuePair("appid", Constants.APP_ID_WX));
 signParams.add(new BasicNameValuePair("noncestr", MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes())));
// signParams.add(new BasicNameValuePair("package", "prepay_id="+xml.get("prepay_id")));
 signParams.add(new BasicNameValuePair("package", "Sign=WXPay"));
 signParams.add(new BasicNameValuePair("partnerid", Constants.MCH_ID));
 signParams.add(new BasicNameValuePair("prepayid", xml.get("prepay_id")));
 signParams.add(new BasicNameValuePair("timestamp", String.valueOf(System.currentTimeMillis() / 1000)));
 xml.put("sign", genPackageSign(signParams));
 for (int i = 0; i < signParams.size(); i++) {
  xml.put(signParams.get(i).getName(),signParams.get(i).getValue());
 }
 return removeElements(xml);
 }

 private static Map<String, String> removeElements(Map<String, String> xml) {
 xml.remove("appid");
 xml.remove("mch_id");
 xml.remove("nonce_str");
 xml.remove("trade_type");
 //xml.remove("partnerid");
 xml.remove("prepay_id");
 xml.remove("result_code");
 xml.remove("return_code");
 xml.remove("return_msg");
 return xml;
 }

 private static String genProductArgs(BigDecimal amount,String out_trade_no) {
 StringBuffer xml = new StringBuffer();

 String nonceStr = genNonceStr();

 xml.append("</xml>");
 List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
 packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID_WX));
 packageParams.add(new BasicNameValuePair("body", "APP pay test"));
 packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));
 packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
 packageParams.add(new BasicNameValuePair("notify_url", "填写服务器的支付回调路径"));
 packageParams.add(new BasicNameValuePair("out_trade_no",out_trade_no));
 packageParams.add(new BasicNameValuePair("spbill_create_ip","127.0.0.1"));
 packageParams.add(new BasicNameValuePair("total_fee", String.valueOf(amount.movePointRight(2))));
// packageParams.add(new BasicNameValuePair("total_fee", "1"));
 packageParams.add(new BasicNameValuePair("trade_type", "APP"));

 String sign = genPackageSign(packageParams);
 packageParams.add(new BasicNameValuePair("sign", sign));

 String xmlstring =toXml(packageParams);
 return xmlstring;
 }

 public static String genNonceStr() {
 Random random = new Random();
 return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
 }

 public static String genPackageSign(List<NameValuePair> params) {
 StringBuilder sb = new StringBuilder();

 for (int i = 0; i < params.size(); i++) {
  sb.append(params.get(i).getName());
  sb.append('=');
  sb.append(params.get(i).getValue());
  sb.append('&');
 }
 sb.append("key=");
 sb.append(Constants.API_KEY);

 String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
 return packageSign;
 }

 public static String toXml(List<NameValuePair> params) {
 StringBuilder sb = new StringBuilder();
 sb.append("<xml>");
 for (int i = 0; i < params.size(); i++) {
  sb.append("<"+params.get(i).getName()+">");

  sb.append(params.get(i).getValue());
  sb.append("</"+params.get(i).getName()+">");
 }
 sb.append("</xml>");

 return sb.toString();
 }

}
public class Alipay {

 public static Map<String,String> prePay(BigDecimal payAbleAmount,String out_trade_no){
 //String orderInfo = getOrderInfo("订单付款", "订单付款",out_trade_no,"0.01");
 String orderInfo = getOrderInfo("订单付款", "订单付款",out_trade_no,String.valueOf(payAbleAmount));

 String sign = sign(orderInfo);

 try {
  /**
  * 仅需对sign 做URL编码
  */
  sign = URLEncoder.encode(sign, "UTF-8");
 } catch (UnsupportedEncodingException e) {
  e.printStackTrace();
 }

 /**
  * 完整的符合支付宝参数规范的订单信息
  */
 final String payInfo = orderInfo + "&sign=\"" + sign + "\"&" + getSignType();

 Map<String,String> map = new HashMap<String, String>();
 map.put("payInfo", payInfo);
 return map;
 }

 private static String getOrderInfo(String subject, String body,String out_trade_no,String price) {

 // 签约合作者身份ID
 String orderInfo = "partner=" + "\"" + Constants.PARTNER + "\"";

 // 签约卖家支付宝账号
 orderInfo += "&seller_id=" + "\"" + Constants.SELLER + "\"";

 // 商户网站唯一订单号
 orderInfo += "&out_trade_no=" + "\"" + out_trade_no + "\"";

 // 商品名称
 orderInfo += "&subject=" + "\"" + subject + "\"";

 // 商品详情
 orderInfo += "&body=" + "\"" + body + "\"";

 // 商品金额
 orderInfo += "&total_fee=" + "\"" + price + "\"";

 // 服务器异步通知页面路径
 orderInfo += "¬ify_url=" + "\"" + "填写服务器的支付回调路径" + "\"";

 // 服务接口名称, 固定值
 orderInfo += "&service=\"mobile.securitypay.pay\"";

 // 支付类型, 固定值
 orderInfo += "&payment_type=\"1\"";

 // 参数编码, 固定值
 orderInfo += "&_input_charset=\"utf-8\"";

 // 设置未付款交易的超时时间
 // 默认30分钟,一旦超时,该笔交易就会自动被关闭。
 // 取值范围:1m~15d。
 // m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。
 // 该参数数值不接受小数点,如1.5h,可转换为90m。
 orderInfo += "&it_b_pay=\"30m\"";

 // extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付
 // orderInfo += "&extern_token=" + "\"" + extern_token + "\"";

 // 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空
 orderInfo += "&return_url=\"m.alipay.com\"";

 // 调用银行卡支付,需配置此参数,参与签名, 固定值 (需要签约《无线银行卡快捷支付》才能使用)
 // orderInfo += "&paymethod=\"expressGateway\"";

 return orderInfo;
 }

 private static String sign(String content) {
 return SignUtils.sign(content, Constants.RSA_PRIVATE);
 }

 private static String getSignType() {
 return "sign_type=\"RSA\"";
 }
}

退款部分

支付宝

String strResponse = null;
AlipayTradeRefundResponse response = null;
try {
   AlipayClient alipayClient = new DefaultAlipayClient(url,Constants.APPID_ALIPAY,Constants.RSA_PRIVATE,"json","utf-8",Constants.RSA_PUBLIC);
   AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();

   RefundInfo alidata = new RefundInfo();
   alidata.setOut_trade_no(out_trade_no);
   alidata.setRefund_amount(refund_amount);

   request.setBizContent(JSON.toJSONString(alidata));

    response = alipayClient.sdkExecute(request);
     if (response.isSuccess()) {
       strResponse="退款成功";
     } else {
     strResponse="退款失败";
     }

      return strResponse;
    } catch (Exception e) {
     strResponse="退款出错";
    }
return strResponse;

微信

public class WXRefund {
 private static final String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";

 /**
 * 微信退款
 * @param out_trade_no 商户订单号
 * @param total_fee 总金额
 * @param refund_fee 退款金额
 * @return
 */
 public static String doRefund(String out_trade_no,int total_fee,int refund_fee) {

 InputStream instream = null;
 KeyStore keyStore = null;
 CloseableHttpResponse response = null;
 CloseableHttpClient httpclient = null;
 StringBuilder text = new StringBuilder();
 String key = Constants.MCH_ID;
 try {
  /**
  * 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的
  */
  keyStore = KeyStore.getInstance("PKCS12");
  instream = WXRefund.class.getResourceAsStream("/apiclient_cert.p12");//P12文件

  /**
  * 此处要改
  */
  keyStore.load(instream, key.toCharArray());// 这里写密码..默认是MCHID

  /**
  * 此处要改
  */
  SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray())// 这里也是写密码的
  .build();
  // Allow TLSv1 protocol only
  SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
  httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

  //=======================证书配置完成========================

  HttpPost httpPost = new HttpPost(url);

  String xmlstring = getRefunArgs(out_trade_no,total_fee,refund_fee);

  httpPost.setEntity(new StringEntity(xmlstring));
  httpPost.setHeader("Accept", "application/json");
  httpPost.setHeader("Content-type", "application/json");

  response = httpclient.execute(httpPost);

  HttpEntity entity = response.getEntity();

  if (entity != null) {
  BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));

  String str;
  while ((str = bufferedReader.readLine()) != null) {
   text.append(str);
  }
  }
  EntityUtils.consume(entity);
 }catch(Exception e){

 }finally {
  if(instream != null){
  try {
   instream.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
  }
  if(response != null){
  try {
   response.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
  }

  if(httpclient != null){
  try {
   httpclient.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
  }
 }
 Map<String,String> map = WXPay.decodeXml(text.toString());
 String return_msg = map.get("return_msg");
 if ("OK".equals(return_msg) && "SUCCESS".equals(map.get("return_code"))) {
  return "退款成功";
 }
 return return_msg;
 }

 //设置请求参数的值
 private static String getRefunArgs(String out_trade_no,int total_fee,int refund_fee) {
 String nonce_str = WXPay.genNonceStr();
 List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
 packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID_WX));
 packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));
 packageParams.add(new BasicNameValuePair("nonce_str", nonce_str));
 packageParams.add(new BasicNameValuePair("op_user_id", Constants.MCH_ID));
 packageParams.add(new BasicNameValuePair("out_refund_no",out_trade_no));
 packageParams.add(new BasicNameValuePair("out_trade_no",out_trade_no));
 packageParams.add(new BasicNameValuePair("refund_fee", String.valueOf(refund_fee)));
 packageParams.add(new BasicNameValuePair("total_fee", String.valueOf(total_fee)));

 String sign = WXPay.genPackageSign(packageParams);
 packageParams.add(new BasicNameValuePair("sign", sign));

 return WXPay.toXml(packageParams);

 }

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • java版微信和支付宝退款接口

    本文实例为大家分享了java微信退款接口和支付宝退款接口的具体代码,供大家参考,具体内容如下 1.微信退款接口  相对来说我感觉微信的退款接口还是比较好调用的,直接发送httppost请求即可: /** * * 微信退款 * @param transaction_id 微信支付订单号 * @param out_refund_no 商户订单号 * @param total_fee 总金额 * @param refund_fee 退款金额 * @param op_user_id 操作人 * @ret

  • 详解java集成支付宝支付接口(JSP+支付宝20160912)

    吐槽一下: 支付宝的接口和微信的DEMO和文档真心太难看懂了,乱七八糟,都不知道去哪里找自己要的东西,最近几天我们公司需要做类似的开发,我作为先锋,率先解决Java集成支付宝支付和微信支付接口工作. 我们的工作环境:JSP网站+支付接口,目前工作的支付宝接口为20160912,微信为V3版本,如遇到版本升级,请联系相关机构的客户服务人员升级. 本文介绍JSP+支付宝接口,本文非原创. 新手注意: 1.本文使用的接口地址和参数为沙箱的地址,无论你在使用沙箱或者正式地址,务必核实使用接口地址和参数,

  • java实现在SSM下使用支付宝扫码支付功能

    本文实例为大家分享了java使用支付宝扫码支付的具体代码,供大家参考,具体内容如下 准备工作 首先开通支付宝沙箱的测试账号,里面会有消费者账户和收款方账户 手机扫码下载手机端app 基础配置 所需jar包 AlipayConfig package com.alipay.config; import java.io.FileWriter; import java.io.IOException; import java.util.ResourceBundle; /* * *类名:AlipayConf

  • Java如何实现支付宝电脑支付基于servlet版本

    这篇文章主要介绍了Java如何实现支付宝电脑支付基于servlet版本,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前期准备: 蚂蚁金融开放平台进行登录操作 进入我的开放平台 在上方找到沙箱,进入沙箱(网络编程虚拟执行环境). 这里的RSA2密钥设置下,我已经设置好了,所以便有了支付宝公钥(公钥是对外公开的,私钥是自己保留的具体的不多做解释) 至于RSA2密钥的生成,可参考如下操作: 生成后在工具文件夹如下路径可以查看自己生成的公钥和私钥一对

  • java后台实现支付宝支付接口和支付宝订单查询接口(前端为APP)

    最近项目APP需要接入微信.支付宝支付功能,在分配开发任务时,听说微信支付接口比支付宝支付接口要难实现,由于我开发经验不是那么丰富(现工作经验1年半)且未接触过支付接口开发,组里刚好又有支付接口的老司机,所以很自然把简单的支付宝接口开发任务交给了我,看来开发组的组长还是很好人的嘛.....,废话就不多说了,我们开始吧! 实现支付宝接口详细过程 1.去支付宝官网申请公司企业账号并开通一个应用,在应用里签约APP支付功能 具体的申请截图步骤,在这里我就不详细说了,因为这不是文章的重点,可参考支付宝官

  • Java实现支付宝之第三方支付宝即时到账支付功能

    alipay 的几个内核功能文件: AlipayFunction.java package com.test.util.alipay; import java.io.FileWriter; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import ja

  • 支付宝APP支付(IOS手机端+java后台)版

    0.介绍预览 针对需要在IOS手机上接入原生微信支付场景,调用微信进行支付.如图: 1.资料准备 1.1 账号注册 打开https://openhome.alipay.com,注册支付宝开放平台开发者账号 1.2 开发者认证 登录,进入开发者中心,进行开发者资质认证,并创建移动应用. 1.3 签约应用 创建应用后上传相关资料,上线应用并通过审核.审核通过后点击应用,进行签约,此步骤不能省略,否则或报ISV权限不足. 1.4 应用配置 打开应用信息,配置一下内容,接口签名可下载支付宝签名验签工具进

  • java实现支付宝退款功能

    最近完成的差不多的项目突然需要加退款的流程需求了,所以来小小的实现以下. 其实对比其他的支付和退款来说,支付宝算是特别专业,也是特别简单的一个了. 一.引入支付宝SDK 在这里说一下,其实每种支付都会有一个官方带的SDK,我们可以把这个sdk引入到我们的项目中去,然后我们就可以调用里面的方法和对象,给里面传值,进行我们相应的请求的访问和介入. 首先引入如上图所示的jar包,然后我们就算是成功了一半了. 下载地址 然后我们需要把这个jar包引入到所需要的地方,这里不做过多的描述. 二.找到需要的资

  • java服务器端微信、支付宝支付和退款功能

    工作需要,写了服务器端的支付和退款功能,包含微信和支付宝,网上也有很多demo可以借鉴,我把我的代码放出来,写的比较简单,有问题的欢迎指正,大家一起学习. 微信支付需要调用微信的统一下单接口,而支付宝不用. 我写的时候微信和支付宝都单独写了一个工具类,来调用支付,给前端返回需要的数据. ps:支付是可以不需要服务器端的,不过为了安全一点点,所以前端需要调起支付的字段都直接从服务器端返回,前端拿到字段直接调起支付就可以了. Map<String,String> map = new HashMap

  • UniApp + SpringBoot 实现支付宝支付和退款功能

    目录 开发准备 支付宝支付开发 后端部分 前端部分 支付宝退款开发 后端部分 上篇介绍了UniApp + SpringBoot 实现微信支付和退款功能,喜欢的朋友可以点击查看. 开发准备 一台用于支付的测试机 用于编写的后端框架接口的 IDE (IDEA 或者 Eclipse 都可以) HBuilder X 用来编辑 UniApp 项目的编辑器和编译器 基本的 SpringBoot 的脚手架,可以去 https://start.spring.io/或者 IDEA 自带的快速生成脚手架插件. Jd

  • java实现微信H5支付方法详解

    前面做了app微信支付的回调处理,现在需要做微信公众号的支付,花了一天多时间,终于折腾出来了!鉴于坑爹的微信官方没有提供Java版的demo,所以全靠自己按照同样坑爹的文档敲敲敲,所以记录下来,以供自己及后来人参考,不足之处,还请指正. 首先,我们贴出调用支付接口的H5页面,当然,在这个页面之前,还需要做很多其他的操作,我们一步一步的来. 坑爹的官方文档给了两个不同的支付接口,在微信公众平台开发中文档的"微信JS-SDK说明文档"中,给出的支付方式是下面被屏蔽的那一部分,而在商户平台的

  • Python对接支付宝支付自实现功能

    代码如下所示: # -*- coding: utf-8 -*- import base64 import json import urllib.parse from datetime import datetime import requests from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.h

  • Java模仿微信实现零钱通简易功能(两种版本)

    目录 1. 需求描述 2. 需求分析 3. 实现零钱通主要功能 3.1 写一个菜单 3.2 零钱通明细 3.3 收益入账 3.4 消费 3.5 用户退出改进 3.6 改进金额判断 4. 面向过程版实现 5. 优化成OOP版 5.1 实现OOP版 5.2 OOP的好处 最近刚刚复习了一下Java的面向对象三大特性,这里跟着hsp做个小零钱通实践一下,以下记录了学习和编写过程 1. 需求描述 使用Java 开发零钱通项目, 模仿微信实现简易功能,可以完成收益入账,消费,查看明细,退出系统等功能,先按

  • UniApp + SpringBoot 实现微信支付和退款功能

    目录 开发准备 微信支付开发 后端部分 前端部分 开发准备 一台用于支付的测试机,必须得是一个安卓机因为需要打支付基座才能使用. 用于编写的后端框架接口的 IDE (IDEA 或者 Eclipse 都可以) HBuilder X 用来编辑 UniApp 项目的编辑器和编译器 基本的 SpringBoot 的脚手架,可以去 https://start.spring.io/或者 IDEA 自带的快速生成脚手架插件. Jdk 11 微信支付开发 我这里省略了申请等步骤.如果没有申请过企业支付的可以去官

  • php实现微信支付之退款功能

    网上的很多PHP微信支付接入教程都颇为复杂,且需要配置和引入较多的文件,本人通过整理后给出一个单文件版的,希望可以给各位想接入微信支付的带来些许帮助和借鉴意义. 直接运行该文件即可给指定的微信用户退款. 需要注意的事项: 1.微信退款到零钱要求必传证书,需要到这里账户中心->账户设置->API安全->下载证书,然后修改代码中的证书路径 2.该文件需放到支付授权目录下,可以在微信支付商户平台->产品中心->开发配置中设置. 3.如提示签名错误可以通过微信支付签名验证工具进行验证

  • java实现微信App支付服务端

    微信App支付服务端的实现方法,供大家参考,具体内容如下 引言 主要实现app支付统一下单.异步通知.调起支付接口.支付订单查询.申请退款.查询退款功能:封装了https对发起退款的证书校验.签名.xml解析等. 支付流程 具体支付流程参考"微信APP"文档,文档地址 APP支付:APP端点击下单--服务端生成订单,并调起"统一下单",返回app支付所需参数-–APP端"调起支付接口",发起支付--微信服务器端调用服务端回调地址-–服务端按照&q

  • Java开发微信Navicat支付完整版

    一:准备工作 1:先去微信公众平台注册一个公众号,选择服务号 2:去微信商户平台注册一个商户号,用于收款 3:在商户号中配置对应的公众号的APPID 4:支付结果异步通知(需要重点注意) 注意:请先详细查看官方文档按步骤开发,一切以官方文档为主 微信Navicat支付官方文档 5:测试的时候一定要使用内网穿透软件,否则回调时会报错  二:开发代码 WeChatPayConfig: public class WeChatPayConfig { //公众号APPID private String A

随机推荐