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实现微信小程序支付(准备)的更多相关文章

  1. Java 后端微信小程序支付demo (网上说的坑里面基本上都有)

    Java 后端微信小程序支付 一.遇到的问题 1. 商户号该产品权限未开通,请前往商户平台>产品中心检查后重试 2.签名错误 3.已经调起微信统一下单接口,可以拿到预支付ID,但是前端支付的时候 ...

  2. Java实现微信小程序支付(完整版)

    在开发微信小程序支付的功能前,我们先熟悉下微信小程序支付的业务流程图: 不熟悉流程的建议还是仔细阅读微信官方的开发者文档. 一,准备工作 事先需要申请企业版小程序,并开通“微信支付”(即商户功能).并 ...

  3. Java实现微信小程序支付(支付,提现,退款)

    1.添加WXpayCommon类用以具体实现功能,代码如下: package com.karat.cn.wxCommon; import java.io.IOException; import jav ...

  4. 【原创】微信小程序支付java后台案例(公众号支付同适用)(签名错误问题)

    前言 1.微信小程序支付官方接口文档:[点击查看微信开放平台api开发文档]2.遇到的坑:预支付统一下单签名结果返回[签名错误]失败,建议用官方[签名验证工具]检查签名是否存在问题.3.遇到的坑:签名 ...

  5. 微信小程序支付开发之申请退款

    微信小程序支付跟微信公众号支付类似,这里不另做记录,如果没有开发过支付,可以查看我关于微信支付的文章 重点记录微信小程序申请退款开发过程中遇到一些坑. 退款接口比支付接口接口多了一个 双向证书 证书介 ...

  6. SpringBoot2.0微信小程序支付多次回调问题

    SpringBoot2.0微信小程序支付多次回调问题 WxJava - 微信开发 Java SDK(开发工具包); 支持包括微信支付.开放平台.公众号.企业微信/企业号.小程序等微信功能的后端开发. ...

  7. 微信小程序支付步骤

    http://blog.csdn.net/wangsf789/article/details/53419781 最近开发微信小程序进入到支付阶段,一直以来从事App开发,所以支付流程还是熟记于心的.但 ...

  8. 微信小程序支付及退款流程详解

    微信小程序的支付和退款流程 近期在做微信小程序时,涉及到了小程序的支付和退款流程,所以也大概的将这方面的东西看了一个遍,就在这篇博客里总结一下. 首先说明一下,微信小程序支付的主要逻辑集中在后端,前端 ...

  9. php对接微信小程序支付

    前言:这里我就假装你已经注册了微信小程序,并且基本的配置都已经好了.注: 个人注册小程序不支持微信支付,所以我还是假装你是企业或者个体工商户的微信小程序,其他的商户号注册,二者绑定,授权,支付开通,就 ...

随机推荐

  1. 修改Windows帐户密码,导致Sql Server 2000无法启动

    修改Windows帐户密码,导致Sql Server 2000无法启动. --现象以管理员或同等权限用户登录 Windows XP,建立 Sql Server 2000 数据库.之后,在修改此 Win ...

  2. LAMP 2.2 Apache配置静态缓存

    这里的静态文件指的是图片.js.css 等文件,用户访问一个站点,其实大多数元素都是图片.js.css 等,这些静态文件其实是会被客户端的浏览器缓存到本地电脑上的,目的就是为了下次再请求时不再去服务器 ...

  3. WPF TextBox 一些设置技巧

    WPF TextBox 一些设置技巧 运行环境:Win10 x64, NetFrameWork 4.8, 作者:乌龙哈里,日期:2019-05-01 参考: 章节: 取消输入法 输入方式设定为Over ...

  4. 基本的数据类型 void关键字 都存在类类型

  5. 【oracle】首次启动SQL Developer配置java.exe出错(Could not find jvm.cfg! )

    1.环境 win7/8/8.1  x64,Oracle 11g r2,jdk7 x64 2.问题 第一次启动Oracle SQL Developer的时候会让我们填写Java.exe的路径,我在jdk ...

  6. [cf557d]Vitaly and Cycle(黑白染色求奇环)

    题目大意:给出一个 n 点 m 边的图,问最少加多少边使其能够存在奇环,加最少边的情况数有多少种. 解题关键:黑白染色求奇环,利用数量分析求解. 奇环:含有奇数个点的环. 二分图不存在奇环.反之亦成立 ...

  7. 安装nodemon热启动

    1.安装: cnpm i nodemon -g 2.执行 nodemon .\launch.js .\config_preview\ .\launch.js 为我要启动的脚本文件 .\config_p ...

  8. winform combobox绑定数据

    mboBox下拉菜单控件,在数据库内的ComboBox应用的表进行修改时,如果是用的普通方法,显示数据一个方法,添加数据一个方法 这样会导致程序后期维护难度增加,在这里使用数据绑定来让ComboBox ...

  9. 算法Sedgewick第四版-第1章基础-2.3 Quicksort-001快速排序

    一. 1.特点 (1)The quicksort algorithm’s desirable features are that it is in-place (uses only a small a ...

  10. U盘刻录14.10镜像出问题的解决方法

    从几个月前的14.10 daily 版本就有U盘刻录无法启动的现象,相关bug可参见:https://bugs.launchpad.net/ubunt ... reator/+bug/1325801 ...