因为项目需求,加入这2个功能记录一些须要注意的地方java
一.微信支付android
微信支付在2016年4月份左右稍微调整了一下支付过程,可是文档却没怎么更新,这也是百度上为何那么多开发者都说微信是个大坑. 身为一个大型互联网公司,作的事却没法让人理解.express
相比之下,支付宝就好太多了.json
微信支付须要注意地方:api
1.要先申请 "商家端"帐户, 须要提交公司信息, 我的很差申请的. 申请成功后,须要去 建立一个应用服务器
建立应用须要 注意2个地方 微信
1>包名, 若是是Android studio开发 ,这个包名要用以下图所示位置的包名, 而不是 androidmanifest.xml中的,由于他俩可能不同,要如下图为准,固然若是是eclipse开发那就以androidmanifest.xml里面的包名为准了.网络
2>签名, 这个签名不能用 debug.keystore(Eclipse的签名后缀是.keystore), 或者 debug.jks(Androidstudio把后缀名换了), 要用本身建立的的签名文件,好比 shop.jsk , shop.keystore去生成签名,或者选择之前本身建立好的,都行,只有不是debug的就行.app
android studio生成签名截图以下: 点击Teminal 启动后,输入图中命令,后面是你jks所在位置. 以后回车 输入密码, 获得MD5值, 它就是微信建立应用时用到的签名,须要去掉冒号,把大写所有改为小写便可. 固然微信还给咱们提供了签名工具apk, 你能够把本身的工程打包后,安装到手机,而后启动微信的签名apk,输入包名便可获得签名, 你能够拿它对比一下用命令行获得的签名是否一致, 若是不一致那就说明一个问题 " 你的应用没有通过打包" , 不要经过编译工具直接部署 到手机,这样获得的签名是不对的. 必定要是打包后的.eclipse
当测试微信的时候,也须要把打包后的apk安装到手机才能测试支付,若是只能调起一次微信,第二次没法调起,那就是签名或者 appid这一块有问题,检查一下. 不过我发现IOS不存在这个问题, 每次都能调起微信.
二.下面说下微信在工程中建立须要注意地方:
1. 若是你的包名是com.xxx.text 那么你须要在test以后建立一个包名 com.xxx.text.wxapi, 必须是wxapi,不能错了. 而后必须拷贝一个类过来:WXPayEntryActivity.java ,这个类的做用是微信支付后,接收微信的支付结果的. 你能够不作任何修改,直接拿来用就行,固然若是你想更改里面的布局,也是彻底OK的, 我对他作了一下修改,代码以下, 我修改了2个地方,代码中给出了注释
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler{ private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity"; private IWXAPI api; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //1.第一个修改的地方 我删掉了,它自带的 布局, 固然若是你想保留,彻底OK.由于布局太难看因此我干掉他了 api = WXAPIFactory.createWXAPI(this, Constants.APP_ID); api.handleIntent(getIntent(), this); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); api.handleIntent(intent, this); } @Override public void onReq(BaseReq req) {} @Override public void onResp(BaseResp resp) { //2.这是我修改的第二个地方, 原版的是弹出一个对话框, 我以为太丑,而且原版也没有给出详细问题提示,只给出了 0, -1 ,-2 这样会让客户不明因此,因此我替换成以下3个文本. 此外 //原版支付后,不会直接跳转到 你的应用,须要按一次 返回键,才行, 因此我加入了finish()便于在提示后,直接返回个人应用 if(resp.errCode==0){ Toast.makeText(this,"支付成功!",Toast.LENGTH_SHORT).show(); }else if(resp.errCode==-1){ Toast.makeText(this,"支付失败!",Toast.LENGTH_SHORT).show(); }else if(resp.errCode==-2){ Toast.makeText(this,"取消支付!",Toast.LENGTH_SHORT).show(); } finish(); } }
2. androidmainfest.xml 的配置,直接上代码,这里只须要注意一个地方那就是 appid
<activity android:name=".wxapi.WXPayEntryActivity" android:label="@string/app_name" android:exported="true" //必须为true android:launchMode="singleTop"> //必须单例 </activity> <receiver android:name=".wxapi.AppRegister"> <intent-filter> <action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_REFRESH_WXAPP" /> </intent-filter> </receiver>
<activity android:name=".ui.PayActivity" //这是我本身定义的支付Activity, 本身修更名字便可 android:exported="true" android:launchMode="singleTop" > <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="wxbdc42b2a35e9884e"/> //这里就是 APPID ,必须和你申请的 应用的 appid保持一致 .不然没法支付,注意,注意,注意 </intent-filter> </activity>
3.下面是我项目中的支付代码, 先说下支付流程, 首先你要 让负责接口的,给你一个接口, 这个接口 须要app端传递 商品的基本信息过去,好比 商品名字 , 描述,订单号 ,价格等等.也不须要传递太多东西, 我就传递了 以上我列举的4个 ,有人会问 "微信不是帮咱们生成了一个 订单号吗?" 我干吗还要传递给他, 我传递的这个订单号,是用于退款使用的. 因此我要传递一个, 这个订单号,在我 下单的同时, 会生成一个随机数, 固然这都是 后台 接口弄得,你只须要拿来使用就好了.
说的有点乱了,给个步骤吧
1>传递商品信息给咱们本身的后台
2>咱们本身的后台会拿着这些商品信息 而后加上 + 商户号id+商户秘钥 (申请商家端时获取的), 给咱们app端返回一个json,该json中包含7个字段,须要解析,后面给出代码
3>咱们解析后, 经过 api.sendReq(req); 调用微信支付
代码以下:
float total3 = orderTotalPrice * 100; //注意微信支付付款 是按照分为单位的,须要把商品价格 乘以100 ,而后强转为 int类型 ,这里(int)total3
param ="?ordertype="+"old"+"&sworkOrderCode="+out_trade_no+"&serviceFee=" +(int)total3+"&serviceItem="+orderItem.orderName.trim()+"&serviceClass="+orderItem.serviceItem.trim();
testWxPay(v);//开始解析接口给咱们返回的json
参数:old 是,一个版本区分,由于公司的多个app都用到了微信支付,而且他们都有关联,因此你能够直接无视该参数,该参数仅用于我本身的项目
参数:out_trade_no 是我从咱们的接口获取到的随机订单号
参数:(int)total3 是商品价格, "分" 为单位,必须转为 整形, 也不知道 int会不会越界,反正我用了int,你可用long
参数:serviceItem 商品名字
参数:serviceClass商品描述
public void testWxPay(View view) { new Thread(new Runnable() { @Override public void run() { String url = HttpUrl.host1+"WeiXinApi.asmx/CreatePrePay_id"+param; Log.e("xxx",url); ToastUtil.shortToastInBackgroundThread(getActivity(), "获取订单中..."); try { byte[] buf = Util.httpGet(url); if (buf != null && buf.length > 0) { String content = new String(buf); Log.e("get server pay params", content); JSONObject json = new JSONObject(content); if (null != json && !json.has("retcode")) { req = new PayReq(); req.appId = json.getString("appid"); //appid req.partnerId = json.getString("partnerid"); //商户号 req.prepayId = json.getString("prepayid"); //预支付交易会话id req.nonceStr = json.getString("noncestr"); //随机字符串,不超过32位 req.timeStamp = json.getString("timestamp");//时间戳 req.packageValue = json.getString("package");//扩展字段 req.sign = json.getString("sign");//签名信息MD5加密后的 ToastUtil.shortToastInBackgroundThread(getActivity(), "正常调起支付"); toPay(); } else { Log.d("PAY_GET", "返回错误" + json.getString("retmsg")); ToastUtil.shortToastInBackgroundThread(getActivity(), "返回错误" + json.getString("retmsg")); } } else { Log.d("PAY_GET", "服务器请求错误"); ToastUtil.shortToastInBackgroundThread(getActivity(), "服务器请求错误"); } } catch (Exception e) { Log.e("PAY_GET", "异常:" + e.getMessage()); ToastUtil.shortToastInBackgroundThread(getActivity(), "异常:" + e.getMessage()); } } }).start();} private void toPay() { // 在支付以前,若是应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信 api.registerApp(Constants.APP_ID); api.sendReq(req); Log.e("跳转结果--",api.sendReq(req)+""); } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); toPay(); } };
整个支付代码很是少,一共就这么多. 须要注意的一点是, 解析的 7个 参数中, sign 是咱们本身服务端 二次加密获得的,这里容易出错, 固然我说的是接口里面容易出错,和咱们app端没有半毛钱关系, 由于这个 加密,老版本微信是咱们 app端生成的, 新版的 是由接口生成的,咱们直接拿来用.
sign 生成过程是: 前6个参数+ 商家秘钥 通过MD5加密就获得了. (这个加密用的前6个参数,须要安装字母排序,不能乱用,商家秘钥不需排序放到最后便可,固然这都是接口的须要完成的,咱们app端 了解便可)
若是这个sign 接口没有弄好, 极容易出错,没法调起支付页. 我在作的时候,就是由于接口的生成sign时,少写一个 = 链接符形成的.
------------------------------------------------------------------------------------------------------------------------------------------
三.支付宝支付
支付宝支付相对来讲要简单的多了, 比较稳定写得清晰明了,一看即懂. 直接上代码吧 ,我去网络太卡了,刚才写了半天,图片没法加载,把我写得从新毁了,先保存吧,等会再上支付宝的.
流程以下:
1.申请帐号,一样须要提交一些公司资料
2.下载须要资源,sdk ,文档什么的, 而后去配置工程
1>在工程中建立一个包存放支付宝所需资源,好比个人
导入alipaySdk-20160427.jar , 目前最新版.
2>androidmainfest.xml中的配置
<!--支付宝--> <activity android:name="com.alipay.sdk.app.H5PayActivity" //H5页面, 若是手机没有安装支付宝,调起这个 android:configChanges="orientation|keyboardHidden|navigation" android:exported="false" android:screenOrientation="behind" > </activity> <activity android:name="com.alipay.sdk.auth.AuthActivity" android:configChanges="orientation|keyboardHidden|navigation" android:exported="false" android:screenOrientation="behind" > </activity>
权限信息
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
3.获取私钥, 公钥
命令以下:
RSA密钥生成命令
生成RSA私钥
openssl>genrsa -out rsa_private_key.pem 1024
生成RSA公钥
openssl>rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
将RSA私钥转换成PKCS8格式
openssl>pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
命令使用的工具在 这里: E:\支付宝钱包支付接口开发包2.0标准版(20160428)\DEMO\openssl\bin --> openssl.exe
双击启动,截图以下: 而后输入上面命令,就能够获得了.最后会生成相应的文件,可是后缀好像不是txt,你改为txt就能看了.具体过程文档说的很清楚,我也记不太清了,作了1周就忘记了,这记性 ...
打开红框框中的2个文件,里面就用公钥和私钥信息了, 注意红色部分不能要,只要中间的, 你最好把中间部分回车去掉,改为1行,否则可能会由于回车形成出错
配置貌似也就这么多了吧. 比较少,文档也很清楚.
4.下面给出代码吧,截图了后面数据不能泄露了,公司的信息
此处点击 : "支付宝"支付这个 线性布局,执行支付功能
rlZfb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { pay(v); } });
/** * call alipay sdk pay. 调用SDK支付 */ public void pay(View v) { if (TextUtils.isEmpty(PARTNER) || TextUtils.isEmpty(RSA_PRIVATE) || TextUtils.isEmpty(SELLER)) { new AlertDialog.Builder(this).setTitle("警告").setMessage("须要配置PARTNER | RSA_PRIVATE| SELLER") .setPositiveButton("肯定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialoginterface, int i) { // finish(); } }).show(); return; } //获得订单信息 String orderInfo = null; //待支付列表item对象 orderInfo = getOrderInfo(orderItem.getServiceCode(), orderTotalPrice); String sign = sign(orderInfo); try { /** * 仅需对sign 作URL编码 */ 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(getActivity()); // 调用支付接口,获取支付结果 String result = alipay.pay(payInfo, true); Message msg = new Message(); msg.what = SDK_PAY_FLAG; msg.obj = result; mHandler.sendMessage(msg); } }; // 必须异步调用 Thread payThread = new Thread(payRunnable); payThread.start(); }
/** * create the order info. 建立订单信息 * subject 商品名字 */ private String getOrderInfo(String subject, float price) { // 签约合做者身份ID String orderInfo = "partner=" + "\"" + PARTNER + "\""; // 签约卖家支付宝帐号 orderInfo += "&seller_id=" + "\"" + SELLER + "\""; // 商户网站惟一订单号 //orderInfo += "&out_trade_no=" + "\"" + getOutTradeNo() + "\""; orderInfo += "&out_trade_no=" + "\"" + out_trade_no + "\""; // 商品名称 orderInfo += "&subject=" + "\"" + subject + "\""; // 商品详情 //orderInfo += "&body=" + "\"" + body + "\""; // 商品金额 orderInfo += "&total_fee=" + "\"" + price + "\""; // 服务器异步通知页面路径 --- 调用服务端地址 //orderInfo += "¬ify_url=" + "\"" + "http://notify.msp.hk/notify.htm" + "\""; //ToastUtils.show(getActivity(),subject+price); Log.e("xxxx", subject + price); orderInfo += "¬ify_url=" + "\"" + "http://xxx.xxx.xxx/HomeWorkOrder.asmx/WorkOrderPayed" + "\"";//此处是接口端给的一个 地址,找他们要吧.... // 服务接口名称, 固定值 orderInfo += "&service=\"mobile.securitypay.pay\""; // 支付类型, 固定值 orderInfo += "&payment_type=\"1\""; // 参数编码, 固定值 orderInfo += "&_input_charset=\"utf-8\""; // 设置未付款交易的超时时间 // 默认30分钟,一旦超时,该笔交易就会自动被关闭。 // 取值范围:1m~15d。 // m-分钟,h-小时,d-天,1c-当天(不管交易什么时候建立,都在0点关闭)。 // 该参数数值不接受小数点,如1.5h,可转换为90m。 orderInfo += "&it_b_pay=\"30m\""; // extern_token为通过快登受权获取到的alipay_open_id,带上此参数用户将使用受权的帐户进行支付 // orderInfo += "&extern_token=" + "\"" + extern_token + "\""; // 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空 orderInfo += "&return_url=\"m.alipay.com\""; // 调用银行卡支付,需配置此参数,参与签名, 固定值 (须要签约《无线银行卡快捷支付》才能使用) // orderInfo += "&paymethod=\"expressGateway\""; return orderInfo; }
大多数都是支付宝代码,贴着也没意思, 只不过修改了订单信息而已. 后面的再也不贴了. demo和文档已经很是清楚了. 支付宝退款很简单,只须要发送订单号给咱们本身的接口便可,其余的由接口去实现.
以上就是全部代码了.写得很差 ,勿喷!!