Android App接入支付功能——支付宝支付

接入前准备

接入APP支付能力前,开发者需要完成以下前置步骤。

本文档展示了如何从零开始,使用支付宝开放平台服务端 SDK 快速接入App支付产品,完成与支付宝对接的部分。

接入准备——支付宝开发能力

一.下载官方sdk,将sdk放入自己工程libs文件中:

 并且在我们的app/build.gradle里配置一下

    // 支付宝 SDK AAR 包所需的配置compile (name: 'alipaysdk-15.8.03.210428205839', ext: 'aar')//这里alipaysdk-15.8.03.210428205839必须和导入的sdk名字一样

二.配置清单文件AndroidManifest.xml:
①添加Activity声明:

        <activityandroid:name="com.alipay.sdk.pay.demo.PayDemoActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name="com.alipay.sdk.pay.demo.H5PayDemoActivity"android:configChanges="orientation|keyboardHidden|navigation"android:exported="false"android:screenOrientation="behind" ></activity>

 ②添加权限声明:

<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" />
<!-- 如果您的 App 的 targetSdkVersion 大于或等于 30,则需要在 AndroidManifest.xml 中提供下面的应用可见性声明,让支付宝 SDK 感知设备上是否已经安装了支付宝 App。同时,您可能还需要升级 Gradle Plugin 到最新版本。关于 Android 11 的 "应用可见性" 机制,参见 https://developer.android.com/about/versions/11/privacy/package-visibility?hl=zh-cn --><queries><package android:name="com.eg.android.AlipayGphone" /> <!-- 支付宝 --><package android:name="hk.alipay.wallet" /> <!-- AlipayHK --></queries>

 如果想混淆代码,在工程proguard-rules.pro添加如下代码:

