Java实现微信小程序支付(准备)
Java语言开发微信小程序支付功能:
1.通过https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1路径到官方下载Java的支付SDK。
2.下载后将pom文件中需要用到的jar包导入自己的项目中,将demo全部导入到自己的工具包中,需导入的demo如下图:


3.此时缺少IWXPayDomain与WXPayConfig抽象类的具体实现,新建WXPayDomainSimpleImpl与WXPayConfigImpl来分别实现抽象类,代码如下:
WXPayDomainSimpleImpl代码:
package com.karat.cn.util;
import org.apache.http.conn.ConnectTimeoutException; import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map; /**
* Created by blaketang on 2017/6/16.
*/
public class WXPayDomainSimpleImpl implements IWXPayDomain {
private WXPayDomainSimpleImpl(){}
private static class WxpayDomainHolder{
private static IWXPayDomain holder = new WXPayDomainSimpleImpl();
}
public static IWXPayDomain instance(){
return WxpayDomainHolder.holder;
} public synchronized void report(final String domain, long elapsedTimeMillis, final Exception ex) {
DomainStatics info = domainData.get(domain);
if(info == null){
info = new DomainStatics(domain);
domainData.put(domain, info);
} if(ex == null){ //success
if(info.succCount >= 2){ //continue succ, clear error count
info.connectTimeoutCount = info.dnsErrorCount = info.otherErrorCount = 0;
}else{
++info.succCount;
}
}else if(ex instanceof ConnectTimeoutException){
info.succCount = info.dnsErrorCount = 0;
++info.connectTimeoutCount;
}else if(ex instanceof UnknownHostException){
info.succCount = 0;
++info.dnsErrorCount;
}else{
info.succCount = 0;
++info.otherErrorCount;
}
} public synchronized DomainInfo getDomain(final WXPayConfig config) {
DomainStatics primaryDomain = domainData.get(WXPayConstants.DOMAIN_API);
if(primaryDomain == null ||
primaryDomain.isGood()) {
return new DomainInfo(WXPayConstants.DOMAIN_API, true);
} long now = System.currentTimeMillis();
if(switchToAlternateDomainTime == 0){ //first switch
switchToAlternateDomainTime = now;
return new DomainInfo(WXPayConstants.DOMAIN_API2, false);
}else if(now - switchToAlternateDomainTime < MIN_SWITCH_PRIMARY_MSEC){
DomainStatics alternateDomain = domainData.get(WXPayConstants.DOMAIN_API2);
if(alternateDomain == null ||
alternateDomain.isGood() ||
alternateDomain.badCount() < primaryDomain.badCount()){
return new DomainInfo(WXPayConstants.DOMAIN_API2, false);
}else{
return new DomainInfo(WXPayConstants.DOMAIN_API, true);
}
}else{ //force switch back
switchToAlternateDomainTime = 0;
primaryDomain.resetCount();
DomainStatics alternateDomain = domainData.get(WXPayConstants.DOMAIN_API2);
if(alternateDomain != null)
alternateDomain.resetCount();
return new DomainInfo(WXPayConstants.DOMAIN_API, true);
}
} static class DomainStatics {
final String domain;
int succCount = 0;
int connectTimeoutCount = 0;
int dnsErrorCount =0;
int otherErrorCount = 0; DomainStatics(String domain) {
this.domain = domain;
}
void resetCount(){
succCount = connectTimeoutCount = dnsErrorCount = otherErrorCount = 0;
}
boolean isGood(){ return connectTimeoutCount <= 2 && dnsErrorCount <= 2; }
int badCount(){
return connectTimeoutCount + dnsErrorCount * 5 + otherErrorCount / 4;
}
}
private final int MIN_SWITCH_PRIMARY_MSEC = 3 * 60 * 1000; //3 minutes
private long switchToAlternateDomainTime = 0;
private Map<String, DomainStatics> domainData = new HashMap<String, DomainStatics>();
}
WXPayConfigImpl代码:
package com.karat.cn.util; import java.io.File;
import java.io.FileInputStream;
import java.io.ByteArrayInputStream;
import java.io.InputStream; public class WXPayConfigImpl extends WXPayConfig{ /**==========================================================================**/
private byte[] certData;
private static WXPayConfigImpl INSTANCE; private WXPayConfigImpl() throws Exception{
String certPath = WXPayConfigImpl.class.getClassLoader().getResource("").getPath();
File file = new File(certPath + "apiclient_cert.p12");
InputStream certStream = new FileInputStream(file);
this.certData = new byte[(int) file.length()];
certStream.read(this.certData);
certStream.close();
} public static WXPayConfigImpl getInstance() throws Exception{
if (INSTANCE == null) {
synchronized (WXPayConfigImpl.class) {
if (INSTANCE == null) {
INSTANCE = new WXPayConfigImpl();
}
}
}
return INSTANCE;
} /**==========================================================================**/
@Override
public String getAppID() {
// TODO Auto-generated method stub
return "小程序AppId";
} @Override
public String getMchID() {
// TODO Auto-generated method stub
return "商户号";
} @Override
public String getKey() {
// TODO Auto-generated method stub
return "商户密钥";
} @Override
public InputStream getCertStream() {
// TODO Auto-generated method stub
ByteArrayInputStream certBis;
certBis = new ByteArrayInputStream(this.certData);
return certBis;
} @Override
public IWXPayDomain getWXPayDomain() {
// TODO Auto-generated method stub
return WXPayDomainSimpleImpl.instance();
} }
4.向WXPayConstants.java中添加常量:
public static final String TRANSFERS_URL_SUFFIX = "/mmpaymkttransfers/promotion/transfers";
public static final String SANDBOX_SENDREDPACK_URL_SUFFIX = "/sandboxnew/mmpaymkttransfers/sendredpack";
public static final String SANDBOX_TRANSFERS_URL_SUFFIX = "/sandboxnew/mmpaymkttransfers/promotion/transfers";
5.向WXPay.java中添加如下代码:
/********************************************/
// 企业付款
public String transfers(Map<String, String> reqData) throws Exception {
return this.transfers(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
}
public String transfers(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
String url;
if (this.useSandbox) {
url = WXPayConstants.SANDBOX_TRANSFERS_URL_SUFFIX;
}
else {
url = WXPayConstants.TRANSFERS_URL_SUFFIX;
}
return this.requestWithCert(url, this.transfersRequestData(reqData), connectTimeoutMs, readTimeoutMs);
}
// 企业付款
public Map<String, String> transfersRequestData(Map<String, String> reqData) throws Exception {
// 商户号绑定的appid(小程序的appid)
reqData.put("mch_appid", config.getAppID());
// 商户号
reqData.put("mchid", config.getMchID());
// 随机字符串
reqData.put("nonce_str", WXPayUtil.generateUUID());
reqData.put("sign", WXPayUtil.generateSignature(reqData, config.getKey(), this.signType));
return reqData;
} /********************************************/
6.创建订单表以及返回给小程序端的参数vo
package com.karat.cn.wxCommon; import java.util.Map; import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document; /**
* 订单表
* @author 开发
*
*/
@Document(collection = "wxWithdrawOrder")
public class WxWithdrawOrder {
/**
* id
*/
@Id
private String id;
/**
* 会员id
*/
@Indexed
private String memberId;
/**
* 订单号
*/
@Indexed(unique = true)
private String orderNo;
/**
* 提现金额(分)
*/
private int money;
/**
* 提现时间
*/
private String createDate;
/**
* 订单状态(0:申请失败或异常 1:已申请成功)
*/
private String orderStatus;
/**
* 扩展
*/
private Map<String, String> remark;
/**
* 扩展2
*/
private String remark2; public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMemberId() {
return memberId;
}
public void setMemberId(String memberId) {
this.memberId = memberId;
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public String getCreateDate() {
return createDate;
}
public void setCreateDate(String createDate) {
this.createDate = createDate;
}
public Map<String, String> getRemark() {
return remark;
}
public void setRemark(Map<String, String> remark) {
this.remark = remark;
}
public String getRemark2() {
return remark2;
}
public void setRemark2(String remark2) {
this.remark2 = remark2;
}
public String getOrderStatus() {
return orderStatus;
}
public void setOrderStatus(String orderStatus) {
this.orderStatus = orderStatus;
}
}
package com.karat.cn.vo;
/**
* 调用微信支付相关信息
* @author 开发
*
*/
public class VoUnifiedOrderWx {
// 时间戳
private String timeStamp;
// 随机串
private String nonceStr;
// 数据包
private String packageValue;
// 签名
private String sign; public String getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}
public String getNonceStr() {
return nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getPackageValue() {
return packageValue;
}
public void setPackageValue(String packageValue) {
this.packageValue = packageValue;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
} }
7.创建工具类(获取系统时间)
package com.karat.cn.wxCommon; import java.text.ParseException;
import java.util.Date; public class BaseToolsUtil {
/**
* 获取系统时间long
*
* @return
* @throws ParseException
*/
public static long systemtimeLong() {
return new Date().getTime();
}
}
8.准备工作完毕,开始实现小程序支付,退款,提现功能。
Java实现微信小程序支付(准备)的更多相关文章
- Java 后端微信小程序支付demo (网上说的坑里面基本上都有)
Java 后端微信小程序支付 一.遇到的问题 1. 商户号该产品权限未开通,请前往商户平台>产品中心检查后重试 2.签名错误 3.已经调起微信统一下单接口,可以拿到预支付ID,但是前端支付的时候 ...
- Java实现微信小程序支付(完整版)
在开发微信小程序支付的功能前,我们先熟悉下微信小程序支付的业务流程图: 不熟悉流程的建议还是仔细阅读微信官方的开发者文档. 一,准备工作 事先需要申请企业版小程序,并开通“微信支付”(即商户功能).并 ...
- Java实现微信小程序支付(支付,提现,退款)
1.添加WXpayCommon类用以具体实现功能,代码如下: package com.karat.cn.wxCommon; import java.io.IOException; import jav ...
- 【原创】微信小程序支付java后台案例(公众号支付同适用)(签名错误问题)
前言 1.微信小程序支付官方接口文档:[点击查看微信开放平台api开发文档]2.遇到的坑:预支付统一下单签名结果返回[签名错误]失败,建议用官方[签名验证工具]检查签名是否存在问题.3.遇到的坑:签名 ...
- 微信小程序支付开发之申请退款
微信小程序支付跟微信公众号支付类似,这里不另做记录,如果没有开发过支付,可以查看我关于微信支付的文章 重点记录微信小程序申请退款开发过程中遇到一些坑. 退款接口比支付接口接口多了一个 双向证书 证书介 ...
- SpringBoot2.0微信小程序支付多次回调问题
SpringBoot2.0微信小程序支付多次回调问题 WxJava - 微信开发 Java SDK(开发工具包); 支持包括微信支付.开放平台.公众号.企业微信/企业号.小程序等微信功能的后端开发. ...
- 微信小程序支付步骤
http://blog.csdn.net/wangsf789/article/details/53419781 最近开发微信小程序进入到支付阶段,一直以来从事App开发,所以支付流程还是熟记于心的.但 ...
- 微信小程序支付及退款流程详解
微信小程序的支付和退款流程 近期在做微信小程序时,涉及到了小程序的支付和退款流程,所以也大概的将这方面的东西看了一个遍,就在这篇博客里总结一下. 首先说明一下,微信小程序支付的主要逻辑集中在后端,前端 ...
- php对接微信小程序支付
前言:这里我就假装你已经注册了微信小程序,并且基本的配置都已经好了.注: 个人注册小程序不支持微信支付,所以我还是假装你是企业或者个体工商户的微信小程序,其他的商户号注册,二者绑定,授权,支付开通,就 ...
随机推荐
- 第十章 Executor框架
在Java中,使用线程来异步执行任务.Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源.同时,为每一个任务创建一个新线程来执行 ...
- 在云服务器上体验Docker
1. 添加Docker repository key sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -" 2. ...
- 用JS,打印三角形
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- apache2不识别php
sudo apt-get install libapache2-mod-php7.0 sudo a2enmod php7.0 sudo service apache2 restart 注意:Apach ...
- 『原』在Linux下反编译Android .apk文件 使用apktool dex2jar JD-eclipse
一.使用apktool 将 apk反编译生成程序的源代码和图片.XML配置.语言资源等文件 具体步骤: (1)下载反编译工具包:apktool 官方的打不开 http://apktool.shouji ...
- PCL—点云滤波(基于点云频率) 低层次点云处理
博客转载自:http://www.cnblogs.com/ironstark/p/5010771.html 1.点云的频率 今天在阅读分割有关的文献时,惊喜的发现,点云和图像一样,有可能也存在频率的概 ...
- python中list的使用
1.list(列表)是一种有序的集合,可以随时添加.修改.删除其中的元素. 举例:listClassName = ['Jack','Tom','Mark'] 列表可以根据索引获取元素,如:listCl ...
- register的功能
register:这个关键字请求编译器尽可能 的将变量存在CPU内部寄存器中,而不是通过内存寻址访问,以提高效率.这里注意是尽可能,不是绝对.你想想,一个CPU拥有 的寄存器也就那么几个或几十个,你要 ...
- mysql存取blob类型数据
参考网址:http://www.cnblogs.com/jway1101/p/5815658.html 首先是建表语句,需要实现将表建立好. CREATE TABLE `blobtest` ( `pr ...
- 使用metasploit进行栈溢出攻击-3
有了shellcode,就可以进行攻击了,但是要有漏洞才行,真实世界中的漏洞很复杂,并且很难发现,因此我专门做一个漏洞来进行攻击. 具体来说就是做一个简单的tcp server,里面包含明显的栈溢出漏 ...