微信开发之微信支付相关算法实现
来源:互联网 发布:mac 照片 文件夹 编辑:程序博客网 时间:2024/06/05 04:03
微信开发中,涉及到微信支付流程较为繁琐。其中以微信红包为例,参考官方文档:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3。
调用微信支付链接中,有以下三个字段,需要依据相关算法要求生成。分别是签名(sign),订单号(mch_billno)以及随机字符串(nonce_str)。下面用Java依据算法流程,实现了微信支付工具类,用于生成上述三个字段。
代码如下,已经过测试:
/** * Created by Song on 2016/11/8. * mail: 1147649695@qq.com * 微信支付相关工具类 */public class PayWxUtil { //上一次订单请求日期 private static Date preDay = new Date(); //当前订单日期 private static Date curDay = new Date(); //用于记录已产生的订单号 private static Set<Long> numPoul = new HashSet<Long>(); /** * 获得签名 * @param params 待编码参数,参数值为空不传入 * @param key key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 * @return */ public static String getSign(Map<String,String> params,String key){ List<String> list = new ArrayList<String>(params.keySet()); Collections.sort(list,new DictionaryCompare()); StringBuffer sb = new StringBuffer(); for(String keyVal:list){ sb.append(keyVal+"="+params.get(keyVal)+"&"); } sb.append("key="+key); return DigestUtils.md5Hex(sb.toString()).toUpperCase(); } /** * 获得随机字符串 * @return */ public static String getNonceStr(){ Random random = new Random(); long val = random.nextLong(); String res = DigestUtils.md5Hex(val+"yzx").toUpperCase(); if(32<res.length()) return res.substring(0,32); else return res; } /** * 获取订单号 * 商户订单号(每个订单号必须唯一) * 组成:mch_id+yyyymmdd+10位一天内不能重复的数字。 * @param mchId * @return */ public static String getMchBillno(String mchId){ Random random = new Random(); long val = random.nextLong()%10000000000L;//获得0-9999999999内的数字 curDay = new Date(); //隔天清空 if(curDay.after(preDay)) numPoul.clear(); while(numPoul.contains(val)){ val = random.nextLong()%10000000000L; } numPoul.add(val); preDay = curDay; //按要求,日期格式化输出 DateFormat df = new SimpleDateFormat("yyyymmdd"); return mchId+df.format(curDay)+format(val+"",10); } /** * 将字符串str按长度在前面添0补齐 * @param str * @param length * @return */ private static String format(String str,int length){ String pre = "0000000000"; int len = str.length(); if(10<=len) return str.substring(0,10); else return pre.substring(0,10-len).concat(str); }}/** * 按字典序排序 */class DictionaryCompare implements Comparator<String>{ public int compare(String o1, String o2) { return o1.compareTo(o2); }}
其中,签名(sign)的算法流程参考官方说明签名算法其具体实现过程摘录如下:
(1)设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA
(2)在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。
关于订单号生成,要求订单号后10位为当天不可重复的10位数。这里用静态Set存储了当天已产生的数字。需要说明的是,这种方式下,如果项目在服务器下重新部署了,该静态值将被清空,从而有可能导致错误;当一天内访问量很高,接近上限值9999999999时,获得该随机数的时间将显著增长,且将耗费JVM中永久区较大内存资源,若JVM相关参数配置不当,可能导致PermSize溢出异常,导致系统崩溃。这两种情况下,建议还是采用基于数据库字段自增来获取该值为好。当然,目前这种方式基于本次项目日红包发送量较低的情况,所以不需考虑以上情况。具体实现方式是:
(1)产生0-9999999999类的随机数
(2)判断当前日期curDay是否在上一次请求日期preDay之后,是则执行(3),否则执行(4)
(3)清空随机数静态缓存numPoul
(4)判断该随机数是否在静态缓存资源numPoul中,存在则执行(1),否则执行(5)
(5)将该随机数写入numPoul中,更新preDay为当前日期
(6)将该随机数添0补齐为10位,并按规则组合,得到订单号并返回。
部分细节方面,可能还有疏漏,若有问题,发现将及时改正更新,也欢迎大家提出存在的问题和看法。
- 微信开发之微信支付相关算法实现
- 微信支付相关
- iOS开发支付之微信支付
- 关于微信支付相关开发
- 微信app开发支付接口相关
- 微信支付之认识微信支付开发
- 微信支付开发
- 微信支付开发
- 微信支付开发
- 微信支付开发
- 微信支付开发
- 微信支付开发
- android开发之微信支付功能的实现
- android开发之微信支付功能的实现
- 微信公众号开发之微信支付开发
- Android开发之微信支付,支付宝支付
- 微信开发大坑汇总之微信支付篇
- php 微信开发之 微信支付 v3 配置
- C语言知识
- Struts2总结1
- 七种排序方法
- Linux下的C语言编程——用链表实现栈操作
- 关于PHP的文件上传
- 微信开发之微信支付相关算法实现
- usaco The Castle
- Unity3D 几个基本动画(控制物体移动、旋转、缩放)
- Krpano vtourskin.xml 默认皮肤详解
- AVI编码器的常见编码
- TestNG系列-第四章 testNG之命令行运行及参数详解
- 安卓启动界面 Handler.postDelay
- 2016csdn高校俱乐部——开讲啦
- LeetCode 407. Trapping Rain Water II