最近项目里面需要支付功能,boss一致决定用微信支付,所以在网上查了很多资料,说的不全,完了就找以前的同事指教。算是成功集成上去了。在这里做个总结记录。

1、在APP上集成微信支付,首先当然是当官网上去注册并获取到支付功能。这些不涉及到开发,官网上说的很详细,这里就不多做文章。获取到这些能力了就为开发提供了条件了。开发中会用到的就是平台给的APPID、APPsercet、以及商户平台上设置的APP_key。

2、具备了支付能力等前提条件之后,就是开发过程了。代码里面怎么才能吊起支付了,参照官网上的DEMO自己也做了一些总结和各方大神的指教。分为了下面几个步奏。

(1)、首先当然是将sdk配置进工程环境中,官网中下载Android端SDK,解压后将libmmsdk.jar导入工程,然后将DEMO中Constant.java(这里是参照官方demo的样式写的,当然也可以采用其他方式)、MD5.java、Util.java放入工程(我这里用到了这些),这些先决条件有了之后就可以下一步写代码操作了。

(2)、生成订单信息

生成订单信息采用了如下方法生成,生成订单信息需要签名文件,所以里面包含了生成签名。微信要求所有请求采用XML参数形式,所有生产订单信息之后又需要转换成xml。订单信息需要的请求参数可以到官网上去对照,这里只加入了一些必要的参数。

生成订单信息方法:

//获取产品订单信息private String genProductArgs() {StringBuffer xml = new StringBuffer();try {String nonceStr = genNonceStr();xml.append("</xml>");List<NameValuePair> packageParams = new LinkedList<NameValuePair>();packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID)); //APPIDpackageParams.add(new BasicNameValuePair("body", "单价:" + singlePrice + " x " + payment_num.getText().toString() + "份"));  //简单描述packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));  //商户IDpackageParams.add(new BasicNameValuePair("nonce_str", nonceStr));   //随机字符串packageParams.add(new BasicNameValuePair("notify_url","http://www.weixin.qq.com/wxpay/pay.php")); //通知地址packageParams.add(new BasicNameValuePair("out_trade_no",getTrade()));  //商户订单号packageParams.add(new BasicNameValuePair("spbill_create_ip",getLocalHostIp())); //终端IP//double price = Double.parseDouble(payment_num.getText().toString()) * (Integer.parseInt(singlePrice) * 100);double price = Double.parseDouble(singlePrice) * 100 * n;int priceInt = (int) price;packageParams.add(new BasicNameValuePair("total_fee", priceInt+""));    //微信接收int型价格packageParams.add(new BasicNameValuePair("trade_type", "APP"));  //支付类型String sign = genAppSign(packageParams);packageParams.add(new BasicNameValuePair("sign", sign));  //签名String xmlstring = parseNodeToXML(packageParams);   //转化成xmlreturn xmlstring;} catch (Exception e) {e.printStackTrace();return null;}}

构造这个xml请求参数采用的是httpclient生成的,所以引入了某些包。也可以采用其他方式生成支付订单,只要最后的形式与官网中的形式相同即可。

里面涉及到某些参数的生成,这里列出的是我们项目里面的业务逻辑,当然不同项目可定是不同的。

