java 7 微信支付 ssl_JAVA微信支付~

1,简单说明

现在好多项目上都需要用到微信支付接口,官方文档上也是简单的描述了下,技术不高深的真的难以理解(我自己看官方文档就看不懂),还是需要自己收集,总结,

网上看了好多

有些照着弄最后还是没法成功。接下来我分享下自己的微信支付。这个微信支付的微信公众号或者小程序,都是需要微信认证的,不然无法申请微信支付,这个就不说了

,既然到了这一步,相信所有的前提都已经准备好了。直接上代码吧~

2,java微信支付

一,首先了解下各个参数的意义

https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1  这个是微信官方的说明 截取部分,详细的请到这个链接查看。

3916e5e09973c97ca15bfd1006b20be7.png

09130557f10a8250ad3c34a7386c6549.png

5c97903d7252f22464424af1e4d6867f.png

二,微信支付代码

首先创建service层插入如下代码:

public interface WeiXinPayService {

Object WeiXinPay(String outTradeNo,String openid, String body, int total_fee) throws UnsupportedEncodingException;

}

@Service

public class WeiXinPayServiceImpl implements WeiXinPayService {

private static final Logger LOGGER = LoggerFactory

.getLogger(WeiXinPayServiceImpl.class);

@Override

public Object WeiXinPay(String outTradeNo,String openid, String body, int total_fee) {

String appid = "" // 公众号--》“开发者ID” 微信小程序,或者公众号的APPID

String mch_id = "" // 商户号,将该值赋值给partner

String key = "" // 微信支付商户平台登录)--》“API安全”--》“API密钥”--“设置密钥”(设置之后的那个值就是partnerkey,32位)

LOGGER.debug(appid);

LOGGER.debug(mch_id);

LOGGER.debug(key);

// String body = body; // 描述 int total_fee = total_fee; // 支付金额

String notify_url = ""; // 回调链接

// String out_trade_no = IdUtils.genOrderName();//生成订单号

// LOGGER.debug("outTradeNo---:"+out_trade_no);

LOGGER.debug("openid是----"+openid);

LOGGER.debug("appid---"+appid);

LOGGER.debug("mch_id---"+mch_id);

Map map = null;

try {

map = WeiXinAtcion.me.weixinPlay(mch_id, appid,

key, openid, total_fee, outTradeNo, notify_url, body);

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

} catch (DocumentException e) {

e.printStackTrace();

}

return map;

}

}

然后创建一个corcontroller层:

/**

*

Title: WeiXinPayController

*

Description: 微信支付

* @author Mr Lin

* @date 2018年7月7日

*/

@Controller

public class WeiXinPayController {

private static final Logger LOGGER = LoggerFactory

.getLogger(WeiXinPayController.class);

@Autowired

private WeiXinPayService weiXinPayService;

/**

* 支付接口

*

* @param openid

* @param body 说明

* @param total_fee 总价

* @return

*/

@RequestMapping("/WeiXinPay")

public @ResponseBody

Object WeiXinPay(String outTradeNo,String openid, String body, int total_fee) {

LOGGER.debug("outTradeNo-------------"+outTradeNo);

LOGGER.debug("openid-------------"+openid);

LOGGER.debug("body-------------"+body);

LOGGER.debug("total_fee-------------"+total_fee);

try {

return weiXinPayService.WeiXinPay(outTradeNo,openid, body, total_fee);

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

}

return TTResult.fail();

}

}

以上代码中使用到的工具类:首先WeiXinAtcion

/**

*

Title: WeiXinAtcion

*

Description:

* @author Mr Lin

* @date 2018年7月7日

*/

@Component

