python导出微信账单_微信下载对账单 - SquintSmile的个人空间 - OSCHINA - 中文开源技术交流社区...

本文介绍如何利用Python结合微信官方API下载商户对账单。通过配置相关参数,生成签名,转换XML格式,然后发送HTTPS请求,解析返回的账单数据,最后将数据存储或处理。提供关键代码实现。
摘要由CSDN通过智能技术生成

最近接触了一些比较新奇的东西,记录一下

先贴出微信官方的API地址,感受一下微信的魅力。。。

了解完微信下载账单的一些注意事项之后,咱们正式开始

下面是具体实现:

先贴出主方法,其他工具类会有具体说明:

public static void main(String[] args) throws Exception {

//downloadBill();

}

public static void downloadBill() throws Exception {

//这里的MyConfig工具类是自己封装的一些配置,为了方便自己使用,大家可以跳过这一步

MyConfig myConfig = new MyConfig();

SortedMap parameters =new TreeMap();

//这里面的value值,大家自己根据自己的微信商户参数配置一下

parameters.put("appid", myConfig.getAppID());//appid

parameters.put("mch_id", myConfig.getMchID());//商户号

parameters.put("nonce_str", CreateNoncestr());//随机字符串

parameters.put("bill_date", "20180125");//对账单日期

parameters.put("bill_type", "ALL");//对账单类型

//这里调用方法生成微信需要的签名(这里是一个坑点,当时在做微信退款的时候因为签名不符合规范被卡一天时间)

String sign = createSign("utf-8", parameters);//签名

parameters.put("sign", sign);

//这里的getRequestXml方法是转xml的工具方法,下面我会贴出来

String reuqestXml = getRequestXml(parameters);

/**

* 这里的CommonUtil是一个https通用工具类,我也会在下面贴出来

* download_bill_url是微信官方提供的对账单下载地址

* download_bill_url = “https://api.mch.weixin.qq.com/pay/downloadbill“

*/

String result=CommonUtil.httpsRequest(myConfig.download_bill_url, "POST", reuqestXml);

//微信对账单生成时间是次日的9点之后,所以查询日期为当天时,错误信息提示日期无效

if(result.startsWith("")){

System.out.println(result);

System.out.println("无订单");

}else {

String tradeMsg = result.substring(result.indexOf("`"));

String tradeInfo = tradeMsg.substring(0, tradeMsg.indexOf("总")).replace("`", "");// 去掉汇总数据,并且去掉'`'

String tradeInfo = tradeMsg.substring(0,tradeMsg.indexOf("总"));

String tradeTotalMsg =tradeMsg.substring(tradeMsg.indexOf("总"));

String tradeTotalInfo =tradeTotalMsg.substring(tradeTotalMsg.indexOf("`"));

System.out.println("result----->"+result);

System.out.println("tradeMsg----->"+tradeMsg);

System.out.println("tradeInfo----->"+tradeInfo);

System.out.println("tradeTotalMsg----->"+tradeTotalMsg);

System.out.println("tradeTotalInfo----->"+tradeTotalInfo);

//最后一栏是费率,里面以%结尾,以此作为切割目标,方便操作存数据库

String[] tradeArray = tradeInfo.split("%");

List> resultList = new ArrayList<>();

for(int i = 0;i < tradeArray.length;i++) {

String[] tradeDetailArray = tradeArray[i].split(",");

Map map = new HashMap<>();

/**

* 这里我取了几个对我来说用处较大的几个字段

* 详细字段的话,大家可以参考一下这里,或自己看控制台打印结果

* https://www.cnblogs.com/mgqy/articles/7657483.html

*/

map.put("readeTime", tradeDetailArray[0]);//交易时间

map.put("appid", tradeDetailArray[1]);//公众号ID

map.put("mchId", tradeDetailArray[2]);//商户号

map.put("transactionId", tradeDetailArray[5]);//微信订单号

map.put("outTradeNo", tradeDetailArray[6]);//商户订单号

map.put("openid", tradeDetailArray[7]);//用户标识(openid)

map.put("tradeState", tradeDetailArray[9]);// 交易状态

map.put("tradeBank", tradeDetailArray[10]);// 付款银行

map.put("totalFee", tradeDetailArray[12]);//总金额

map.put("refundFee", tradeDetailArray[16]);//退款金额

map.put("tradeName", tradeDetailArray[20]);// 商品名称

map.put("poundage", tradeDetailArray[22]);//手续费

resultList.add(map);

}

System.out.println("resultList--->"+resultList);

}

}

