记一次微信支付的爬坑经历

xiaoxiao2021-02-28  116

微信支付步骤: 1.先去微信开放平台申请账号,创建移动应用,并审核通过,这样就可以获取到

// APP_ID 替换为你的应用从官方网站申请到的合法appId public static final String APP_ID = "wwwwwwww"; // 微信支付商户号 public static final String APP_TENANT = "yyyyyy"; // 秘钥(审核通过后会邮件通知你,然后让你登陆在里面设置秘钥) public static final String APP_TENANT_SIGN = "XXXXXXXXXXXXXXXXXXXXX";

2.接入微信支付的SDK

3.在AndroidManifest.xml文件中加入

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xxx.yyyyy"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- for mta statistics --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".wxapi.WXPayEntryActivity" android:exported="true" android:launchMode="singleTop" /> <receiver android:name=".AppRegister"> <intent-filter> <action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_REFRESH_WXAPP" /> </intent-filter> </receiver> </application> </manifest>

4.在你的包(必须是AndroidManifest.xml中的包名,上面3中的com.xxx.yyyyy)下面创建wxapi文件,在wxapi文件下面创建WXPayEntryActivity.java类;

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.pay_result); 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) { } /** * 微信支付成功或失败取消支付的回调方法 * @param resp */ @Override public void onResp(BaseResp resp) { Log.e("WXPayEntryActivity", "onPayFinish, errCode = " + resp.errCode + ""); // if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) { // AlertDialog.Builder builder = new AlertDialog.Builder(this); // builder.setTitle(R.string.app_tip); // builder.setMessage(getString(R.string.pay_result_callback_msg, String.valueOf(resp.errCode))); // builder.show(); // } System.out.println(resp.errCode); if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) { if (resp.errCode == 0) { // 0 成功 展示成功页面 AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("微信支付结果"); builder.setMessage("支付订单成功!"); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }); builder.show(); } else if (resp.errCode == -1) { // -1 错误 可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。 Toast.makeText(WXPayEntryActivity.this, "支付出错:" + resp.errStr, Toast.LENGTH_SHORT) .show(); finish(); } else if (resp.errCode == -2) { // -2 用户取消 无需处理。发生场景:用户不支付了,点击取消,返回APP。 Toast.makeText(WXPayEntryActivity.this, "取消支付:" + resp.errStr, Toast.LENGTH_SHORT) .show(); finish(); } } } }

5.写一个广播类:AppRegister.java(这一步关系到是否能接收到微信的回调)

public class AppRegister extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { final IWXAPI msgApi = WXAPIFactory.createWXAPI(context, null); // 将该app注册到微信 msgApi.registerApp("11225566666"); } }

注册到清单文件中:

<receiver android:name=".AppRegister"> <intent-filter> <action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_REFRESH_WXAPP" /> </intent-filter> </receiver>

接下来就是重点了:(踩坑比较多)

public class MainActivity extends Activity { private IWXAPI api; private OrderPayBean orderPaybean; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 商户APP工程中引入微信JAR包,调用API前,需要先向微信注册您的APPID api = WXAPIFactory.createWXAPI(this, Constants.APP_ID); // 参数二是申请的APPID // 将该app注册到微信 api.registerApp(Constants.APP_ID); // 参数是申请的APPID orderPaybean = new OrderPayBean(); initData(); // if (!TextUtils.isEmpty(IpUtil.getIPAddress(this))) { // String ipAddress = IpUtil.getIPAddress(this); // String s = ipAddress.substring(1,ipAddress.length()).trim(); // Log.e("手机当前ip地址 = ", s); // } // Log.e("手机当前ip地址", IpUtil.getIPAddress(this)); } private void initData() { orderPaybean.appid = Constants.APP_ID; orderPaybean.body = "微信支付"; orderPaybean.mch_id = Constants.APP_TENANT; // 商户号 orderPaybean.nonce_str = Constants.genNonceStr(); // 获得随机字符串 orderPaybean.notify_url = "https://www.google.com"; // //微信通知后台支付结果url orderPaybean.total_fee = 1; orderPaybean.trade_type = "APP"; orderPaybean.out_trade_no = Constants.getNonceStr(); orderPaybean.spbill_create_ip = "196.168.1.1"; SortedMap<Object, Object> parameters = new TreeMap<Object, Object>(); parameters.put("appid", orderPaybean.appid); parameters.put("body", orderPaybean.body); parameters.put("mch_id", orderPaybean.mch_id); parameters.put("nonce_str", orderPaybean.nonce_str); parameters.put("notify_url", orderPaybean.notify_url); parameters.put("out_trade_no", orderPaybean.out_trade_no); parameters.put("total_fee", orderPaybean.total_fee); parameters.put("trade_type", orderPaybean.trade_type); parameters.put("spbill_create_ip", orderPaybean.spbill_create_ip); parameters.put("sign", Constants.createSign("UTF-8", parameters, Constants.APP_TENANT_SIGN));//传入签名好的参数值 StringBuilder xmlBuilder = new StringBuilder(); xmlBuilder.append("<xml>"); Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序) Iterator it = es.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String k = (String) entry.getKey(); Object v = entry.getValue(); xmlBuilder.append("<").append(k).append(">"); xmlBuilder.append(v); xmlBuilder.append("</").append(k).append(">"); } xmlBuilder.append("</xml>"); System.out.println(xmlBuilder.toString()); try { new GetPrepayId(new String(xmlBuilder.toString().getBytes(), "ISO8859-1")).execute();//这一步非常重要,不这样转换编码的话,传递中文就会报“签名错误”,这是很多人都会遇到的错误。 } catch (Exception e) { e.printStackTrace(); } } public class GetPrepayId extends AsyncTask { String str; public GetPrepayId(String str) { this.str = str; } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Object doInBackground(Object[] params) { String url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; Log.e("参数", ">>>>" + str); byte[] buf = Util.httpPost(url, str); // 发起订单向微信获取预支付交易会话标识prepay_id String content = null; if (buf != null) { content = new String(buf); } // String content = new String(buf); Log.e("返回数据", ">>>>" + content); Map<String, String> map = Constants.xmlToMap(content); String nonceStr = Constants.genNonceStr(); String timeStamp = String.valueOf(Constants.genTimeStamp()); SortedMap<Object, Object> parameters = new TreeMap<Object, Object>(); parameters.put("appid", orderPaybean.appid); parameters.put("partnerid", orderPaybean.mch_id); parameters.put("prepayid", map.get("prepay_id")); parameters.put("package", "Sign=WXPay"); parameters.put("noncestr", nonceStr); parameters.put("timestamp", timeStamp); PayReq request = new PayReq(); request.appId = orderPaybean.appid; request.partnerId = orderPaybean.mch_id; request.prepayId = map.get("prepay_id"); request.packageValue = "Sign=WXPay"; request.nonceStr = nonceStr; request.timeStamp = timeStamp; request.sign = Constants.createSign("UTF-8", parameters, Constants.APP_TENANT_SIGN); api.sendReq(request); // 发起支付 return content; } } }

PS: 当手机上面的微信在别处登陆的时候有时候会支付失败的(不提示没登录) 到此结束,感谢阅读。 当然奉上源码源码

下面贴上完整的代码: 工具类:Constants.java

package com.fly.weixin.utils; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import java.util.SortedMap; public class Constants { // APP_ID 替换为你的应用从官方网站申请到的合法appId public static final String APP_ID = "flyflflyflyfly"; // 微信支付商户号 public static final String APP_TENANT = "20170611"; // 应用签名 // public static final String APP_TENANT_SIGN = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyy"; // 秘钥 public static final String APP_TENANT_SIGN = "xxxxxxxxxxxxxxxxxxxxxxxxx"; //********************************************************************************************************************************** /** * 微信支付签名算法sign * @param characterEncoding 签名编码(UTF-8) * @param parameters 要签名的参数的集合 * @param key 商户自己设置的key */ @SuppressWarnings("unchecked") public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters, String key){ StringBuffer sb = new StringBuffer(); Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序) Iterator it = es.iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); String k = (String)entry.getKey(); Object v = entry.getValue(); if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + key); System.out.println(sb.toString()); String sign = WxMd5.MD5Encode(sb.toString(), characterEncoding).toUpperCase(); System.out.println(sign); return sign; } /** * 获取时间戳 * @return */ public static long genTimeStamp() { return System.currentTimeMillis() / 1000; } /** * 获得随机字符串 * @return */ public static String genNonceStr() { Random random = new Random(); return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes()); } // 生成随机号,防重复 public static String getNonceStr() { Random random = new Random(); return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)) .getBytes()); } public static Map<String, String> xmlToMap(String xmlstr) { Map<String, String> map = new HashMap<>(); try { SAXReader reader = new SAXReader(); InputStream ins = new ByteArrayInputStream(xmlstr.getBytes("UTF-8")); Document doc = reader.read(ins); Element root = doc.getRootElement(); List<Element> list = root.elements(); for (Element e : list) { map.put(e.getName(), e.getText()); } ins.close(); } catch (Exception e) { e.printStackTrace(); } return map; } }

IpUtil.java

package com.fly.weixin.utils; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; /** * Created by Administrator on 2017/6/7. * */ public class IpUtil { /** * 获取手机的ip地址 * @param context * @return */ public static String getIPAddress(Context context) { NetworkInfo info = ((ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo(); if (info != null && info.isConnected()) { if (info.getType() == ConnectivityManager.TYPE_MOBILE) {//当前使用2G/3G/4G网络 try { //Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces(); for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) { NetworkInterface intf = en.nextElement(); for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) { InetAddress inetAddress = enumIpAddr.nextElement(); if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) { return inetAddress.getHostAddress(); } } } } catch (SocketException e) { e.printStackTrace(); } } else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络 WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); String ipAddress = intIP2StringIP(wifiInfo.getIpAddress());//得到IPV4地址 return ipAddress; } } else { //当前无网络连接,请在设置中打开网络 } return null; } /** * 将得到的int类型的IP转换为String类型 * * @param ip * @return */ public static String intIP2StringIP(int ip) { return (ip & 0xFF) + "." + ((ip >> 8) & 0xFF) + "." + ((ip >> 16) & 0xFF) + "." + (ip >> 24 & 0xFF); } }

MD5.java

package com.fly.weixin.utils; import java.security.MessageDigest; public class MD5 { private MD5() {} public final static String getMessageDigest(byte[] buffer) { char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; try { MessageDigest mdTemp = MessageDigest.getInstance("MD5"); mdTemp.update(buffer); byte[] md = mdTemp.digest(); int j = md.length; char str[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } return new String(str); } catch (Exception e) { return null; } } private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; /** * 转换字节数组为16进制字串 * @param b 字节数组 * @return 16进制字串 */ public static String byteArrayToHexString(byte[] b) { StringBuilder resultSb = new StringBuilder(); for (byte aB : b) { resultSb.append(byteToHexString(aB)); } return resultSb.toString(); } /** * 转换byte到16进制 * @param b 要转换的byte * @return 16进制格式 */ private static String byteToHexString(byte b) { int n = b; if (n < 0) { n = 256 + n; } int d1 = n / 16; int d2 = n % 16; return hexDigits[d1] + hexDigits[d2]; } /** * MD5编码 * @param origin 原始字符串 * @return 经过MD5加密之后的结果 */ public static String MD5Encode(String origin) { String resultString = null; try { resultString = origin; MessageDigest md = MessageDigest.getInstance("MD5"); md.update(resultString.getBytes("UTF-8")); resultString = byteArrayToHexString(md.digest()); } catch (Exception e) { e.printStackTrace(); } return resultString; } }

Util.java

package com.fly.weixin.utils; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.util.Log; import junit.framework.Assert; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.net.Socket; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class Util { private static final String TAG = "SDK_Sample.Util"; public static byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) { ByteArrayOutputStream output = new ByteArrayOutputStream(); bmp.compress(CompressFormat.PNG, 100, output); if (needRecycle) { bmp.recycle(); } byte[] result = output.toByteArray(); try { output.close(); } catch (Exception e) { e.printStackTrace(); } return result; } public static byte[] httpGet(final String url) { if (url == null || url.length() == 0) { Log.e(TAG, "httpGet, url is null"); return null; } HttpClient httpClient = getNewHttpClient(); HttpGet httpGet = new HttpGet(url); try { HttpResponse resp = httpClient.execute(httpGet); if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { Log.e(TAG, "httpGet fail, status code = " + resp.getStatusLine().getStatusCode()); return null; } return EntityUtils.toByteArray(resp.getEntity()); } catch (Exception e) { Log.e(TAG, "httpGet exception, e = " + e.getMessage()); e.printStackTrace(); return null; } } public static byte[] httpPost(String url, String entity) { if (url == null || url.length() == 0) { Log.e(TAG, "httpPost, url is null"); return null; } HttpClient httpClient = getNewHttpClient(); HttpPost httpPost = new HttpPost(url); try { httpPost.setEntity(new StringEntity(entity)); httpPost.setHeader("Accept", "application/json"); httpPost.setHeader("Content-type", "application/json"); HttpResponse resp = httpClient.execute(httpPost); if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { Log.e(TAG, "httpGet fail, status code = " + resp.getStatusLine().getStatusCode()); return null; } return EntityUtils.toByteArray(resp.getEntity()); } catch (Exception e) { Log.e(TAG, "httpPost exception, e = " + e.getMessage()); e.printStackTrace(); return null; } } private static class SSLSocketFactoryEx extends SSLSocketFactory { SSLContext sslContext = SSLContext.getInstance("TLS"); public SSLSocketFactoryEx(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { super(truststore); TrustManager tm = new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException { } }; sslContext.init(null, new TrustManager[] { tm }, null); } @Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); } @Override public Socket createSocket() throws IOException { return sslContext.getSocketFactory().createSocket(); } } private static HttpClient getNewHttpClient() { try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore); sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); registry.register(new Scheme("https", sf, 443)); ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); return new DefaultHttpClient(ccm, params); } catch (Exception e) { return new DefaultHttpClient(); } } public static byte[] readFromFile(String fileName, int offset, int len) { if (fileName == null) { return null; } File file = new File(fileName); if (!file.exists()) { Log.i(TAG, "readFromFile: file not found"); return null; } if (len == -1) { len = (int) file.length(); } Log.d(TAG, "readFromFile : offset = " + offset + " len = " + len + " offset + len = " + (offset + len)); if(offset <0){ Log.e(TAG, "readFromFile invalid offset:" + offset); return null; } if(len <=0 ){ Log.e(TAG, "readFromFile invalid len:" + len); return null; } if(offset + len > (int) file.length()){ Log.e(TAG, "readFromFile invalid file len:" + file.length()); return null; } byte[] b = null; try { RandomAccessFile in = new RandomAccessFile(fileName, "r"); b = new byte[len]; // ���������ļ���С������ in.seek(offset); in.readFully(b); in.close(); } catch (Exception e) { Log.e(TAG, "readFromFile : errMsg = " + e.getMessage()); e.printStackTrace(); } return b; } private static final int MAX_DECODE_PICTURE_SIZE = 1920 * 1440; public static Bitmap extractThumbNail(final String path, final int height, final int width, final boolean crop) { Assert.assertTrue(path != null && !path.equals("") && height > 0 && width > 0); BitmapFactory.Options options = new BitmapFactory.Options(); try { options.inJustDecodeBounds = true; Bitmap tmp = BitmapFactory.decodeFile(path, options); if (tmp != null) { tmp.recycle(); tmp = null; } Log.d(TAG, "extractThumbNail: round=" + width + "x" + height + ", crop=" + crop); final double beY = options.outHeight * 1.0 / height; final double beX = options.outWidth * 1.0 / width; Log.d(TAG, "extractThumbNail: extract beX = " + beX + ", beY = " + beY); options.inSampleSize = (int) (crop ? (beY > beX ? beX : beY) : (beY < beX ? beX : beY)); if (options.inSampleSize <= 1) { options.inSampleSize = 1; } // NOTE: out of memory error while (options.outHeight * options.outWidth / options.inSampleSize > MAX_DECODE_PICTURE_SIZE) { options.inSampleSize++; } int newHeight = height; int newWidth = width; if (crop) { if (beY > beX) { newHeight = (int) (newWidth * 1.0 * options.outHeight / options.outWidth); } else { newWidth = (int) (newHeight * 1.0 * options.outWidth / options.outHeight); } } else { if (beY < beX) { newHeight = (int) (newWidth * 1.0 * options.outHeight / options.outWidth); } else { newWidth = (int) (newHeight * 1.0 * options.outWidth / options.outHeight); } } options.inJustDecodeBounds = false; Log.i(TAG, "bitmap required size=" + newWidth + "x" + newHeight + ", orig=" + options.outWidth + "x" + options.outHeight + ", sample=" + options.inSampleSize); Bitmap bm = BitmapFactory.decodeFile(path, options); if (bm == null) { Log.e(TAG, "bitmap decode failed"); return null; } Log.i(TAG, "bitmap decoded size=" + bm.getWidth() + "x" + bm.getHeight()); final Bitmap scale = Bitmap.createScaledBitmap(bm, newWidth, newHeight, true); if (scale != null) { bm.recycle(); bm = scale; } if (crop) { final Bitmap cropped = Bitmap.createBitmap(bm, (bm.getWidth() - width) >> 1, (bm.getHeight() - height) >> 1, width, height); if (cropped == null) { return bm; } bm.recycle(); bm = cropped; Log.i(TAG, "bitmap croped size=" + bm.getWidth() + "x" + bm.getHeight()); } return bm; } catch (final OutOfMemoryError e) { Log.e(TAG, "decode bitmap failed: " + e.getMessage()); options = null; } return null; } public static String sha1(String str) { if (str == null || str.length() == 0) { return null; } char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; try { MessageDigest mdTemp = MessageDigest.getInstance("SHA1"); mdTemp.update(str.getBytes()); byte[] md = mdTemp.digest(); int j = md.length; char buf[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; buf[k++] = hexDigits[byte0 >>> 4 & 0xf]; buf[k++] = hexDigits[byte0 & 0xf]; } return new String(buf); } catch (Exception e) { return null; } } public static List<String> stringsToList(final String[] src) { if (src == null || src.length == 0) { return null; } final List<String> result = new ArrayList<String>(); for (int i = 0; i < src.length; i++) { result.add(src[i]); } return result; } }

WxMd5.java

package com.fly.weixin.utils; import java.security.MessageDigest; /** * Created by Administrator on 2017/6/6. */ public class WxMd5 { private static String byteArrayToHexString(byte b[]) { StringBuffer resultSb = new StringBuffer(); for (int i = 0; i < b.length; i++) resultSb.append(byteToHexString(b[i])); return resultSb.toString(); } private static String byteToHexString(byte b) { int n = b; if (n < 0) n += 256; int d1 = n / 16; int d2 = n % 16; return hexDigits[d1] + hexDigits[d2]; } public static String MD5Encode(String origin, String charsetname) { String resultString = null; try { resultString = new String(origin); MessageDigest md = MessageDigest.getInstance("MD5"); if (charsetname == null || "".equals(charsetname)) resultString = byteArrayToHexString(md.digest(resultString .getBytes())); else resultString = byteArrayToHexString(md.digest(resultString .getBytes("utf-8"))); } catch (Exception exception) { } return resultString; } private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; }

bean包下的:OrderPayBean.java

package com.fly.weixin.bean; import java.io.Serializable; /** * Created by fly on 2017/6/6. */ public class OrderPayBean implements Serializable { public String appid; //appid public String body; //商品描述 public String mch_id; //商户ID public String nonce_str; //随机字符串 public String notify_url; //微信通知后台支付结果url public String out_trade_no; //我们自己的订单号 public String spbill_create_ip; //客户端IP public int total_fee; //总的支付金额 public String trade_type; //因为是移动应用 所以是APP public String sign; //以上所有参数的MD5签名 }

wxapi包下:WXPayEntryActivity.java

package com.fly.weixin.wxapi; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import com.fly.weixin.R; import com.fly.weixin.utils.Constants; import com.tencent.mm.opensdk.constants.ConstantsAPI; import com.tencent.mm.opensdk.modelbase.BaseReq; import com.tencent.mm.opensdk.modelbase.BaseResp; import com.tencent.mm.opensdk.openapi.IWXAPI; import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler; import com.tencent.mm.opensdk.openapi.WXAPIFactory; /** * 把这个activity设置成dialog的样式,效果会更好 */ 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.pay_result); 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) { } /** * 微信支付成功或失败取消支付的回调方法 * @param resp */ @Override public void onResp(BaseResp resp) { Log.e("WXPayEntryActivity", "onPayFinish, errCode = " + resp.errCode + ""); // if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) { // AlertDialog.Builder builder = new AlertDialog.Builder(this); // builder.setTitle(R.string.app_tip); // builder.setMessage(getString(R.string.pay_result_callback_msg, String.valueOf(resp.errCode))); // builder.show(); // } System.out.println(resp.errCode); if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) { if (resp.errCode == 0) { // 0 成功 展示成功页面 AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("微信支付结果"); builder.setMessage("支付订单成功!"); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }); builder.show(); } else if (resp.errCode == -1) { // -1 错误 可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。 Toast.makeText(WXPayEntryActivity.this, "支付出错:" + resp.errStr, Toast.LENGTH_SHORT) .show(); finish(); } else if (resp.errCode == -2) { // -2 用户取消 无需处理。发生场景:用户不支付了,点击取消,返回APP。 Toast.makeText(WXPayEntryActivity.this, "取消支付:" + resp.errStr, Toast.LENGTH_SHORT) .show(); finish(); } } } }

广播:

package com.fly.weixin.wx_success; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import com.fly.weixin.utils.Constants; import com.tencent.mm.opensdk.openapi.IWXAPI; import com.tencent.mm.opensdk.openapi.WXAPIFactory; public class AppRegister extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { final IWXAPI msgApi = WXAPIFactory.createWXAPI(context, null); // 将该app注册到微信 msgApi.registerApp(Constants.APP_ID); } }

发起支付的代码:MainActivity.java

package com.fly.weixin.wx_success; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import com.fly.weixin.R; import com.fly.weixin.bean.OrderPayBean; import com.fly.weixin.utils.Constants; import com.fly.weixin.utils.Util; import com.tencent.mm.opensdk.modelpay.PayReq; import com.tencent.mm.opensdk.openapi.IWXAPI; import com.tencent.mm.opensdk.openapi.WXAPIFactory; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; public class MainActivity extends Activity { private IWXAPI api; private OrderPayBean orderPaybean; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 商户APP工程中引入微信JAR包,调用API前,需要先向微信注册您的APPID api = WXAPIFactory.createWXAPI(this, Constants.APP_ID); // 参数二是申请的APPID // 将该app注册到微信 api.registerApp(Constants.APP_ID); // 参数是申请的APPID orderPaybean = new OrderPayBean(); initData(); // if (!TextUtils.isEmpty(IpUtil.getIPAddress(this))) { // String ipAddress = IpUtil.getIPAddress(this); // String s = ipAddress.substring(1,ipAddress.length()).trim(); // Log.e("手机当前ip地址 = ", s); // } // Log.e("手机当前ip地址", IpUtil.getIPAddress(this)); } private void initData() { orderPaybean.appid = Constants.APP_ID; orderPaybean.body = "微信支付"; orderPaybean.mch_id = Constants.APP_TENANT; // 商户号 orderPaybean.nonce_str = Constants.genNonceStr(); // 获得随机字符串 orderPaybean.notify_url = "https://www.google.com"; // //微信通知后台支付结果url orderPaybean.total_fee = 1; orderPaybean.trade_type = "APP"; orderPaybean.out_trade_no = Constants.getNonceStr(); orderPaybean.spbill_create_ip = "196.168.1.1"; SortedMap<Object, Object> parameters = new TreeMap<Object, Object>(); parameters.put("appid", orderPaybean.appid); parameters.put("body", orderPaybean.body); parameters.put("mch_id", orderPaybean.mch_id); parameters.put("nonce_str", orderPaybean.nonce_str); parameters.put("notify_url", orderPaybean.notify_url); parameters.put("out_trade_no", orderPaybean.out_trade_no); parameters.put("total_fee", orderPaybean.total_fee); parameters.put("trade_type", orderPaybean.trade_type); parameters.put("spbill_create_ip", orderPaybean.spbill_create_ip); parameters.put("sign", Constants.createSign("UTF-8", parameters, Constants.APP_TENANT_SIGN));//传入签名好的参数值 StringBuilder xmlBuilder = new StringBuilder(); xmlBuilder.append("<xml>"); Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序) Iterator it = es.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String k = (String) entry.getKey(); Object v = entry.getValue(); xmlBuilder.append("<").append(k).append(">"); xmlBuilder.append(v); xmlBuilder.append("</").append(k).append(">"); } xmlBuilder.append("</xml>"); System.out.println(xmlBuilder.toString()); try { new GetPrepayId(new String(xmlBuilder.toString().getBytes(), "ISO8859-1")).execute();//这一步非常重要,不这样转换编码的话,传递中文就会报“签名错误”,这是很多人都会遇到的错误。 } catch (Exception e) { e.printStackTrace(); } } public class GetPrepayId extends AsyncTask { String str; public GetPrepayId(String str) { this.str = str; } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Object doInBackground(Object[] params) { String url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; Log.e("参数", ">>>>" + str); byte[] buf = Util.httpPost(url, str); // 发起订单向微信获取预支付交易会话标识prepay_id String content = null; if (buf != null) { content = new String(buf); } // String content = new String(buf); Log.e("返回数据", ">>>>" + content); Map<String, String> map = Constants.xmlToMap(content); String nonceStr = Constants.genNonceStr(); String timeStamp = String.valueOf(Constants.genTimeStamp()); SortedMap<Object, Object> parameters = new TreeMap<Object, Object>(); parameters.put("appid", orderPaybean.appid); parameters.put("partnerid", orderPaybean.mch_id); parameters.put("prepayid", map.get("prepay_id")); parameters.put("package", "Sign=WXPay"); parameters.put("noncestr", nonceStr); parameters.put("timestamp", timeStamp); PayReq request = new PayReq(); request.appId = orderPaybean.appid; request.partnerId = orderPaybean.mch_id; request.prepayId = map.get("prepay_id"); request.packageValue = "Sign=WXPay"; request.nonceStr = nonceStr; request.timeStamp = timeStamp; request.sign = Constants.createSign("UTF-8", parameters, Constants.APP_TENANT_SIGN); api.sendReq(request); // 发起支付 return content; } } }

配置文件:

apply plugin: 'com.android.application' android { signingConfigs { fly_wx { keyAlias 'keyStore' keyPassword 'android' storeFile file('C:/Users/Administrator.SKY-20170131CUA/Desktop/keyStore.jks') storePassword 'android' } } compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "com.fly.weixin" minSdkVersion 14 targetSdkVersion 25 versionCode 1 versionName "1.0" /*ndk{ moduleName "helloJni"/*//*生成的so文件名,必填 abiFilters "armeabi", "armeabi-v7a", "x86" //配置输出的abi体系结构下的so库, }*/ } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.fly_wx } debug { signingConfig signingConfigs.fly_wx } } useLibrary 'org.apache.http.legacy' } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+' compile files('libs/dom4j-1.6.1.jar') }
转载请注明原文地址: https://www.6miu.com/read-21190.html

最新回复(0)