//获取订单号private String getTrade(){long nowTime = System.currentTimeMillis();SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss");return format.format(new Date(nowTime));}//获取支付签名SignStringBuilder sb = new StringBuilder();private String genAppSign(List<NameValuePair> params) {StringBuilder sb = new StringBuilder();for (int i = 0; i < params.size(); i++) {sb.append(params.get(i).getName());sb.append('=');sb.append(params.get(i).getValue());sb.append('&');}sb.append("key=");sb.append(Constants.API_KEY);this.sb.append("sign str\n" + sb.toString() + "\n\n");String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();return appSign;}//获取随机字符串private String genNonceStr() {Random random = new Random();return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());}/*** 解析为xml格式* @param treeNodes* @return*/public String parseNodeToXML(List<NameValuePair> treeNodes) {StringBuffer xmlnodes = new StringBuffer();if (treeNodes != null && treeNodes.size() > 0) {xmlnodes.append("<xml>");for (int i = 0; i < treeNodes.size(); i++) {NameValuePair node = treeNodes.get(i);xmlnodes.append("<"+node.getName()+">").append(node.getValue()).append("</"+node.getName()+">");}xmlnodes.append("</xml>");}//return xmlnodes.toString();String xml = xmlnodes.toString();try {xml = new String(xml.toString().getBytes(), "ISO8859-1");  //商品详情为中文,将其转化为统一编码,不然获取perpred_id失败return xml;} catch (UnsupportedEncodingException e) {e.printStackTrace();return null;}}//获取手机IPpublic String getLocalHostIp() {String ipaddress = "";try {Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();// 遍历所用的网络接口while (en.hasMoreElements()) {NetworkInterface nif = en.nextElement();// 得到每一个网络接口绑定的所有ipEnumeration<InetAddress> inet = nif.getInetAddresses();// 遍历每一个接口绑定的所有ipwhile (inet.hasMoreElements()) {InetAddress ip = inet.nextElement();if (!ip.isLoopbackAddress() && InetAddressUtils.isIPv4Address(ip.getHostAddress())) {return ip.getHostAddress();}}}}catch (SocketException e) {Log.e("feige", "获取本地ip地址失败");e.printStackTrace();}return ipaddress;}

(3)、访问微信后台指定接口,获取perpay_id。

可以说前面的都是为了获取这个perpay_id做准备的,官网上给出的指定接口是“https://api.mch.weixin.qq.com/pay/unifiedorder” 请求采用官网demo中util提供的请求方式

这里采用异步处理方式,当请求指定接口得到perapy_id之后直接吊起支付的方式。

//调用支付获取idpublic void gotoWechat() {new AsyncTask() {@Overrideprotected Object doInBackground(Object[] objects) {   //获取Prepay_idString url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");String entity = genProductArgs();   //获取订单信息byte[] buf = Util.httpPost(url, entity);String content = new String(buf);  //请求成功返回的信息//Log.e("orion", content);try {xmlParseTest(content);  //解析返回的信息} catch (IOException e) {e.printStackTrace();} catch (XmlPullParserException e) {e.printStackTrace();}return null;}@Overrideprotected void onPostExecute(Object o) {super.onPostExecute(o);wechatPay();}}.execute();}

请求成功返回的数据当然也是xml格式的,需要解析并从中取到perpay_id(返回的结果不止perpay_id,包括其他信息,个人感觉吊起支付只需要perpay_id就行了)。这里也是参考demo中的方式将获取到的信息通过xml解析到

WeixinParentId对象当中。

/*** 解析xml* 返回prepay_id* 通过对象Books获取数据*/WeixinParentId book = null;                //通过对象Books获取数据public void xmlParseTest(String str) throws IOException, XmlPullParserException {XmlPullParser pullParser = Xml.newPullParser();            //获取XmlPullParser对象//InputStream is = getContext().getAssets().open("parse.xml");   //解析文本ByteArrayInputStream is = new ByteArrayInputStream(str.getBytes("UTF-8"));ArrayList<WeixinParentId> books = null ;pullParser.setInput(is, "UTF-8");int type = pullParser.getEventType();    //获取事件类型while (type != pullParser.END_DOCUMENT) {   //结束文本</books>switch(type){case XmlPullParser.START_DOCUMENT:    //开始文本<books>books = new ArrayList<WeixinParentId>();break;case XmlPullParser.START_TAG:    //开始标记   <book>if (pullParser.getName().equals("xml")) {book = new WeixinParentId();}else if (pullParser.getName().equals("return_msg")) {type = pullParser.next();    //指向下一个位置,不然无法获取数据book.setReturn_msg(pullParser.getText());}else if (pullParser.getName().equals("appid")) {type = pullParser.next();book.setAppid(pullParser.getText());}else if (pullParser.getName().equals("prepay_id")) {type = pullParser.next();book.setPrepay_id(pullParser.getText());}break;case XmlPullParser.END_TAG:   //结束标记      </books>if (pullParser.getName().equals("book")) {books.add(book);book = null;    //置为空释放资源}break;}type = pullParser.next();    //指向下一个标记}//Log.e("test", "book------id----" + book.getPrepay_id());}
成功执行这不之后,book对象中perpay_id已经被赋值。只需在异步中取出使用即可。