下面是一些用到的工具类和方法:

1、随机字符串生成方法

/**

* 随机字符串

* @return

*/

public static String CreateNoncestr() {

String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

String res = "";

for (int i = 0; i < 16; i++) {

Random rd = new Random();

res += chars.charAt(rd.nextInt(chars.length() - 1));

}

return res;

}

2、编写签名方法

/**

* 编写签名

* @param charSet

* @param parameters

* @return

* @throws Exception

*/

public static String createSign(String charSet,SortedMap parameters) throws Exception{

MyConfig myconfig = new MyConfig();

StringBuffer sb = new StringBuffer();

Set es = parameters.entrySet();

Iterator it = es.iterator();

while(it.hasNext()) {

Map.Entry entry = (Map.Entry)it.next();

String k = (String)entry.getKey();

Object v = entry.getValue();

if(null != v && !"".equals(v)

&& !"sign".equals(k) && !"key".equals(k)) {

sb.append(k + "=" + v + "&");

}

}

sb.append("key=" + myconfig.getKey());

// String sign = MD5Util.MD5Encode(sb.toString(), charSet).toUpperCase();

String sign = MD5Util.MD5Encode(sb.toString(), charSet).toUpperCase();

// String sign = MD5.MD5Encode(sb.toString(), charSet).toUpperCase();

return sign;

}

3、转xml格式方法

/**

* 转为xml格式

* @param parameters

* @return

*/

public static String getRequestXml(SortedMap parameters){

StringBuffer sb = new StringBuffer();

sb.append("");

Set es = parameters.entrySet();

Iterator it = es.iterator();

while(it.hasNext()) {

Map.Entry entry = (Map.Entry)it.next();

String k = (String)entry.getKey();

String v = (String)entry.getValue();

if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) {

sb.append(""+""+k+">");

}else {

sb.append(""+v+""+k+">");

}

}

sb.append("");

return sb.toString();

}

4、https通用工具类

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.net.ConnectException;

import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

import org.apache.log4j.Logger;

import net.sf.json.JSONObject;

/**

* https通用工具类

*/

public class CommonUtil {

private static Logger log = Logger.getLogger(CommonUtil.class);

public static JSONObject httpsRequestToJsonObject(String requestUrl, String requestMethod, String outputStr) {

JSONObject jsonObject = null;

try {

String buffer = httpsRequest(requestUrl, requestMethod, outputStr);

jsonObject = JSONObject.fromObject(buffer.toString());

} catch (Exception e) {

log.error("https请求异常:"+e.getMessage());

}

return jsonObject;

}

public static String httpsRequest(String requestUrl, String requestMethod, String outputStr){

try {

URL url = new URL(requestUrl);

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

conn.setDoOutput(true);

conn.setDoInput(true);

conn.setUseCaches(false);

// 设置请求方式(GET/POST)

conn.setRequestMethod(requestMethod);

conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");

// 当outputStr不为null时向输出流写数据

if (null != outputStr) {

OutputStream outputStream = conn.getOutputStream();

// 注意编码格式

outputStream.write(outputStr.getBytes("UTF-8"));

outputStream.close();

}

// 从输入流读取返回内容

InputStream inputStream = conn.getInputStream();

InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");

BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

String str = null;

StringBuffer buffer = new StringBuffer();

while ((str = bufferedReader.readLine()) != null) {

buffer.append(str);

}

// 释放资源

bufferedReader.close();

inputStreamReader.close();

inputStream.close();

inputStream = null;

conn.disconnect();

return buffer.toString();

} catch (ConnectException ce) {

System.out.println("连接超时:{}");

} catch (Exception e) {

System.out.println("https请求异常:{}");

}

return null;

}

}

到此,微信下载对账单功能就实现了

代码写的不好之处,请大家多多包涵并提出宝贵意见  937017870@qq.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值