项目中需要使用到微信刷卡支付的功能。所以就去微信开发平台看了看官方文档。
去微信开放平台注册应用什么就不多说了,网上大把的。
以下三个是从开放平台获取的。
appid,公众号id
mch_id,商户id
key, 秘钥
根据开发文档得出只需要传递以下必须的参数即可:
appid,公众号id
mch_id,商户id
nonce_str, 随机字符串
sign, 签名
body, 商品简单描述
out_trade_no, 商户订单号(不可重复,32个字符以内)
total_fee, 金额(单位:分)
spbill_create_ip, 机器ip
auth_code, 付款码
- 提交刷卡支付是不需要用到证书的。
但使用官方Demo是必须使用证书的。这让我感到很蛋疼。
为此我纠结了好久,但我还是试了试,在我把所有的数据都填进去之后运行, 报错了。是从来没碰到过的错误,有关ssl的。 代码和错误如下。
WXPay.initSDKConfiguration("秘钥","appid","商户id","子商户id","证书路径","证书密码");
ScanPayReqData scanPayReqData = new ScanPayReqData("支付授权号码","商品描述信息",
"附加数据","商品订单号",1,"扫码支付终端设备号","机器ip","订单生成时间",
"订单失效时间","优惠满减使用");
WXPay.requestScanPayService(scanPayReqData);
我在网上找了好久也没找到问题的关键所在。所以我放弃了。
没办法,就自己定义参数直接访问网络请求支付。
布局一个edittext,一个button,edittext为了输入付款码。
拼接字符串和生成签名如下:
private String buildProductArgs(String tradeNo, String desp, String number, int amount) {
List<TwoTuple<String, String>> paramList = new ArrayList<>();
paramList.add(new TwoTuple<>("appid", Constants.WX_APP_ID));//填入自己的appid
paramList.add(new TwoTuple<>("auth_code", number));
paramList.add(new TwoTuple<>("body", desp));
paramList.add(new TwoTuple<>("mch_id", Constants.WX_PARTNER_ID));//商户id
paramList.add(new TwoTuple<>("nonce_str", UUID.randomUUID().toString().replace("-", "")));
paramList.add(new TwoTuple<>("out_trade_no", tradeNo));
paramList.add(new TwoTuple<>("spbill_create_ip", "127.0.0.1"));
paramList.add(new TwoTuple<>("total_fee", amount+""));
//获取MD5签名并追加到参数列表中
String sign = generateWechatMD5Signature(paramList);
paramList.add(new TwoTuple<>("sign", sign));
// 构建XML参数
StringBuilder xmlBuilder = new StringBuilder();
xmlBuilder.append("<xml>").append("\n");
for (TwoTuple<String, String> paramTuple : paramList) {
xmlBuilder.append("<").append(paramTuple.first).append(">");
// xmlBuilder.append("<![CDATA["+paramTuple.second+"]]>");
xmlBuilder.append(paramTuple.second);
xmlBuilder.append("</").append(paramTuple.first).append(">").append("\n");
}
xmlBuilder.append("</xml>").append("\n");
return xmlBuilder.toString();
}
// 根据参数列表生成MD5签名
private String generateWechatMD5Signature(List<TwoTuple<String, String>> paramList) {
StringBuilder sb = new StringBuilder();
for (TwoTuple<String, String> paramTuple : paramList) {
sb.append(paramTuple.first);
sb.append('=');
sb.append(paramTuple.second);
sb.append('&');
}
sb.append("key=").append(Constants.WX_SECURITY_KEY);//key 秘钥
return MD5.MD5Encode(sb.toString()).toUpperCase();
}
还有个java类
public class TwoTuple<A, B> {
public final A first;
public final B second;
public TwoTuple(A a, B b) {
first = a;
second = b;
}
/**
* 创建一个二元组, 用所给参数初始化
* @param a 第一个参数
* @param b 第二个参数
* @param <A> 第一个参数的类型
* @param <B> 第二参数的类型
* @return 包含所给参数的二元组
*/
public static <A, B> TwoTuple<A, B> tuple(A a, B b) {
return new TwoTuple<>(a, b);
}
}
- 调用buildProductArgs方法传入订单号,商品描述,付款码,金额生成xml字符串。
xmlParam = buildProductArgs("20160817101811", "支付测试", trim, 1);
然后我使用Volley,okHttp,xUtils使用post请求该接口:
https://api.mch.weixin.qq.com/pay/micropay
得到同样的结果。
这个我试了不下20多次,真想说一句,日了狗了。完全看不出xml哪里有问题。
后来我又试着加上了CDATA标签,依然没什么用。
因为看了这个我才加的。
然后我又查了xml转义,xml中< 和 > 要用< 和 >表示。
我把它替换之后发现并没有什么用,还是报之前的错误。
真是对着文档无语了,没啥用你写在那误导人。
最后用HttpURLConnection试试,代码如下:
public static String getPostData(String strUrl,String data){
String result = "";
HttpURLConnection connection = null;
OutputStreamWriter osw = null;
try{
URL url = new URL(strUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("User-Agent","Mozilla/4.0 (compatiable; MSIE 6.0; Windows Nt 5.0)");
connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
connection.connect();
osw = new OutputStreamWriter(connection.getOutputStream(),"UTF-8");
osw.write(data);
osw.flush();
osw.close();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuffer sb = new StringBuffer();
String s;
while ((s = in.readLine()) != null){
sb.append(s).append("\n");
}
in.close();
result = sb.toString();
}catch (Exception e){
e.printStackTrace();
}
return result;
}
在按钮事件中调用该方法。
new Thread(new Runnable() {
@Override
public void run() {
String postData = getPostData("https://api.mch.weixin.qq.com/pay/micropay", xmlParam);
Log.e("errorerror",postData);
}
}).start();
然后运行程序,随便输入数字,哎呀,log如下:
好像可以了,但是为什么呢,其实我也不知道。无限懵逼中...
我打开自己的微信,将付款码输入进去。微信给我弹出页面说我的钱没了。我是该哭还是该笑呢。咯咯咯...
支付结果需要查看result_code。解析返回值这里就不多说了。