java后台程序员转android 之《三B》 支付宝支付 client join server 及采坑记录
16lz
2021-01-23
目录
前言:
介绍:
demo:
先看下 我的目录结构
java 代码
activit代码
总结思路:
server 端 开发思路
前言:
最近公司打算做先关android 方面的技术,然后招andirod 还挺贵,老板打算让我来搞搞,那就搞一搞,顺便做些总结,从java后台转型快速入手 android 的小策略支付还是挺总要的一部分毕竟用手机主要一点就是支付所以记录一下经验。
andoird 官网地址 https://developer.android.google.cn/
介绍:
- 首先查看下支付宝沙箱文档 https://docs.open.alipay.com/200/105311/
- 这个文档中很详细的介绍了些内容
- 然后去获取一下appid 等账号,还有加密的秘钥等内容
- 接下来就是看代码了
- 官方提供的demo是为了方便把代码都放到了android
- 这里为了方便我把代码顺便分了下那些放到server那些放到android center
demo:
- https://download.csdn.net/download/weixin_42749765/10992832
- 这里为了方便纯开发java后台的朋友 还带上来我之前讲的 webview 混合开发的代码
- 混合开发的时候就通过js调用java方法 然后启动 alipay 的方法 来实现支付
- 这里不做太多介绍
先看下 我的目录结构
- 红色地方都是重点需要关注的
java 代码
package com.example.app002;import android.Manifest;import android.annotation.SuppressLint;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.content.pm.PackageManager;import android.os.Build;import android.os.Handler;import android.os.Message;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.text.TextUtils;import android.util.Log;import android.view.View;import android.webkit.WebView;import android.widget.TextView;import android.widget.Toast;import com.alipay.sdk.app.AuthTask;import com.alipay.sdk.app.PayTask;import com.example.alipay.base.AuthResult;import com.example.alipay.base.PayResult;import com.example.alipay.uitl.OrderInfoUtil2_0;import org.json.JSONArray;import org.json.JSONObject;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/** * java主启动类 * */public class MainActivity extends AppCompatActivity implements JsBridge{ public void MainActivity(){ } //定义日志 private static final String TAG = "MainActivity"; //定义一个webview 操作界面使用 private WebView mwebView; //定义一个textview 操作界面文字使用 private TextView mtextView; //定义一个 hadler private Handler mHandler; //自带的启动方法 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化添加接口内容 initWidgets(savedInstanceState); requestPermission(); } /** * 初始化以下 * * @param savedInstanceState */ private void initWidgets(Bundle savedInstanceState){ //链接到activitymain.xml中的配置的id(webview) mwebView = findViewById(R.id.webview); //链接到activitymain.xml中的配置的id(tv_result) mtextView = findViewById(R.id.tv_result); mHandler = new Handler(); //允许webview加载js mwebView.getSettings().setJavaScriptEnabled(true); //给WebView添加js接口 java中new ImoocJsInterface()对象等于js中 imoocJsInterface调用的时候使用 mwebView.addJavascriptInterface(new ImoocJsInterface(this),"imoocJsInterface"); //加载页面 file:///android_asset/index.html mwebView.loadUrl("file:///android_asset/index.html"); //调试使用 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { mwebView.setWebContentsDebuggingEnabled(true); } } //实现接口中操作文本及传递数据使用 @Override public void setTextViewValue(final String value) { Log.d(TAG, "value2="+value); //通过mHandler.post(方法操作mtextView文本 mHandler.post(new Runnable() { @Override public void run() { mtextView.setText(value); } }); String cz = value + "vk"; Map ma = new HashMap(); String sdkver = ""; Log.d("liteavsdk", "liteav sdk version is : " + sdkver); ma.put("ab","sss"+sdkver); //调用js方法 CallJS(ma); } /** * java调用js方法 * * @param str 传递的是一个map的数据也可以传递别的类型 */ public void CallJS(final Map str){ // 通过Handler发送消息//通过mHandler.post(方法操作mwebView并且调用js方法 mwebView.post(new Runnable() { @Override public void run() { // 注意调用的JS方法名要对应上 // 调用javascript的remo()方法 mwebView.loadUrl("javascript:if(window.remo){window.remo('"+str+"');}"); } }); } //-----------------------------------------支付宝相关-------------------------------------------------------- public static final String PID = "";//用于支付宝账户登录授入权业务的参 pid。 public static final String TARGET_ID = "";//用于支付宝账户登录授权业务的入参 target_id。 private static final int SDK_PAY_FLAG = 1; private static final int SDK_AUTH_FLAG = 2; @SuppressLint("HandlerLeak") private Handler alipayHandler = new Handler() { @SuppressWarnings("unused") public void handleMessage(Message msg) { switch (msg.what) { case SDK_PAY_FLAG: { @SuppressWarnings("unchecked") PayResult payResult = new PayResult((Map) msg.obj); /** * 对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。 */ String resultInfo = payResult.getResult();// 同步返回需要验证的信息 String resultStatus = payResult.getResultStatus(); // 判断resultStatus 为9000则代表支付成功 if (TextUtils.equals(resultStatus, "9000")) { // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。 showAlert(MainActivity.this, getString(R.string.pay_success) + payResult); } else { // 该笔订单真实的支付结果,需要依赖服务端的异步通知。 showAlert(MainActivity.this, getString(R.string.pay_failed) + payResult); } break; } case SDK_AUTH_FLAG: { @SuppressWarnings("unchecked") AuthResult authResult = new AuthResult((Map) msg.obj, true); String resultStatus = authResult.getResultStatus(); // 判断resultStatus 为“9000”且result_code // 为“200”则代表授权成功,具体状态码代表含义可参考授权接口文档 if (TextUtils.equals(resultStatus, "9000") && TextUtils.equals(authResult.getResultCode(), "200")) { // 获取alipay_open_id,调支付时作为参数extern_token 的value // 传入,则支付账户为该授权账户 showAlert(MainActivity.this, getString(R.string.auth_success) + authResult); } else { // 其他状态值则为授权失败 showAlert(MainActivity.this, getString(R.string.auth_failed) + authResult); } break; } default: break; } }; }; //从这往下和下边那个方法放到服务器上其他的都放在android 中 public static final String APPID = "201********";//用于支付宝支付业务的入参 app_id。 public static final String RSA2_PRIVATE = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwg************************=="; public static final String RSA_PRIVATE = ""; /** * 获取 加密内容 这个方法放在 服务器上 * * @return */ public String getorderParamSgin(){ if (TextUtils.isEmpty(APPID) || (TextUtils.isEmpty(RSA2_PRIVATE) && TextUtils.isEmpty(RSA_PRIVATE))) { return null; } boolean rsa2 = (RSA2_PRIVATE.length() > 0); Map params = OrderInfoUtil2_0.buildOrderParamMap(APPID, rsa2); String orderParam = OrderInfoUtil2_0.buildOrderParam(params); String privateKey = rsa2 ? RSA2_PRIVATE : RSA_PRIVATE; String sign = OrderInfoUtil2_0.getSign(params, privateKey, rsa2); String orderInfo = orderParam + "&" +sign; return orderInfo; } /** * 支付宝支付业务示例 */ public void payV22(View v) { final String orderInfo = getorderParamSgin(); final Runnable payRunnable = new Runnable() { @Override public void run() { PayTask alipay = new PayTask(MainActivity.this); Map result = alipay.payV2(orderInfo, true); Log.i("msp", result.toString()); Message msg = new Message(); msg.what = SDK_PAY_FLAG; msg.obj = result; alipayHandler.sendMessage(msg); } }; // 必须异步调用 Thread payThread = new Thread(payRunnable); payThread.start(); } /** * 支付宝账户授权业务示例 */ public void authV2(View v) { if (TextUtils.isEmpty(PID) || TextUtils.isEmpty(APPID) || (TextUtils.isEmpty(RSA2_PRIVATE) && TextUtils.isEmpty(RSA_PRIVATE)) || TextUtils.isEmpty(TARGET_ID)) { showAlert(this, getString(R.string.error_auth_missing_partner_appid_rsa_private_target_id)); return; } /* * 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成; * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成; * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险; * * authInfo 的获取必须来自服务端; */ boolean rsa2 = (RSA2_PRIVATE.length() > 0); Map authInfoMap = OrderInfoUtil2_0.buildAuthInfoMap(PID, APPID, TARGET_ID, rsa2); String info = OrderInfoUtil2_0.buildOrderParam(authInfoMap); String privateKey = rsa2 ? RSA2_PRIVATE : RSA_PRIVATE; String sign = OrderInfoUtil2_0.getSign(authInfoMap, privateKey, rsa2); final String authInfo = info + "&" + sign; Runnable authRunnable = new Runnable() { @Override public void run() { // 构造AuthTask 对象 AuthTask authTask = new AuthTask(MainActivity.this); // 调用授权接口,获取授权结果 Map result = authTask.authV2(authInfo, true); Message msg = new Message(); msg.what = SDK_AUTH_FLAG; msg.obj = result; alipayHandler.sendMessage(msg); } }; // 必须异步调用 Thread authThread = new Thread(authRunnable); authThread.start(); } /** * 获取支付宝 SDK 版本号。 */ public void showSdkVersion(View v) { PayTask payTask = new PayTask(this); String version = payTask.getVersion(); showAlert(this, getString(R.string.alipay_sdk_version_is) + version); } /** * 获取权限使用的 RequestCode */ private static final int PERMISSIONS_REQUEST_CODE = 1002; /** * 检查支付宝 SDK 所需的权限,并在必要的时候动态获取。 * 在 targetSDK = 23 以上,READ_PHONE_STATE 和 WRITE_EXTERNAL_STORAGE 权限需要应用在运行时获取。 * 如果接入支付宝 SDK 的应用 targetSdk 在 23 以下,可以省略这个步骤。 */ private void requestPermission() { // Here, thisActivity is the current activity if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.READ_PHONE_STATE, Manifest.permission.WRITE_EXTERNAL_STORAGE }, PERMISSIONS_REQUEST_CODE); } else { showToast(this, getString(R.string.permission_already_granted)); } } /** * 权限获取回调 */ @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case PERMISSIONS_REQUEST_CODE: { // 用户取消了弹权限窗 if (grantResults.length == 0) { showToast(this, getString(R.string.permission_rejected)); return; } // 用户拒绝了某些权限 for (int x : grantResults) { if (x == PackageManager.PERMISSION_DENIED) { showToast(this, getString(R.string.permission_rejected)); return; } } // 所需的权限均正常获取 showToast(this, getString(R.string.permission_granted)); } } } private static void showAlert(Context ctx, String info) { showAlert(ctx, info, null); } private static void showAlert(Context ctx, String info, DialogInterface.OnDismissListener onDismiss) { final AlertDialog show = new AlertDialog.Builder(ctx) .setMessage(info) .setPositiveButton(R.string.confirm, null) // .setOnDismissListener(onDismiss) .show(); } private static void showToast(Context ctx, String msg) { Toast.makeText(ctx, msg, Toast.LENGTH_LONG).show(); } //-----------------------------------------支付宝相关-------------------------------------------------------- }
- 代码中专门做了表中除了 appid 和秘钥 还有一个方法放到服务端剩下的都放在android 中就ok
- 对于引用aar包看官方文档就好
- 在demo中还有些alipay目录下的代码也放到服务端
- 其中有些 TextUitl 类中的方法 java server中可能没有 可以自己建一个类 然后放上 比较方法和判断为空的方法
activit代码
<?xml version="1.0" encoding="utf-8"?>
- activity 中重要的就是一个button 的点击按钮 别的没啥用是没有删除
- 里边有个webview 方便开发使用,不需要的key直接删了就好
总结思路:
- android 集成alipay 的思路就是通过调用 alipay的方法直接就可以启动alipay 支付宝的内容
server 端 开发思路
- 先看张图
- 这里专门介绍下server策略
- 1.通过客户端向服务端发起请求获取 加密的数据和加签
- 2.服务端获取到请求后解析出用户相关信息
- 3.然后通过demo中的 代码生成 加密数据和加签数据
- 4.传回到client 中
ok
文章持续更新!
更多相关文章
- android 程序开发的插件化 模块化方法 之二
- 关于“Android SDK manager中不出现完整Android版本安装包列表”
- 卜若的代码笔记系列-unity系列-第三章:android交互之android stud
- Android社交类APP动态详情代码实现通用模板
- Android关于apk版本更新方法
- Android之gallery 常见2种使用方法和3D效果总结
- 在 Android 中调用二进制可执行程序(native executable )-- 在代码