微信支付

Posted mozq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信支付相关的知识,希望对你有一定的参考价值。

二维码生成的 js 插件

# bootcdn 网站
https://www.bootcdn.cn/

qrious

qrious 下载

https://www.bootcdn.cn/qrious/
https://github.com/neocotic/qrious
https://cdnjs.cloudflare.com/ajax/libs/qrious/3.0.1/qrious.min.js

技术图片

Field Type Description Default Read Only
background String Background color of the QR code "white" No
backgroundAlpha Number Background alpha of the QR code 1.0 No
element Element Element to render the QR code <canvas> Yes
foreground String Foreground color of the QR code "black" No
foregroundAlpha Number Foreground alpha of the QR code 1.0 No
level String Error correction level of the QR code (L, M, Q, H) "L" No
mime String MIME type used to render the image for the QR code "image/png" No
padding Number Padding for the QR code (pixels) null (auto) No
size Number Size of the QR code (pixels) 100 No
value String Value encoded within the QR code "" No

qrious 参数和演示

element 页面容纳二维码的元素,必须是 <canvas> 或者 <img> 。只读,通过构造器传入。
value 二维码表示的信息
background 背景色
backgroundAlpha 背景色透明度 [0, 1] 0:完全透明 1:完全不透明
foreground 前景色
foregroundAlpha 前景色透明度 [0, 1] 0:完全透明 1:完全不透明
level 容错级别
padding 填充
size 大小 (包括填充在内)
mime 指定生成二维码的 mime 类型
<!DOCTYPE html>
<html>
<head>
    <title>二维码入门小demo</title>
</head>
<body>
<div >
    <!--
    <canvas id="qrious"></canvas>
    -->
    <img id="qrious" >
</div>
<script src="js/QRious.js"></script>
<script>
    var qr = new QRious(
        element: document.getElementById('qrious')
    );
    qr.value = 'https://github.com/neocotic/qrious';
    qr.background = 'pink';
    qr.backgroundAlpha = 0.5;//背景色透明度为 0.5
    qr.foreground = 'orange';
    qr.foregroundAlpha = 1;
    qr.level = 'H';
    qr.padding = 20;
    qr.size = 400;
</script>
</body>
</html>

qrcode

https://www.bootcdn.cn/qrcode-generator/

黑马公众号支付信息

appid=wx8397f8696b538317 微信公众账号或开放平台 APP 的唯一标识
partner=1473426802 财付通平台的商户账号
partnerkey=T6m9iK73b0kn9g5v426MKfHQH7X8rKwb 财付通平台的商户密钥
notifyurl=http://a31ef7db.ngrok.io/WeChatPay/WeChatPayNotify 回调地址

微信支付接口

微信支付参考文档

# 微信支付文档导航
微信支付 > 帮助中心 > 开发文档 > Native 支付
https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1
# 微信开发者社区
https://developers.weixin.qq.com/community/develop/mixflow

安装微信支付 SDK

SDK 与 DEMO 下载,下载的 zip 是一个 maven 项目,使用集成开发环境打开,并执行 maven install ,将 SDK 安装到本地仓库。

https://pay.weixin.qq.com/wiki/doc/api/download/WxPayAPI_JAVA.zip
<dependency>
    <groupId>com.github.wxpay</groupId>
    <artifactId>wxpay-sdk</artifactId>
    <version>3.0.9</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.3</version>
</dependency>

签名算法

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_3
Tunnel a31ef7db.ngrok.io not found
<xml>
    <return_code><![CDATA[FAIL]]></return_code>
    <return_msg><![CDATA[XML格式错误]]></return_msg>
</xml>

<!--
    param.put("total_fee", String.valueOf(0.01));
-->
<xml>
    <return_code><![CDATA[FAIL]]></return_code>
    <return_msg><![CDATA[invalid total_fee]]></return_msg>
</xml>

下单

package com.mozq.wxpay.demo;

import com.github.wxpay.sdk.WXPayUtil;

import java.util.HashMap;
import java.util.Map;

