admin 管理员组

文章数量: 887007

简单微信扫码支付集成(java)

微信扫码支付(java)

项目中引入微信支付,按API要求组装参数,以XML方式发送(POST)给微信支付接口(URL),微信支付接口也是以XML方式给予响应。程序根据返回的结果(其中包括支付URL)生成二维码或判断订单状态。

1.导入SDK依赖和httpClient

httpclient用于在后端发送请求

<dependency><groupId>com.github.wxpay</groupId><artifactId>wxpay-sdk</artifactId><version>0.0.3</version>
</dependency>
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId>	  		
</dependency>
2.编写配置文件properties
# 微信公众账号或开放平台APP的唯一标识
appid=******XXX
# 财付通平台的商户账号
partner=******XXX
# 财付通平台的商户密钥
partnerkey=******XXX
3.httpClient工具类
package com.pyg.util;import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;import javax.ssl.SSLContext;
import javax.ssl.SSLException;
import javax.ssl.SSLSession;
import javax.ssl.SSLSocket;
import javax.ssl.TrustManager;
import javax.ssl.X509TrustManager;import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;/*** http请求客户端* * @author Administrator* */
public class HttpClient {private String url;private Map<String, String> param;private int statusCode;private String content;private String xmlParam;private boolean isHttps;public boolean isHttps() {return isHttps;}public void setHttps(boolean isHttps) {this.isHttps = isHttps;}public String getXmlParam() {return xmlParam;}public void setXmlParam(String xmlParam) {this.xmlParam = xmlParam;}public HttpClient(String url, Map<String, String> param) {this.url = url;this.param = param;}public HttpClient(String url) {this.url = url;}public void setParameter(Map<String, String> map) {param = map;}public void addParameter(String key, String value) {if (param == null)param = new HashMap<String, String>();param.put(key, value);}public void post() throws ClientProtocolException, IOException {HttpPost http = new HttpPost(url);setEntity(http);execute(http);}public void put() throws ClientProtocolException, IOException {HttpPut http = new HttpPut(url);setEntity(http);execute(http);}public void get() throws ClientProtocolException, IOException {if (param != null) {StringBuilder url = new StringBuilder(this.url);boolean isFirst = true;for (String key : param.keySet()) {if (isFirst)url.append("?");elseurl.append("&");url.append(key).append("=").append(param.get(key));}this.url = url.toString();}HttpGet http = new HttpGet(url);execute(http);}/*** set http post,put param*/private void setEntity(HttpEntityEnclosingRequestBase http) {if (param != null) {List<NameValuePair> nvps = new LinkedList<NameValuePair>();for (String key : param.keySet())nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数}if (xmlParam != null) {http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));}}private void execute(HttpUriRequest http) throws ClientProtocolException,IOException {CloseableHttpClient httpClient = null;try {if (isHttps) {SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {// 信任所有public boolean isTrusted(X509Certificate[] chain,String authType)throws CertificateException {return true;}}).build();SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();} else {httpClient = HttpClients.createDefault();}CloseableHttpResponse response = httpClient.execute(http);try {if (response != null) {if (response.getStatusLine() != null)statusCode = response.getStatusLine().getStatusCode();HttpEntity entity = response.getEntity();// 响应内容content = EntityUtils.toString(entity, Consts.UTF_8);}} finally {response.close();}} catch (Exception e) {e.printStackTrace();} finally {httpClient.close();}}public int getStatusCode() {return statusCode;}public String getContent() throws ParseException, IOException {return content;}}
4.后端controller
package com.pyg.cart.controller;import com.alibaba.dubbo.config.annotation.Reference;
import com.pyg.pay.service.WeixinPayService;
import com.pyg.util.IdWorker;
import entity.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;/*** @Title: PayController* @ProjectName PYG* @Description: TODO*/
@RestController
@RequestMapping("/pay")
public class PayController {@Referenceprivate WeixinPayService weixinPayService;@Autowiredprivate IdWorker idWorker;@RequestMapping("/createNative")public Map createNative( String out_trade_no,String total_fee){//返回 订单号 支付金额 code_url(支付地址)return weixinPayService.createNative(out_trade_no,total_fee);}@RequestMapping("/queryPayStatus")public Result queryPayStatus(String out_trade_no){Result result=null;//限时5分钟int x=0;while (true){Map map = weixinPayService.queryPayStatus(out_trade_no);if(map==null){result=new Result(false,"支付出错");break;}if(map.get("trade_state").equals("SUCCESS")){result=new Result(true,"支付成功");break;}try{Thread.sleep(3000);//每隔3秒 发送请求确认订单状态}catch (Exception e){e.printStackTrace();}x++;if(x>=100){result=new Result(false,"二维码超时");}}return result;}}
5.服务层接口
package com.pyg.pay.service;import java.util.Map;/*** @Title: WeixinPayService* @ProjectName PYG* @Description: TODO*/
public interface WeixinPayService {/*** @Description: 生成微信支付二维码* @param out_trade_no  订单号* @param total_fee     金额(单位: 分)* @return java.util.Map*/Map createNative(String out_trade_no,String total_fee);/*** @Description: 查询支付状态* @param out_trade_no 订单号* @return java.util.Map*/Map queryPayStatus(String out_trade_no);/*** @Description: 关闭订单* @param out_trade_no* @return java.util.Map<java.lang.String,java.lang.String>*/Map<String,String> closePay(String out_trade_no);}
6.服务层实现类

(1)获取随机字符串

WXPayUtil.generateNonceStr()

(2)MAP转换为XML字符串(自动添加签名)

WXPayUtil.generateSignedXml(param, partnerkey)

(3)XML字符串转换为MAP

WXPayUtil.xmlToMap(result)

我们要生成支付二维码,就需要一个支付地址, 支付地址在预支付响应中–> code_url

package com.pyg.pay.service.impl;import com.alibaba.dubbo.config.annotation.Service;
import com.github.wxpay.sdk.WXPayUtil;
import com.pyg.pay.service.WeixinPayService;
import com.pyg.util.HttpClient;
import org.springframework.beans.factory.annotation.Value;
import sun.security.action.PutAllAction;
import java.util.HashMap;
import java.util.Map;/*** @Title: WeixinPayServiceImpl* @ProjectName PYG* @Description: TODO*/
@Service(timeout = 10000)
public class WeixinPayServiceImpl implements WeixinPayService{@Value("${appid}")private String appid;@Value("${partner}")private String partner;@Value("${partnerkey}")private String partnerKey;/*** @param out_trade_no 订单号* @param total_fee    金额(分)* @return java.util.Map* @Description: 生成微信支付二维码*/@Overridepublic Map createNative(String out_trade_no, String total_fee) {//需要发送xml 我们就先定义map数据 然后使用wxpayUtil 进行转换Map<String,String> param=new HashMap<>();param.put("appid",appid);//公众号param.put("mch_id",partner);//商户号param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串		param.put("body","QuietHR旗舰店");//商品描述param.put("out_trade_no",out_trade_no);//商户订单号param.put("total_fee",total_fee);//总金额(分)param.put("spbill_create_ip","127.0.0.1");//IPparam.put("notify_url","/");//回调地址param.put("trade_type","NATIVE");//交易类型try{//生成发送的xmlString xmlParam = WXPayUtil.generateSignedXml(param, partnerKey);//发送post请求HttpClient client = new HttpClient("");client.setHttps(true);client.setXmlParam(xmlParam);client.post();//获得预支付响应String result = client.getContent();Map<String, String> resultMap = WXPayUtil.xmlToMap(result);//重新封装数据到前端  前端需要什么就传什么Map<String,String> map=new HashMap<>();map.put("code_url",resultMap.get("code_url"));//返回的支付地址 根据这个url生成二维码map.put("total_fee",total_fee);map.put("out_trade_no",out_trade_no);return map;}catch (Exception e){e.printStackTrace();return new HashMap();}}/*** @param out_trade_no 订单号* @return java.util.Map* @Description: 查询支付状态*/@Overridepublic Map queryPayStatus(String out_trade_no) {Map param=new HashMap();param.put("appid",appid);param.put("mch_id",partner);param.put("out_trade_no",out_trade_no);param.put("nonce_str",WXPayUtil.generateNonceStr());String url="";try{String xmlParam = WXPayUtil.generateSignedXml(param, partnerKey);HttpClient client = new HttpClient(url);client.setHttps(true);client.setXmlParam(xmlParam);client.post();String result = client.getContent();Map<String, String> resultMap = WXPayUtil.xmlToMap(result);System.out.println(result);return resultMap;}catch (Exception e){e.printStackTrace();return null;}}/*** @Description: 关闭订单* @param out_trade_no* @return java.util.Map<java.lang.String,java.lang.String>*/@Overridepublic Map<String, String> closePay(String out_trade_no) {Map param=new HashMap();param.put("appid",appid);param.put("mch_id",partner);param.put("out_trade_no",out_trade_no);param.put("nonce_str",WXPayUtil.generateNonceStr());try {HttpClient client = new HttpClient("");client.setHttps(true);String signedXml = WXPayUtil.generateSignedXml(param, partnerKey);client.setXmlParam(signedXml);client.post();String content = client.getContent();Map<String, String> resultMap = WXPayUtil.xmlToMap(content);System.out.println(resultMap);return resultMap;} catch (Exception e) {e.printStackTrace();return null;}}
}
发送的xml和接收的xml
<!--统一下单API 预支付发送的xml-->
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xml>
<nonce_str>62fe30a4646b4eb4b46eefd25f1ac4d3</nonce_str>
<out_trade_no>1059415625195061248</out_trade_no>
<appid>******XXX</appid>
<total_fee>1</total_fee>
<sign>06CE9EE392E771955E9F748667273FCF</sign>
<trade_type>NATIVE</trade_type>
<mch_id>******XXX</mch_id>
<body>QuietHR旗舰店</body>
<notify_url>/</notify_url>
<spbill_create_ip>127.0.0.1</spbill_create_ip>
</xml>
<!--统一下单API 预支付响应的xml-->
<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[******XXX]]></appid>
<mch_id><![CDATA[******XXX]]></mch_id>
<nonce_str><![CDATA[yyUe8Zez8djJhTiw]]></nonce_str>
<sign><![CDATA[E0EDEC1D6B6268DE6B1172FFFBE3FCD9]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx0520022407695355d74a5cb20329414550]]></prepay_id>
<trade_type><![CDATA[NATIVE]]></trade_type>
<code_url><![CDATA[weixin://wxpay/bizpayurl?pr=nE1oWY9]]></code_url>
</xml>
<!--查询订单API 返回的xml-->
<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[******XXX]]></appid>
<mch_id><![CDATA[******XXX]]></mch_id>
<nonce_str><![CDATA[GUXcF2078yXq3JV9]]></nonce_str>
<sign><![CDATA[44152FA2993AA49BBE1176CB9F30574C]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<out_trade_no><![CDATA[1059415625195061248]]></out_trade_no>
<trade_state><![CDATA[NOTPAY]]></trade_state>
<trade_state_desc><![CDATA[订单未支付]]></trade_state_desc>
</xml>
<!--查询订单API 返回的xml-->
<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[******XXX]]></appid>
<mch_id><![CDATA[******XXX]]></mch_id>
<nonce_str><![CDATA[PUTtEeWs3l8wxt2i]]></nonce_str>
<sign><![CDATA[2FAFE2328050760166FEBC87786A5E2D]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<openid><![CDATA[******XXX]]></openid>
<is_subscribe><![CDATA[N]]></is_subscribe>
<trade_type><![CDATA[NATIVE]]></trade_type>
<bank_type><![CDATA[CFT]]></bank_type>
<total_fee>1</total_fee>
<fee_type><![CDATA[CNY]]></fee_type>
<transaction_id><![CDATA[4200000218201811057232858782]]></transaction_id>
<out_trade_no><![CDATA[1059415625195061248]]></out_trade_no>
<attach><![CDATA[]]></attach>
<time_end><![CDATA[20181105200235]]></time_end>
<trade_state><![CDATA[SUCCESS]]></trade_state>
<cash_fee>1</cash_fee>
<trade_state_desc><![CDATA[支付成功]]></trade_state_desc>
</xml>

本文标签: 简单微信扫码支付集成(java)