这一段时间项目需要加上微信支付和支付宝支付,经过一段时间摸索,总算能够正常进行支付使用了。想想在支付上遇到的坑,我觉得有必要进行一个记录,在后续的开发中避开支付中遇到的坑:
一、支付宝支付:
ps:支付宝支付是坑较少的地方,从它开说。
(1)准备工作:支付宝商户平台申请帐号,获取商户PID,设置收款账号,这一点与其他第三方的控件不同之处在于不需要申请注册App,相对来说比较方便。获取PID和收款账号后就是私匙和公钥的设置,私匙和公钥在开发端生成,windows下通过openssl工具进行安装生成。官网示例网址:https://doc.open.alipay.com/doc2/detail.htm?treeId=58&articleId=103242&docType=1,公钥上传支付宝网关即可。
私匙和公钥生成命令:Windows用户在cmd窗口中进行以下操作:
C:\Users\Hammer>cd C:\OpenSSL-Win32\bin
进入OpenSSL安装目录
C:\OpenSSL-Win32\bin>openssl.exe
进入OpenSSL程序
OpenSSL> genrsa -out rsa_private_key.pem 1024
生成私钥
OpenSSL> pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
Java开发者需要将私钥转换成PKCS8格式
OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
生成公钥
OpenSSL> exit ##
退出OpenSSL程序
(2)签名:开始项目时后台没有完善,签名在前端。步骤:
1、导入jar包alipaySdk-20160223.jar。
2、SignUtils.sign(info, Constants.RSA_PRIVATE)签名工具进行签名,后一个参数为私匙。前一个参数为按照支付宝需求生成的字符串getOrderInfo(subject, body, total_fee)。核心代码:try {
sign = URLEncoder.encode(sign, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
/**
* 完整的符合支付宝参数规范的订单信息
*/
final String payInfo = orderInfo + "&sign=\"" + sign + "\"&" + getSignType();
Runnable payRunnable = new Runnable() {
@Override
public void run() {
// 构造PayTask 对象
PayTask alipay = new PayTask(PayActivity.this);
// 调用支付接口,获取支付结果
String result = alipay.pay(payInfo, true);
Message msg = new Message();
msg.what = Constants.SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
}
};
// 必须异步调用
Thread payThread = new Thread(payRunnable);
payThread.start();
mHandler中对结果进行处理,对支付宝的调用,是比较顺利的。这几步基本没有遇到问题。但是遇到的坑在将签名放到后台时坑一堆堆的。因为只是包签名放在后台,前台拼接字符串。这时候就出现问题了,一直包ALI164的错,跟后台对接纠结了半天,最后排查的原因在于拼接的字符串与后台用于签名的字符串参数不一致,这地方纯属自己挖坑,早知道这样,直接让后台将String payInfo = orderInfo + "&sign=\"" + sign + "\"&" + getSignType();拼接好返回,啥事都没有。但是总算是解决了,支付宝还有一个问题,在调试的时候付款0.001,这样回报ALI59的错。原因在于金额太小,貌似一定要0.01以上,也小坑了我一把。支付宝就这些。完事。
二、微信支付
微信支付整了整整半个月,当然主要时间是申请上的那堆破事。微信在这方面确实婆婆妈妈的有的一比,客户开始申请的是公众号支付,等发现这个问题回过神来申请开发平台app支付,已经逝者如斯乎,不舍昼夜了。app支付中有一个签名。必须得用正式打包生成的签名。否则。。。。app申请经过三天时间,之后。。。才发现微信支付是需要单独提出来申请的。。。然后,就没有然后了,最好找财务的去申请吧,一堆子的财务上的问题,磨蹭了一个多星期,总算将申请的东西申请好。插一句:貌似微信支付申请的时候对浏览器有需求,我的上帝客户申请的时候总是打不开申请界面,我这边倒是一切顺利。申请审核完事了。这时候有一个API_KEY需要自己设置,在微信支付申请好后会有一个邮件,邮件包含了一个微信商户平台的登陆帐号密码,微信就是这么罗嗦。--》打开微信商户平台,登陆,找到API设置,下载一个证书,证书的下面有一个API帐号设置,需要32位,只要是数字加字母就ok,随便百度一下32位密匙生成,填上去了事。至此:获取到了微信app支付的所有信息,这一段太长了点,第一次写博客,冒得经验。
准备的信息:APPID,APPSECRECT,API_KEY,貌似就这些,有点记不清了,
准备工作就绪,开始正文:
(1)、导包/yuanju/libs/libammsdk.jar。
(2)、在配置文件需要调用微信支付的activity加上<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="APP_ID"/>
</intent-filter>.不过百度有大牛说可以不要,没试过。我是加了。
(3)、关键代码:IWXAPI api= WXAPIFactory.createWXAPI(this, null);PS:通过WXAPIFactory工厂,获取IWXAPI的实例
api.registerApp(APP_ID);PS:注册app到微信
if (api.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT) {
PayReq req = new PayReq();
req.appId = we.appid;// appId
req.partnerId = we.mch_id;// 微信支付分配的商户号
req.prepayId = we.prepayid;// 微信返回的支付交易会话ID
req.packageValue = "Sign=WXPay";// 暂填写固定值Sign=WXPay
req.nonceStr = we.noncestr;// 随机字符串,不长于32位。推荐随机数生成算法
req.timeStamp = we.timestamp;// 时间戳,请见接口规则-参数规定
req.sign = we.sign;// 签名,详见签名生成算法
boolean ee = api.registerApp(Constants.APP_ID);
boolean yy = api.sendReq(req);
Log.i("OUT", ee + "==微信调启动信息===" + yy);
} else {
show.show("您的微信版本太低,不支持微信支付");
}
这地方懒人懒办法,一切信息都从后台获取。就是这样,坑来了。跟后台扯了三天的皮。。。因为调动不了微信支付,一启动直接进入支付结果的界面了。ps:微信支付这个设置让人不愉快,有个叫做WXPayEntryActivity的类接收支付结果信息,0成功,-1失败,-2取消。这破玩意必须在包名加.wxapi的包下经过配置文件配置才能工作,让人很不愉快,不说。。。
下面还是说说微信支付的这个坑:
首先是API_KEY的获取,必须在商户平台下自己设置,也就算了,毕竟能够获取到。
第二个:就是这个签名,后台php百度找到的东西一堆坑,没几个好用的,经过几天对接,对后台的签名大概也了解一点点了,后台签名有两次,第一次通过微信服务器进行的签名,再然后,在后台自己再一次签名,PS:后台代码没得,大致是这样。将第二次签名返回。
建议:将那个啥子时间戳啊,随即字符串啊,连带着会话ID和签名一起返回吧。其他的商户号跟Appid倒无所谓。req.packageValue = "Sign=WXPay"固定的也无所谓,其实没么子坑,微信支付的问题百分之九十是后台签名的坑。调到坑里出得来出不来看天气了。
最后,测试微信支付一定用正式打包的APK.不然,我是用测试的包测试了N遍,自己坑自己还以为代码有问题。。。。