public class WeiXinAtcion {

//密钥

public static final WeiXinAtcion me = new WeiXinAtcion();

private static final Logger LOGGER = LoggerFactory

.getLogger(WeiXinAtcion.class);

/**

* 生成微信订单

*

* @param mch_id

* @param appid

* @param key

* @param openid

* @param total_fee

* @param out_trade_no

* @param notify_url

* @param body

* @return

* @throws UnsupportedEncodingException

* @throws DocumentException

*/

public SortedMap weixinPlay(String mch_id, String appid, String key, String openid, int total_fee, String out_trade_no, String notify_url, String body) throws UnsupportedEncodingException, DocumentException, DocumentException {

SortedMap paymentPo = new TreeMap();

paymentPo.put("appid", appid);

paymentPo.put("mch_id", mch_id);

paymentPo.put("nonce_str", WXUtil.generate());

paymentPo.put("body", body);

paymentPo.put("out_trade_no", out_trade_no);

paymentPo.put("total_fee", String.valueOf(total_fee));

paymentPo.put("spbill_create_ip","服务器的ip地址");//此处是公网ip

paymentPo.put("notify_url", notify_url);

paymentPo.put("trade_type", "JSAPI");

paymentPo.put("openid", openid);

String sign = WXUtil.createSign_ChooseWXPay("UTF-8", paymentPo, key);

paymentPo.put("sign", sign);

String param = WXUtil.getRequestXml(paymentPo);

//将参数通过post请求传给微信端

String request = WXUtil.httpRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST", param);

Map map = new HashMap(); // 将解析结果存储在HashMap中

InputStream in = new ByteArrayInputStream(request.getBytes());

SAXReader reader = new SAXReader(); // 读取输入流

Document document = reader.read(in);

Element root = document.getRootElement(); // 得到xml根元素

@SuppressWarnings("unchecked") // 得到根元素的所有子节点

List elementList = root.elements();

for (Element element : elementList) {

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

}

SortedMap result = new TreeMap();

LOGGER.debug("第一次签名返回码" + map.get("return_code"));

LOGGER.debug("第一次签名返回结果" + map.get("return_msg"));

//第一次签名成功

if (map.get("return_code").equals("SUCCESS")) { // 业务结果

String nonceStr = WXUtil.generate();

Long timeStamp = System.currentTimeMillis() / 1000;

SortedMap params = new TreeMap();

params.put("appId", appid);

params.put("nonceStr", nonceStr);

params.put("package", "prepay_id=" + map.get("prepay_id"));

params.put("signType", "MD5");

params.put("timeStamp", timeStamp);

//第二次签名成功

LOGGER.debug("开始第二次签名");

String paySign = WXUtil.createSign_ChooseWXPay("UTF-8", params, key);

result.put("paySign", paySign);

result.put("timeStamp", timeStamp + "");

result.put("nonceStr", nonceStr);

result.put("out_trade_no", paymentPo.get("out_trade_no"));

result.put("package", "prepay_id=" + map.get("prepay_id"));

result.put("return_code", "SUCCESS");

} else {

result.put("return_code", "Fail");

result.put("return_msg", map.get("return_msg"));

}

return result;

}

}

工具类:WXUtil

public class WXUtil {

private static final Logger LOGGER = LoggerFactory.getLogger(WXUtil.class);

/**

* 随机字符串

* @return

*/

public static String generate() {

return UUID.randomUUID().toString().trim().replaceAll("-", "");

}

/**

* 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。

* @param strxml

* @return

* @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();

} else {

v = WXUtil.getChildrenText(children);

}

m.put(k, v);

}

//关闭流

in.close();

return m;

}

/**

* 获取子结点的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("");

if(!list.isEmpty()) {

sb.append(WXUtil.getChildrenText(list));

}

sb.append(value);

sb.append("" + name + ">");

}

}

return sb.toString();

}

/**

* 将请求参数转换为xml格式的string字符串,微信服务器接收的是xml格式的字符串

* @param parameters

* @return

*/

public static String getRequestXml(SortedMap parameters) {

StringBuffer sb = new StringBuffer();

sb.append("");

Set> es = parameters.entrySet();

Iterator> it = es.iterator();

while (it.hasNext()) {

Entry entry = (Entry) it.next();

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

String v = (String) entry.getValue();

if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {

sb.append("" + "" + k + ">");

} else {

sb.append("" + v + "" + k + ">");

}

}

sb.append("");

return sb.toString();

}

/**

* sign签名,必须使用MD5签名,且编码为UTF-8

* @param characterEncoding

* @param parameters

* @return

*/

public static String createSign_ChooseWXPay(String characterEncoding, SortedMap parameters, String key) {

StringBuffer sb = new StringBuffer();

Set> es = parameters.entrySet();

Iterator> it = es.iterator();

while (it.hasNext()) {

Entry entry = (Entry) it.next();

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

Object v = entry.getValue();

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

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

}

}

/** 支付密钥必须参与加密,放在字符串最后面 */

sb.append("key=" + key);

String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();

return sign;

}