//获取到perpay_id之后吊起微信支付protected void wechatPay() {PayReq req = new PayReq();req.appId = Constants.APP_ID;req.partnerId = Constants.MCH_ID;req.prepayId = book.getPrepay_id();req.packageValue = "Sign=WXPay";req.nonceStr = genNonceStr();req.timeStamp = String.valueOf(genTimeStamp());List<NameValuePair> signParams = new LinkedList<NameValuePair>();signParams.add(new BasicNameValuePair("appid", req.appId));signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));signParams.add(new BasicNameValuePair("package", req.packageValue));signParams.add(new BasicNameValuePair("partnerid", req.partnerId));signParams.add(new BasicNameValuePair("prepayid", req.prepayId));signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));req.sign = genAppSign(signParams);sb.append("sign\n" + req.sign + "\n\n");// 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信//Log.e("test","book.getPrepay_id()----------"+book.getPrepay_id()+"-------genNonceStr()-------"+genNonceStr()+"--------genTimeStamp()-------"+genTimeStamp()+"---genAppSign(signParams)--"+genAppSign(signParams));api.sendReq(req);// dialog.dismiss();}//获取时间搓private long genTimeStamp() {return System.currentTimeMillis() / 1000;}
把前面的异步操作方法赋给一个按钮点击事件,如果所有步奏正确,就可以进入支付界面了,如下图:


点击确支付当然就是输入密码什么的操作了,支付成功后有一个反馈信息如下图:



点击完成,当然是回到APP咯,这里就是微信提供的一个回调了。也就是官网上强调的wxapi包下的
WXPayEntryActivity里的Onresp()方法中做回调处理,该包必须在项目工程包目录下才能回调成功。下面贴出的是示例工程结构



在回调中弹出了对话框提示用户支付成功并处理其他逻辑。

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);//        setContentView(R.layout.activity_main2);api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);api.handleIntent(getIntent(), this);api.registerApp(Constants.APP_ID);}@Overrideprotected void onNewIntent(Intent intent) {super.onNewIntent(intent);setIntent(intent);api.handleIntent(intent, this);}@Overridepublic void onReq(BaseReq req) {}@Overridepublic void onResp(BaseResp resp) {int errCode = resp.errCode;if (errCode == 0) {// 0成功 展示成功页面// Intent intent = new Intent("name");// sendBroadcast(intent);// Log.e("test","支付成功的回调方法--onResp--");// Toast.makeText(this,"支付完成",Toast.LENGTH_SHORT).show();new AlertDialog.Builder(this).setMessage("支付成功").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();finish();PaymentActivity.instance.finish();Intent intent = new Intent(WXPayEntryActivity.this, PuzzGameActivity.class);intent.putExtra("ISPLAY",true);startActivity(intent);}}).setTitle("提示").create().show();Toast.makeText(this,"点击确定按钮开始参与拼图游戏活动",Toast.LENGTH_LONG).show();}else if (errCode == -1) {//-1 错误 可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。new AlertDialog.Builder(this).setMessage("支付出错").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();finish();}}).setTitle("提示").create().show();finish();}else if (errCode == -2) {//-2 用户取消 无需处理。发生场景:用户不支付了,点击取消,返回APP。finish();}}}

这样所有步骤就几乎完全了,结合官方示例和文档,应该可以快速的在项目中加入支付功能了。

当然,这里所涉及到的步骤全是在app客户端进行的,官网上建议将获取签名等操作放在服务后台进行,应该是为了安全吧,也就是客服端将订单信息传给服务端。服务端返回吊起支付必要的信息

(包括perpay_id、商户id 、签名等),然后由客户端吊起微信支付的。

