微信支付
二维码生成的 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