简单微信扫码支付集成(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.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.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("?");
				else
					url.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 {

    @Reference
    private WeixinPayService weixinPayService;

    @Autowired
    private 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: 生成微信支付二维码
     */
    @Override
    public 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");//IP
        param.put("notify_url","http://47.93.49.119/");//回调地址
        param.put("trade_type","NATIVE");//交易类型

        try{
            //生成发送的xml
            String xmlParam = WXPayUtil.generateSignedXml(param, partnerKey);
            //发送post请求
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            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: 查询支付状态
     */
    @Override
    public 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="https://api.mch.weixin.qq.com/pay/orderquery";

        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>
     */
    @Override
    public 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("https://api.mch.weixin.qq.com/pay/closeorder");
            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>http://47.93.49.119/</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>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值