最近项目里面需要支付功能,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。订单信息需要的请求参数可以到官网上去对照,这里只加入了一些必要的参数。

生成订单信息方法:

[java]  view plain copy
  1. //获取产品订单信息
  2. private String genProductArgs() {
  3. StringBuffer xml = new StringBuffer();
  4. try {
  5. String nonceStr = genNonceStr();
  6. xml.append("</xml>");
  7. List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
  8. packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID)); //APPID
  9. packageParams.add(new BasicNameValuePair("body", "单价:" + singlePrice + " x " + payment_num.getText().toString() + "份"));  //简单描述
  10. packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));  //商户ID
  11. packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));   //随机字符串
  12. packageParams.add(new BasicNameValuePair("notify_url","http://www.weixin.qq.com/wxpay/pay.php")); //通知地址
  13. packageParams.add(new BasicNameValuePair("out_trade_no",getTrade()));  //商户订单号
  14. packageParams.add(new BasicNameValuePair("spbill_create_ip",getLocalHostIp())); //终端IP
  15. //double price = Double.parseDouble(payment_num.getText().toString()) * (Integer.parseInt(singlePrice) * 100);
  16. double price = Double.parseDouble(singlePrice) * 100 * n;
  17. int priceInt = (int) price;
  18. packageParams.add(new BasicNameValuePair("total_fee", priceInt+""));    //微信接收int型价格
  19. packageParams.add(new BasicNameValuePair("trade_type", "APP"));  //支付类型
  20. String sign = genAppSign(packageParams);
  21. packageParams.add(new BasicNameValuePair("sign", sign));  //签名
  22. String xmlstring = parseNodeToXML(packageParams);   //转化成xml
  23. return xmlstring;
  24. } catch (Exception e) {
  25. e.printStackTrace();
  26. return null;
  27. }
  28. }

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

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

[java]  view plain copy
  1. //获取订单号
  2. private String getTrade(){
  3. long nowTime = System.currentTimeMillis();
  4. SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss");
  5. return format.format(new Date(nowTime));
  6. }
  7. //获取支付签名Sign
  8. StringBuilder sb = new StringBuilder();
  9. private String genAppSign(List<NameValuePair> params) {
  10. StringBuilder sb = new StringBuilder();
  11. for (int i = 0; i < params.size(); i++) {
  12. sb.append(params.get(i).getName());
  13. sb.append('=');
  14. sb.append(params.get(i).getValue());
  15. sb.append('&');
  16. }
  17. sb.append("key=");
  18. sb.append(Constants.API_KEY);
  19. this.sb.append("sign str\n" + sb.toString() + "\n\n");
  20. String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
  21. return appSign;
  22. }
  23. //获取随机字符串
  24. private String genNonceStr() {
  25. Random random = new Random();
  26. return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
  27. }
  28. /**
  29. * 解析为xml格式
  30. * @param treeNodes
  31. * @return
  32. */
  33. public String parseNodeToXML(List<NameValuePair> treeNodes) {
  34. StringBuffer xmlnodes = new StringBuffer();
  35. if (treeNodes != null && treeNodes.size() > 0) {
  36. xmlnodes.append("<xml>");
  37. for (int i = 0; i < treeNodes.size(); i++) {
  38. NameValuePair node = treeNodes.get(i);
  39. xmlnodes.append("<"+node.getName()+">").append(node.getValue()).append("</"+node.getName()+">");
  40. }
  41. xmlnodes.append("</xml>");
  42. }
  43. //return xmlnodes.toString();
  44. String xml = xmlnodes.toString();
  45. try {
  46. xml = new String(xml.toString().getBytes(), "ISO8859-1");  //商品详情为中文,将其转化为统一编码,不然获取perpred_id失败
  47. return xml;
  48. } catch (UnsupportedEncodingException e) {
  49. e.printStackTrace();
  50. return null;
  51. }
  52. }
  53. //获取手机IP
  54. public String getLocalHostIp() {
  55. String ipaddress = "";
  56. try {
  57. Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
  58. // 遍历所用的网络接口
  59. while (en.hasMoreElements()) {
  60. NetworkInterface nif = en.nextElement();// 得到每一个网络接口绑定的所有ip
  61. Enumeration<InetAddress> inet = nif.getInetAddresses();
  62. // 遍历每一个接口绑定的所有ip
  63. while (inet.hasMoreElements()) {
  64. InetAddress ip = inet.nextElement();
  65. if (!ip.isLoopbackAddress() && InetAddressUtils.isIPv4Address(ip.getHostAddress())) {
  66. return ip.getHostAddress();
  67. }
  68. }
  69. }
  70. }
  71. catch (SocketException e) {
  72. Log.e("feige", "获取本地ip地址失败");
  73. e.printStackTrace();
  74. }
  75. return ipaddress;
  76. }

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

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

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

