1.注册企业账号;
2.创建应用 ;
3.配置应用 ;
4.开启支付APP支付 ;
5.签约,在支付宝开放平台中跟着步骤走就可以完成的操作,为对接做准备工作。
6.去管理中心得到应用的APPID;
7.用支付宝开放平台开发助手生成一一对密钥,分别是应用公钥和私钥
8.用应用公钥去生成支付宝公钥,如图,点击 设置公钥
9.填写异步通知URL;
然后就可以开始做服务端和客户端的开发啦!
(1)首先要配置的东西:APP_ID、APP_PRIVATE_KEY(用支付宝开放平台开发助手生成的私钥)、ALIPAY_PUBLIC_KEY(支付宝公钥)。
对于怎么才能得到APPID。首先你得是企业账号才能接入支付宝支付,因为还要签约的。
在这里想说明一下,很多人都分不清私钥和公钥到底要怎么用,用哪一个?其实很简单。首先是打开这个支付宝开放平台开发助手,如下图
点击生成密钥,就会生成一个公钥和一个私钥。这个私钥就是我上面所说的APP_PRIVATE_KEY,但是这个生成的公钥有什么用呢?
这个公钥要把它放到支付宝开发平台那里,把它生成支付宝公钥,而生成的支付宝公钥,就是我上述所说的ALIPAY_PUBLIC_KEY。至于普通的公钥怎么才能生成支付宝公钥呢?
点击设置公钥,就能生成支付宝公钥了。
有写可能会问,为什么要这么做呢?我们要知道这三个密钥的作用分别是什么,用着才不会乱。
1.应用私钥:用于请求支付宝数据加签(放在服务端);
2.应用公钥:用于提供给支付宝,让支付宝去拿着公钥获取你私钥加签后的数据;(放在支付宝开发平台用于生成支付宝公钥);
3.支付宝公钥:是用来接收支付宝回调信息的(放在服务端);
这样说应该可以明白了吧。
(2)jar包:支付宝SDK.jar包
(3)代码实现:springboot
6个java类
1.先来看看 DemoApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
2.BaseEntity.java
public class BaseEntity {
private String code;
private String message;
private Object content;
public BaseEntity(String code, String message, Object content) {
this.code = code;
this.message = message;
this.content = content;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getContent() {
return content;
}
public void setContent(Object content) {
this.content = content;
}
}
3.AlipayConfig.java 这个类是配置三个参数的
public class AlipayConfig {
public static final String APP_ID = “这里填签约后的APPID”;
public static final String APP_PRIVATE_KEY = “这里填用支付宝开放平台开发助手生成的应用私钥”;
public static final String ALIPAY_PUBLIC_KEY = “这里填支付宝公钥”;
public static final String CHARSET = “UTF-8”;
}
4.AlipayController.java 当客户端发起支付宝请求时,会先生成一个商户号,并根据这个商户号来新建订单表,订单状态暂时为未支付。当客户端支付成功之后,服务端会接收到异步通知,当通知支付成功的时候,可以把订单的状态改成已支付。但是要确保异步通知的URL必须是外网可以访问得到。
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.example.demo.bean.BaseEntity;
import com.example.demo.config.AlipayConfig;
import com.example.demo.utils.AliRequestParam;
import com.example.demo.utils.OrderNo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
public class AlipayController {
@SuppressWarnings(“unchecked”)
@RequestMapping(value = “/alipay”, method = RequestMethod.POST)
public Object alipayment(@RequestParam String payMoney) {
AlipayClient alipayClient = new DefaultAlipayClient(“https://openapi.alipay.com/gateway.do”,
AlipayConfig.APP_ID, AlipayConfig.APP_PRIVATE_KEY, “json”,
AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY,
“RSA2”);
String out_trade_no=OrderNo.getOutTradeNo();
System.out.println(“商户订单号”+out_trade_no);
//构建支付宝请求参数
AlipayTradeAppPayRequest request = AliRequestParam.startRequestAli(payMoney,out_trade_no);
try {
//这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
System.out.println(response.getBody());//就是orderString 可以直接给客户端请求,客户端可以直接发起支付,无需再做处理。
@SuppressWarnings(“rawtypes”)
Map map = new HashMap();
map.put(“orderString”, response.getBody());
BaseEntity baseEntity = new BaseEntity(“200”, “支付宝下单成功”, map);
//这里做生成订单操作,订单状态为未支付
return baseEntity;
} catch (AlipayApiException e) {
e.printStackTrace();
}
BaseEntity baseEntity = new BaseEntity(“200”, “支付宝下单失败”, null);
return baseEntity;
}
//异步通知
@RequestMapping(value = “/pay_notify”,method = RequestMethod.POST)
public void notifyUrl(HttpServletResponse response,HttpServletRequest request) throws IOException, AlipayApiException {
System.out.println(“异步通知”);
PrintWriter out = response.getWriter();
request.setCharacterEncoding(“utf-8”);//乱码解决,这段代码在出现乱码时使用
//获取支付宝POST过来反馈信息
Map<String,String> params = new HashMap<String,String>();
Map<String,String[]> requestParams = request.getParameterMap();
for(String str :requestParams.keySet()){
String name = str;
String[] values = (String[]) requestParams.get(name);
String valueStr = “”;
for (int i = 0; i < values.length; i++) {
-
valueStr = (i == values.length - 1) ? valueStr + values[i]
- valueStr + values[i] + “,”;
}
params.put(name, valueStr);
}
boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, “RSA2”); //调用SDK验证签名
if(!signVerified) {
System.out.println(“验签失败”);
out.print(“fail”);
return;
}
//商户订单号,之前生成的带用户ID的订单号
String out_trade_no = params.get(“out_trade_no”);
//支付宝交易号
String trade_no = params.get(“trade_no”);
//付款金额
String total_amount = params.get(“total_amount”);
//交易状态
String trade_status = new String(request.getParameter(“trade_status”).getBytes(“ISO-8859-1”),“UTF-8”);
// String appId=params.get(“app_id”);//支付宝分配给开发者的应用Id
// String notifyTime=params.get(“notify_time”);//通知时间:yyyy-MM-dd HH:mm:ss
// String gmtCreate=params.get(“gmt_create”);//交易创建时间:yyyy-MM-dd HH:mm:ss
String gmtPayment=params.get(“gmt_payment”);//交易付款时间
// String gmtRefund=params.get(“gmt_refund”);//交易退款时间
// String gmtClose=params.get(“gmt_close”);//交易结束时间
// String tradeNo=params.get(“trade_no”);//支付宝的交易号
// String outTradeNo = params.get(“out_trade_no”);//获取商户之前传给支付宝的订单号(商户系统的唯一订单号)
// String outBizNo=params.get(“out_biz_no”);//商户业务号(商户业务ID,主要是退款通知中返回退款申请的流水号)
// String buyerLogonId=params.get(“buyer_logon_id”);//买家支付宝账号
// String sellerId=params.get(“seller_id”);//卖家支付宝用户号
// String sellerEmail=params.get(“seller_email”);//卖家支付宝账号
// String totalAmount=params.get(“total_amount”);//订单金额:本次交易支付的订单金额,单位为人民币(元)
// String receiptAmount=params.get(“receipt_amount”);//实收金额:商家在交易中实际收到的款项,单位为元
// String invoiceAmount=params.get(“invoice_amount”);//开票金额:用户在交易中支付的可开发票的金额
// String buyerPayAmount=params.get(“buyer_pay_amount”);//付款金额:用户在交易中支付的金额
// String tradeStatus = params.get(“trade_status”);// 获取交易状态
if(trade_status.equals(“TRADE_FINISHED”)){
/此处可自由发挥/
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//如果有做过处理,不执行商户的业务程序
//注意:
//退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
}else if (trade_status.equals(“TRADE_SUCCESS”)){
//这里就可以更新订单状态为已支付啦
}
out.print(“success”);
}
}
5.AliRequestParam.java
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
public class AliRequestParam {
public static AlipayTradeAppPayRequest startRequestAli(String payMoney,String trade_no) {
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody(“某公司”);
model.setSubject(“某商品”);
model.setOutTradeNo(trade_no);
model.setTimeoutExpress(“30m”);
model.setTotalAmount(payMoney);
model.setProductCode(“QUICK_MSECURITY_PAY”);
request.setBizModel(model);
request.setNotifyUrl(“这里填你服务端的地址+异步通知的地址,如:http://example.com/pay_notify”);//这里要注意的是,这个地址外网必须要能访问,不然服务端无法接收到异步通知的,你只需要把example.com改成你的ip地址和端口号即可,如果做了端口映射的话就只填ip地址即可
return request;
}
}
6.OrderNo.java
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Random;
public class OrderNo {
/**
- get the out_trade_no for an order. 生成商户订单号,该值在商户端应保持唯一(可自定义格式规范)
*/
public 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;
}
}
7.application.properties
server.port=8080
8.pom.xml
<?xml version="1.0" encoding="UTF-8"?><project xmlns=“http://maven.apache.org/POM/4.0.0” xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
4.0.0
com.example
demo
0.0.1-SNAPSHOT
jar
demo
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
1.5.8.RELEASE
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
服务器到这就完成啦。
1.依赖
//http请求
implementation ‘com.zhy:okhttputils:2.6.2’
implementation ‘com.squareup.okhttp3:okhttp:3.10.0’
implementation ‘com.alibaba:fastjson:1.2.39’
2…PayDemoActivity 活动
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;
import androidx.fragment.app.FragmentActivity;
import com.alibaba.fastjson.JSON;
import com.alipay.sdk.app.EnvUtils;
import com.learn.agg.R;
import com.learn.agg.alipay.AlipayAck;
import com.learn.agg.alipay.AlipayHelper;
import com.learn.agg.alipay.URLInterface;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;
import okhttp3.Call;
/**
-
重要说明:
-
-
这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;
-
真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;
-
防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险;
*/
public class PayDemoActivity extends FragmentActivity {
/** 商户私钥,pkcs8格式 */
/** 如下私钥,RSA2_PRIVATE 或者 RSA_PRIVATE 只需要填入一个 */
/** 如果商户两个都设置了,优先使用 RSA2_PRIVATE */
/** RSA2_PRIVATE 可以保证商户交易在更加安全的环境下进行,建议使用 RSA2_PRIVATE */
/** 获取 RSA2_PRIVATE,建议使用支付宝提供的公私钥生成工具生成, */
public PayDemoActivity() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
super.onCreate(savedInstanceState);
setContentView(R.layout.pay_main);
RadioGroup radioGroup;
final RadioButton alipay;
alipay = findViewById(R.id.alipay);
radioGroup = findViewById(R.id.payWay_choose);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
if (alipay.getId()==i){
}
}
});
}
/**
-
支付宝支付业务
-
@param v
*/
public void payV2(View v) {
/**
-
这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;
-
真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;
-
防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险;
-
orderInfo的获取必须来自服务端
-
如果RSA2_PRIVATE RSA_PRIVATE都设置了,那么我是优先选择RSA2_PRIVATE,因为更加安全
*/
//这里是用OkHttpUtils向服务器发起请求
String url = URLInterface.BASE_URL + “/alipay”;
String paymoney = “0.05”;//分为单位 1==1元
OkHttpUtils
.post()
.url(url)
.addParams(“payMoney”, paymoney )
.build()
.execute(new StringCallback() {
@Override
public void onError(Call call, Exception e, int id) {
Toast.makeText(PayDemoActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
@Override
public void onResponse(String response, int id) {
AlipayAck alipayAck = JSON.parseObject(response, AlipayAck.class);
Toast.makeText(PayDemoActivity.this, alipayAck.getMessage(), Toast.LENGTH_SHORT).show();
testAliPay(alipayAck.getContent().getOrderString());
}
});
}
private void testAliPay(String orderInfo) {
AlipayHelper mAlipayHelper = new AlipayHelper();
mAlipayHelper.startAlipay(this, orderInfo, new AlipayHelper.OnPayClickListener() {
@Override
public void paySuccess() {
//支付成功
Log.d(“tag”, “paySuccess: 哈哈哈”);
Toast.makeText(PayDemoActivity.this,“支付成功”,Toast.LENGTH_LONG).show();
//支付成功的操作
}
@Override
public void payFailure() {
//支付失败
Log.d(“tag”, "payFailure: ");
}
});
}
}
3.AlipayAck.java
public class AlipayAck extends BaseEntity {
private ContentBean content;
public ContentBean getContent() {
return content;
}
public void setContent(ContentBean content) {
this.content = content;
}
public static class ContentBean {
private String orderString;
private String out_trade_no;
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getOrderString() {
return orderString;
}
public void setOrderString(String orderString) {
this.orderString = orderString;
}
}
}
4.AlipayHelper.java
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import com.alipay.sdk.app.PayTask;
import java.util.Map;
public class AlipayHelper {
private static final int SDK_PAY_FLAG = 1;
private static AlipayHelper mAlipayHelper = new AlipayHelper();
private OnPayClickListener onPayClickListener;
//支付成功接口回调
public interface OnPayClickListener {
void paySuccess();
void payFailure();
}
public void startAlipay(final Activity activity, final String orderInfo, OnPayClickListener onPayClickListener) {
if (onPayClickListener == null || activity == null || orderInfo == null) {
return;
}
this.onPayClickListener = onPayClickListener;
Runnable payRunnable = new Runnable() {
@Override
public void run() {
PayTask alipay = new PayTask(activity);
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();
}
@SuppressLint(“HandlerLeak”)
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
Android开发除了flutter还有什么是必须掌握的吗?
相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了
除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
}
};
Thread payThread = new Thread(payRunnable);
payThread.start();
}
@SuppressLint(“HandlerLeak”)
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-H83OlH8u-1713634711104)]
[外链图片转存中…(img-hQubokZo-1713634711106)]
[外链图片转存中…(img-SdkQBU8u-1713634711108)]
[外链图片转存中…(img-LLTWHOvH-1713634711110)]
[外链图片转存中…(img-PDurO4GF-1713634711111)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
Android开发除了flutter还有什么是必须掌握的吗?
相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了
除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;
[外链图片转存中…(img-YATYbDEm-1713634711112)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!