1.场景介绍:用户扫描商户展示在各种场景的二维码进行支付
目前已上线支付案例,商户可进行实际体验。
线下:家乐福超市、7-11便利店、上品折扣线下店等
线上:大众点评网站、携程网站、唯品会、美丽说网站等
商户后台系统先调用微信支付的统一下单接口,微信后台系统返回链接参数code_url,商户后台系统将code_url值生成二维码图片,用户使用微信客户端扫码后发起支付。注意:code_url有效期为2小时,过期后扫码不能再发起支付。
注意:商户后台只会得到支付成功的通知,支付失败的通知会堆积一起等下次支付成功一起发送。
2.下单支付
访问地址:
http://localhost:8080/pay?outtradeno=1001&totalfee=1
server:
port: 8080
#微信支付信息配置
weixin:
#应用ID
appid:
#商户ID
partner:
#秘钥
partnerkey:
#支付回调地址,需要内网穿透
notifyurl:
//应用ID
@Value("${weixin.appid}")
private String appid;
//商户号
@Value("${weixin.partner}")
private String partner;
//秘钥
@Value("${weixin.partnerkey}")
private String partnerkey;
//支付回调地址
@Value("${weixin.notifyurl}")
private String notifyurl;
/**
* 微信支付
* @param parameterMap
* @return
* @throws Exception
*/
@RequestMapping("/pay")
public void createNative(@RequestParam Map<String,String> parameterMap, HttpServletResponse response) throws Exception {
//设置响应头为图片
response.setContentType("image/png");
try {
//参数
Map<String,String> paramMap=new HashMap<>();
paramMap.put("appid",appid);
paramMap.put("mch_id",partner);
//随机字符串
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
paramMap.put("body","腾讯充值中心-QQ会员充值");
//订单号
paramMap.put("out_trade_no",parameterMap.get("outtradeno"));
//交易金额,单位:分
paramMap.put("total_fee",parameterMap.get("totalfee"));
paramMap.put("spbill_create_ip","127.0.0.1");
//交易结果回调地址
paramMap.put("notify_url",notifyurl);
paramMap.put("trade_type","NATIVE");
//Map转成XML字符串,可以携带签名
String xmlparameters=WXPayUtil.generateSignedXml(paramMap,partnerkey);
//URL地址
String url="https://api.mch.weixin.qq.com/pay/unifiedorder";
HttpClient httpClient=new HttpClient(url);
//提交方式
httpClient.setHttps(true);
//提交参数
httpClient.setXmlParam(xmlparameters);
System.out.println(xmlparameters);
//执行请求
httpClient.post();
//获取返回的数据
String result = httpClient.getContent();
//返回数据转成Map
Map<String,String> resultMap=WXPayUtil.xmlToMap(result);
String returnCode = resultMap.get("return_code");
String resultCode = resultMap.get("result_code");
if(returnCode.equalsIgnoreCase("SUCCESS")&&resultCode.equalsIgnoreCase("SUCCESS")) {
String codeUrl = resultMap.get("code_url");
//TODO 拿到codeUrl,写代码生成二维码
System.out.println("codeUrl=" + codeUrl);
int width = 300;
int height = 300;
//二维码的图片格式
String format = "JPEG";
Hashtable hints = new Hashtable();
//内容所使用编码
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
BitMatrix bitMatrix = new MultiFormatWriter().encode(codeUrl,
BarcodeFormat.QR_CODE, width, height, hints);
// response.setContentType("image/JPEG");
MatrixToImageWriter.writeToStream(bitMatrix, format, response.getOutputStream());
//存订单
}else{
//失败
throw new Exception(result);
}
}catch(Exception e) {
e.printStackTrace();
}
}
MatrixToImageWriter类生成图片二维码
package com.example.wechatpay.wepay;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Hashtable;
public final class MatrixToImageWriter {
private static final int BLACK = 0xFF000000;
private static final int WHITE = 0xFFFFFFFF;
private MatrixToImageWriter() {}
public static BufferedImage toBufferedImage(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
}
}
return image;
}
public static void writeToFile(BitMatrix matrix, String format, File file)
throws IOException {
BufferedImage image = toBufferedImage(matrix);
if (!ImageIO.write(image, format, file)) {
throw new IOException("Could not write an image of format " + format + " to " + file);
}
}
public static void writeToStream(BitMatrix matrix, String format, OutputStream stream)
throws IOException {
BufferedImage image = toBufferedImage(matrix);
if (!ImageIO.write(image, format, stream)) {
throw new IOException("Could not write an image of format " + format);
}
}
public static void main(String[] args) throws Exception {
String text = "www.baidu.com";
int width = 300;
int height = 300;
String format = "gif";
Hashtable hints = new Hashtable();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
BitMatrix bitMatrix = new MultiFormatWriter().encode(text,
BarcodeFormat.QR_CODE, width, height, hints);
File outputFile = new File("d:"+ File.separator+"new.gif");
MatrixToImageWriter.writeToFile(bitMatrix, format, outputFile);
}
}
package com.example.wechatpay.wepay;
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.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import java.io.IOException;
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;
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);
}
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;
}
}
3.回调接口
package com.example.wechatpay.service.impl;
import com.github.wxpay.sdk.WXPayConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
@Configuration
public class WXPayConfigImpl implements WXPayConfig {
//应用ID
@Value("${weixin.appid}")
private String appid;
//商户号
@Value("${weixin.partner}")
private String partner;
//秘钥
@Value("${weixin.partnerkey}")
private String partnerkey;
private byte[] certData;
@Override
public String getAppID() {
return appid;
}
@Override
public String getMchID() {
return partner;
}
@Override
public String getKey() {
return partnerkey;
}
@Override
public InputStream getCertStream() {
return new ByteArrayInputStream(this.certData);
}
@Override
public int getHttpConnectTimeoutMs() {
return 0;
}
@Override
public int getHttpReadTimeoutMs() {
return 0;
}
}
package com.example.wechatpay.service.impl;
import com.github.wxpay.sdk.WXPayConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
@Configuration
public class WXPayConfigImpl implements WXPayConfig {
//应用ID
@Value("${weixin.appid}")
private String appid;
//商户号
@Value("${weixin.partner}")
private String partner;
//秘钥
@Value("${weixin.partnerkey}")
private String partnerkey;
private byte[] certData;
@Override
public String getAppID() {
return appid;
}
@Override
public String getMchID() {
return partner;
}
@Override
public String getKey() {
return partnerkey;
}
@Override
public InputStream getCertStream() {
return new ByteArrayInputStream(this.certData);
}
@Override
public int getHttpConnectTimeoutMs() {
return 0;
}
@Override
public int getHttpReadTimeoutMs() {
return 0;
}
}
本文详细介绍了微信支付二维码的生成流程,包括商户后台如何调用微信支付接口获取code_url并生成二维码,以及用户扫码后的支付处理。文中提供了一个Java实现的示例,涉及统一下单接口、二维码生成、支付状态回调以及HTTPS证书处理。同时,还展示了回调接口的配置和使用。
2160

被折叠的 条评论
为什么被折叠?