[html]  view plain copy
  1. //调用支付获取id
  2. public void gotoWechat() {
  3. new AsyncTask() {
  4. @Override
  5. protected Object doInBackground(Object[] objects) {   //获取Prepay_id
  6. String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
  7. String entity = genProductArgs();   //获取订单信息
  8. byte[] buf = Util.httpPost(url, entity);
  9. String content = new String(buf);  //请求成功返回的信息
  10. //Log.e("orion", content);
  11. try {
  12. xmlParseTest(content);  //解析返回的信息
  13. } catch (IOException e) {
  14. e.printStackTrace();
  15. } catch (XmlPullParserException e) {
  16. e.printStackTrace();
  17. }
  18. return null;
  19. }
  20. @Override
  21. protected void onPostExecute(Object o) {
  22. super.onPostExecute(o);
  23. wechatPay();
  24. }
  25. }.execute();
  26. }

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

成功执行这不之后只需在异步中perpay_id取出使用即可。

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


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



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



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

[java]  view plain copy
  1. public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
  2. private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity";
  3. private IWXAPI api;
  4. @Override public void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. //        setContentView(R.layout.activity_main2);
  7. api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
  8. api.handleIntent(getIntent(), this);
  9. api.registerApp(Constants.APP_ID);
  10. }
  11. @Override
  12. protected void onNewIntent(Intent intent) {
  13. super.onNewIntent(intent);
  14. setIntent(intent);
  15. api.handleIntent(intent, this);
  16. }
  17. @Override
  18. public void onReq(BaseReq req) {
  19. }
  20. @Override
  21. public void onResp(BaseResp resp) {
  22. int errCode = resp.errCode;
  23. if (errCode == 0) {
  24. // 0成功 展示成功页面
  25. // Intent intent = new Intent("name");
  26. // sendBroadcast(intent);
  27. // Log.e("test","支付成功的回调方法--onResp--");
  28. // Toast.makeText(this,"支付完成",Toast.LENGTH_SHORT).show();
  29. new AlertDialog.Builder(this).setMessage("支付成功").setPositiveButton("确定", new DialogInterface.OnClickListener() {
  30. @Override
  31. public void onClick(DialogInterface dialog, int which) {
  32. dialog.dismiss();
  33. finish();
  34. PaymentActivity.instance.finish();
  35. Intent intent = new Intent(WXPayEntryActivity.this, PuzzGameActivity.class);
  36. intent.putExtra("ISPLAY",true);
  37. startActivity(intent);
  38. }
  39. }).setTitle("提示").create().show();
  40. }
  41. else if (errCode == -1) {
  42. //-1 错误 可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。
  43. new AlertDialog.Builder(this).setMessage("支付出错").setPositiveButton("确定", new DialogInterface.OnClickListener() {
  44. @Override
  45. public void onClick(DialogInterface dialog, int which) {
  46. dialog.dismiss();
  47. finish();
  48. }
  49. }).setTitle("提示").create().show();
  50. finish();
  51. }
  52. else if (errCode == -2) {
  53. //-2 用户取消 无需处理。发生场景:用户不支付了,点击取消,返回APP。
  54. finish();
  55. }
  56. }
  57. }

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

当然,这里所涉及到的步骤全是在app客户端进行的,但是我们在实际开发中一定要将获取签名等操作放在服务后台进行,也就是客服端将订单信息传给服务端。服务端返回吊起支付必要的信息

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