public class WXPayOrderDemo 
    public static void main(String[] args) throws Exception 
        //参数
        Map<String, String> param = new HashMap<>();
        param.put("appid", "wx8397f8696b538317");
        param.put("mch_id", "1473426802");
        String nonceStr = WXPayUtil.generateNonceStr();
        param.put("nonce_str", nonceStr);
        param.put("body", "凡人修仙充值中心-凡人仙院充值");
        param.put("out_trade_no", "201907280001");
        param.put("total_fee", String.valueOf(1));
        param.put("spbill_create_ip", "123.12.12.123");
        param.put("notify_url", "http://a31ef7db.ngrok.io/WeChatPay/WeChatPayNotify");
        param.put("trade_type", "NATIVE");

        HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
        //生成签名
        String xmlParam = WXPayUtil.generateSignedXml(param, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb");
        httpClient.setXmlParam(xmlParam);
        httpClient.setHttps(false);

        //请求
        httpClient.post();

        //解析结果
        String content = httpClient.getContent();
        Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
        System.out.println(resultMap);
    

    nonce_str=OUPjKBzycEz8cz10, 
    code_url=weixin://wxpay/bizpayurl?pr=gh8wAgg, 
    appid=wx8397f8696b538317, 
    sign=CDAD758D394BC2DA2484E89617022736, 
    trade_type=NATIVE, 
    return_msg=OK, 
    result_code=SUCCESS, 
    mch_id=1473426802, 
    return_code=SUCCESS, 
    prepay_id=wx282236255907477d09cfe0341493615900
<xml>
   <return_code><![CDATA[SUCCESS]]></return_code>
   <return_msg><![CDATA[OK]]></return_msg>
   <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
   <mch_id><![CDATA[10000100]]></mch_id>
   <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
   <openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
   <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
   <result_code><![CDATA[SUCCESS]]></result_code>
   <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
   <trade_type><![CDATA[JSAPI]]></trade_type>
</xml>
package com.mozq.wxpay.demo;

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;
    

查询订单

下单后,并没有返回 transaction_id ,所以这个值是我先用 out_trade_no 查询后知道的。

package com.mozq.wxpay.demo;

import com.github.wxpay.sdk.WXPayUtil;

import java.util.HashMap;
import java.util.Map;

public class WXPayQueryPayStatus 
    public static void main(String[] args) throws Exception 
        //查询参数
        Map<String, String> param = new HashMap<>();
        param.put("appid", "wx8397f8696b538317");
        param.put("mch_id", "1473426802");
        String nonceStr = WXPayUtil.generateNonceStr();
        param.put("nonce_str", nonceStr);
        //发现下单后,并没有返回 transaction_id ,所以这个值是我先用 out_trade_no 查询后知道的。
        param.put("transaction_id", "4200000344201907286520086822");
//        param.put("out_trade_no", "201907280001");
        String url = "https://api.mch.weixin.qq.com/pay/orderquery";

        HttpClient httpClient = new HttpClient(url);
        //生成签名
        String xmlParam = WXPayUtil.generateSignedXml(param, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb");
        httpClient.setXmlParam(xmlParam);
        httpClient.setHttps(false);
        //请求
        httpClient.post();

        //解析结果
        String content = httpClient.getContent();
        Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
        System.out.println(resultMap);
    
param.put("transaction_id", "wx282236255907477d09cfe0341493615900");
return_msg=transaction_id参数长度有误, return_code=FAIL

    transaction_id=4200000344201907286520086822,
    nonce_str=zY9Kxhrt5oGxYZSW, 
    trade_state=SUCCESS, bank_type=CFT,
    openid=oNpSGwYhk9R8kJz6MqLz79KvTaM4,
    sign=A0B8AFA851CAA0AB5A33953FD9E454E8, 
    return_msg=OK, 
    fee_type=CNY, 
    mch_id=1473426802, 
    cash_fee=1, 
    out_trade_no=201907280001, 
    appid=wx8397f8696b538317, 
    total_fee=1, 
    trade_state_desc=支付成功,
    trade_type=NATIVE, 
    result_code=SUCCESS, 
    attach=, 
    time_end=20190728223947, 
    is_subscribe=N, 
    return_code=SUCCESS
<xml>
   <return_code><![CDATA[SUCCESS]]></return_code>
   <return_msg><![CDATA[OK]]></return_msg>
   <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
   <mch_id><![CDATA[10000100]]></mch_id>
   <device_info><![CDATA[1000]]></device_info>
   <nonce_str><![CDATA[TN55wO9Pba5yENl8]]></nonce_str>
   <sign><![CDATA[BDF0099C15FF7BC6B1585FBB110AB635]]></sign>
   <result_code><![CDATA[SUCCESS]]></result_code>
   <openid><![CDATA[oUpF8uN95-Ptaags6E_roPHg7AG0]]></openid>
   <is_subscribe><![CDATA[Y]]></is_subscribe>
   <trade_type><![CDATA[MICROPAY]]></trade_type>
   <bank_type><![CDATA[CCB_DEBIT]]></bank_type>
   <total_fee>1</total_fee>
   <fee_type><![CDATA[CNY]]></fee_type>
   <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>
   <out_trade_no><![CDATA[1415757673]]></out_trade_no>
   <attach><![CDATA[订单额外描述]]></attach>
   <time_end><![CDATA[20141111170043]]></time_end>
   <trade_state><![CDATA[SUCCESS]]></trade_state>
</xml>

实战

package com.pinyougou.pay.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.github.wxpay.sdk.WXPayUtil;
import com.pinyougou.pay.service.WeixinPayService;
import org.springframework.beans.factory.annotation.Value;
import util.HttpClient;

import java.util.HashMap;
import java.util.Map;

@Service
public class WeixinPayServiceImpl implements WeixinPayService 

    @Value("$appid")
    private String appid;

    @Value("$partner")
    private String partner;

    @Value("$partnerkey")
    private String partnerkey;

    @Value("$notifyurl")
    private String notifyurl;


    @Override
    public Map<String, String> createNative(String out_trade_no, String total_fee) 

        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("appid", appid);//公众号
        paramMap.put("mch_id", partner);//商户号
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
        paramMap.put("body", "品优购充值");//订单描述
        paramMap.put("out_trade_no", out_trade_no);//商户订单号
        paramMap.put("total_fee", total_fee);//总金额(分)
        paramMap.put("spbill_create_ip", "123.12.12.123");// IP
        paramMap.put("notify_url", "http://a31ef7db.ngrok.io/WeChatPay/WeChatPayNotify");//回调地址
        paramMap.put("trade_type", "NATIVE");//交易类型
        System.out.println(paramMap);

        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//支付接口

        try 
            HttpClient httpClient = new HttpClient(url);
            //生成签名
            String xmlParamMap = WXPayUtil.generateSignedXml(paramMap, partnerkey);
            httpClient.setXmlParam(xmlParamMap);
            httpClient.setHttps(true);
            //请求
            httpClient.post();

            //解析结果
            String content = httpClient.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
            System.out.println(resultMap);

            Map<String, String> result = new HashMap<>();
            result.put("code_url", resultMap.get("code_url"));//支付 url
            result.put("out_trade_no", out_trade_no);//订单号
            result.put("total_fee", total_fee);//总金额

            return  result;
         catch (Exception e) 
            e.printStackTrace();
            return new HashMap<>();
        
    

    @Override
    public Map<String, String> queryPayStatus(String out_trade_no) 
        //查询参数
        Map<String, String> param = new HashMap<>();
        param.put("appid", appid);
        param.put("mch_id", partner);
        param.put("nonce_str", WXPayUtil.generateNonceStr());
        param.put("out_trade_no", out_trade_no);
        String url = "https://api.mch.weixin.qq.com/pay/orderquery";

        try 
            HttpClient httpClient = new HttpClient(url);
            //生成签名
            String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey);
            httpClient.setXmlParam(xmlParam);
            httpClient.setHttps(true);
            //请求
            httpClient.post();

            //解析结果
            String content = httpClient.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
            System.out.println(resultMap);

            return resultMap;
         catch (Exception e) 
            e.printStackTrace();
        
        return null;
    
# weixinpay.properties 文件
appid=wx8397f8696b538317
partner=1473426802
partnerkey=T6m9iK73b0kn9g5v426MKfHQH7X8rKwb
notifyurl=http://a31ef7db.ngrok.io/WeChatPay/WeChatPayNotify

以上是关于微信支付的主要内容,如果未能解决你的问题,请参考以下文章

如何申请微信H5支付

微信支付—微信H5支付「微信内部浏览器」

java微信支付v3系列——5.微信支付成功回调

***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结

微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结

H5微信支付啥意思