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对接微信小程序支付
前言:这里我就假装你已经注册了微信小程序,并且基本的配置都已经好了.注: 个人注册小程序不支持微信支付,所以我还是假装你是企业或者个体工商户的微信小程序,其他的商户号注册,二者绑定,授权,支付开通,就 ...
随机推荐
- Oracle中REGEXP_SUBSTR函数(字符串转多行)
Oracle中REGEXP_SUBSTR函数 Oracle中REGEXP_SUBSTR函数的使用说明: 题目如下: 在oracle中,使用一条语句实现将'17,20,23'拆分成'17','20',' ...
- 10-09C#语言基础
10-09C#语言基础 第一课 一.新项目的建立:打开Visual studio2012,单击“文件→新建项目→模板isualC# Windows 控制台应用程序→确定”即可. 在新建的项目中,首 ...
- Python之条件语句以及循环
Python代码的缩进规则.具有相同缩进的代码被视为代码块 缩进请严格按照Python的习惯写法:4个空格,不要使用Tab,更不要混合Tab和空格,否则很容易造成因为缩进引起的语法错误. 注意: if ...
- hibernate学习笔记(6)组件属性以及单表操作
组件属性:实体类中的某个属性属于用户自定义类的对象: 作用:将两个实体类合并在一起组建成一个表 在hbm.xml文件中配置: 格式: <component name="取的名字&quo ...
- 【259】ucpole.dat update
2017年2月21日 57871 +0.020896 0.007232 +0.414732 0.009212 +0.418044 0.007533 p 57872 +0.022055 0.007284 ...
- Contset Hunter 1102 高精度求卡特兰数
用递推的方式写的写挂了,而如果用组合数又不会高精度除法,偶然看到了别人的只用高精度乘低精度求组合数的方法,记录一下 #include<bits/stdc++.h> using namesp ...
- 常用linux配置文件
/etc/hosts:用户IP与域名的对应解析表/etc/sysconfig/network:机器名.网卡启动.网关等配置/etc/fstab:记录开机自动挂载的文件系统/etc/rc.local:开 ...
- MyBatis02 MyBatis基础知识之Mapper映射器
1 Mapper映射器是什么 是符合映射文件要求的接口 接口要求 a. 方法名要与sql的id一致. b. 方法的参数类型要与parameterType一致. c. 方法的返回类型要与resultTy ...
- protocol buffers的使用示例
protocol buffers的使用示例 如果不了解protocol buffers,可以先参看:http://blog.csdn.net/zhu_xun/article/details/19343 ...
- 一道java笔试题目:Vector和ArrayList的区别
Vector和ArrayList的区别 线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构这些类均在java.util包中本文试图通过 ...