前言
本文适用于有一定基础的开发者,简单易通。后台用的的是java,我用的是springBoot,其它框架基本同理,前端就是一个简单的demo。微信官方提供了V2和V3两种方式,本文基于V2版支付开发(后续更新V3)。V2和V3版本区别
微信支付接入前准备
1.思路介绍
本次以微信小程序开发为例,如果自己想要玩一下,需要在微信公众平台注册一个小程序账号,其次微信支付 平台,进行接入微信支付,然后就可以着手开发了。(公司开发的话,参数账号之类都会提供的,不用担心)
2.如何注册小程序账号?
可以直接进入微信公众平台直接注册,也可根据文档指引进行注册。申请账号官方详细文档 如商户已拥有自己的APP,且希望该APP接入微信支付,请前往 开放平台申请 
3.如何接入微信支付,需要准备哪些东西?
简单介绍一下自己的经验,重点是营业执照信息。关键这玩意怎么搞方面快捷呢。 我提供两种方案: 1.最方便的是自己注册个电商营业执照,拼多多商铺0元直接入驻即可。注册地址要和营业执照地址相同(要有房产证明等,写自己老家就行)。 2.如果自己租的房子,合同中必须体现可以作为商铺,要不然没法。 直接注册实体个体工商户,目前非常方便线下线上都可以办理-不同地方的软件不同 这里以杭州为例,直接下载浙里办-搜索个体工商户,在线办理即可。 最重要的是地址(可以借助朋友,或者租房的时候说好可以作为商铺,当然自己本地有房子咋样搞都行),其次网上那些挂靠地址等,如果你可以承担费用,自主决定。 请参考微信支付商户号申请,详细的一批。
4.小程序接入前的准备(APPID及mchid以上两步已拿到,只需配置一下API KEY即可)
官方文档指引-小程序支付 注意:API秘钥,一定要记住。最好记事本记录一下。 由于本文基于V2版支付开发,记得设置一下。 
微信支付-完整代码
前端代码
index.wxml
<view class="container">
<view class="container">
<input type="text" bindinput="getOrderCode" style="border:1px solid #ccc;" />
<button type="primary" bindtap="pay">微信支付</button>
</view>
</view>
index.js
const app = getApp()
Page({
data: {
txtOrderCode: '',
},
pay: function () {
var ordercode = this.data.txtOrderCode;
wx.login({
success: function (res) {
console.log("code值是多少"+res.code)
if (res.code) {
wx.request({
url: 'http://localhost:8081/wechatPay/wxPay',
data: {
code: res.code,
money: ordercode,
name:"",
idCard:"",
post:"",
phone:"",
receiverInfo:"",
duesDate:"",
partyOrg:"",
agyCode:"",
agyName:"",
orderId:""
},
method: 'POST',
success: function (res) {
console.log("是否进来方法"+res.data.package)
wx.requestPayment({
timeStamp: res.data.timeStamp,
nonceStr: res.data.nonceStr,
package: res.data.package,
signType: 'MD5',
paySign: res.data.paySign,
success: function (res) {
console.log("支付成功")
console.log(res);
},
fail: function (res) {
console.log("支付失败");
wx.showToast({
title: '支付失败',
icon:'none',
duration:2000
})
},
complete: function (res) {
console.log('支付完成');
if (res.errMsg == 'requestPayment:ok') {
wx.showModal({
title: '提示',
content: '支付成功'
});
}
}
})
},
fail: function (res) {
wx.showToast({
title: '调用接口失败',
icon:'none',
duration:2000
})
},
})
} else {
console.log('获取用户登录态失败!' + res.errMsg)
}
}
});
},
getOrderCode: function (event) {
console.log(event)
this.setData({
txtOrderCode: event.detail.value
});
},
onLoad: function () {
if (app.globalData.userInfo) {
this.setData({
userInfo: app.globalData.userInfo,
hasUserInfo: true
})
} else if (this.data.canIUse){
app.userInfoReadyCallback = res => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
} else {
wx.getUserInfo({
success: res => {
app.globalData.userInfo = res.userInfo
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
}
},
})
效果图

后端代码
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.hn.yuan</groupId>
<artifactId>demo_wxpay</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo_wxpay</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--解析xml-->
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.6</version>
</dependency>
<!--Java对象和JSON数据之间进行映射的Java类库-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<!--处理输入输出流-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.21</version>
</dependency>
<!--小程序支付包-->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.8</version>
</dependency>
<!--http commons client-->
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.1</version>
</dependency>
<!--springboot整合redisCluster-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!--redis框架-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml
server:
port: 8081
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/yuan_productlist?useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: root
password: root
# 配置slq打印日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
log.path: F:/logs #打印日志路径
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--注意resource属于.yml还是.properties-->
<property resource="application.yml"/>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 使用spring-boot的配置项LOG_PATH-->
<springProperty scope="context" name="LOG_HOME" source="log.path"/>
<!--下面用于application.properties-->
<!-- <property name="LOG_HOME" value="${log.path}" />-->
<property name="LOG_LEVEL" value="INFO" />
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/springbootjpa.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<logger name="com.wm.springbootjpa01" level="INFO"/>
<logger name="org.apache.ibatis" level="${LOG_LEVEL}"/>
<logger name="org.mybatis.spring" level="${LOG_LEVEL}"/>
<logger name="org.springframework" level="${LOG_LEVEL}"/>
<logger name="java.sql.Connection" level="${LOG_LEVEL}"/>
<logger name="java.sql.Statement" level="${LOG_LEVEL}"/>
<logger name="java.sql.PreparedStatement" level="${LOG_LEVEL}"/>
<!--设置为OFF,即屏蔽; 留下sqltiming作为INFO级别输出-->
<logger name="jdbc.connection" level="OFF"/>
<logger name="jdbc.resultset" level="OFF"/>
<logger name="jdbc.resultsettable" level="OFF"/>
<logger name="jdbc.audit" level="OFF"/>
<logger name="jdbc.sqltiming" level="INFO"/>
<logger name="jdbc.sqlonly" level="OFF"/>
<!-- 日志输出级别 -->
<root level="${LOG_LEVEL}">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>
WechatConfig支付配置类
package com.hn.yuan.wxinterface;
public class WechatConfig {
public static final String appid ="";
public static final String APP_SECRET="";
public static final String mch_id = "";
public static final String key = "";
public static final String notify_url = "";
public static final String SIGNTYPE = "MD5";
public static final String TRADETYPE = "JSAPI";
public static final String pay_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
}
WxPayDto类
package com.hn.yuan.entity;
import lombok.Data;
import java.io.Serializable;
@Data
public class WxPayDto implements Serializable {
private static final long serialVersionUID = 1L;
private String partyOrg;
private String duesDate;
private String money;
private String name;
private String idCard;
private String post;
private String phone;
private String orderId;
private String receiverInfo;
private String code;
private String agyCode;
private String agyName;
}
业务代码WxpayController
package com.hn.yuan.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hn.yuan.entity.WxPayDto;
import com.hn.yuan.wxinterface.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import static com.hn.yuan.wxinterface.WXPayConstants.RETURN_CODE;
import static com.hn.yuan.wxinterface.WechatConfig.APP_SECRET;
@CrossOrigin
@RestController
@RequestMapping("/wechatPay")
public class WxpayController {
private static Logger logger = LoggerFactory.getLogger(WxpayController.class);
@Autowired
private HttpServletRequest request;
@Resource
private HttpServletResponse response;
@PostMapping("/wxPay")
public String wxPay(@RequestBody WxPayDto dto) {
System.out.println("进来方法了");
Object result = new Object();
try {
String spbill_create_ip = getIpAddr(request);
System.out.println("客户端Ip地址" + spbill_create_ip);
System.out.println("code是什么样式的" + dto.getCode());
String openid = getOpenId(dto.getCode());
String outTradeNo = WXPayUtil.generateUUID();
result = wxPay(spbill_create_ip, openid, outTradeNo, dto);
} catch (Exception e) {
e.printStackTrace();
}
return PayUtil.toJson(result);
}
private String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
int index = ip.indexOf(",");
if (index != -1) {
return ip.substring(0, index);
} else {
return ip;
}
}
ip = request.getHeader("X-Real-IP");
if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
return ip;
}
return request.getRemoteAddr();
}
public Map wxPay(String spbill_create_ip, String openId, String orderNumber, WxPayDto dto) {
Map<String, String> payMap = new HashMap<String, String>();
try {
logger.info("【小程序支付】 统一下单开始, 订单编号=" + orderNumber);
String body = dto.getAgyName() + "-" + dto.getName() + "-测试费用";
BigDecimal money = new BigDecimal(dto.getMoney());
logger.info("----------下单接口签名-------");
Map<String, String> packageParams = new HashMap<>();
packageParams.put("appid", WechatConfig.appid);
packageParams.put("mch_id", WechatConfig.mch_id);
packageParams.put("nonce_str", System.currentTimeMillis() / 1000 + "");
packageParams.put("sign_type", "MD5");
packageParams.put("body", body);
packageParams.put("out_trade_no", orderNumber);
packageParams.put("total_fee", money.multiply(BigDecimal.valueOf(100)).intValue() + "");
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("notify_url", WechatConfig.notify_url);
packageParams.put("trade_type", WechatConfig.TRADETYPE);
packageParams.put("openid", openId);
String sign = WXPayUtil.generateSignature(packageParams, WechatConfig.key);
System.out.println("第一签名打印的是个啥" + sign);
packageParams.put("sign", sign);
System.out.println("字符串是啥" + PaymentKit.toXml(packageParams));
String result = HttpKit.post(WechatConfig.pay_url, PaymentKit.toXml(packageParams));
logger.info("调试模式_统一下单接口 返回XML数据:" + result);
Map<String, String> map = PaymentKit.xmlToMap(result);
String return_code = map.get("return_code");
String result_code = map.get("result_code");
if (return_code.equals("SUCCESS") || return_code.equals(result_code)) {
String prepay_id = map.get("prepay_id");
payMap.put("appId", WechatConfig.appid);
payMap.put("timeStamp", System.currentTimeMillis() / 1000 + "");
payMap.put("nonceStr", System.currentTimeMillis() + "");
payMap.put("package", "prepay_id=" + prepay_id);
payMap.put("signType", "MD5");
String paySign = WXPayUtil.generateSignature(payMap, WechatConfig.key);
System.out.println("第二签名打印的是个啥" + sign);
logger.info("=======================第二次签名:", paySign + "============ ======");
payMap.put("paySign", paySign);
payMap.put("status", "success");
} else {
logger.info("----------统一下单失败-------");
payMap.put("status", "error");
return payMap;
}
} catch (Exception e) {
e.printStackTrace();
}
return payMap;
}
public static String getOpenId(String code) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
RestTemplate restTemplate = new RestTemplate();
String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + WechatConfig.appid + "&secret=" + APP_SECRET + "&js_code=" + code + "&grant_type=authorization_code";
ResponseEntity<String> responseEntity =
restTemplate.getForEntity(url, String.class);
String body = responseEntity.getBody();
JSONObject object = JSON.parseObject(body);
String openId = object.getString("openid");
System.out.println("该用户的openid——>" + openId);
return openId;
}
@GetMapping("/wxProPayNotify")
public void wxProPayNotify() throws Exception {
logger.info("进入微信小程序支付回调");
String xmlMsg = HttpKit.readData(request);
logger.info("微信小程序通知信息" + xmlMsg);
Map<String, String> resultMap = PaymentKit.xmlToMap(xmlMsg);
if (resultMap.get(RETURN_CODE).equals("SUCCESS")) {
String orderNo = resultMap.get("out_trade_no");
logger.info("微信小程序支付成功,订单号{}", orderNo);
}
String result = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
try {
response.getWriter().write(result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
工具类
package com.hn.yuan.wxinterface;
import javax.net.ssl.*;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;
public class HttpKit {
private static String CHARSET = "UTF-8";
private static final SSLSocketFactory sslSocketFactory = initSSLSocketFactory();
private static final TrustAnyHostnameVerifier trustAnyHostnameVerifier = new HttpKit().new TrustAnyHostnameVerifier();
private HttpKit() {
}
private static SSLSocketFactory initSSLSocketFactory() {
try {
TrustManager[] e = new TrustManager[]{new HttpKit().new TrustAnyTrustManager()};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init((KeyManager[])null, e, new SecureRandom());
return sslContext.getSocketFactory();
} catch (Exception var2) {
throw new RuntimeException(var2);
}
}
public static void setCharSet(String charSet) {
if(charSet!=null && !charSet.equals("")) {
throw new IllegalArgumentException("charSet can not be blank.");
} else {
CHARSET = charSet;
}
}
private static HttpURLConnection getHttpConnection(String url, String method, Map<String, String> headers) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {
URL _url = new URL(url);
HttpURLConnection conn = (HttpURLConnection)_url.openConnection();
if(conn instanceof HttpsURLConnection) {
((HttpsURLConnection)conn).setSSLSocketFactory(sslSocketFactory);
((HttpsURLConnection)conn).setHostnameVerifier(trustAnyHostnameVerifier);
}
conn.setRequestMethod(method);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setConnectTimeout(19000);
conn.setReadTimeout(19000);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("AuthUser-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");
if(headers != null && !headers.isEmpty()) {
Iterator i$ = headers.entrySet().iterator();
while(i$.hasNext()) {
Map.Entry entry = (Map.Entry)i$.next();
conn.setRequestProperty((String)entry.getKey(), (String)entry.getValue());
}
}
return conn;
}
public static String get(String url, Map<String, String> queryParas, Map<String, String> headers) {
HttpURLConnection conn = null;
String e;
try {
conn = getHttpConnection(buildUrlWithQueryString(url, queryParas), "GET", headers);
conn.connect();
e = readResponseString(conn);
} catch (Exception var8) {
throw new RuntimeException(var8);
} finally {
if(conn != null) {
conn.disconnect();
}
}
return e;
}
public static String get(String url, Map<String, String> queryParas) {
return get(url, queryParas, (Map)null);
}
public static String get(String url) {
return get(url, (Map)null, (Map)null);
}
public static String post(String url, Map<String, String> queryParas, String data, Map<String, String> headers) {
HttpURLConnection conn = null;
String var6;
try {
conn = getHttpConnection(buildUrlWithQueryString(url, queryParas), "POST", headers);
conn.connect();
OutputStream e = conn.getOutputStream();
e.write(data.getBytes(CHARSET));
e.flush();
e.close();
var6 = readResponseString(conn);
} catch (Exception var10) {
throw new RuntimeException(var10);
} finally {
if(conn != null) {
conn.disconnect();
}
}
return var6;
}
public static String post(String url, Map<String, String> queryParas, String data) {
return post(url, queryParas, data, (Map)null);
}
public static String post(String url, String data, Map<String, String> headers) {
return post(url, (Map)null, data, headers);
}
public static String post(String url, String data) {
return post(url, (Map)null, data, (Map)null);
}
private static String readResponseString(HttpURLConnection conn) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
try {
inputStream = conn.getInputStream();
BufferedReader e = new BufferedReader(new InputStreamReader(inputStream, CHARSET));
String line = null;
while((line = e.readLine()) != null) {
sb.append(line).append("\n");
}
String var5 = sb.toString();
return var5;
} catch (Exception var14) {
throw new RuntimeException(var14);
} finally {
if(inputStream != null) {
try {
inputStream.close();
} catch (IOException var13) {
}
}
}
}
private static String buildUrlWithQueryString(String url, Map<String, String> queryParas) {
if(queryParas != null && !queryParas.isEmpty()) {
StringBuilder sb = new StringBuilder(url);
boolean isFirst;
if(url.indexOf("?") == -1) {
isFirst = true;
sb.append("?");
} else {
isFirst = false;
}
String key;
String value;
for(Iterator i$ = queryParas.entrySet().iterator(); i$.hasNext(); sb.append(key).append("=").append(value)) {
Map.Entry entry = (Map.Entry)i$.next();
if(isFirst) {
isFirst = false;
} else {
sb.append("&");
}
key = (String)entry.getKey();
value = (String)entry.getValue();
if(value!=null && !value.equals("")) {
try {
value = URLEncoder.encode(value, CHARSET);
} catch (UnsupportedEncodingException var9) {
throw new RuntimeException(var9);
}
}
}
return sb.toString();
} else {
return url;
}
}
public static String readData(HttpServletRequest request) {
BufferedReader br = null;
try {
StringBuilder e = new StringBuilder();
br = request.getReader();
String line = null;
while((line = br.readLine()) != null) {
e.append(line).append("\n");
}
line = e.toString();
return line;
} catch (IOException var12) {
throw new RuntimeException(var12);
} finally {
if(br != null) {
try {
br.close();
} catch (IOException var11) {
}
}
}
}
@Deprecated
public static String readIncommingRequestData(HttpServletRequest request) {
return readData(request);
}
private class TrustAnyTrustManager implements X509TrustManager {
private TrustAnyTrustManager() {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
}
private class TrustAnyHostnameVerifier implements HostnameVerifier {
private TrustAnyHostnameVerifier() {
}
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
}
package com.hn.yuan.wxinterface;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
public class PaymentApi {
private PaymentApi() {}
private static String unifiedOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
public enum TradeType {
JSAPI, NATIVE, APP, WAP, MWEB
}
public static String pushOrder(Map<String, String> params) {
return HttpKit.post(unifiedOrderUrl, PaymentKit.toXml(params));
}
private static Map<String, String> request(String url, Map<String, String> params, String paternerKey) {
params.put("nonce_str", System.currentTimeMillis() + "");
String sign = PaymentKit.createSign(params, paternerKey);
params.put("sign", sign);
String xmlStr = HttpKit.post(url, PaymentKit.toXml(params));
return PaymentKit.xmlToMap(xmlStr);
}
public static String getDeepLink(String appId, String prepayId, String paternerKey) {
Map<String, String> params = new HashMap<String, String>();
params.put("appid", appId);
params.put("noncestr", System.currentTimeMillis() + "");
params.put("package", "WAP");
params.put("prepayid", prepayId);
params.put("timestamp", System.currentTimeMillis() / 1000 + "");
String sign = PaymentKit.createSign(params, paternerKey);
params.put("sign", sign);
String string1 = PaymentKit.packageSign(params, true);
String string2 = "";
try { string2 = PaymentKit.urlEncode(string1); } catch (UnsupportedEncodingException e) {}
return "weixin://wap/pay?" + string2;
}
private static String orderQueryUrl = "https://api.mch.weixin.qq.com/pay/orderquery";
public static Map<String, String> queryByTransactionId(String appid, String mch_id, String paternerKey, String transaction_id) {
Map<String, String> params = new HashMap<String, String>();
params.put("appid", appid);
params.put("mch_id", mch_id);
params.put("transaction_id", transaction_id);
return request(orderQueryUrl, params, paternerKey);
}
public static Map<String, String> queryByOutTradeNo(String appid, String mch_id, String paternerKey, String out_trade_no) {
Map<String, String> params = new HashMap<String, String>();
params.put("appid", appid);
params.put("mch_id", mch_id);
params.put("out_trade_no", out_trade_no);
return request(orderQueryUrl, params, paternerKey);
}
private static String closeOrderUrl = "https://api.mch.weixin.qq.com/pay/closeorder";
public static Map<String, String> closeOrder(String appid, String mch_id, String paternerKey, String out_trade_no) {
Map<String, String> params = new HashMap<String, String>();
params.put("appid", appid);
params.put("mch_id", mch_id);
params.put("out_trade_no", out_trade_no);
return request(closeOrderUrl, params, paternerKey);
}
public static String refundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
private static String refundQueryUrl = "https://api.mch.weixin.qq.com/pay/refundquery";
private static Map<String, String> baseRefundQuery(Map<String, String> params, String appid, String mch_id, String paternerKey) {
params.put("appid", appid);
params.put("mch_id", mch_id);
return request(refundQueryUrl, params, paternerKey);
}
public static Map<String, String> refundQueryByTransactionId(String appid, String mch_id, String paternerKey, String transaction_id) {
Map<String, String> params = new HashMap<String, String>();
params.put("transaction_id", transaction_id);
return baseRefundQuery(params, appid, mch_id, paternerKey);
}
public static Map<String, String> refundQueryByOutTradeNo(String appid, String mch_id, String paternerKey, String out_trade_no) {
Map<String, String> params = new HashMap<String, String>();
params.put("out_trade_no", out_trade_no);
return baseRefundQuery(params, appid, mch_id, paternerKey);
}
public static Map<String, String> refundQueryByOutRefundNo(String appid, String mch_id, String paternerKey, String out_refund_no) {
Map<String, String> params = new HashMap<String, String>();
params.put("out_refund_no", out_refund_no);
return baseRefundQuery(params, appid, mch_id, paternerKey);
}
public static Map<String, String> refundQueryByRefundId(String appid, String mch_id, String paternerKey, String refund_id) {
Map<String, String> params = new HashMap<String, String>();
params.put("refund_id", refund_id);
return baseRefundQuery(params, appid, mch_id, paternerKey);
}
private static String downloadBillUrl = "https://api.mch.weixin.qq.com/pay/downloadbill";
public static enum BillType {
ALL, SUCCESS, REFUND, REVOKED
}
public static Map<String,String> downloadBill(String appid, String mch_id, String paternerKey, String billDate) {
return downloadBill(appid, mch_id, paternerKey, billDate, null);
}
public static Map<String,String> downloadBill(String appid, String mch_id, String paternerKey, String billDate, BillType billType) {
Map<String, String> params = new HashMap<String, String>();
params.put("appid", appid);
params.put("mch_id", mch_id);
params.put("nonce_str", System.currentTimeMillis() + "");
params.put("bill_date", billDate);
if (null != billType) {
params.put("bill_type", billType.name());
} else {
params.put("bill_type", BillType.ALL.name());
}
String sign = PaymentKit.createSign(params, paternerKey);
params.put("sign", sign);
String str = HttpKit.post(downloadBillUrl, PaymentKit.toXml(params));
return PaymentKit.xmlToMap(str);
}
}
package com.hn.yuan.wxinterface;
import org.apache.commons.io.Charsets;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
public class PaymentKit {
public static String packageSign(Map<String, String> params, boolean urlEncoder) {
TreeMap<String, String> sortedParams = new TreeMap<String, String>(params);
StringBuilder sb = new StringBuilder();
boolean first = true;
for (Entry<String, String> param : sortedParams.entrySet()) {
String value = param.getValue();
if (Tools.isEmpty(value)) {
continue;
}
if (first) {
first = false;
} else {
sb.append("&");
}
sb.append(param.getKey()).append("=");
if (urlEncoder) {
try { value = urlEncode(value); } catch (UnsupportedEncodingException e) {}
}
sb.append(value);
}
return sb.toString();
}
public static String urlEncode(String src) throws UnsupportedEncodingException {
return URLEncoder.encode(src, Charsets.UTF_8.name()).replace("+", "%20");
}
public static String createSign(Map<String, String> params, String paternerKey) {
params.remove("sign");
String stringA = packageSign(params, false);
String stringSignTemp = stringA + "&key=" + paternerKey;
return Tools.md5(stringSignTemp).toUpperCase();
}
public static boolean verifyNotify(Map<String, String> params, String paternerKey){
String sign = params.get("sign");
String localSign = PaymentKit.createSign(params, paternerKey);
return sign.equals(localSign);
}
public static String toXml(Map<String, String> params) {
StringBuilder xml = new StringBuilder();
xml.append("<xml>");
for (Entry<String, String> entry : params.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (Tools.isEmpty(value)) continue;
xml.append("<").append(key).append(">");
xml.append(entry.getValue());
xml.append("</").append(key).append(">");
}
xml.append("</xml>");
return xml.toString();
}
public static Map<String, String> xmlToMap(String xmlStr) {
XmlHelper xmlHelper = XmlHelper.of(xmlStr);
return xmlHelper.toMap();
}
}
package com.hn.yuan.wxinterface;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.commons.codec.digest.DigestUtils;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
public class PayUtil {
public static String sign(String text, String key, String input_charset) {
text = text + "&key=" + key;
return DigestUtils.md5Hex(getContentBytes(text, input_charset));
}
public static boolean verify(String text, String sign, String key, String input_charset) {
text = text +"&key=" + key;
String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset)).toUpperCase();
if (mysign.equals(sign)) {
return true;
} else {
return false;
}
}
public static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
private static boolean isValidChar(char ch) {
if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
return true;
if ((ch >= 0x4e00 && ch <= 0x7fff) || (ch >= 0x8000 && ch <= 0x952f))
return true;
return false;
}
public static Map<String, String> paraFilter(Map<String, String> sArray) {
Map<String, String> result = new HashMap<String, String>();
if (sArray == null || sArray.size() <= 0) {
return result;
}
for (String key : sArray.keySet()) {
String value = sArray.get(key);
if (value == null || value.equals("") || key.equalsIgnoreCase("sign")
|| key.equalsIgnoreCase("sign_type")) {
continue;
}
result.put(key, value);
}
return result;
}
public static String createLinkString(Map<String, String> params) {
List<String> keys = new ArrayList<>(params.keySet());
Collections.sort(keys);
String prestr = "";
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
if (i == keys.size() - 1) {
prestr = prestr + key + "=" + value;
} else {
prestr = prestr + key + "=" + value + "&";
}
}
return prestr;
}
public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {
StringBuffer buffer = null;
try {
URL url = new URL(requestUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(requestMethod);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.connect();
if (null != outputStr) {
OutputStream os = conn.getOutputStream();
os.write(outputStr.getBytes("utf-8"));
os.close();
}
InputStream is = conn.getInputStream();
InputStreamReader isr = new InputStreamReader(is, "utf-8");
BufferedReader br = new BufferedReader(isr);
buffer = new StringBuffer();
String line = null;
while ((line = br.readLine()) != null) {
buffer.append(line);
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return buffer.toString();
}
public static String urlEncodeUTF8(String source) {
String result = source;
try {
result = java.net.URLEncoder.encode(source, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
public static Map doXMLParse(String strxml) throws Exception {
if (null == strxml || "".equals(strxml)) {
return null;
}
Map m = new HashMap();
InputStream in = String2Inputstream(strxml);
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if (children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = getChildrenText(children);
}
m.put(k, v);
}
in.close();
return m;
}
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if (!children.isEmpty()) {
Iterator it = children.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if (!list.isEmpty()) {
sb.append(getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
}
return sb.toString();
}
public static InputStream String2Inputstream(String str) {
return new ByteArrayInputStream(str.getBytes());
}
public static <T> String toJson(T obj) {
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").enableComplexMapKeySerialization().create();
return gson.toJson(obj);
}
}
package com.hn.yuan.wxinterface;
public class WXPayConstants {
public enum SignType {
MD5, HMACSHA256
}
public static final String DOMAIN_API = "api.mch.weixin.qq.com";
public static final String DOMAIN_API2 = "api2.mch.weixin.qq.com";
public static final String DOMAIN_APIHK = "apihk.mch.weixin.qq.com";
public static final String DOMAIN_APIUS = "apius.mch.weixin.qq.com";
public static final String FAIL = "FAIL";
public static final String SUCCESS = "SUCCESS";
public static final String RETURN_CODE = "return_code";
public static final String HMACSHA256 = "HMAC-SHA256";
public static final String MD5 = "MD5";
public static final String FIELD_SIGN = "sign";
public static final String FIELD_SIGN_TYPE = "sign_type";
public static final String MICROPAY_URL_SUFFIX = "/pay/micropay";
public static final String UNIFIEDORDER_URL_SUFFIX = "/pay/unifiedorder";
public static final String ORDERQUERY_URL_SUFFIX = "/pay/orderquery";
public static final String REVERSE_URL_SUFFIX = "/secapi/pay/reverse";
public static final String CLOSEORDER_URL_SUFFIX = "/pay/closeorder";
public static final String REFUNDQUERY_URL_SUFFIX = "/pay/refundquery";
public static final String DOWNLOADBILL_URL_SUFFIX = "/pay/downloadbill";
public static final String SANDBOX_MICROPAY_URL_SUFFIX = "/sandboxnew/pay/micropay";
public static final String SANDBOX_UNIFIEDORDER_URL_SUFFIX = "/sandboxnew/pay/unifiedorder";
public static final String SANDBOX_ORDERQUERY_URL_SUFFIX = "/sandboxnew/pay/orderquery";
public static final String SANDBOX_REVERSE_URL_SUFFIX = "/sandboxnew/secapi/pay/reverse";
public static final String SANDBOX_CLOSEORDER_URL_SUFFIX = "/sandboxnew/pay/closeorder";
public static final String SANDBOX_REFUND_URL_SUFFIX = "/sandboxnew/secapi/pay/refund";
public static final String SANDBOX_REFUNDQUERY_URL_SUFFIX = "/sandboxnew/pay/refundquery";
public static final String SANDBOX_DOWNLOADBILL_URL_SUFFIX = "/sandboxnew/pay/downloadbill";
public static final String SANDBOX_REPORT_URL_SUFFIX = "/sandboxnew/payitil/report";
public static final String SANDBOX_SHORTURL_URL_SUFFIX = "/sandboxnew/tools/shorturl";
public static final String SANDBOX_AUTHCODETOOPENID_URL_SUFFIX = "/sandboxnew/tools/authcodetoopenid";
}
package com.hn.yuan.wxinterface;
import org.apache.commons.io.IOUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
public class XmlHelper {
private final XPath path;
private final Document doc;
private XmlHelper(InputSource inputSource) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory dbf = getDocumentBuilderFactory();
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(inputSource);
path = getXPathFactory().newXPath();
}
private static XmlHelper create(InputSource inputSource) {
try {
return new XmlHelper(inputSource);
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
} catch (SAXException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static XmlHelper of(InputStream is) {
InputSource inputSource = new InputSource(is);
return create(inputSource);
}
public static XmlHelper of(String xmlStr) {
StringReader sr = new StringReader(xmlStr.trim());
InputSource inputSource = new InputSource(sr);
XmlHelper xmlHelper = create(inputSource);
IOUtils.closeQuietly(sr);
return xmlHelper;
}
private Object evalXPath(String expression, Object item, QName returnType) {
item = null == item ? doc : item;
try {
return path.evaluate(expression, item, returnType);
} catch (XPathExpressionException e) {
throw new RuntimeException(e);
}
}
public String getString(String expression) {
return (String) evalXPath(expression, null, XPathConstants.STRING);
}
public Boolean getBoolean(String expression) {
return (Boolean) evalXPath(expression, null, XPathConstants.BOOLEAN);
}
public Number getNumber(String expression) {
return (Number) evalXPath(expression, null, XPathConstants.NUMBER);
}
public Node getNode(String expression) {
return (Node) evalXPath(expression, null, XPathConstants.NODE);
}
public NodeList getNodeList(String expression) {
return (NodeList) evalXPath(expression, null, XPathConstants.NODESET);
}
public String getString(Object node, String expression) {
return (String) evalXPath(expression, node, XPathConstants.STRING);
}
public Boolean getBoolean(Object node, String expression) {
return (Boolean) evalXPath(expression, node, XPathConstants.BOOLEAN);
}
public Number getNumber(Object node, String expression) {
return (Number) evalXPath(expression, node, XPathConstants.NUMBER);
}
public Node getNode(Object node, String expression) {
return (Node) evalXPath(expression, node, XPathConstants.NODE);
}
public NodeList getNodeList(Object node, String expression) {
return (NodeList) evalXPath(expression, node, XPathConstants.NODESET);
}
public Map<String, String> toMap() {
Element root = doc.getDocumentElement();
Map<String, String> params = new HashMap<String, String>();
NodeList list = root.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
Node node = list.item(i);
if (node instanceof Element) {
params.put(node.getNodeName(), node.getTextContent());
}
}
return params;
}
private static DocumentBuilderFactory getDocumentBuilderFactory(){
return XmlHelperHolder.documentBuilderFactory;
}
private static XPathFactory getXPathFactory() {
return XmlHelperHolder.xPathFactory;
}
private static class XmlHelperHolder {
private static DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
private static XPathFactory xPathFactory = XPathFactory.newInstance();
}
}
package com.hn.yuan.wxinterface;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.security.MessageDigest;
import java.util.*;
public class WXPayUtil {
public static Map<String, String> xmlToMap(String strXML) throws Exception {
try {
Map<String, String> data = new HashMap<String, String>();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
org.w3c.dom.Document doc = documentBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getDocumentElement().getChildNodes();
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
Node node = nodeList.item(idx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element element = (org.w3c.dom.Element) node;
data.put(element.getNodeName(), element.getTextContent());
}
}
try {
stream.close();
} catch (Exception ex) {
}
return data;
} catch (Exception ex) {
WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);
throw ex;
}
}
public static String mapToXml(Map<String, String> data) throws Exception {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
org.w3c.dom.Document document = documentBuilder.newDocument();
org.w3c.dom.Element root = document.createElement("xml");
document.appendChild(root);
for (String key: data.keySet()) {
String value = data.get(key);
if (value == null) {
value = "";
}
value = value.trim();
org.w3c.dom.Element filed = document.createElement(key);
filed.appendChild(document.createTextNode(value));
root.appendChild(filed);
}
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(source, result);
String output = writer.getBuffer().toString();
try {
writer.close();
}
catch (Exception ex) {
}
return output;
}
public static String generateSignedXml(final Map<String, String> data, String key) throws Exception {
return generateSignedXml(data, key, WXPayConstants.SignType.MD5);
}
public static String generateSignedXml(final Map<String, String> data, String key, WXPayConstants.SignType signType) throws Exception {
String sign = generateSignature(data, key, signType);
data.put(WXPayConstants.FIELD_SIGN, sign);
return mapToXml(data);
}
public static boolean isSignatureValid(String xmlStr, String key) throws Exception {
Map<String, String> data = xmlToMap(xmlStr);
if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) {
return false;
}
String sign = data.get(WXPayConstants.FIELD_SIGN);
return generateSignature(data, key).equals(sign);
}
public static boolean isSignatureValid(Map<String, String> data, String key) throws Exception {
return isSignatureValid(data, key, WXPayConstants.SignType.MD5);
}
public static boolean isSignatureValid(Map<String, String> data, String key, WXPayConstants.SignType signType) throws Exception {
if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) {
return false;
}
String sign = data.get(WXPayConstants.FIELD_SIGN);
return generateSignature(data, key, signType).equals(sign);
}
public static String generateSignature(final Map<String, String> data, String key) throws Exception {
return generateSignature(data, key, WXPayConstants.SignType.MD5);
}
public static String generateSignature(final Map<String, String> data, String key, WXPayConstants.SignType signType) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals(WXPayConstants.FIELD_SIGN)) {
continue;
}
if(data.get(k).trim().length() > 0)
sb.append(k).append("=").append(data.get(k).trim()).append("&");
}
sb.append("key=").append(key);
if (WXPayConstants.SignType.MD5.equals(signType)) {
return MD5(sb.toString()).toUpperCase();
}
else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) {
return HMACSHA256(sb.toString(), key);
}
else {
throw new Exception(String.format("Invalid sign_type: %s", signType));
}
}
public static String generateNonceStr() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
}
public static String MD5(String data) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
}
public static String HMACSHA256(String data, String key) throws Exception {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
sha256_HMAC.init(secret_key);
byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
}
public static Logger getLogger() {
Logger logger = LoggerFactory.getLogger("wxpay java sdk");
return logger;
}
public static long getCurrentTimestamp() {
return System.currentTimeMillis()/1000;
}
public static long getCurrentTimestampMs() {
return System.currentTimeMillis();
}
public static String generateUUID() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
}
}
package com.hn.yuan.wxinterface;
import java.security.MessageDigest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Tools {
public static int getRandomNum(){
Random r = new Random();
return r.nextInt(900000)+100000;
}
public static boolean notEmpty(String s){
return s!=null && !"".equals(s) && !"null".equals(s);
}
public static boolean isEmpty(String s){
return s==null || "".equals(s) || "null".equals(s);
}
public static String[] str2StrArray(String str,String splitRegex){
if(isEmpty(str)){
return null;
}
return str.split(splitRegex);
}
public static String[] str2StrArray(String str){
return str2StrArray(str,",\\s*");
}
public static String date2Str(Date date){
return date2Str(date,"yyyy-MM-dd HH:mm:ss");
}
public static Date str2Date(String date){
if(notEmpty(date)){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
return sdf.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return new Date();
}else{
return null;
}
}
public static String date2Str(Date date,String format){
if(date!=null){
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(date);
}else{
return "";
}
}
public static String getTimes(String StrDate){
String resultTimes = "";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date now;
try {
now = new Date();
Date date=df.parse(StrDate);
long times = now.getTime()-date.getTime();
long day = times/(24*60*60*1000);
long hour = (times/(60*60*1000)-day*24);
long min = ((times/(60*1000))-day*24*60-hour*60);
long sec = (times/1000-day*24*60*60-hour*60*60-min*60);
StringBuffer sb = new StringBuffer();
if(hour>0 ){
sb.append(hour+"小时前");
} else if(min>0){
sb.append(min+"分钟前");
} else{
sb.append(sec+"秒前");
}
resultTimes = sb.toString();
} catch (ParseException e) {
e.printStackTrace();
}
return resultTimes;
}
public static boolean checkEmail(String email){
boolean flag = false;
try{
String check = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
Pattern regex = Pattern.compile(check);
Matcher matcher = regex.matcher(email);
flag = matcher.matches();
}catch(Exception e){
flag = false;
}
return flag;
}
public static boolean checkMobileNumber(String mobileNumber){
Pattern p = null;
Matcher m = null;
boolean b = false;
p = Pattern.compile("^[1][3,4,5,7,8][0-9]{9}$");
m = p.matcher(mobileNumber);
b = m.matches();
return b;
}
public static String camelToUnderline(String param){
if (param==null||"".equals(param.trim())){
return "";
}
int len=param.length();
StringBuilder sb=new StringBuilder(len);
for (int i = 0; i < len; i++) {
char c=param.charAt(i);
if (Character.isUpperCase(c)){
sb.append("_");
sb.append(Character.toLowerCase(c));
}else{
sb.append(c);
}
}
return sb.toString();
}
public static String transformStr(String str){
if(str.contains("_")) {
String[] names = str.split("_");
String firstPart = names[0];
String otherPart = "";
for (int i = 1; i < names.length; i++) {
String word = names[i].replaceFirst(names[i].substring(0, 1), names[i].substring(0, 1).toUpperCase());
otherPart += word;
}
str = firstPart + otherPart;
}
return str;
}
public static List<Map<String,Object>> transformMap(List<Map<String,Object>> list){
List<Map<String,Object>> resultMapList = new ArrayList<>();
for (Map<String, Object> map : list) {
Map<String,Object> tempMap = new HashMap<>();
for (String s : map.keySet()) {
tempMap.put(transformStr(s),map.get(s));
}
resultMapList.add(tempMap);
}
return resultMapList;
}
public static String clearHtml(String content,int p) {
if(null==content) return "";
if(0==p) return "";
Pattern p_script;
Matcher m_script;
Pattern p_style;
Matcher m_style;
Pattern p_html;
Matcher m_html;
try {
String regEx_script = "<[\\s]*?script[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?script[\\s]*?>";
String regEx_style = "<[\\s]*?style[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?style[\\s]*?>";
String regEx_html = "<[^>]+>";
p_script = Pattern.compile(regEx_script,Pattern.CASE_INSENSITIVE);
m_script = p_script.matcher(content);
content = m_script.replaceAll("");
p_style = Pattern.compile(regEx_style,Pattern.CASE_INSENSITIVE);
m_style = p_style.matcher(content);
content = m_style.replaceAll("");
p_html = Pattern.compile(regEx_html,Pattern.CASE_INSENSITIVE);
m_html = p_html.matcher(content);
content = m_html.replaceAll("");
}catch(Exception e) {
return "";
}
if(content.length()>p){
content = content.substring(0, p)+"...";
}else{
content = content + "...";
}
return content;
}
public static String md5(String str) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
str = buf.toString();
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
}
微信小程序支付功能完整流程-总结(可忽略)

