苹果app微信支付退款可以退款么

查看: 28715|回复: 38
新兵, 积分 122, 距离下一级还需 178 积分
本帖最后由 旧城故人. 于
22:19 编辑
刚刚看到有个小哥发帖说G胖支持微信支付了
赶紧选了一个愿望单里的游戏买了试试,正好今天细胞分裂打折
似乎是从今天(10月28日)开始支持微信支付
特地去网上查了下,似乎已经出现卡单一小时的情况了,而且退款的话可以退回到微信零钱(谢谢4楼提醒,亲自验证果然是),也有人用零钱支付成功的。不知道是否需要绑定银行卡呢?
学徒, 积分 33, 距离下一级还需 -23 积分
好棒\^O^/,啥时候的事
领主, 积分 5663, 距离下一级还需 337 积分
就是让你来砍手的哈哈
暴雪DV丧天良,誓与MK共存亡。
[armory]http://cn.battle.net/d3/en/profile/KID-5422/hero/[/armory]
骑士, 积分 801, 距离下一级还需 699 积分
别乱说好吗,已经测试过了!会回到微信钱包
学徒, 积分 5, 距离下一级还需 5 积分
穷人路过,根本没钱玩这游戏
新兵, 积分 122, 距离下一级还需 178 积分
别乱说好吗,已经测试过了!会回到微信钱包
我没试过退款,今天在网上听人说的,刚刚看你说我买了个1元小游戏试了下,确实是退回到微信零钱,现在改一下,谢谢提醒!
新兵, 积分 38, 距离下一级还需 262 积分
又多了一个剁手的选择。
学徒, 积分 23, 距离下一级还需 -13 积分
安卓什么时候能啊!?的
骑士, 积分 1205, 距离下一级还需 295 积分
强势,无敌,买买买!
国王, 积分 7221, 距离下一级还需 4779 积分
不错,比银联方便多了。。。。。。
[armory]http://cn.battle.net/d3/en/profile/Messiah-5226/hero/80629[/armory]
骑士, 积分 994, 距离下一级还需 506 积分
支付方便了,剁手也更方便了。
学徒, 积分 25, 距离下一级还需 -15 积分
这是为了保护你们啊!把手留到双11剁给我表哥啊
骑士, 积分 1218, 距离下一级还需 282 积分
竟然支持微信支付,厉害啊
[armory]http://tw.battle.net/d3/zh/profile/%E5%A5%87%E5%BC%82%E6%9E%9C-3821/hero/[/armory]
领主, 积分 3821, 距离下一级还需 2179 积分
不错了,可以支持微信支付了
学徒, 积分 3, 距离下一级还需 7 积分
楼主,麻烦问下微信退款需要多久
凯恩·感谢有你
凯恩之角金币纪念勋章:一阶
凯恩·寻宝者
凯恩之角金币纪念勋章:四阶
“夺魂之镰”资料片纪念勋章
凯恩之角赛季纪念勋章
守望先锋爱好者
终极成就达人
完成凯恩之角初阶任务
拥有完善的论坛资料
暗黑3忠实粉丝
英雄驿站活动优胜者
在论坛最二的人评选中获得优胜
情人节纪念勋章
在任何活动中获得过第三名!
注册满一周年
夺魂之镰武僧职业大师[3阶]
我的武僧我做主
特立独行的武僧玩家[2阶]
圣诞快乐!
凯恩之角圣诞纪念勋章
爱玩APP积分商城礼物
爱玩APP积分商城礼物
金质纪念币
暗黑二十周年活动金质纪念勋章
凯恩·开荒者
凯恩之角金币纪念勋章:二阶
注册满三周年
注册满四周年
Powered by内容字号:
段落设置:
字体设置:
精准搜索请尝试:
iOS 9被抛弃:苹果App Store已支持微信支付
来源:作者:仲平责编:仲平
更新:苹果App Store微信免密支付只支持iOS10.3以及以上系统。8月29日消息 苹果正式向用户开放了App Store微信免密支付功能,在Apple ID的付款信息当中进行微信授权之后就可以在购买App时采用微信支付,到目前为止国内两大支付软件均已支持了App Store付款。苹果表示:“我们很高兴中国大陆的用户现可以使用微信支付购买他们喜欢的 App 或是订阅 Apple Music。我们继续致力于在 Apple 生态内为顾客提供多种简单又方便的支付方式。”经过实测,该功能只支持iOS10以及最新的iOS11系统,而iOS 9系统并不包含在支持范围之内,想要添加微信免密支付的用户可以在Apple ID查看页更新自己的付款信息,添加之后就可以使用,体验类似于支付宝支付。授权之后,除了App Store之外,Apple Music当中也可以通过微信付款购买音乐会员。
软媒旗下软件:
IT之家,软媒旗下科技门户网站 - 爱科技,爱这里。
Copyright (C) , All Rights Reserved.app微信支付-java服务端接口 支付-查询-退款 - Spirit桥 - 博客园
个人不怎么看得懂微信的文档,看了很多前辈的写法,终于调通了,在这里做一下记录。
首先来定义各种处理类(微信支付不需要特殊jar包,很多处理需要自己封装,当然也可以自己写完打个jar包)
参数要用jdom解析& &自行导入jar包& &
或者在maven pom.xml中导入&
&dependency&
&groupId&org.jdom&/groupId&
&artifactId&jdom&/artifactId&
&version&1.1.3&/version&&/dependency&
version根据自己maven库中版本号进行设置
1、常用参数类
* 微信支付请求常量
* Created by HQ on
public class ConstantUtil {
* 微信开发平台应用ID
public static final String APP_ID="***";
* 应用对应的凭证
public static final String APP_SECRET="***";
* 应用对应的密钥
public static final String APP_KEY="***";
* 微信支付商户号
public static final String MCH_ID="***";
* 商品描述
public static final String BODY="***";
* 商户号对应的密钥
public static final String PARTNER_key="***";
我是用的与商户号相同
public static final String PARTNER_ID="***";
* 常量固定值 可自定义
public static final String GRANT_TYPE="client_credential";
* 获取预支付id的接口url
微信端提供的预支付信息生成借口
public static String GATEURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
* 获取支付订单信息url
微信端提供的查询订单接口
public static String GATESELECTURL = "https://api.mch.weixin.qq.com/pay/orderquery";
* 微信退款url
微信端提供的退款接口
public static String GATEREFUNDURL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
* 微信服务器回调通知url
编写的回调借口
根据自己框架的url访问方式配置
* 我们的url格式是
http://ip:端口/项目名/controller.do?方法requestMap
public static String NOTIFY_URL=".do?weiXinNotify";
2、http客户端工具类
import javax.net.ssl.HttpsURLC
import javax.net.ssl.KeyManagerF
import javax.net.ssl.SSLC
import javax.net.ssl.TrustManagerF
import java.io.*;
import java.net.HttpURLC
import java.net.URL;
import java.security.*;
import java.security.cert.CertificateE
import java.util.HashM
import java.util.M
public class HttpClientUtil {
* http客户端工具类
public static final String SunX509 = "SunX509";
public static final String JKS = "JKS";
public static final String PKCS12 = "PKCS12";
public static final String TLS = "TLS";
* get HttpURLConnection
* @param strUrl url地址
* @return HttpURLConnection
* @throws java.io.IOException
public static HttpURLConnection getHttpURLConnection(String strUrl)
throws IOException {
URL url = new URL(strUrl);
HttpURLConnection httpURLConnection = (HttpURLConnection) url
.openConnection();
return httpURLC
* get HttpsURLConnection
* @param strUrl url地址?
* @return HttpsURLConnection
* @throws IOException
public static HttpsURLConnection getHttpsURLConnection(String strUrl)
throws IOException {
URL url = new URL(strUrl);
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url
.openConnection();
return httpsURLC
* 获取不带查询串的url
* @param strUrl
* @return String
public static String getURL(String strUrl) {
if(null != strUrl) {
int indexOf = strUrl.indexOf("?");
if(-1 != indexOf) {
return strUrl.substring(0, indexOf);
return strU
return strU
* 获取查询串
* @param strUrl
* @return String
public static String getQueryString(String strUrl) {
if(null != strUrl) {
int indexOf = strUrl.indexOf("?");
if(-1 != indexOf) {
return strUrl.substring(indexOf+1, strUrl.length());
return "";
return strU
* 查询字符串转化为map
* name1=key1&name2=key2&...
* @param queryString
public static Map queryString2Map(String queryString) {
if(null == queryString || "".equals(queryString)) {
return null;
Map m = new HashMap();
String[] strArray = queryString.split("&");
for(int index = 0; index & strArray. index++) {
String pair = strArray[index];
HttpClientUtil.putMapByPair(pair, m);
* 把键值添加到map
* pair:name=value
* @param pair name=value
* @param m
public static void putMapByPair(String pair, Map m) {
if(null == pair || "".equals(pair)) {
int indexOf = pair.indexOf("=");
if(-1 != indexOf) {
String k = pair.substring(0, indexOf);
String v = pair.substring(indexOf+1, pair.length());
if(null != k && !"".equals(k)) {
m.put(k, v);
m.put(pair, "");
* BufferedReader转换成String&br/&
* 注意:流关闭需要自行处理
* @param reader
* @throws IOException
public static String bufferedReader2String(BufferedReader reader) throws IOException {
StringBuffer buf = new StringBuffer();
String line = null;
while( (line = reader.readLine()) != null) {
buf.append(line);
buf.append("\r\n");
return buf.toString();
* 处理输出&br/&
* 注意:流关闭需要自行处理
* @param out
* @param data
* @param len
* @throws IOException
public static void doOutput(OutputStream out, byte[] data, int len)
throws IOException {
int dataLen = data.
int off = 0;
while (off & data.length) {
if (len &= dataLen) {
out.write(data, off, dataLen);
off += dataL
out.write(data, off, len);
dataLen -=
// ??>>?????
out.flush();
* 获取SSLContext
* @param trustFileInputStream
* @param trustPasswd
* @param keyFileInputStream
* @param keyPasswd
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
* @throws IOException
* @throws CertificateException
* @throws UnrecoverableKeyException
* @throws KeyManagementException
public static SSLContext getSSLContext(
FileInputStream trustFileInputStream, String trustPasswd,
FileInputStream keyFileInputStream, String keyPasswd)
throws NoSuchAlgorithmException, KeyStoreException,
CertificateException, IOException, UnrecoverableKeyException,
KeyManagementException {
TrustManagerFactory tmf = TrustManagerFactory.getInstance(HttpClientUtil.SunX509);
KeyStore trustKeyStore = KeyStore.getInstance(HttpClientUtil.JKS);
trustKeyStore.load(trustFileInputStream, HttpClientUtil
.str2CharArray(trustPasswd));
tmf.init(trustKeyStore);
final char[] kp = HttpClientUtil.str2CharArray(keyPasswd);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(HttpClientUtil.SunX509);
KeyStore ks = KeyStore.getInstance(HttpClientUtil.PKCS12);
ks.load(keyFileInputStream, kp);
kmf.init(ks, kp);
SecureRandom rand = new SecureRandom();
SSLContext ctx = SSLContext.getInstance(HttpClientUtil.TLS);
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), rand);
* 字符串转换成char数组
* @param str
* @return char[]
public static char[] str2CharArray(String str) {
if(null == str) return null;
return str.toCharArray();
public static InputStream String2Inputstream(String str) {
return new ByteArrayInputStream(str.getBytes());
* InputStream转换成Byte
* 注意:流关闭需要自行处理
* @param in
* @return byte
* @throws Exception
public static byte[] InputStreamTOByte(InputStream in) throws IOException{
int BUFFER_SIZE = 4096;
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] data = new byte[BUFFER_SIZE];
int count = -1;
while((count = in.read(data,0,BUFFER_SIZE)) != -1)
outStream.write(data, 0, count);
data = null;
byte[] outByte = outStream.toByteArray();
outStream.close();
return outB
* InputStream转换成String
* 注意:流关闭需要自行处理
* @param in
* @param encoding 编码
* @return String
* @throws Exception
public static String InputStreamTOString(InputStream in,String encoding) throws IOException{
return new String(InputStreamTOByte(in),encoding);
3、MD5加密类
import java.security.MessageD
* Created by HQ on
public class MD5Util {
* @param b
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i & b. i++)
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
private static String byteToHexString(byte b) {
if (n & 0)
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString
.getBytes()));
resultString = byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
} catch (Exception exception) {
return resultS
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
static String getMessageDigest(byte[] buffer) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(buffer);
byte[] md = mdTemp.digest();
int j = md.
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i & i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 &&& 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
return new String(str);
} catch (Exception e) {
return "异常";
4、订单号生成类& & 这个可以自行判断要不要(只要不重复就行)& & 我是提前有个订单信息 前端直接给我订单号,当然订单号也是用这个类生成的。
import org.jeecgframework.core.util.DateU
import javax.servlet.http.HttpServletR
import java.util.D
import java.util.R
* Created by HQ on
public class OrderNumUtil {
private static Date date = new Date();
private static StringBuilder buf = new StringBuilder();
private static int seq = 0;
private static final int ROTATION = 99999;
public static synchronized String next() {
if (seq & ROTATION)
buf.delete(0, buf.length());
date.setTime(System.currentTimeMillis());
String str = String.format("%1$tY%1$tm%1$td%1$tk%1$tM%1$tS%2$05d", date, seq++);
public static synchronized String orderDatrNum() {
String randNum ="";
Random rand = new Random();
int shu2 = rand.nextInt(9);
randNum+= DateUtils.getDate("yyyyMMddHHmmss") + shu2;//
DateUtils 是项目中统一处理时间的 没有的话可自行处理
就是个时间格式转换
} catch (Exception e) {
e.printStackTrace();
return randN
5、获取支付prypPayId请求类
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import java.util.I
import java.util.M
import java.util.S
* 微信支付处理
* Created by HQon
public class PrepayIdRequestHandler extends RequestHandler{
public PrepayIdRequestHandler(HttpServletRequest request,
HttpServletResponse response) {
super(request, response);
public String createMD5Sign() {
StringBuffer sb = new StringBuffer();
Set es = super.getAllParameters().entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
sb.append(k + "=" + v + "&");
String params=sb.append("key="+ ConstantUtil.APP_KEY).substring(0);
String sign = MD5Util.MD5Encode(params, "utf8");
return sign.toUpperCase();
// 提交预支付
public String sendPrepay() throws Exception {
String prepayid = "";
Set es=super.getAllParameters().entrySet();
Iterator it=es.iterator();
StringBuffer sb = new StringBuffer("&xml&");
while(it.hasNext()){
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
sb.append("&"+k+"&"+v+"&/"+k+"&");
sb.append("&/xml&");
String params=sb.substring(0);
System.out.println("请求参数:"+params);
String requestUrl = super.getGateUrl();
System.out.println("请求url:"+requestUrl);
TenpayHttpClient httpClient = new TenpayHttpClient();
httpClient.setReqContent(requestUrl);
String resContent = "";
if (httpClient.callHttpPost(requestUrl, params)) {
resContent = httpClient.getResContent();
System.out.println("获取prepayid的返回值:"+resContent);
Map&String,String& map=XMLUtil.doXMLParse(resContent);
if(map.containsKey("prepay_id"))
prepayid=map.get("prepay_id");
6、签名请求类
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import java.io.IOE
import java.io.PrintW
import java.io.UnsupportedEncodingE
import java.net.URLE
import java.util.*;
* Created by HQ on
public class RequestHandler {
/** 网关url地址 */
private String gateU
/** 密钥 */
/** 请求的参数 */
private SortedM
protected HttpServletR
protected HttpServletR
* 构造函数
* @param request
* @param response
public RequestHandler(HttpServletRequest request, HttpServletResponse response) {
this.request =
this.response =
this.gateUrl = "https://gw.tenpay.com/gateway/pay.htm";
this.key = "";
this.parameters = new TreeMap();
*初始化函数。
public void init() {
//nothing to do
*获取入口地址,不包含参数值
public String getGateUrl() {
return gateU
*设置入口地址,不包含参数值
public void setGateUrl(String gateUrl) {
this.gateUrl = gateU
public String getKey() {
public void setKey(String key) {
this.key =
* 获取参数值
* @param parameter 参数名称
* @return String
public String getParameter(String parameter) {
String s = (String)this.parameters.get(parameter);
return (null == s) ? "" :
* 设置参数值
* @param parameter 参数名称
* @param parameterValue 参数值
public void setParameter(String parameter, Object parameterValue) {
String v = "";
if(null != parameterValue) {
if(parameterValue instanceof String)
v = ((String) parameterValue).trim();
this.parameters.put(parameter, v);
* 返回所有的参数
* @return SortedMap
public SortedMap getAllParameters() {
return this.
* 获取带参数的请求URL
* @return String
* @throws UnsupportedEncodingException
public String getRequestURL() throws UnsupportedEncodingException {
this.createSign();
StringBuffer sb = new StringBuffer();
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(!"spbill_create_ip".equals(k)) {
sb.append(k + "=" + URLEncoder.encode(v, enc) + "&");
sb.append(k + "=" + v.replace("\\.", "%2E") + "&");
//去掉最后一个&
String reqPars = sb.substring(0, sb.lastIndexOf("&"));
return this.getGateUrl() + "?" + reqP
public void doSend() throws UnsupportedEncodingException, IOException {
this.response.sendRedirect(this.getRequestURL());
* 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
protected void createSign() {
StringBuffer sb = new StringBuffer();
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
sb.append("key=" + this.getKey());
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
String sign = MD5Util.MD5Encode(sb.toString(), enc).toUpperCase();
this.setParameter("sign", sign);
protected HttpServletRequest getHttpServletRequest() {
return this.
protected HttpServletResponse getHttpServletResponse() {
return this.
7、响应参数处理类
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import java.io.IOE
import java.io.PrintW
import java.io.UnsupportedEncodingE
import java.util.*;
* Created by HQ on
public class ResponseHandler {
/** 密钥 */
/** 应答的参数 */
private SortedM
private HttpServletR
private HttpServletR
private String uriE
* 构造函数
* @param request
* @param response
public ResponseHandler(HttpServletRequest request,
HttpServletResponse response)
this.request =
this.response =
this.key = "";
this.parameters = new TreeMap();
this.uriEncoding = "";
Map m = this.request.getParameterMap();
Iterator it = m.keySet().iterator();
while (it.hasNext()) {
String k = (String) it.next();
String v = ((String[]) m.get(k))[0];
this.setParameter(k, v);
public String getKey() {
public void setKey(String key) {
this.key =
* 获取参数值
* @param parameter 参数名称
* @return String
public String getParameter(String parameter) {
String s = (String)this.parameters.get(parameter);
return (null == s) ? "" :
* 设置参数值
* @param parameter 参数名称
* @param parameterValue 参数值
public void setParameter(String parameter, String parameterValue) {
String v = "";
if(null != parameterValue) {
v = parameterValue.trim();
this.parameters.put(parameter, v);
* 返回所有的参数
* @return SortedMap
public SortedMap getAllParameters() {
return this.
* 是否财付通签名,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
* @return boolean
public boolean isTenpaySign() {
StringBuffer sb = new StringBuffer();
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(!"sign".equals(k) && null != v && !"".equals(v)) {
sb.append(k + "=" + v + "&");
sb.append("key=" + this.getKey());
//算出摘要
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();
String tenpaySign = this.getParameter("sign").toLowerCase();
return tenpaySign.equals(sign);
* 返回处理结果给财付通服务器。
* @param msg: Success or fail。
* @throws IOException
public void sendToCFT(String msg) throws IOException {
String strHtml =
PrintWriter out = this.getHttpServletResponse().getWriter();
out.println(strHtml);
out.flush();
out.close();
* 获取uri编码
* @return String
public String getUriEncoding() {
return uriE
* 设置uri编码
* @param uriEncoding
* @throws UnsupportedEncodingException
public void setUriEncoding(String uriEncoding)
throws UnsupportedEncodingException {
if (!"".equals(uriEncoding.trim())) {
this.uriEncoding = uriE
// 编码转换
String enc = TenpayUtil.getCharacterEncoding(request, response);
Iterator it = this.parameters.keySet().iterator();
while (it.hasNext()) {
String k = (String) it.next();
String v = this.getParameter(k);
v = new String(v.getBytes(uriEncoding.trim()), enc);
this.setParameter(k, v);
protected HttpServletRequest getHttpServletRequest() {
return this.
protected HttpServletResponse getHttpServletResponse() {
return this.
8、财付通请求客户端
import javax.net.ssl.HttpsURLC
import javax.net.ssl.SSLC
import javax.net.ssl.SSLSocketF
import java.io.BufferedOutputS
import java.io.IOE
import java.io.InputS
import java.net.HttpURLC
* Created by heqiao on
public class TenpayHttpClient {
/** 请求内容,无论post和get,都用get方式提供 */
private String reqC
/** 应答内容 */
private String resC
/** 请求方法 */
/** 错误信息 */
private String errI
/** 超时时间,以秒为单位 */
private int timeO
/** http应答编码 */
private int responseC
/** 字符编码 */
private InputStream inputS
public TenpayHttpClient() {
this.reqContent = "";
this.resContent = "";
this.method = "POST";
this.errInfo = "";
this.timeOut = 30;//<span style="color: #秒
this.responseCode = 0;
this.charset = "utf8";
this.inputStream = null;
* 设置请求内容
* @param reqContent 表求内容
public void setReqContent(String reqContent) {
this.reqContent = reqC
* 获取结果内容
* @return String
* @throws IOException
public String getResContent() {
this.doResponse();
} catch (IOException e) {
this.errInfo = e.getMessage();
//return "";
return this.resC
* 设置请求方法post或者get
* @param method 请求方法post/get
public void setMethod(String method) {
this.method =
* 获取错误信息
* @return String
public String getErrInfo() {
return this.errI
* 设置超时时间,以秒为单位
* @param timeOut 超时时间,以秒为单位
public void setTimeOut(int timeOut) {
this.timeOut = timeO
* 获取http状态码
* @return int
public int getResponseCode() {
return this.responseC
protected void callHttp() throws IOException {
if("POST".equals(this.method.toUpperCase())) {
String url = HttpClientUtil.getURL(this.reqContent);
String queryString = HttpClientUtil.getQueryString(this.reqContent);
byte[] postData = queryString.getBytes(this.charset);
this.httpPostMethod(url, postData);
this.httpGetMethod(this.reqContent);
public boolean callHttpPost(String url, String postdata) {
boolean flag = false;
byte[] postD
postData = postdata.getBytes(this.charset);
this.httpPostMethod(url, postData);
flag = true;
} catch (IOException e1) {
e1.printStackTrace();
* 以http post方式通信
* @param url
* @param postData
* @throws IOException
protected void httpPostMethod(String url, byte[] postData)
throws IOException {
HttpURLConnection conn = HttpClientUtil.getHttpURLConnection(url);
this.doPost(conn, postData);
* 以http get方式通信
* @param url
* @throws IOException
protected void httpGetMethod(String url) throws IOException {
HttpURLConnection httpConnection =
HttpClientUtil.getHttpURLConnection(url);
this.setHttpRequest(httpConnection);
httpConnection.setRequestMethod("GET");
this.responseCode = httpConnection.getResponseCode();
this.inputStream = httpConnection.getInputStream();
* 以https get方式通信
* @param url
* @param sslContext
* @throws IOException
protected void httpsGetMethod(String url, SSLContext sslContext)
throws IOException {
SSLSocketFactory sf = sslContext.getSocketFactory();
HttpsURLConnection conn = HttpClientUtil.getHttpsURLConnection(url);
conn.setSSLSocketFactory(sf);
this.doGet(conn);
protected void httpsPostMethod(String url, byte[] postData,
SSLContext sslContext) throws IOException {
SSLSocketFactory sf = sslContext.getSocketFactory();
HttpsURLConnection conn = HttpClientUtil.getHttpsURLConnection(url);
conn.setSSLSocketFactory(sf);
this.doPost(conn, postData);
* 设置http请求默认属性
* @param httpConnection
protected void setHttpRequest(HttpURLConnection httpConnection) {
//设置连接超时时间
httpConnection.setConnectTimeout(this.timeOut * 1000);
//不使用缓存
httpConnection.setUseCaches(false);
//允许输入输出
httpConnection.setDoInput(true);
httpConnection.setDoOutput(true);
* 处理应答
* @throws IOException
protected void doResponse() throws IOException {
if(null == this.inputStream) {
//获取应答内容
this.resContent=HttpClientUtil.InputStreamTOString(this.inputStream,this.charset);
//关闭输入流
this.inputStream.close();
* post方式处理
* @param conn
* @param postData
* @throws IOException
protected void doPost(HttpURLConnection conn, byte[] postData)
throws IOException {
// 以post方式通信
conn.setRequestMethod("POST");
// 设置请求默认属性
this.setHttpRequest(conn);
// Content-Type
conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
BufferedOutputStream out = new BufferedOutputStream(conn
.getOutputStream());
final int len = 1024; // 1KB
HttpClientUtil.doOutput(out, postData, len);
out.close();
// 获取响应返回状态码
this.responseCode = conn.getResponseCode();
// 获取应答输入流
this.inputStream = conn.getInputStream();
* get方式处理
* @param conn
* @throws IOException
protected void doGet(HttpURLConnection conn) throws IOException {
//以GET方式通信
conn.setRequestMethod("GET");
//设置请求默认属性
this.setHttpRequest(conn);
//获取响应返回状态码
this.responseCode = conn.getResponseCode();
//获取应答输入流
this.inputStream = conn.getInputStream();
9、财付通Util类
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import java.text.SimpleDateF
import java.util.D
* Created by heqiao on
public class TenpayUtil {
* 把对象转换成字符串
* @param obj
* @return String 转换成字符串,若对象为null,则返回空字符串.
public static String toString(Object obj) {
if(obj == null)
return "";
return obj.toString();
* 把对象转换为int数值.
* @param obj
包含数字的对象.
* @return int 转换后的数值,对不能转换的对象返回0。
public static int toInt(Object obj) {
int a = 0;
if (obj != null)
a = Integer.parseInt(obj.toString());
} catch (Exception e) {
* 获取当前时间 yyyyMMddHHmmss
* @return String
public static String getCurrTime() {
Date now = new Date();
SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
String s = outFormat.format(now);
* 获取当前日期 yyyyMMdd
* @param date
* @return String
public static String formatDate(Date date) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
String strDate = formatter.format(date);
return strD
* 取出一个指定长度大小的随机正整数.
* @param length
int 设定所取出随机数的长度。length小于11
* @return int 返回生成的随机数。
public static int buildRandom(int length) {
int num = 1;
double random = Math.random();
if (random & 0.1) {
random = random + 0.1;
for (int i = 0; i & i++) {
num = num * 10;
return (int) ((random * num));
* 获取编码字符集
* @param request
* @param response
* @return String
public static String getCharacterEncoding(HttpServletRequest request,
HttpServletResponse response) {
if(null == request || null == response) {
return "gbk";
String enc = request.getCharacterEncoding();
if(null == enc || "".equals(enc)) {
enc = response.getCharacterEncoding();
if(null == enc || "".equals(enc)) {
enc = "gbk";
* 获取unix时间,从 00:00:00开始的秒数
* @param date
* @return long
public static long getUnixTime(Date date) {
if( null == date ) {
return date.getTime()/1000;
* 时间转换成字符串
* @param date 时间
* @param formatType 格式化类型
* @return String
public static String date2String(Date date, String formatType) {
SimpleDateFormat sdf = new SimpleDateFormat(formatType);
return sdf.format(date);
public static
String getIpAddr(HttpServletRequest request)
request.getHeader( " x-forwarded-for " );
ip.length()
" unknown " .equalsIgnoreCase(ip))
request.getHeader( " Proxy-Client-IP " );
ip.length()
" unknown " .equalsIgnoreCase(ip))
request.getHeader( " WL-Proxy-Client-IP " );
ip.length()
" unknown " .equalsIgnoreCase(ip))
request.getRemoteAddr();
10、其他处理Util类
import com.sun.org.apache.bcel.internal.generic.RETURN;
import org.apache.http.HttpE
import org.apache.http.client.methods.CloseableHttpR
import org.apache.http.client.methods.HttpP
import org.apache.http.conn.ssl.SSLConnectionSocketF
import org.apache.http.entity.StringE
import org.apache.http.impl.client.CloseableHttpC
import org.apache.http.impl.client.HttpC
import org.apache.http.ssl.SSLC
import org.apache.http.util.EntityU
import org.hibernate.loader.custom.R
import org.jdom.D
import org.jdom.E
import org.jdom.input.SAXB
import org.jeecgframework.core.util.ResourceU
import org.xml.sax.InputS
import javax.net.ssl.SSLC
import javax.servlet.http.HttpServletR
import java.io.F
import java.io.FileInputS
import java.io.StringR
import java.security.KeyS
import java.util.*;
* Created by heqiao on
public class WXUtil {
* 生成随机字符串
public static String getNonceStr() {
Random random = new Random();
return MD5Util.MD5Encode(String.valueOf(random.nextInt(10000)), "utf8");
* 获取时间戳
public static String getTimeStamp() {
return String.valueOf(System.currentTimeMillis() / 1000);
* 获取十位的时间戳
* @param d 时间
public static String getTimeStamp(Date d) {
return String.valueOf(d.getTime() / 1000);
* https双向签名认证,用于支付申请退款
public static String payHttps(String url,String xml) throws Exception {
String MCH_ID = ConstantUtil.MCH_ID;
//指定读取证书格式为PKCS12
KeyStore keyStore = KeyStore.getInstance("PKCS12");
String path = ResourceUtil.getConfigByName("pay.weixin.certificate.localaddress");
//读取本机存放的PKCS12证书文件
FileInputStream instream = new FileInputStream(new File(path));
//指定PKCS12的密码(商户ID)
keyStore.load(instream, MCH_ID.toCharArray());
} finally {
instream.close();
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, MCH_ID.toCharArray()).build();
//指定TLS版本
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,new String[] { "TLSv1" },null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
//设置httpclient的SSLSocketFactory
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
HttpPost httpost = new HttpPost(url); // 设置响应头信息
httpost.addHeader("Connection", "keep-alive");
httpost.addHeader("Accept", "*/*");
httpost.addHeader("Content-Type", "application/x-www-form- charset=UTF-8");
httpost.addHeader("Host", "api.mch.weixin.qq.com");
httpost.addHeader("X-Requested-With", "XMLHttpRequest");
httpost.addHeader("Cache-Control", "max-age=0");
httpost.addHeader("User-Agent", "Mozilla/4.0 ( MSIE 8.0; Windows NT 6.0) ");
httpost.setEntity(new StringEntity(xml, "UTF-8"));
CloseableHttpResponse response = httpclient.execute(httpost);
HttpEntity entity = response.getEntity();
String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
EntityUtils.consume(entity);
return jsonS
}finally {
response.close();
}finally {
httpclient.close();
* 获取回调地址
* @param request
public static String getNotifyUrl(HttpServletRequest request) {
String url = request.getRequestURL().toString();
String domain = url.substring(0, url.length()-13);
//生产环境
return domain+ConstantUtil.NOTIFY_URL;
public static Map parseXmlToMap(String xml) {
Map retMap = new HashMap();
SortedMap&String, String& retMap = new TreeMap&&();
StringReader read = new StringReader(xml);
// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
InputSource source = new InputSource(read);
// 创建一个新的SAXBuilder
SAXBuilder sb = new SAXBuilder();
// 通过输入源构造一个Document
Document doc =
sb.build(source);
Element root = (Element) doc.getRootElement();// 指向根节点
List&Element& es = root.getChildren();
if (es != null && es.size() != 0) {
for (Element element : es) {
retMap.put(element.getName(), element.getValue());
} catch (Exception e) {
e.printStackTrace();
return retM
/*public static void main(String[] args){
System.out.println(getTimeStamp(new Date()));
11、XML解析类
import org.jdom.D
import org.jdom.E
import org.jdom.JDOME
import org.jdom.input.SAXB
import java.io.IOE
import java.io.InputS
import java.util.HashM
import java.util.I
import java.util.L
import java.util.M
import java.util.Map.E
import java.util.S
import java.io.ByteArrayInputS
public class XMLUtil {
* 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
* @param strxml
* @throws JDOMException
* @throws IOException
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
if(null == strxml || "".equals(strxml)) {
return null;
Map m = new HashMap();
InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
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();
v = XMLUtil.getChildrenText(children);
m.put(k, v);
in.close();
* 获取子结点的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
* @throws IOException
* @throws JDOMException
public static String getXMLEncoding(String strxml) throws JDOMException, IOException {
InputStream in = HttpClientUtil.String2Inputstream(strxml);
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
in.close();
return (String)doc.getProperty("encoding");
* 支付成功,返回微信那服务器
* @param return_code
* @param return_msg
public static String setXML(String return_code, String return_msg) {
return "&xml&&return_code&&![CDATA[" + return_code + "]]&&/return_code&&return_msg&&![CDATA[" + return_msg + "]]&&/return_msg&&/xml&";
public static String createXML(Map&String,Object& map){
Set&Entry&String,Object&& set=map.entrySet();
set.iterator();
return null;
12、支付接口
(生成签名& 获取 prePayId) 返回给APP端
此处参数除& &均可根据具体业务自定义& &只要可获取平台需支付的信息即可
返回参数与前端商量& 此处返回的Map& 也可返回json字符串& 或者后台统一的类型
* 微信生成预支付订单,获取prepayId
* @param request
* @param out_trade_no 订单号
* @param total_fee
* @param payType
* @param couponId
* @param addressId
* @param response
* @throws Exception , method = RequestMethod.POST
@ResponseBody
@RequestMapping(params = "getWeXinOrderString")
public Map&String, Object& getWeXinOrderString(HttpServletRequest request,
String out_trade_no,
Float total_fee,
String payType,
String couponId,
String addressId,
HttpServletResponse response) throws Exception {
Map&String, Object& map = new HashMap&&();
判断信息是否有误
根据参数判断要支付的信息是否存在或有误
根据自己业务进行处理
获取生成预支付订单的请求类
PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);
int totalFee = (int) (total_fee * 100);//微信支付是以分为单位的
System.out.println("total_fee:" + totalFee);
prepayReqHandler.setParameter("appid", ConstantUtil.APP_ID);
prepayReqHandler.setParameter("body", ConstantUtil.BODY);
prepayReqHandler.setParameter("mch_id", ConstantUtil.MCH_ID);
String nonce_str = WXUtil.getNonceStr();
prepayReqHandler.setParameter("nonce_str", nonce_str);
//设置回调地址-获取当前的地址拼接回调地址
prepayReqHandler.setParameter("notify_url", WXUtil.getNotifyUrl(request));
String outTradeNo = out_trade_//OrderNumUtil.orderDatrNum();//新的订单号
若订单号是实时生成的则在此处修改
prepayReqHandler.setParameter("out_trade_no", outTradeNo);
prepayReqHandler.setParameter("spbill_create_ip", TenpayUtil.getIpAddr(request));//request.getRemoteAddr()
Date timestamp = new Date();//WXUtil.getTimeStamp();
//开始时间和结束时间可不填
prepayReqHandler.setParameter("time_start", DateUtils.formatDate(timestamp, "yyyyMMddHHmmss"));// 此处时间是微信规定的格式
请自己些工具类转换 格式为
prepayReqHandler.setParameter("time_expire", DateUtils.formatDate(DateUtils.getTimeByMinute(10), "yyyyMMddHHmmss"));// 此处是交易结束时间
System.out.println(String.valueOf(total_fee));
prepayReqHandler.setParameter("total_fee", String.valueOf(totalFee));
prepayReqHandler.setParameter("trade_type", "APP");
* 注意签名(sign)的生成方式,具体见官方文档(传参都要参与生成签名,且参数名按照字典序排序,最后接上APP_KEY,转化成大写)
prepayReqHandler.setParameter("sign", prepayReqHandler.createMD5Sign());
prepayReqHandler.setGateUrl(ConstantUtil.GATEURL);
String prepayid = prepayReqHandler.sendPrepay();
// 若获取prepayid成功,将相关信息返回客户端
if (prepayid != null && !prepayid.equals("")) {//修改信息
此处根据业务自行处理
如商品支付信息为支付中 等信息 ,将当前订单号保存起来等
生成返回给app端的签名
和其他信息
* 签名方式与上面类似
StringBuffer sb = new StringBuffer();
sb.append("appid=" + ConstantUtil.APP_ID);
sb.append("&noncestr=" + nonce_str);
sb.append("&package=" + "Sign=WXPay");
sb.append("&partnerid=" + ConstantUtil.PARTNER_ID);
sb.append("&prepayid=" + prepayid);
String ts = WXUtil.getTimeStamp(timestamp);//此处是十位的时间戳
sb.append("&timestamp=" + ts);
sb.append("&key=" + ConstantUtil.APP_KEY);
//sign使用自己拼接的字符创定义
String sign = MD5Util.getMessageDigest(sb.toString().getBytes(Charset.forName("utf-8"))).toUpperCase();//MD5Util.MD5Encode(sb.toString(),"").toUpperCase();
map.put("sign", sign);
map.put("appId", ConstantUtil.APP_ID);
map.put("nonceStr", nonce_str);
//与请求prepayId时值一致
map.put("packageValue", "Sign=WXPay");
//固定常量
map.put("partnerId", ConstantUtil.PARTNER_ID);
map.put("timeStamp", ts);
map.put("code", 0);
map.put("out_trade_no", outTradeNo);
map.put("info", "success");
map.put("prepayId", prepayid);
map.put("code", 1);
map.put("info", "获取prepayid失败");
//net.sf.json.JSONObject json = net.sf.json.JSONObject.fromObject(map);
//json.toString();
// System.out.println("json=========="+json.toString());
* 接收微信支付成功通知
* ConstantUtil 中的
NOTIFY_URL
* @param request
* @param response
* @throws IOException
@ResponseBody
@RequestMapping(value = "weiXinNotify")
public void getnotify(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
System.out.println("微信支付回调");
PrintWriter writer = response.getWriter();
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 result = new String(outSteam.toByteArray(), "utf-8");
System.out.println("微信支付通知结果:" + result);
Map&String, String& map = null;
* 解析微信通知返回的信息
map = XMLUtil.doXMLParse(result);
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("=========:" + result);
// 若支付成功,则告知微信服务器收到通知
if (map.get("return_code").equals("SUCCESS")) {
if (map.get("result_code").equals("SUCCESS")) {
String out_trade_no = map.get("out_trade_no");
System.out.println("成功!" + out_trade_no);
//判断通知是否已处理,若已处理,则不予处理
// 根据订单号查询订单信息
做订单信息修改和支付信息修改
if (StringUtil.isNotEmpty(out_trade_no)) {
//根据订单号查询订单信息
//修改订单状态等信息
String notifyStr = XMLUtil.setXML("SUCCESS", ""); writer.write(notifyStr); writer.flush(); // return notifyS
} } }else{ String notifyStr = XMLUtil.setXML("FALSE", ""); writer.write(notifyStr); writer.flush(); } // return XMLUtil.setXML("FALSE", ""); }
13、去微信端查询支付的订单信息
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import java.io.IOE
import java.io.UnsupportedEncodingE
import java.net.URLE
import java.util.*;
* 微信支付查询 操作类
* Created by heqiao on
public class SelectReqHandler {
/** 网关url地址 */
private String gateSelectU
/** 密钥 */
/** 请求的参数 */
private SortedM
protected HttpServletR
protected HttpServletR
* 构造函数
* @param request
* @param response
public SelectReqHandler(HttpServletRequest request, HttpServletResponse response) {
this.request =
this.response =
this.gateSelectUrl = "https://api.mch.weixin.qq.com/pay/orderquery";
this.key = "";
this.parameters = new TreeMap();
*初始化函数。
public void init() {
//nothing to do
*获取入口地址,不包含参数值
public String getGateSelectUrl() {
return gateSelectU
*设置入口地址,不包含参数值
public void setGateSelectUrl(String gateSelectUrl) {
this.gateSelectUrl = gateSelectU
public String getKey() {
public void setKey(String key) {
this.key =
* 获取参数值
* @param parameter 参数名称
* @return String
public String getParameter(String parameter) {
String s = (String)this.parameters.get(parameter);
return (null == s) ? "" :
* 设置参数值
* @param parameter 参数名称
* @param parameterValue 参数值
public void setParameter(String parameter, Object parameterValue) {
String v = "";
if(null != parameterValue) {
if(parameterValue instanceof String)
v = ((String) parameterValue).trim();
this.parameters.put(parameter, v);
* 返回所有的参数
* @return SortedMap
public SortedMap getAllParameters() {
return this.
* 获取带参数的请求URL
* @return String
* @throws UnsupportedEncodingException
public String getRequestURL() throws UnsupportedEncodingException {
this.createSign();
StringBuffer sb = new StringBuffer();
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(!"spbill_create_ip".equals(k)) {
sb.append(k + "=" + URLEncoder.encode(v, enc) + "&");
sb.append(k + "=" + v.replace("\\.", "%2E") + "&");
//去掉最后一个&
String reqPars = sb.substring(<span style="color: #, sb.lastIndexOf("&"));
return this.getGateSelectUrl() + "?" + reqP
public void doSend() throws UnsupportedEncodingException, IOException {
this.response.sendRedirect(this.getRequestURL());
* 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
protected void createSign() {
StringBuffer sb = new StringBuffer();
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
sb.append("key=" + this.getKey());
String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);
String sign = MD5Util.MD5Encode(sb.toString(), enc).toUpperCase();
this.setParameter("sign", sign);
protected HttpServletRequest getHttpServletRequest() {
return this.
protected HttpServletResponse getHttpServletResponse() {
return this.
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import java.util.I
import java.util.M
import java.util.S
* 微信订单查询 退款
等处理信息
* Created by HQ on
public class PreRequestHandler extends SelectReqHandler{
public PreRequestHandler(HttpServletRequest request,
HttpServletResponse response) {
super(request, response);
public String createMD5Sign() {
StringBuffer sb = new StringBuffer();
Set es = super.getAllParameters().entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
sb.append(k + "=" + v + "&");
String params=sb.append("key="+ ConstantUtil.APP_KEY).substring(0);
String sign = MD5Util.MD5Encode(params, "utf8");
return sign.toUpperCase();
Map&String,String& sendPreSelect() throws Exception {
Set es=super.getAllParameters().entrySet();
Iterator it=es.iterator();
StringBuffer sb = new StringBuffer("&xml&");
while(it.hasNext()){
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
sb.append("&"+k+"&"+v+"&/"+k+"&");
sb.append("&/xml&");
String params=sb.substring(0);
System.out.println("请求参数:"+params);
String requestUrl = super.getGateSelectUrl();
System.out.println("请求url:"+requestUrl);
TenpayHttpClient httpClient = new TenpayHttpClient();
httpClient.setReqContent(requestUrl);
String resContent = "";
if (httpClient.callHttpPost(requestUrl, params)) {
resContent = httpClient.getResContent();
System.out.println("获取select的返回值:"+resContent);
Map&String,String& map=XMLUtil.doXMLParse(resContent);
return null;
* xml 参数
* @throws Exception
String sendPreSelectXml() throws Exception {
Set es=super.getAllParameters().entrySet();
Iterator it=es.iterator();
StringBuffer sb = new StringBuffer("&xml&");
while(it.hasNext()){
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
sb.append("&"+k+"&"+v+"&/"+k+"&");
sb.append("&/xml&");
System.out.println("退款请求参数:"+sb.substring(0));
return sb.substring(0);
* 微信支出订单状态查询
* 此接口直接去查询支付情况
防止回调不成功无法获取支付状态
* @param request
* @param response
* @return 返回参数见微信支付查询订单
@RequestMapping(params = "getWeiXinPayOrderSuccess")
@ResponseBody
public Page&Map&String, Object&& getWeiXinPayOrderSuccess(HttpServletRequest request,
HttpServletResponse response,
@RequestParam(required = false) String transactionId,
@RequestParam(required = false) String outTradeNo,
Page&Map&String, Object&& page) {
// 获取生成预支付订单的请求类
PreRequestHandler preSelectReqHandler = new PreRequestHandler(request, response);
preSelectReqHandler.setParameter("appid", ConstantUtil.APP_ID);
preSelectReqHandler.setParameter("mch_id", ConstantUtil.MCH_ID);
String nonce_str = WXUtil.getNonceStr();
preSelectReqHandler.setParameter("nonce_str", nonce_str);
if (com.senta.base.utils.StringUtil.isNotEmpty(transactionId)) {
preSelectReqHandler.setParameter("transaction_id ", transactionId);
preSelectReqHandler.setParameter("out_trade_no", outTradeNo);
* 注意签名(sign)的生成方式,具体见官方文档(传参都要参与生成签名,且参数名按照字典序排序,最后接上APP_KEY,转化成大写)
preSelectReqHandler.setParameter("sign", preSelectReqHandler.createMD5Sign());
preSelectReqHandler.setGateSelectUrl(ConstantUtil.GATESELECTURL);
Map&String, String& preSelectMap = preSelectReqHandler.sendPreSelect();
//判断是否成功
if (com.senta.base.utils.StringUtil.isNotEmpty(preSelectMap.get("trade_state")) && "SUCCESS".equals(preSelectMap.get("trade_state"))) {
//处理订单信息
也可不处理 看具体业务
page.setSuccess(true);
//处理返回参数
page.setObj(preSelectMap);
} catch (Exception e) {
e.printStackTrace();
page.setMessage("异常!");
14、退款操作
退款是需要证书的,下载下来放在某个目录
WXUtil.payHttps& 方法时修改方法里的
String path = ResourceUtil.getConfigByName("pay.weixin.certificate.localaddress");
这里的path是我在配置文件里配的证书路径&& 改为自己的证书存放路径
ex: path="D:/weixinZS/apiclient_cert.p12"
* 微信退款
* 此处用的
自己生成的订单号
就是上面支付中生成的订单号
* @param request
* @param response
* @return 返回参数见微信支付查询订单
@RequestMapping(params = "weiXinPayOrderRefund")
@ResponseBody
public Page&Map&String, Object&& weiXinPayOrderRefund(HttpServletRequest request,
HttpServletResponse response,
@RequestParam(required = false) String transactionId,
@RequestParam(required = false) String outTradeNo,
Page&Map&String, Object&& page) {
//transactionId为微信订单号
我没用这个号
//查询订单信息 根据订单号 这里是我自己的订单信息 此处换成自己 的PayOrderEntity payOrder = getPayOrderByNo(outTradeNo); if (payOrder == null || com.senta.base.utils.StringUtil.isEmpty(payOrder.getId())) { page.setMessage("订单号有误!"); } else if (!"1".equals(payOrder.getStatus())) { page.setMessage("该订单不能进行退款!"); } else {
// 获取生成预支付订单的请求类
PreRequestHandler preRefundReqHandler = new PreRequestHandler(request, response);
preRefundReqHandler.setParameter("appid", ConstantUtil.APP_ID);
preRefundReqHandler.setParameter("mch_id", ConstantUtil.MCH_ID);
String outRefundNo = payOrder.getOutRefundNo();
if (com.senta.base.utils.StringUtil.isEmpty(outRefundNo)) {
payOrder.setOutRefundNo(OrderNumUtil.orderDatrNum());
preRefundReqHandler.setParameter("out_refund_no", payOrder.getOutRefundNo());
String nonce_str = WXUtil.getNonceStr();
preRefundReqHandler.setParameter("nonce_str", nonce_str);
if (com.senta.base.utils.StringUtil.isNotEmpty(transactionId)) {
preRefundReqHandler.setParameter("transaction_id ", transactionId);
preRefundReqHandler.setParameter("out_trade_no", outTradeNo);
int total_fee = (payOrder.getCost().multiply(new BigDecimal(100))).intValue();//金额以分为单位
preRefundReqHandler.setParameter("total_fee", String.valueOf(total_fee));//订单金额
preRefundReqHandler.setParameter("refund_fee", String.valueOf(total_fee));//退款金额
* 注意签名(sign)的生成方式,具体见官方文档(传参都要参与生成签名,且参数名按照字典序排序,最后接上APP_KEY,转化成大写)
preRefundReqHandler.setParameter("sign", preRefundReqHandler.createMD5Sign());
preRefundReqHandler.setGateSelectUrl(ConstantUtil.GATEREFUNDURL);
String preSelectXml = preRefundReqHandler.sendPreSelectXml();
String retur = WXUtil.payHttps(ConstantUtil.GATEREFUNDURL, preSelectXml);
Map returnMap = new HashMap();
if (com.senta.base.utils.StringUtil.isNotEmpty(retur)) {
returnMap = WXUtil.parseXmlToMap(retur);
//判断是否成功
if (com.senta.base.utils.StringUtil.isNotEmpty(returnMap.get("result_code")) && "SUCCESS".equals(returnMap.get("result_code"))) {
//处理订单信息
//根据订单号查询订单信息//修改订单信息
修改支付状态
为退款状态
page.setSuccess(true);
//处理返回参数
也可不处理
返回值参考微信文档
page.setObj(returnMap);
} catch (Exception e) {
e.printStackTrace();
page.setMessage("异常!");
阅读(...) 评论()
Copyright & Spirit桥
Powered by:
模板提供:

我要回帖

更多关于 微信支付退款接口 的文章

 

随机推荐