android集成微信支付,脱坑篇"/>
android集成微信支付,脱坑篇
本屌也是做开发多年,遇到微信支付也是用起来相当棘手,今天就要写一篇脱坑攻略。
微信支付开发文档:.php?chapter=11_1#
集成步骤:
1、申请appkID。
2、下载sdk,放到项目lib文件夹下。
3、添加权限:
<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"/>
4、添加微信回调activity:
<activity
android:name=".wxapi.WXPayEntryActivity"
android:exported="true" />
并在项目根目录下创建包:wxapi,在wxapi包内创建WXPayEntryActivity。如下:
注意:微信官方对于此类并没有做过多的介绍,废话少说直接上代码:
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {//app_id 替换为你的应用从官方网站申请到的合法appid private static final String WXAPP_ID = "xxxxxxxxxxxxx"; private IWXAPI api; @Override public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.activity_home);//此处布局并没有什么用 并不显示,设置一个空页面就好 api = WXAPIFactory.createWXAPI(this,WXAPP_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) {//Log.d(TAG, "onPayFinish, errCode = " + resp.errCode); //resp.errCode 0:成功 -1:失败 -2:取消 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, resp.errStr +";code=" + String.valueOf(resp.errCode))); builder.show(); */ if (0== resp.errCode){// 支付成功 为方便页面刷新等 此处我用的 ReceiverUtils.paysuc(this); }else if (-1== resp.errCode){// 支付失败 为方便页面刷新等 此处我用的广播 ReceiverUtils.payfaile(this); }else if (-2== resp.errCode){// 取消支付 为方便页面刷新等 此处我用的广播 ReceiverUtils.payfaile(this); } // UIUtils.showToastSafe("支付结果:"+resp.errCode); finish(); }} }5、为了方便以后使用,我把支付相关的都放在基类里面,其实放在工具类中也挺好,因为activity中逻辑很多,很可能会有微信银联等其他支付集成,所以放在基类中提供一个方法就行,代码看起来更好看一些,还不影响activity中的逻辑。(注意:微信支付需要二次加密才能成功成功支付,不然会一直失败,在这个地方我就被坑了大半天,这两次加密全都放在后台加密最好,前端请求到支付的 实体PayReq后直接调用支付就好了,如果这第二次加密是放在前端做的话,就需要下面的方法了)废话少说直接上代码,代码中我会做解释:
public class JKPayActivity extends JKActivity {private static final String WXORIVATEKEY = "asdasdasdjasdkjahsdjkha";//微信支付设置的key //app_id 替换为你的应用从官方网站申请到的合法appid private static final String WXAPP_ID = "wxaasdasdq12d1d0"; //IWXAPI是第三方app和微信通信的openapi接口 private IWXAPI api; /** * 微信支付的初始化,在页面oncreat方法中一定要调用 */ public void initWx() {//工厂模式获取实例 api = WXAPIFactory.createWXAPI(this, WXAPP_ID, true); }/** * 进行微信支付,此方法直接调起微信支付 此支付官方要求需要放在子线程调用 * * @param bean 从后台获取的经过第一次加密的实体,包含以下属性(如果后台经过两次加密,则此处不需要进行加密,直接发起支付)。 * String appId; * String nonceStr; * String partnerid; * String prepay_id; * String sign; * String timeStamp; */ public void gotoWxPay(final WXPayBean bean) {new Thread(new Runnable() {@Override public void run() {PayReq req = new PayReq(); StringBuffer sb = new StringBuffer(); genPayReq(req, bean, sb);//参数 可以看成微信支付实体的赋值 把后台生成的订单信息赋值给PayReq //将应用的appid注册到微信 api.registerApp(WXAPP_ID); api.sendReq(req); }}).start(); }/** * 将后台数据赋值给微信支付的实体中 * * @param req 微信支付的实体 * @param bean 后台经过一次加密的订单信息 * @param sb 没什么用处,只为打印log方便查看 */ private void genPayReq(PayReq req, WXPayBean bean, StringBuffer sb) {if (bean == null || bean.getData() == null) {UIUtils.showToastSafe("支付失败"); return; }WXPayBean.DataBean.ParamsBean params = bean.getData().getParams(); req.appId = params.getAppId(); req.partnerId = params.getPartnerid(); req.prepayId = params.getPrepay_id(); // req.packageValue = "prepay_id="+params.getPrepay_id(); 这个值有些网上这样设置,我也试过,并没有什么卵用 req.packageValue = "Sign=WXPay"; //就这样设置 req.nonceStr = params.getNonceStr(); req.timeStamp = params.getTimeStamp(); // req.sign = ...... 如果后台进行了二次加密 就不需要下面的操作,直接将req return //以下为二次加密,就只为了req.sign这个属性赋值 MyNameValuePair就是自定义的键值对 稍后会贴出代码 List<MyNameValuePair> signParams = new LinkedList<>(); //将订单信息放到键值对中进行第二次加密 signParams.add(new MyNameValuePair("appid", req.appId)); signParams.add(new MyNameValuePair("noncestr", req.nonceStr)); signParams.add(new MyNameValuePair("package", "Sign=WXPay")); signParams.add(new MyNameValuePair("partnerid", req.partnerId)); signParams.add(new MyNameValuePair("prepayid", req.prepayId)); signParams.add(new MyNameValuePair("timestamp", req.timeStamp)); req.sign = genAppSign(signParams);//二次加密 sb.append("sign\n" + req.sign + "\n\n"); Log.e("orion", signParams.toString()); }/** * 二次加密 * * @param params * @return */ private String genAppSign(List<MyNameValuePair> 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(WXORIVATEKEY); return stringToMD5(sb.toString()).toUpperCase(); }/** * 将字符串转成MD5值 * * @param string 需要转换的字符串 * @return 字符串的MD5值 */ public static String stringToMD5(String string) {byte[] hash; try {hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8")); } catch (NoSuchAlgorithmException e) {e.printStackTrace(); return null; } catch (UnsupportedEncodingException e) {e.printStackTrace(); return null; }StringBuilder hex = new StringBuilder(hash.length * 2); for (byte b : hash) {if ((b & 0xFF) < 0x10)hex.append("0"); hex.append(Integer.toHexString(b & 0xFF)); }return hex.toString(); }}
public class MyNameValuePair {private String name; private String value; public MyNameValuePair(String name, String value) {this.name = name; this.value = value; }public String getName() {return name; }public void setName(String name) {this.name = name; }public String getValue() {return value; }public void setValue(String value) {this.value = value; } }
此处存在一个坑,稍后说。
下面介绍集成微信支付失败的坑:
1、签名不对:平常测试一些第三方都是需要签名的,因为一般运行项目都会使用工具默认的debug签名,所以会导致第三方的功能失败,此时就需要下面的操作了,运行时直接签名,此时手机上的app就是签过名的,同时还可以看log日志,再也不需要打包发送到手机上看效果了
(1)我用的是android studio ,所以签名直接在gradle中配置就行(在android{} 中添加如下代码,注意上下顺序不可调换 其中的信息替换成自己的就行 :keyalias 、keypassword、storefile、storepassword):
//配置keystore签名 signingConfigs {release {keyAlias 'app' keyPassword '123456789' storeFile file('C:/Users/iningke/Desktop/xxx/key/xxx.jks')storePassword '123456789' }}buildTypes { // release { // minifyEnabled false // proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' // } release {signingConfig signingConfigs.release}debug {signingConfig signingConfigs.release}}
(2)也可以直接打开设置(右键app,选择)
下图设置好也是同样的效果
2,支付失败:参数不对,主要体现在二次加密后的sign值不对,如果调起支付的时候签名没问题,那就要看看这个地方了,不管是后台还是前端,进行第二次签名的时候都要放到 微信公众平台支付接口调试工具 中,地址为:/
只要你二次加密得到的值跟微信调试工具的值一样,这才说明你的签名是对的,有些人很难想到是加密算法导致支付失败的。
入坑需谨慎,别人的拿来用还是要自己祥读的,微信的开发文档我就不详细介绍了,支付可以按照上面的集成,但是真正出问题还是要详细阅读官方文档的。
请大家多多关注,一起成长
总结的不周之处请谅解,谢谢
更多推荐
android集成微信支付,脱坑篇
发布评论