public static String httpRequest(String requestUrl,String requestMethod,String outputStr){

// 创建SSLContext

StringBuffer buffer=null;

try{

URL url = new URL(requestUrl);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod(requestMethod);

conn.setDoOutput(true);

conn.setDoInput(true);

conn.connect();

//往服务器端写内容

if(null !=outputStr){

OutputStream os=conn.getOutputStream();

os.write(outputStr.getBytes("utf-8"));

os.close();

}

// 读取服务器端返回的内容

InputStream is = conn.getInputStream();

InputStreamReader isr = new InputStreamReader(is, "utf-8");

BufferedReader br = new BufferedReader(isr);

buffer = new StringBuffer();

String line = null;

while ((line = br.readLine()) != null) {

buffer.append(line);

}

}catch(Exception e){

e.printStackTrace();

}

return buffer.toString();

}

public static String urlEncodeUTF8(String source){

String result=source;

try {

result=java.net.URLEncoder.encode(source, "UTF-8");

} catch (UnsupportedEncodingException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return result;

}

/**

* 退款和企业付款到银行卡

*/

public static Map doRefund(HttpServletRequest request,String url,String data,String partner,String apiclient_certLocation) throws Exception {

// p12证书的位置

// 微信公众平台:“微信支付”--》“商户信息”--》“交易数据”--》“详情请登录微信支付商户平台查看”(登录)--》“API安全”--》“API证书”--》“下载证书”

// 下载证书后将apiclient_cert.p12放在src目录下面(出于安全考虑,请自行下载自己的证书)

KeyStore keyStore = KeyStore.getInstance("PKCS12");

String url2 = request.getSession().getServletContext().getRealPath("/")

+ "cert/" + apiclient_certLocation;

LOGGER.debug("url2--->"+url2);

File file=new File(url2);

FileInputStream instream = new FileInputStream(file);// P12文件目录

try {

keyStore.load(instream, partner.toCharArray());

} finally {

instream.close();

}

SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, partner.toCharArray()).build();

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" }, null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

try {

HttpPost httpost = new HttpPost(url); // 设置响应头信息

httpost.addHeader("Connection", "keep-alive");

httpost.addHeader("Accept", "*/*");

httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; 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 (compatible; MSIE 8.0; Windows NT 6.0) ");

httpost.setEntity(new StringEntity(data, "UTF-8"));

CloseableHttpResponse response = httpclient.execute(httpost);

try {

HttpEntity entity = response.getEntity();

String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");

EntityUtils.consume(entity);

return WXUtil.doXMLParse(jsonStr);

} finally {

response.close();

}

} finally {

httpclient.close();

}

}

/**

* 得到公钥

* @param request

* @param url 请求微信端的链接

* @param data//请求的数据

* @param partner

* @param apiclient_certLocation

* @return

* @throws Exception

*/

public static Object getPublicKey(HttpServletRequest request,String url,String data,String partner,String apiclient_certLocation) throws Exception {

// p12证书的位置

// 微信公众平台:“微信支付”--》“商户信息”--》“交易数据”--》“详情请登录微信支付商户平台查看”(登录)--》“API安全”--》“API证书”--》“下载证书”

// 下载证书后将apiclient_cert.p12放在src目录下面(出于安全考虑,请自行下载自己的证书)

KeyStore keyStore = KeyStore.getInstance("PKCS12");

String url2 = request.getSession().getServletContext().getRealPath("/")

+ "cert/" + apiclient_certLocation;

LOGGER.debug("url2--->"+url2);

File file=new File(url2);

FileInputStream instream = new FileInputStream(file);// P12文件目录

try {

keyStore.load(instream, partner.toCharArray());

} finally {

instream.close();

}

SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, partner.toCharArray()).build();

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" }, null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

