Java语言开发微信小程序支付功能:
1.通过路径到官方下载Java的支付SDK。
2.下载后将pom文件中需要用到的jar包导入自己的项目中,将demo全部导入到自己的工具包中,需导入的demo如下图:
3.此时缺少IWXPayDomain与WXPayConfig抽象类的具体实现,新建WXPayDomainSimpleImpl与WXPayConfigImpl来分别实现抽象类,代码如下:
WXPayDomainSimpleImpl代码:
1 package com.karat.cn.util; 2 import org.apache.http.conn.ConnectTimeoutException; 3 4 import java.net.UnknownHostException; 5 import java.util.HashMap; 6 import java.util.Map; 7 8 /** 9 * Created by blaketang on 2017/6/16.10 */11 public class WXPayDomainSimpleImpl implements IWXPayDomain {12 private WXPayDomainSimpleImpl(){}13 private static class WxpayDomainHolder{14 private static IWXPayDomain holder = new WXPayDomainSimpleImpl();15 }16 public static IWXPayDomain instance(){17 return WxpayDomainHolder.holder;18 }19 20 public synchronized void report(final String domain, long elapsedTimeMillis, final Exception ex) {21 DomainStatics info = domainData.get(domain);22 if(info == null){23 info = new DomainStatics(domain);24 domainData.put(domain, info);25 }26 27 if(ex == null){ //success28 if(info.succCount >= 2){ //continue succ, clear error count29 info.connectTimeoutCount = info.dnsErrorCount = info.otherErrorCount = 0;30 }else{31 ++info.succCount;32 }33 }else if(ex instanceof ConnectTimeoutException){34 info.succCount = info.dnsErrorCount = 0;35 ++info.connectTimeoutCount;36 }else if(ex instanceof UnknownHostException){37 info.succCount = 0;38 ++info.dnsErrorCount;39 }else{40 info.succCount = 0;41 ++info.otherErrorCount;42 }43 }44 45 public synchronized DomainInfo getDomain(final WXPayConfig config) {46 DomainStatics primaryDomain = domainData.get(WXPayConstants.DOMAIN_API);47 if(primaryDomain == null ||48 primaryDomain.isGood()) {49 return new DomainInfo(WXPayConstants.DOMAIN_API, true);50 }51 52 long now = System.currentTimeMillis();53 if(switchToAlternateDomainTime == 0){ //first switch54 switchToAlternateDomainTime = now;55 return new DomainInfo(WXPayConstants.DOMAIN_API2, false);56 }else if(now - switchToAlternateDomainTime < MIN_SWITCH_PRIMARY_MSEC){57 DomainStatics alternateDomain = domainData.get(WXPayConstants.DOMAIN_API2);58 if(alternateDomain == null ||59 alternateDomain.isGood() ||60 alternateDomain.badCount() < primaryDomain.badCount()){61 return new DomainInfo(WXPayConstants.DOMAIN_API2, false);62 }else{63 return new DomainInfo(WXPayConstants.DOMAIN_API, true);64 }65 }else{ //force switch back66 switchToAlternateDomainTime = 0;67 primaryDomain.resetCount();68 DomainStatics alternateDomain = domainData.get(WXPayConstants.DOMAIN_API2);69 if(alternateDomain != null)70 alternateDomain.resetCount();71 return new DomainInfo(WXPayConstants.DOMAIN_API, true);72 }73 }74 75 static class DomainStatics {76 final String domain;77 int succCount = 0;78 int connectTimeoutCount = 0;79 int dnsErrorCount =0;80 int otherErrorCount = 0;81 82 DomainStatics(String domain) {83 this.domain = domain;84 }85 void resetCount(){86 succCount = connectTimeoutCount = dnsErrorCount = otherErrorCount = 0;87 }88 boolean isGood(){ return connectTimeoutCount <= 2 && dnsErrorCount <= 2; }89 int badCount(){90 return connectTimeoutCount + dnsErrorCount * 5 + otherErrorCount / 4;91 }92 }93 private final int MIN_SWITCH_PRIMARY_MSEC = 3 * 60 * 1000; //3 minutes94 private long switchToAlternateDomainTime = 0;95 private MapdomainData = new HashMap ();96 }
WXPayConfigImpl代码:
1 package com.karat.cn.util; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.ByteArrayInputStream; 6 import java.io.InputStream; 7 8 9 public class WXPayConfigImpl extends WXPayConfig{10 11 /**==========================================================================**/12 private byte[] certData;13 private static WXPayConfigImpl INSTANCE;14 15 private WXPayConfigImpl() throws Exception{16 String certPath = WXPayConfigImpl.class.getClassLoader().getResource("").getPath();17 File file = new File(certPath + "apiclient_cert.p12");18 InputStream certStream = new FileInputStream(file);19 this.certData = new byte[(int) file.length()];20 certStream.read(this.certData);21 certStream.close();22 }23 24 public static WXPayConfigImpl getInstance() throws Exception{25 if (INSTANCE == null) {26 synchronized (WXPayConfigImpl.class) {27 if (INSTANCE == null) {28 INSTANCE = new WXPayConfigImpl();29 }30 }31 }32 return INSTANCE;33 }34 35 /**==========================================================================**/36 @Override37 public String getAppID() {38 // TODO Auto-generated method stub39 return "小程序AppId";40 }41 42 @Override43 public String getMchID() {44 // TODO Auto-generated method stub45 return "商户号";46 }47 48 @Override49 public String getKey() {50 // TODO Auto-generated method stub51 return "商户密钥";52 }53 54 @Override55 public InputStream getCertStream() {56 // TODO Auto-generated method stub57 ByteArrayInputStream certBis;58 certBis = new ByteArrayInputStream(this.certData);59 return certBis;60 }61 62 @Override63 public IWXPayDomain getWXPayDomain() {64 // TODO Auto-generated method stub65 return WXPayDomainSimpleImpl.instance();66 }67 68 }
4.向WXPayConstants.java中添加常量:
1 public static final String TRANSFERS_URL_SUFFIX = "/mmpaymkttransfers/promotion/transfers";2 public static final String SANDBOX_SENDREDPACK_URL_SUFFIX = "/sandboxnew/mmpaymkttransfers/sendredpack";3 public static final String SANDBOX_TRANSFERS_URL_SUFFIX = "/sandboxnew/mmpaymkttransfers/promotion/transfers";
5.向WXPay.java中添加如下代码:
1 /********************************************/ 2 // 企业付款 3 public String transfers(MapreqData) throws Exception { 4 return this.transfers(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); 5 } 6 public String transfers(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { 7 String url; 8 if (this.useSandbox) { 9 url = WXPayConstants.SANDBOX_TRANSFERS_URL_SUFFIX;10 }11 else {12 url = WXPayConstants.TRANSFERS_URL_SUFFIX;13 }14 return this.requestWithCert(url, this.transfersRequestData(reqData), connectTimeoutMs, readTimeoutMs);15 }16 // 企业付款17 public Map transfersRequestData(Map reqData) throws Exception {18 // 商户号绑定的appid(小程序的appid)19 reqData.put("mch_appid", config.getAppID());20 // 商户号21 reqData.put("mchid", config.getMchID());22 // 随机字符串23 reqData.put("nonce_str", WXPayUtil.generateUUID());24 reqData.put("sign", WXPayUtil.generateSignature(reqData, config.getKey(), this.signType));25 return reqData;26 }27 28 /********************************************/
6.创建订单表以及返回给小程序端的参数vo
1 package com.karat.cn.wxCommon; 2 3 import java.util.Map; 4 5 import org.springframework.data.annotation.Id; 6 import org.springframework.data.mongodb.core.index.Indexed; 7 import org.springframework.data.mongodb.core.mapping.Document; 8 9 /** 10 * 订单表 11 * @author 开发 12 * 13 */ 14 @Document(collection = "wxWithdrawOrder") 15 public class WxWithdrawOrder { 16 /** 17 * id 18 */ 19 @Id 20 private String id; 21 /** 22 * 会员id 23 */ 24 @Indexed 25 private String memberId; 26 /** 27 * 订单号 28 */ 29 @Indexed(unique = true) 30 private String orderNo; 31 /** 32 * 提现金额(分) 33 */ 34 private int money; 35 /** 36 * 提现时间 37 */ 38 private String createDate; 39 /** 40 * 订单状态(0:申请失败或异常 1:已申请成功) 41 */ 42 private String orderStatus; 43 /** 44 * 扩展 45 */ 46 private Mapremark; 47 /** 48 * 扩展2 49 */ 50 private String remark2; 51 52 53 public String getId() { 54 return id; 55 } 56 public void setId(String id) { 57 this.id = id; 58 } 59 public String getMemberId() { 60 return memberId; 61 } 62 public void setMemberId(String memberId) { 63 this.memberId = memberId; 64 } 65 public String getOrderNo() { 66 return orderNo; 67 } 68 public void setOrderNo(String orderNo) { 69 this.orderNo = orderNo; 70 } 71 public int getMoney() { 72 return money; 73 } 74 public void setMoney(int money) { 75 this.money = money; 76 } 77 public String getCreateDate() { 78 return createDate; 79 } 80 public void setCreateDate(String createDate) { 81 this.createDate = createDate; 82 } 83 public Map getRemark() { 84 return remark; 85 } 86 public void setRemark(Map remark) { 87 this.remark = remark; 88 } 89 public String getRemark2() { 90 return remark2; 91 } 92 public void setRemark2(String remark2) { 93 this.remark2 = remark2; 94 } 95 public String getOrderStatus() { 96 return orderStatus; 97 } 98 public void setOrderStatus(String orderStatus) { 99 this.orderStatus = orderStatus;100 }101 }
1 package com.karat.cn.vo; 2 /** 3 * 调用微信支付相关信息 4 * @author 开发 5 * 6 */ 7 public class VoUnifiedOrderWx { 8 // 时间戳 9 private String timeStamp;10 // 随机串11 private String nonceStr;12 // 数据包13 private String packageValue;14 // 签名15 private String sign;16 17 public String getTimeStamp() {18 return timeStamp;19 }20 public void setTimeStamp(String timeStamp) {21 this.timeStamp = timeStamp;22 }23 public String getNonceStr() {24 return nonceStr;25 }26 public void setNonceStr(String nonceStr) {27 this.nonceStr = nonceStr;28 }29 public String getPackageValue() {30 return packageValue;31 }32 public void setPackageValue(String packageValue) {33 this.packageValue = packageValue;34 }35 public String getSign() {36 return sign;37 }38 public void setSign(String sign) {39 this.sign = sign;40 }41 42 }
7.创建工具类(获取系统时间)
1 package com.karat.cn.wxCommon; 2 3 import java.text.ParseException; 4 import java.util.Date; 5 6 public class BaseToolsUtil { 7 /** 8 * 获取系统时间long 9 * 10 * @return11 * @throws ParseException12 */13 public static long systemtimeLong() {14 return new Date().getTime();15 }16 }
8.准备工作完毕,开始实现小程序支付,退款,提现功能。