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代码:

  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){ //success
  28. if(info.succCount >= 2){ //continue succ, clear error count
  29. 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 switch
  54. 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 back
  66. 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 minutes
  94. private long switchToAlternateDomainTime = 0;
  95. private Map<String, DomainStatics> domainData = new HashMap<String, DomainStatics>();
  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. public class WXPayConfigImpl extends WXPayConfig{
  9.  
  10. /**==========================================================================**/
  11. private byte[] certData;
  12. private static WXPayConfigImpl INSTANCE;
  13.  
  14. private WXPayConfigImpl() throws Exception{
  15. String certPath = WXPayConfigImpl.class.getClassLoader().getResource("").getPath();
  16. File file = new File(certPath + "apiclient_cert.p12");
  17. InputStream certStream = new FileInputStream(file);
  18. this.certData = new byte[(int) file.length()];
  19. certStream.read(this.certData);
  20. certStream.close();
  21. }
  22.  
  23. public static WXPayConfigImpl getInstance() throws Exception{
  24. if (INSTANCE == null) {
  25. synchronized (WXPayConfigImpl.class) {
  26. if (INSTANCE == null) {
  27. INSTANCE = new WXPayConfigImpl();
  28. }
  29. }
  30. }
  31. return INSTANCE;
  32. }
  33.  
  34. /**==========================================================================**/
  35. @Override
  36. public String getAppID() {
  37. // TODO Auto-generated method stub
  38. return "小程序AppId";
  39. }
  40.  
  41. @Override
  42. public String getMchID() {
  43. // TODO Auto-generated method stub
  44. return "商户号";
  45. }
  46.  
  47. @Override
  48. public String getKey() {
  49. // TODO Auto-generated method stub
  50. return "商户密钥";
  51. }
  52.  
  53. @Override
  54. public InputStream getCertStream() {
  55. // TODO Auto-generated method stub
  56. ByteArrayInputStream certBis;
  57. certBis = new ByteArrayInputStream(this.certData);
  58. return certBis;
  59. }
  60.  
  61. @Override
  62. public IWXPayDomain getWXPayDomain() {
  63. // TODO Auto-generated method stub
  64. return WXPayDomainSimpleImpl.instance();
  65. }
  66.  
  67. }

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(Map<String, String> reqData) throws Exception {
  4. return this.transfers(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
  5. }
  6. public String transfers(Map<String, String> 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<String, String> transfersRequestData(Map<String, String> 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 Map<String, String> remark;
  47. /**
  48. * 扩展2
  49. */
  50. private String remark2;
  51.  
  52. public String getId() {
  53. return id;
  54. }
  55. public void setId(String id) {
  56. this.id = id;
  57. }
  58. public String getMemberId() {
  59. return memberId;
  60. }
  61. public void setMemberId(String memberId) {
  62. this.memberId = memberId;
  63. }
  64. public String getOrderNo() {
  65. return orderNo;
  66. }
  67. public void setOrderNo(String orderNo) {
  68. this.orderNo = orderNo;
  69. }
  70. public int getMoney() {
  71. return money;
  72. }
  73. public void setMoney(int money) {
  74. this.money = money;
  75. }
  76. public String getCreateDate() {
  77. return createDate;
  78. }
  79. public void setCreateDate(String createDate) {
  80. this.createDate = createDate;
  81. }
  82. public Map<String, String> getRemark() {
  83. return remark;
  84. }
  85. public void setRemark(Map<String, String> remark) {
  86. this.remark = remark;
  87. }
  88. public String getRemark2() {
  89. return remark2;
  90. }
  91. public void setRemark2(String remark2) {
  92. this.remark2 = remark2;
  93. }
  94. public String getOrderStatus() {
  95. return orderStatus;
  96. }
  97. public void setOrderStatus(String orderStatus) {
  98. this.orderStatus = orderStatus;
  99. }
  100. }
  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. * @return
  11. * @throws ParseException
  12. */
  13. public static long systemtimeLong() {
  14. return new Date().getTime();
  15. }
  16. }

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. 获取Linux权限后安装rootkit

    1.首先获得远程服务器的root权限,当然这是基本的也是最难的. 2.然后下载rootkit程序,本文用到的是mafix. 3.开始安装 wget http://godpock.googlecode. ...

  2. Howto Reboot or halt Linux system in emergency (ZT)

    http://www.cyberciti.biz/tips/reboot-or-halt-linux-system-in-emergency.html Linux kernel includes ma ...

  3. 11-02SQLserver基础--字符串函数

    数据库の函数 一.内置函数--字符串函数 1.--ASCII 返回字符串的首字母的ASCII编码 select ASCII('ame') select ASCII(xingming)from xues ...

  4. When install ”matplotlib” with ”pip”, if you get the following error, it means the “freetype” and “png” libraries needed by matplotlib are not installed:

    ============================================================================ * The following require ...

  5. leetcode319

    public class Solution { public int BulbSwitch(int n) { var x = Math.Sqrt(n); var y = Convert.ToInt32 ...

  6. django的render的说明

    return render(request,"homesite.html",locals()) homesite.html页面中的所有内容都可以被渲染,不论是标签还是js代码,包括 ...

  7. POJ 1187 陨石的秘密 (线性DP)

    题意: 公元11380年,一颗巨大的陨石坠落在南极.于是,灾难降临了,地球上出现了一系列反常的现象.当人们焦急万分的时候,一支中国科学家组成的南极考察队赶到了出事地点.经过一番侦察,科学家们发现陨石上 ...

  8. ECMAScript 定义类、对象

    使用预定义对象只是面向对象语言的能力的一部分,它真正强大之处在于能够创建自己专用的类和对象. ECMAScript 拥有很多创建对象或类的方法. 工厂方式 原始的方式 因为对象的属性可以在对象创建后动 ...

  9. 项目一:第九天 1、前台客户登录 2、Jquery citypicker省市区三级联动插件 4、业务受理(在线下单)

    1. 前台客户登录 2. Jquery citypicker省市区三级联动插件 3. 百度地图介绍 4. 业务受理(在线下单) 1 实现前台系统登录功能 1.1 Md5加密 admin(明文)---- ...

  10. php学习笔记-for循环

    for(init;condition;statement) { func(); } for循环的执行逻辑是先执行一次init语句,然后判断condition是否为true,是则执行func(),再执行 ...