当前位置:   article > 正文

Android微信支付接入_android webview微信支付怎么判断支付成功

android webview微信支付怎么判断支付成功

前言:本文主要说明如何在Android项目中接入微信支付,介绍微信支付在项目中的配置,分析微信支付数据与其交互流程,分享个人遇到的坑,以帮助有需要的朋友能更快的在项目中进行微信支付的接入。 
正文: 
1,开发资质申请: 
这个过程在本文中不详细介绍,总的来说需要企业资质申请微信支付功能以及微信开发者,最终是为了得到APPID和商户密钥(后面会详讲这个两个值怎么使用) 
2,流程总体介绍 
微信支付总体结构图: 
这里写图片描述 
订单信息:简单来讲就是对订单的封装,其中包含了支付金额,支付时间,订单号,签名信息等等订单信息。这些信息在项目中一般是由服务端构建的,交付给APP转发给微信服务器即可。但是实际情况中服务端可能也没有做这个工作,那么订单信息也有可能在APP端合成。所以开发时务必和后端开发人员协商好关于订单信息构造的工作。(订单构造详情见下文) 
支付请求:即APP在程序中调用支付SDK将订单信息发送给微信服务器,这个过程在代码中是很简单的,微信封装好了这个请求接口执行一行代码即可调用(详情见下文) 
支付结果反馈:微信会在特定回调接口通知支付接口 
总体上这就是微信支付的结构,操作上稍微复杂的是订单信息的构造,容易导致出错的微信SDK的配置。那么接下来就具体的一一介绍每个点的实现。 
3,下载官方demo 
官网SDK以及demo下载地址:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419319167&token=&lang=zh_CN 
官方文档地址:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=1_1 
下载完成后将libammsdk.jar导入到项目中,至于官方demo,建议大家看看就好,不要太相信。因为写的是在太烂了(不知道为什么微信这么大个平台,开发的demo是如此的不考虑用户的感受) 
4,实现 
a,导入jar包 
b,在工程包名下根目录新建wxapi包,这个wxapi包的位置一定要是包名根目录,包名也不能错。(这让对包名有强迫症的开发者会很不爽,但是没办法) 
这里写图片描述 
c,在该包下新建回调类WXPayEntryActivity,该类的名字一定是在wxapi包下,名字也一定是WXPayEntryActivity。因为他是微信回调的接口,如果改变位置或名字,就会导致微信无法将支付结果反馈,从而导致支付失败。 
这里写图片描述 
(图中WXEntryActivity是用作微信分享或其他功能的,只做微信支付的朋友可以忽略) 
d,WXPayEntryActivity的代码实现以及使用说明: 
该类是不需要开发者自己调用的,他是在微信支付后SDK为了回调通知APP的接口,SDK内部会调用该Activity,该Activity的界面布局可以自定义的设置。 
其具体的回调接口是该类中的onResp函数,在该函数中可判断是否支付成功。

  1. public class WXPayEntryActivity extends AppCompatActivity implements IWXAPIEventHandler {
  2. private IWXAPI api;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_wxpay_entry);
  7. api = WXAPIFactory.createWXAPI(this, "wxAPPID");//这里填入自己的微信APPID
  8. api.handleIntent(getIntent(), this);
  9. }
  10. @Override
  11. public void onReq(BaseReq baseReq) {
  12. }
  13. @Override
  14. public void onResp(BaseResp baseResp) {
  15. Log.d("coyc", "onPayFinish, errCode = " + baseResp.errCode);
  16. if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
  17. int errCord = baseResp.errCode;
  18. if (errCord == 0) {
  19. App.getInstance().tos("支付成功!");
  20. } else {
  21. App.getInstance().tos("支付失败");
  22. }
  23. //这里接收到了返回的状态码可以进行相应的操作,如果不想在这个页面操作可以把状态码存在本地然后finish掉这个页面,这样就回到了你调起支付的那个页面
  24. //获取到你刚刚存到本地的状态码进行相应的操作就可以了
  25. finish();
  26. }
  27. }
  28. @Override
  29. protected void onNewIntent(Intent intent) {
  30. super.onNewIntent(intent);
  31. setIntent(intent);
  32. api.handleIntent(intent, this);
  33. }
  34. }