try {

HttpPost httpost = new HttpPost(url); // 设置响应头信息

httpost.addHeader("Connection", "keep-alive");

httpost.addHeader("Accept", "*/*");

httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

httpost.addHeader("X-Requested-With", "XMLHttpRequest");

httpost.addHeader("Cache-Control", "max-age=0");

httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");

httpost.setEntity(new StringEntity(data, "UTF-8"));

CloseableHttpResponse response = httpclient.execute(httpost);

try {

HttpEntity entity = response.getEntity();

String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");

EntityUtils.consume(entity);

return jsonStr;

} finally {

response.close();

}

} finally {

httpclient.close();

}

}

/**

* 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。

* @return boolean

*/

public static boolean isTenpaySign(String characterEncoding, SortedMap packageParams, String API_KEY) {

StringBuffer sb = new StringBuffer();

Set es = packageParams.entrySet();

Iterator it = es.iterator();

while(it.hasNext()) {

Entry entry = (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=" + API_KEY);

//算出摘要

String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase();

String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();

return tenpaySign.equals(mysign);

}

public static Map doRefund(String string, String xML, String mCH_ID, String cERT) {

// TODO Auto-generated method stub

return null;

}

}

返回结果的工具类:TTResult

public class TTResult {

// 定义jackson对象

private static final ObjectMapper MAPPER = new ObjectMapper();

// 响应业务状态

private Integer status; // 200 代表成功, 500 代表失败

// 响应消息

private String msg;

// 响应中的数据

private Object data;

public static TTResult build(Integer status, String msg, Object data) {

return new TTResult(status, msg, data);

}

public static TTResult ok(Object data) {

return new TTResult(data);

}

public static TTResult ok() {

return new TTResult(null);

}

public static TTResult fail(){

return new TTResult(500,"fail",null);

}

public static TTResult fail(Object data){

return new TTResult(500,"fail",data);

}

public TTResult() {

}

public static TTResult build(Integer status, String msg) {

return new TTResult(status, msg, null);

}

public TTResult(Integer status, String msg, Object data) {

this.status = status;

this.msg = msg;

this.data = data;

}

public TTResult(Object data) {

this.status = 200;

this.msg = "OK";

this.data = data;

}

// public Boolean isOK() {

// return this.status == 200;

// }

public Integer getStatus() {

return status;

}

public void setStatus(Integer status) {

this.status = status;

}

public String getMsg() {

return msg;

}

public void setMsg(String msg) {

this.msg = msg;

}

public Object getData() {

return data;

}

public void setData(Object data) {

this.data = data;

}

/**

* 将json结果集转化为TTResult对象

*

* @param jsonData

* json数据

* @param clazz

* TTResult中的object类型

* @return

*/

public static TTResult formatToPojo(String jsonData, Class> clazz) {

try {

if (clazz == null) {

return MAPPER.readValue(jsonData, TTResult.class);

}

JsonNode jsonNode = MAPPER.readTree(jsonData);

JsonNode data = jsonNode.get("data");

Object obj = null;

if (clazz != null) {

if (data.isObject()) {

obj = MAPPER.readValue(data.traverse(), clazz);

} else if (data.isTextual() || data.isNumber()) {

obj = MAPPER.readValue(data.asText(), clazz);

}

}

return build(jsonNode.get("status").intValue(), jsonNode.get("msg")

.asText(), obj);

} catch (Exception e) {

return null;

}

}

/**

* 没有object对象的转化

*

* @param json

* @return

*/

public static TTResult format(String json) {

try {

return MAPPER.readValue(json, TTResult.class);

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

/**

* Object是集合转化

*

* @param jsonData

* json数据

* @param clazz

* 集合中的类型

* @return

*/

public static TTResult formatToList(String jsonData, Class> clazz) {

try {

JsonNode jsonNode = MAPPER.readTree(jsonData);

JsonNode data = jsonNode.get("data");

Object obj = null;

if (data.isArray() && data.size() > 0) {

obj = MAPPER.readValue(data.traverse(), MAPPER.getTypeFactory()

.constructCollectionType(List.class, clazz));

}

return build(jsonNode.get("status").intValue(), jsonNode.get("msg")

.asText(), obj);

} catch (Exception e) {

return null;

}

}

}

上面代码中所涉及到的参数,要去微信官方文档看说明,每个参数都有解释的,按照我这个来,微信支付是肯定能跑通的。有啥不足之处请指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值