androidAPP 集成微信支付相关推荐

  1. Android集成微信支付之-天坑

    项目集成微信支付,折腾了三天左右,坑太多,做个简单记录 开通和主要原理不再讲了,参考微信支付官网 截个官网的业务流程图,下面好说明 1 支付结果回调(图中的17步) 支付结果回调,微信官方的说法是: ...

  2. SpringBoot集成微信支付V3

    河南循中网络科技有限公司 - 精心创作,详细分解,按照步骤,均可成功! 文章目录 吐槽! 此文章包含实现了哪些接口? 学习资料 集成微信支付V3 什么是"商户证书"?什么是&quo ...

  3. 微信小程序、app集成微信支付

    一.微信小程序支付 开发文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_11&index=2 申请小程序 ...

  4. android微信迁移数据,【CSDN博客迁移】Android集成微信支付之-天坑

    项目集成微信支付,折腾了三天左右,坑太多,做个简单记录 开通和主要原理不再讲了,参考微信支付官网 截个官网的业务流程图,下面好说明 微信支付业务流程.png 1 支付结果回调(图中的17步) 支付结果 ...

  5. Android集成微信支付

    Android集成微信支付 项目中集成第三方支付的功能,基本是我们app中经常用到的功能.今天先给大家讲一下微信支付的集成过程,重点只说一下代码部分.首先,你要到微信开发者平台注册账号,并创建你的应用 ...

  6. SpringCloud集成微信支付

    SpringCloud集成微信支付 参照文档地址 代码里面有注释替换自己的微信参数即可 里面的加密直接搜MD5,AES加解密就可以,随机生成字符串 然后配置文件配置一下回调地址还有微信支付参数就ok了 ...

  7. Android 集成微信支付和支付宝支付工具类

    Android 集成微信支付和支付宝支付工具类 1.前言 去年年底接了一个商城app 外包项目,里面尼涉及到 微信和支付宝支付,这里我整理出几个工具类,下面就和大家分享一下,废话不多说,下面我一步一步 ...

  8. Hbuilder集成微信支付教程(简单流程)

    整个系统运作的流程大致是这样: (1)APP向服务器发出需要付款的请求 (2)服务器请求微信服务端下单 (3)服务器将下单数据回复给APP (4)APP向微信服务端发起请求并输入密码进行支付 关键字用 ...

  9. android微信支付插件,React Native集成微信支付【Android】

    wechat.jpg 本次博客主要讲解主要在RN中集成微信支付以及被我踩平的坑,需要一定的原生集成经验! 一. 导入微信SDK 用Android Studio打开RN项目中的android部分,在ap ...

最新文章

  1. 【C++ 语言】线程 ( 线程创建方法 | 线程标识符 | 线程属性 | 线程属性初始化 | 线程属性销毁 | 分离线程 | 线程调度策略 | 线程优先级 | 线程等待 )
  2. php 自动创建文件,php:自动创建多级文件夹
  3. 什么是MyCat?为什么要用到MyCat呢?
  4. bzoj 3572 [Hnoi2014]世界树——虚树
  5. HDU - 2859 Phalanx(动态规划/哈希表)
  6. Python module模块 包 __name__
  7. 计算机七年级书籍段落,七年级下册片段.doc
  8. java 8 新功能详解_Java 8的8个新功能
  9. intl扩展 mac 安装php_mac下php安装intl扩展代码分享
  10. NHibernate文档翻译--体系结构
  11. win32com 读doc,doc表格
  12. 设备\Device\Harddisk0\D 有一个不正确的区块
  13. bin和cue怎么合并,BIN和CUE文件如何打开?
  14. 家用千兆路由器排行榜前十名_家用路由器排名前十名
  15. uni-app开发小程序-引用腾讯地图选点
  16. 【硬件】LED灯发光原理总结
  17. Global Illumination_Voxel Global Illumintaion (VXGI)
  18. 最重要的会计期间是_数据备份应该在每个会计期间完成( )后进行
  19. 零时科技 || BEGO Token 攻击事件分析
  20. 文件目录和目录文件的作用区别和联系 C语言文件相关操作 FILE用法

热门文章

  1. 直通车关键词 关键字 直通车排名 把握好操作直通车推广的7个技巧
  2. Structured Exception Handling 异常扑捉
  3. html语言作业2,HTML语言寒假作业.doc
  4. m3u8文件下载合并的一种方法
  5. Android应用图标微技巧,8.0系统中应用图标的适配
  6. Win10笔记本自带神器
  7. hackmap-[windows权限提升(windows提权思路)]
  8. occ+vtk显示igs模型
  9. 第7章 为什么巴比伦塔会失败
  10. excel 转化sql