-keep class com.alipay.android.app.IAlixPay{*;}
-keep class com.alipay.android.app.IAlixPay$Stub{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
-keep class com.alipay.sdk.app.PayTask{ public *;}
-keep class com.alipay.sdk.app.AuthTask{ public *;}
-keep class com.alipay.sdk.app.H5PayCallback {
<fields>;
<methods>;
}
-keep class com.alipay.android.phone.mrpc.core.** { *; }
-keep class com.alipay.apmobilesecuritysdk.** { *; }
-keep class com.alipay.mobile.framework.service.annotation.** { *; }
-keep class com.alipay.mobilesecuritysdk.face.** { *; }
-keep class com.alipay.tscenter.biz.rpc.** { *; }
-keep class org.json.alipay.** { *; }
-keep class com.alipay.tscenter.** { *; }
-keep class com.ta.utdid2.** { *;}
-keep class com.ut.device.** { *;}

三.支付接口调用

     PayDemoActivity.java


public class PayDemoActivity extends AppCompatActivity {public static int price=100;/*** 用于支付宝支付业务的入参 app_id。*/public static final String APPID = "************";/*** 用于支付宝账户登录授权业务的入参 pid。*/public static final String PID = "************";/*** 用于支付宝账户登录授权业务的入参 target_id。商家的收款账号*/public static final String TARGET_ID = "************";/***  pkcs8 格式的商户私钥。** 	如下私钥,RSA2_PRIVATE 或者 RSA_PRIVATE 只需要填入一个,如果两个都设置了,本 Demo 将优先* 	使用 RSA2_PRIVATE。RSA2_PRIVATE 可以保证商户交易在更加安全的环境下进行,建议商户使用* 	RSA2_PRIVATE。** 	建议使用支付宝提供的公私钥生成工具生成和获取 RSA2_PRIVATE。* 	工具地址:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=106097&docType=1*/public static final String RSA2_PRIVATE = "************";//密钥public static final String RSA_PRIVATE = "";private static final int SDK_PAY_FLAG = 1;private static final int SDK_AUTH_FLAG = 2;@SuppressLint("HandlerLeak")private Handler mHandler = new Handler() {@SuppressWarnings("unused")public void handleMessage(Message msg) {switch (msg.what) {case SDK_PAY_FLAG: {@SuppressWarnings("unchecked")PayResult payResult = new PayResult((Map<String, String>) msg.obj);/*** 对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。*/String resultInfo = payResult.getResult();// 同步返回需要验证的信息String resultStatus = payResult.getResultStatus();// 判断resultStatus 为9000则代表支付成功if (TextUtils.equals(resultStatus, "9000")) {// 该笔订单是否真实支付成功,需要依赖服务端的异步通知。showAlert(PayDemoActivity.this, getString(R.string.pay_success) + payResult);} else {// 该笔订单真实的支付结果,需要依赖服务端的异步通知。showAlert(PayDemoActivity.this, getString(R.string.pay_failed) + payResult);}break;}}};};@Overrideprotected void onCreate(Bundle savedInstanceState) {
//		EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);//沙箱环境需要的代码super.onCreate(savedInstanceState);setContentView(R.layout.pay_main);Button button = findViewById(R.id.payV2);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {payV2(v);}});}/*** 支付宝支付业务示例*/public void payV2(View v) {if (TextUtils.isEmpty(APPID) || (TextUtils.isEmpty(RSA2_PRIVATE) && TextUtils.isEmpty(RSA_PRIVATE))) {showAlert(this, getString(R.string.error_missing_appid_rsa_private));return;}/** 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;* 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;* 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险; * * orderInfo 的获取必须来自服务端;*/boolean rsa2 = (RSA2_PRIVATE.length() > 0);Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID, rsa2,price);String orderParam = OrderInfoUtil2_0.buildOrderParam(params);String privateKey = rsa2 ? RSA2_PRIVATE : RSA_PRIVATE;String sign = OrderInfoUtil2_0.getSign(params, privateKey, rsa2);final String orderInfo = orderParam + "&" + sign;final Runnable payRunnable = new Runnable() {@Overridepublic void run() {PayTask alipay = new PayTask(PayDemoActivity.this);Map<String, String> result = alipay.payV2(orderInfo, true);Log.i("msp", result.toString());Message msg = new Message();msg.what = SDK_PAY_FLAG;msg.obj = result;mHandler.sendMessage(msg);}};// 必须异步调用Thread payThread = new Thread(payRunnable);payThread.start();}private static void showAlert(Context ctx, String info) {showAlert(ctx, info, null);}private static void showAlert(Context ctx, String info, DialogInterface.OnDismissListener onDismiss) {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();}private static String bundleToString(Bundle bundle) {if (bundle == null) {return "null";}final StringBuilder sb = new StringBuilder();for (String key: bundle.keySet()) {sb.append(key).append("=>").append(bundle.get(key)).append("\n");}return sb.toString();}
}

OrderInfoUtil2_0.java


public class OrderInfoUtil2_0 {/*** 构造授权参数列表** @param pid* @param app_id* @param target_id* @return*/public static Map<String, String> buildAuthInfoMap(String pid, String app_id, String target_id, boolean rsa2) {Map<String, String> keyValues = new HashMap<String, String>();// 商户签约拿到的app_id,如:2013081700024223keyValues.put("app_id", app_id);// 商户签约拿到的pid,如:2088102123816631keyValues.put("pid", pid);// 服务接口名称, 固定值keyValues.put("apiname", "com.alipay.account.auth");// 服务接口名称, 固定值keyValues.put("methodname", "alipay.open.auth.sdk.code.get");// 商户类型标识, 固定值keyValues.put("app_name", "mc");// 业务类型, 固定值keyValues.put("biz_type", "openservice");// 产品码, 固定值keyValues.put("product_id", "APP_FAST_LOGIN");// 授权范围, 固定值keyValues.put("scope", "kuaijie");// 商户唯一标识,如:kkkkk091125keyValues.put("target_id", target_id);// 授权类型, 固定值keyValues.put("auth_type", "AUTHACCOUNT");// 签名类型keyValues.put("sign_type", rsa2 ? "RSA2" : "RSA");return keyValues;}/*** 构造支付订单参数列表*/public static Map<String, String> buildOrderParamMap(String app_id, boolean rsa2,int price) {Map<String, String> keyValues = new HashMap<String, String>();keyValues.put("app_id", app_id);keyValues.put("biz_content", "{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"total_amount\":\""+price+"\",\"subject\":\"1\",\"body\":\"我是测试数据\",\"out_trade_no\":\"" + getOutTradeNo() +  "\"}");keyValues.put("charset", "utf-8");keyValues.put("method", "alipay.trade.app.pay");keyValues.put("sign_type", rsa2 ? "RSA2" : "RSA");keyValues.put("timestamp", "2016-07-29 16:55:53");keyValues.put("version", "1.0");return keyValues;}/*** 构造支付订单参数信息** @param map* 支付订单参数* @return*/public static String buildOrderParam(Map<String, String> map) {List<String> keys = new ArrayList<String>(map.keySet());StringBuilder sb = new StringBuilder();for (int i = 0; i < keys.size() - 1; i++) {String key = keys.get(i);String value = map.get(key);sb.append(buildKeyValue(key, value, true));sb.append("&");}String tailKey = keys.get(keys.size() - 1);String tailValue = map.get(tailKey);sb.append(buildKeyValue(tailKey, tailValue, true));return sb.toString();}/*** 拼接键值对** @param key* @param value* @param isEncode* @return*/private static String buildKeyValue(String key, String value, boolean isEncode) {StringBuilder sb = new StringBuilder();sb.append(key);sb.append("=");if (isEncode) {try {sb.append(URLEncoder.encode(value, "UTF-8"));} catch (UnsupportedEncodingException e) {sb.append(value);}} else {sb.append(value);}return sb.toString();}/*** 对支付参数信息进行签名** @param map*            待签名授权信息** @return*/public static String getSign(Map<String, String> map, String rsaKey, boolean rsa2) {List<String> keys = new ArrayList<String>(map.keySet());// key排序Collections.sort(keys);StringBuilder authInfo = new StringBuilder();for (int i = 0; i < keys.size() - 1; i++) {String key = keys.get(i);String value = map.get(key);authInfo.append(buildKeyValue(key, value, false));authInfo.append("&");}String tailKey = keys.get(keys.size() - 1);String tailValue = map.get(tailKey);authInfo.append(buildKeyValue(tailKey, tailValue, false));String oriSign = SignUtils.sign(authInfo.toString(), rsaKey, rsa2);String encodedSign = "";try {encodedSign = URLEncoder.encode(oriSign, "UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}return "sign=" + encodedSign;}/*** 要求外部订单号必须唯一。* @return*/private static String getOutTradeNo() {SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss", Locale.getDefault());Date date = new Date();String key = format.format(date);Random r = new Random();key = key + r.nextInt();key = key.substring(0, 15);return key;}}

 工具类

     1.SignUtils.java


public class SignUtils {private static final String ALGORITHM = "RSA";private static final String SIGN_ALGORITHMS = "SHA1WithRSA";private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";private static final String DEFAULT_CHARSET = "UTF-8";private static String getAlgorithms(boolean rsa2) {return rsa2 ? SIGN_SHA256RSA_ALGORITHMS : SIGN_ALGORITHMS;}public static String sign(String content, String privateKey, boolean rsa2) {try {PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey));KeyFactory keyf = KeyFactory.getInstance(ALGORITHM);PrivateKey priKey = keyf.generatePrivate(priPKCS8);java.security.Signature signature = java.security.Signature.getInstance(getAlgorithms(rsa2));signature.initSign(priKey);signature.update(content.getBytes(DEFAULT_CHARSET));byte[] signed = signature.sign();return Base64.encode(signed);} catch (Exception e) {e.printStackTrace();}return null;}}

 2.PayResult.java


public class PayResult {private String resultStatus;private String result;private String memo;public PayResult(Map<String, String> rawResult) {if (rawResult == null) {return;}for (String key : rawResult.keySet()) {if (TextUtils.equals(key, "resultStatus")) {resultStatus = rawResult.get(key);} else if (TextUtils.equals(key, "result")) {result = rawResult.get(key);} else if (TextUtils.equals(key, "memo")) {memo = rawResult.get(key);}}}@Overridepublic String toString() {return "resultStatus={" + resultStatus + "};memo={" + memo+ "};result={" + result + "}";}/*** @return the resultStatus*/public String getResultStatus() {return resultStatus;}/*** @return the memo*/public String getMemo() {return memo;}/*** @return the result*/public String getResult() {return result;}
}

 3.ExternalFragment.java


public class ExternalFragment extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {return inflater.inflate(R.layout.pay_external, container, false);}
}

4.在 Android_Demo中移过来这三个

五.布局文件

    pay_external.xml

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><Buttonandroid:id="@+id/payV2"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:onClick="payV2"android:textAllCaps="false"android:text="@string/pay_with_alipay" /></LinearLayout></ScrollView>

     pay_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical"android:gravity="center_horizontal"android:background="#FFFFFF"><ImageViewandroid:layout_marginTop="16dp"android:layout_marginBottom="16dp"android:layout_width="wrap_content"android:layout_height="wrap_content"android:scaleType="centerInside"android:src="@drawable/alipay_logo" /><fragmentandroid:id="@+id/fragment"android:name="com.alipay.sdk.pay.demo.ExternalFragment"android:layout_width="fill_parent"android:layout_height="wrap_content"tools:layout="@layout/pay_external" /></LinearLayout>

本方法调用的返回结果,参数说明见"客户端同步返回参数说明"。

 至此,支付宝支付代码已完成!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/70649.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

推荐一个优秀人工智能(AI)学习网站:Quester AI

网站链接如下&#xff1a; QuesterAI 简要介绍&#xff1a; Quester AI全方位地整合AI学习资源&#xff0c;对每一个从业者&#xff0c;学习者开放&#xff0c;并且是免费开放。同时&#xff0c;Quester AI努力为AI领域学习者和爱好者大量提供持续的AI开源资源&#xff0c;给…

人工智能的数学方法

要成为一名出色的 AI 软件工程师&#xff0c;需要了解多少数学知识&#xff1f;&#x1f914; 在之前的一篇文章中&#xff0c;我写过学习任何主题或领域基础知识的重要性。我建议你先阅读它&#xff08;如果你还没有&#xff09;&#xff0c;以便完全理解这篇文章。 如果您已经…

让人工智能解数学题,可能没你想象的那么简单

来源&#xff1a;微软研究院AI头条&#xff0c;授权CSDN发布。 欢迎人工智能领域技术投稿、约稿、给文章纠错&#xff0c;请发送邮件至heyccsdn.net 约1500年前的古代数学著作《孙子算经》中记载了一个有趣的问题&#xff1a;“今有雉兔同笼&#xff0c;上有三十五头&#xff0…

给自己的课程打个广告

给自己的一些付费课程打个广告吧&#xff0c;金额不高&#xff0c;但你们的支持可以让我在写作、分享时更有动力&#xff0c;在媳妇面前也更有地位哈哈&#xff0c;谢谢支持了&#xff01;&#xff01; 有问题欢迎留言或者加我微信: sxkejinet 面试经验分享OkHttp3 和 Retrofit…

大学生个人职业生涯规划书PPT

大学生如何职业生涯规划主要是指根据个人的兴趣、性格特点、内在潜能来确立个人的职业发展目标&#xff0c;并根据自身情况对未来职业生涯上的短期目标、中期目标和长期目标进行设定&#xff0c;根据设定的这些目标来规划不同阶段下需要完成自我提升的通道。简而言之就是自身通…

python职业规划书_大学生职业规划书

职业生涯规划&#xff08;简称生涯规划&#xff09;&#xff0c;又叫职业生涯设计&#xff0c;是将个人与组织相结合&#xff0c;在对一个人职业生涯的主客观条件进行测定、分析、总结的基础上&#xff0c;对自己的兴趣、爱好、能力、特点进行综合分析与权衡&#xff0c;结合时…

计算机相关专业的学生如何规划自己的职业?

一、 前言 2017年曾经写过一篇关于学什么编程方向的文章&#xff0c;当时反响很大&#xff0c;有不少在校的社团组织私下授权转载我的文章。现在的大学&#xff0c;两极分化极其严重&#xff0c;优秀的同学毕业找工作顺风顺水&#xff0c;平庸甚至较差的同学&#xff0c;找工作…

大学生职业规划策划书

一.前言 我时常问自己“人生之路到底该如何去走”&#xff0c;长久以来我也不断思考并在实践中体会这个问题。心中记得这样一句话“走好每一步&#xff0c;这就是你的人生。”人生之路其实十分短暂&#xff0c;因为你度过的每一天或者每一秒就是你的人生。正因为人生经不起虚度…

大学生职业生涯规划的意义

前言职业生涯规划是指个人发展与组织发展相结合&#xff0c;通过对职业生涯的主客观因素分析、总结和测定&#xff0c;确定一个人的奋斗目标&#xff0c;并为实现这一事业职业目标&#xff0c;而预先进行生涯系统安排的过程。在任何社会、任何体制下&#xff0c;个人职业设计更…

职业生涯规划(career planning)

本文转自&#xff1a;WIKI智库&#xff08;https://wiki.mbalib.com/wiki/职业生涯规划&#xff09; 职业生涯规划的定义 职业生涯规划&#xff08;简称生涯规划&#xff09;&#xff0c;又叫职业生涯设计&#xff0c;是指个人与组织相结合&#xff0c;在对一个人职业生涯的主…

计算机个人职业生涯规划

个人职业生涯规划 摘要 在当下竞争激烈的时代&#xff0c;如果没有做好充分的准备就去迎接社会的毒打&#xff0c;往往是遍体鳞伤。而一个人的职业规划将是我们面对社会的最好的铠甲&#xff0c;即使是简单的未来规划&#xff0c;也会使你成长的路上少点磕绊&#xff0c;所以…

大一上:大学生职业生涯规划书【自我性格、气质、及其优缺点的分析】

大学生职业生涯规划书 一、My MBTI 二、自我描述 我的性格类型倾向为“ INTJ ”(内向 直觉 思维 判断 倾向度&#xff1a; I57 N100 T86 J100 不假思索指数&#xff1a;11) 我在实现自己的想法和达成自己的目标时有创新的想法和非凡的动力。能很快洞察到外界事物间的规律并形…

软件工程大学生职业规划书

引言 在今天这个人才竞争时代&#xff0c;职业生涯规划开始成为在人争夺战中 另一重要利器&#xff0c;对企业而言&#xff0c;如何体现公司“以人为本”人才理念&#xff0c; 关注员工人才理念&#xff0c;关注员工持续成长&#xff0c;职业生涯规划是一种有效手段; 而对每个人…

职业生涯规划访谈,写给在校的你们

今天一位在校大学生邀请我在线做一个关于职业生涯规划的访谈&#xff0c;在此我将他提出的问题以及我个人的一些看法贴出&#xff0c;希望能给在校或是即将毕业的你们有所帮助。 问: 老师你好&#xff0c;就是我想问一下我们计算机专业的大学生&#xff0c;在课堂上学好必要的知…

大学生职业生涯发展与规划

《创业教育课程&#xff08;一&#xff09;----大学生职业生涯发展与规划》 结课作业要求 作业选题&#xff1a;大学规划书 作业要求&#xff1a;从自身的情况、现状出发&#xff0c;有针对性地制定一份详尽的增强自身就业能力的大学规划书&#xff0c;根据相关社会要求有针对性…

流利阅读 2019.2.23 China’s Forbidden City opens to the general public at night for the first time in 94

下载 笔记版/无笔记版 pdf资料&#xff1a; GitHub - zhbink/LiuLiYueDu: 流利阅读pdf汇总 本文内容全部来源于流利阅读。流利阅读对每期内容均有很好的文章讲解&#xff0c;向您推荐。 您可以关注微信公众号&#xff1a;流利阅读 了解详情。 China’s Forbidden City opens to…

英语阅读——2004

文章目录 词汇名词性从句1.主语从句与It形式主语1.1主语从句1.2It形式主语 独立主格结构with独立主格结构倒装句1.完全倒装句1.1副词在句首的倒装1.1.1地点副词在句首的倒装(here、there)1.1.2时间副词在句首的倒装(now、then)1.1.3表运动方向的副词在句首的倒装(in、out、up、…

chatgpt赋能python:用Python开发软件的SEO技巧

用Python开发软件的SEO技巧 随着互联网的发展&#xff0c;越来越多的企业开始意识到网络营销的重要性&#xff0c;而SEO&#xff08;搜索引擎优化&#xff09;是网络营销的重中之重。对于软件开发企业来说&#xff0c;利用SEO技术进行软件推广是很实用的。本文将介绍如何使用P…

目标检测算法——YOLOv5/YOLOv7改进|结合轻量型网络ShuffleNetV2

深度学习Tricks&#xff0c;第一时间送达 论文题目&#xff1a;《ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design》论文地址&#xff1a; https://arxiv.org/abs/1807.11164 FLOPS&#xff1a;每秒浮点运算次数&#xff0c;这个由硬件决定。 G…

魔改YOLOv5/YOLOv7高阶版——改进之结合解耦头Decoupled_Detect

💖💖>>>加勒比海带,QQ2479200884<<<💖💖 🍀🍀>>>【YOLO魔法搭配&论文投稿咨询】<<<🍀 ✨✨>>>学习交流 | 温澜潮生 | 合作共赢 | 共同进步<<<✨✨