e,AndroidManifest.xml配置:

  1. <uses-permission android:name="android.permission.INTERNET" />
  2. <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
  3. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  4. <!-- 微信支付 -->
  5. <activity
  6. android:name=".wxapi.WXPayEntryActivity"
  7. android:exported="true"
  8. android:launchMode="singleTop">
  9. <intent-filter>
  10. <action android:name="android.intent.action.VIEW" />
  11. <category android:name="android.intent.category.DEFAULT" />
  12. <data android:scheme="自己的wxAPPID" />
  13. </intent-filter>
  14. </activity>

f,调用支付接口:

  1. IWXAPI api= WXAPIFactory.createWXAPI(context, "wxAPPID",false);//填写自己的APPID
  2. api.registerApp("wxAPPID");//填写自己的APPID,注册本身APP
  3. PayReq req = new PayReq();//PayReq就是订单信息对象
  4. //给req对象赋值
  5. req.appId = appid;//APPID
  6. req.partnerId = partnerid;// 商户号
  7. req.prepayId = prepayid;// 预付款ID
  8. req.nonceStr = getRoundString();//随机数
  9. req.timeStamp = getTimeStamp();//时间戳
  10. req.packageValue = "Sign=WXPay";//固定值Sign=WXPay
  11. req.sign = sign;//签名
  12. api.sendReq(req);//将订单信息对象发送给微信服务器,即发送支付请求

那么写到这里,上面的PayReq 对象其实是未被赋值的

  1. req.appId = appid;//APPID
  2. req.partnerId = partnerid;// 商户号
  3. req.prepayId = prepayid;// 预付款ID
  4. req.nonceStr = getRoundString();//随机数
  5. req.timeStamp = getTimeStamp();//时间戳
  6. req.packageValue = "Sign=WXPay";//固定值Sign=WXPay
  7. req.sign = sign;//签名

而且这7个参数是缺一不可的,如果这些参数都是在服务端生成的,那么在Android开发人员就不用做什么工作了,将服务端给的值给其赋值就好了,那么整个微信支付流程也就做完了(一般来讲也确实是这个样子)。但是有些情况下服务端的同事没有做这些工作,比如说签名工作等等。那么这么这些工作就要在APP本地实现。 
下面我给出随机数获取算法,时间戳获取算法,签名算法。

  1. private String getRoundString() {
  2. Random random = new Random();
  3. return random.nextInt(10000) + "";
  4. }
  5. private String getTimeStamp() {
  6. return new Date().getTime() / 10 + "";
  7. }
  8. private String getSign() {
  9. Map<String, String> map = new HashMap<>();
  10. map.put("appid", req.appId);
  11. map.put("partnerid", req.partnerId);
  12. map.put("prepayid", req.prepayId);
  13. map.put("package", req.packageValue);
  14. map.put("noncestr", req.nonceStr);
  15. map.put("timestamp", req.timeStamp);
  16. ArrayList<String> sortList = new ArrayList<>();
  17. sortList.add("appid");
  18. sortList.add("partnerid");
  19. sortList.add("prepayid");
  20. sortList.add("package");
  21. sortList.add("noncestr");
  22. sortList.add("timestamp");
  23. sort(sortList);
  24. String md5 = "";
  25. int size = sortList.size();
  26. for (int k = 0; k < size; k++) {
  27. if (k == 0) {
  28. md5 += sortList.get(k) + "=" + map.get(sortList.get(k));
  29. } else {
  30. md5 += "&" + sortList.get(k) + "=" + map.get(sortList.get(k));
  31. }
  32. }
  33. String stringSignTemp = md5+"&key=商户密钥";//这里填写自己的商户密钥,所以说如果签名工作实在服务端完成的,商户密钥在APP端是用不到的
  34. String sign=MD5.Md5(stringSignTemp).toUpperCase();
  35. return sign;
  36. }

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package com.android.pc.util;
  6. import java.security.MessageDigest;
  7. public class MD5 {
  8. public MD5() {
  9. }
  10. public static final String Md5(String s) {
  11. char[] hexDigits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  12. try {
  13. byte[] e = s.getBytes("UTF-8");
  14. MessageDigest mdTemp = MessageDigest.getInstance("MD5");
  15. mdTemp.update(e);
  16. byte[] md = mdTemp.digest();
  17. int j = md.length;
  18. char[] str = new char[j * 2];
  19. int k = 0;
  20. for(int i = 0; i < j; ++i) {
  21. byte byte0 = md[i];
  22. str[k++] = hexDigits[byte0 >>> 4 & 15];
  23. str[k++] = hexDigits[byte0 & 15];
  24. }
  25. return new String(str);
  26. } catch (Exception var10) {
  27. return null;
  28. }
  29. }
  30. }