获取令牌token
async handleOrderPay() {
const token = wx.getStorageSync('token')
if (!token) {
wx.navigateTo({
url: '/pages/auth/auth',
})
}
<!-- 点击按钮获取用户信息 -->
<button type="primary" plain open-type="getUserInfo" bindgetuserinfo="handleGetUserInfo">授权</button>
import {request} from '../../request/index.js'
import regeneratorRuntime from '../../lib/runtime/runtime'
import {login} from '../../utils/asyncWx.js'
Page({
async handleGetUserInfo(e) {
try {
const {
encryptedData,
rawData,
iv,
signature
} = e.detail
const {
code
} = await login()
const loginParams = {
encryptedData,
rawData,
iv,
signature,
code
}
const {
token
} = await request({
url: '/users/wxlogin',
data: loginParams,
method: 'POST'
})
wx.setStorageSync('token', token)
wx.navigateBack({
delta: 1,
})
} catch (error) {
console.log(error)
}
}
})
创建订单
const header = {
Authorization: token
}
const order_price = this.data.totalPrice
const consignee_addr = this.data.address.all
const cart = this.data.cart
let goods = []
goods = cart.forEach(v => {
goods_id: v.goods_id
goods_number: v.num
goods_price: v.goods_price
})
const orderParams = {
order_price,
consignee_addr,
goods
}
const {order_number} = await request({
url: '/my/orders/create',
method: 'POST',
data: orderParams,
header
})
console.log(order_number)
}
预支付
const {pay} = await request({
url: '/my/orders/req_unifiedorder',
method: "POST",
header,
data: {
order_number
}
})
console.log('pay')
发起微信支付
- 将支付参数pay传入到requestPayment中即可
await requestPayment(pay)
收尾工作
await showToast('支付成功')
let newCart = wx.getStorageSync('cart')
newCart = newCart.filter(v => !v.checked)
wx.setStorageSync('cart', newCart)
wx.navigateTo({
url: '/pages/order/order',
})
后续V3版本-待编辑 
各位看官》创作不易,点个赞!!! 诸君共勉:万事开头难,只愿肯放弃。
免责声明:本文章仅用于学习参考
|