android_app开发微信支付集成相关推荐

  1. iOS微信支付集成 SDK1 7 5

    最近做了一个新项目,涉及到支付宝和微信支付,支付宝和微信都是业界的老大哥,相信大家都有所觉得文档.SDK都是各种坑吧(纯粹吐槽而已),这是继上篇支付宝支付集成后接着的微信支付集成. 1.微信商户申请步 ...

  2. Spring Boot入门教程(四十):微信支付集成-刷卡支付

    分享一个朋友的人工智能教程.比较通俗易懂,风趣幽默,感兴趣的朋友可以去看看. 一:准备工作 使用微信支付需要先开通服务号,然后还要开通微信支付,最后还要配置一些开发参数,过程比较多. 申请服务号(企业 ...

  3. Spring Boot入门教程(四十一):微信支付集成-扫码支付

    分享一个朋友的人工智能教程.比较通俗易懂,风趣幽默,感兴趣的朋友可以去看看. 一:准备工作 使用微信支付需要先开通服务号,然后还要开通微信支付,最后还要配置一些开发参数,过程比较多. 申请服务号(企业 ...

  4. 如何使用easywechat开发微信支付功能

    easywechat是神一样的存在.非常好用.希望大家都能转到这上面来. 用easywechat来开发微信支付功能,步骤如下: 一,需要有一个商品下单页面,页面上有你的商品的信息,还要有购买数量,和一 ...

  5. 微信小程序开发-微信支付之免密支付(自动扣费)一 小程序+java接口

    微信小程序开发-微信支付之免密支付(自动扣费)一 小程序+java接口 链接: 点击进入

  6. .Net 微信支付集成

    关于.NET微信支付集成的记录 闲来无事集成一下微信支付,涉及到 pc端支付.小程序.H5.公众号内部支付等. 因此特意封装了一个类库,这里简单记录一下. 类库名:Yi.WeiXin.Pay 里面集成 ...

  7. 小程序云开发 ——微信支付

    云开发的微信支付:免鉴权.免签名计算.免 access_token,在云函数内原生调用微信支付接口.以前的实现微信支付,必须要有自己的服务器,有自己的备案域名,还有后端部分代码 云开发-微信支付,官方 ...

  8. 微信小程序云开发微信支付、订单查询、申请退款

    微信小程序云开发微信支付 使用云开发微信支付功能的前提 统一下单 查询订单 申请退款 常见问题总结: 使用云开发微信支付功能的前提 小程序主体为企业或者工商个体户 小程序完成了微信认证 小程序接入微信 ...

  9. php开发微信商户平台支付宝支付,不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...

    我们知道,开发微信支付需要申请服务号并且需要一系列的资料才可以开通.怪麻烦的,现在我们可以用第三方开放的免签约微信支付接口,支付宝接口和QQ钱包接口,实现实时到帐的微信支付开发. 我们只需要在第三方的 ...

最新文章

  1. 如何删除chrome地址栏里面曾经输错的地址
  2. 全球与中国丙烷脱氢制丙烯市场发展形势与前景规划分析报告2022-2028年版
  3. 鸿蒙系统第二款产品,鸿蒙OS第二款产品 “华为智慧屏”在Mate 30系列发布会上亮相...
  4. mysql 数据相加_mysql,php_mysql查询将两列数值相加问题,mysql,php,sql - phpStudy
  5. javascript 查看变量类型
  6. Machine Learning on Spark—— 统计基础(一)
  7. 当年要是早知道这4步框架,我就不会为数据管理发愁了
  8. python怎么打包_如何打包python程序
  9. 【Spring学习笔记-0】Spring开发所需要的核心jar包
  10. python安装whl文件的注意事项(windows系统)
  11. mysql 去重 性能比较_mysql 去重方法distinct 与 group by 性能比较 | 学步园
  12. FISCO BCOS 零知识证明 Fiat-Shamir 实例源码
  13. Linux基础命令1
  14. atitit.商业版 源码保护 与 java本地原生代码转换 的方案总结
  15. 技能Get·手动更新HP笔记本BIOS过程记录
  16. 火狐浏览器播放插件Linux,Firefox浏览器带flash播放器插件
  17. XiaoXin 13Pro-Hackintosh 小新13pro崇尚极简的黑苹果双系统
  18. linux 网络安全工具,常用的Linux网络安全工具简介
  19. 德声科技代理M-Live音视频播放器
  20. UI自动化测试(一)

热门文章

  1. js 删除字符串中第一个逗号
  2. Ubuntu9.04配置命令宝典
  3. HDU 6555 The Fool (整除分块 / 打表找规律)
  4. 高通量测序数据质控神器Trimmomatic
  5. C# 将字符串(符合xml格式)与XML互转
  6. a计权声功率级计算公式_超高层建筑气动噪声总声压级和A计权声压级的计算
  7. Java 正则表达式对数据脱敏处理
  8. 信息安全技术:健康医疗数据安全指南思维导图
  9. 开发中国最好的视频推荐系统
  10. python携程酒店评论_python爬取携程景点评论信息