商户号以及预付款ID这个必须是服务端同事给定的值,在APP端是无法代码生成的。 
那么整个微信支付的代码工作到这里就结束了。这里我将自己封装的支付类贴出来,仅供参考。

  1. public class WX_Pay {
  2. public IWXAPI api;
  3. private PayReq req;
  4. public WX_Pay(Context context) {
  5. api = WXAPIFactory.createWXAPI(context, "wxAPPID",false);
  6. }
  7. /**
  8. * 向微信服务器发起的支付请求
  9. */
  10. public void pay(String appid,String partnerid,String prepayid) {
  11. req = new PayReq();
  12. req.appId = appid;//APPID
  13. req.partnerId = partnerid;// 商户号
  14. req.prepayId = prepayid;// 预付款ID
  15. req.nonceStr = getRoundString();//随机数
  16. req.timeStamp = getTimeStamp();//时间戳
  17. req.packageValue = "Sign=WXPay";//固定值Sign=WXPay
  18. String sign = getSign();
  19. req.sign = sign;//签名
  20. api.registerApp("wxAPPID");
  21. api.sendReq(req);
  22. }
  23. @NonNull
  24. private String getSign() {
  25. Map<String, String> map = new HashMap<>();
  26. map.put("appid", req.appId);
  27. map.put("partnerid", req.partnerId);
  28. map.put("prepayid", req.prepayId);
  29. map.put("package", req.packageValue);
  30. map.put("noncestr", req.nonceStr);
  31. map.put("timestamp", req.timeStamp);
  32. ArrayList<String> sortList = new ArrayList<>();
  33. sortList.add("appid");
  34. sortList.add("partnerid");
  35. sortList.add("prepayid");
  36. sortList.add("package");
  37. sortList.add("noncestr");
  38. sortList.add("timestamp");
  39. sort(sortList);
  40. String md5 = "";
  41. int size = sortList.size();
  42. for (int k = 0; k < size; k++) {
  43. if (k == 0) {
  44. md5 += sortList.get(k) + "=" + map.get(sortList.get(k));
  45. } else {
  46. md5 += "&" + sortList.get(k) + "=" + map.get(sortList.get(k));
  47. }
  48. }
  49. String stringSignTemp = md5+"&key=商户密钥";
  50. String sign=MD5.Md5(stringSignTemp).toUpperCase();
  51. return sign;
  52. }
  53. private String getRoundString() {
  54. Random random = new Random();
  55. return random.nextInt(10000) + "";
  56. }
  57. private String getTimeStamp() {
  58. return new Date().getTime() / 10 + "";
  59. }
  60. private static void sort(ArrayList<String> strings) {
  61. Collections.sort(strings);
  62. }
  63. }

那么在APP中这样使用就好

  1. WX_Pay pay = new WX_Pay(getContext());
  2. pay.pay(str1,str2,str3);

5,错误小结:本人在开发中遇到过两个错误 
a,无法起调微信支付界面:错误原因是没有将WXPayEntryActivity 类放在在wxapi包下。 
b,支付失败:错误原因是在签名算法中忘记将商户密钥签名。 
这里基本可以总结下错误类型: 
1,起调失败:工程配置错误 
2,支付订单报错:订单信息错误 
c,千万注意微信支付要编译为release版才能通过支付测试

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/989129
推荐阅读
相关标签
  

闽ICP备14008679号