个人网站实现支付宝支付
学习Java web,对于电商支付应用…应该比较频繁;
前期准备沙箱环境
首先要登录支付宝~
进入管理中心, 阿里巴巴提供的开发者中心控制台
开发选择中选择 研发服务
- 这里提供了一些沙盒模型. 可以进行测试模拟交易。。。
沙盒应用:
这里的RSA2密钥最好设置下,我已经设置好了,所以便有了支付宝公钥(公钥是对外公开的,私钥是自己保留的具体的不多做解释)
工具的话官方都有提供:
使用商户公钥——获取支付宝公钥但是私钥还是要保存的, 自己还需要用私钥来建立连接....
将公钥放进保存即可自动生成 支付宝公钥
ok, 环境准备好了就是写代码了…
了解支付宝支付流程
一共有三个角色: 用户
商家服务/客户端
支付宝服务/客户端
- 1:用户 通过 商家客户端
- 2:请求一个支付宝付款
- 3:商家服务 生成一个带签名的订单发送给商家客户端 这个签名订单
唯一标识了这个订单
- 4:客户端通过这个订单向app sdk请求付款
- 5.6.7.8:支付成功后支付宝向前端返回支付成功结果,
- 9:并且向服务器发送一个支付通知
- 10.11:服务器接收通知并且验证是否是支付宝发送的成功结果
商家app需要做的很简单:
- 向自己的服务器请求一个订单,
- 接收到订单后,向支付宝sdk发情一个支付请求:
根据用户对支付做出的操作...
支付宝服务器/客户端,返回响应的数据进行处理…订单状态更改…记录数据库… - 交易结束后返回一个成功或者失败
创建一个Myelipse 项目:
开发环境
myelipse2014
SpringMVC 工程…需要引入Spring的环境;
jdk1.8
需要Jar
web.xml | applicationContext-mvc.xml 就不讲解了....
com.wsm.config 配置
这是支付宝进行连接的配置…AlipayConfig.Java
public class AlipayConfig {
// 商户appid
public static String APPID = "填写自己的商家appid";
// 商户私钥 pkcs8格式的
public static String RSA_PRIVATE_KEY = "填写自己的商家私钥!";
// 支付宝公钥
public static String ALIPAY_PUBLIC_KEY = "填写自己的支付宝公钥!";
//根据商家自己的项目来: localhost:8080/项目 本地:端口/项目...
// 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问;
public static String notify_url = "http://localhost:8080/zfb_demo/mynotify";
// 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
public static String return_url = "http://localhost:8080/zfb_demo/myreturn"; //支付宝,完成订单后返回的商家接口...
// ?参数会覆盖支付宝服务器,返回的参数...所以一定不能加 ?问号!!
// 请求网关地址
public static String URL = "https://openapi.alipaydev.com/gateway.do";
// 编码
public static String CHARSET = "UTF-8";
// 返回格式
public static String FORMAT = "json";
// 日志记录目录
public static String log_path = "/log";
// RSA2
public static String SIGNTYPE = "RSA2";
}
//将商家appid 商户私钥 支付宝公钥修改为对于的商家...
//其它的就使用默认配置即可...
支付宝提供的页面 index.jsp
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>支付宝手机网站支付接口</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<style>
* {
margin: 0;
padding: 0;
}
ul,ol {
list-style: none;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
}
.hidden {
display: none;
}
.new-btn-login-sp {
padding: 1px;
display: inline-block;
width: 75%;
}
.new-btn-login {
background-color: #02aaf1;
color: #FFFFFF;
font-weight: bold;
border: none;
width: 100%;
height: 30px;
border-radius: 5px;
font-size: 16px;
}
#main {
width: 100%;
margin: 0 auto;
font-size: 14px;
}
.red-star {
color: #f00;
width: 10px;
display: inline-block;
}
.null-star {
color: #fff;
}
.content {
margin-top: 5px;
}
.content dt {
width: 100px;
display: inline-block;
float: left;
margin-left: 20px;
color: #666;
font-size: 13px;
margin-top: 8px;
}
.content dd {
margin-left: 120px;
margin-bottom: 5px;
}
.content dd input {
width: 85%;
height: 28px;
border: 0;
-webkit-border-radius: 0;
-webkit-appearance: none;
}
#foot {
margin-top: 10px;
position: absolute;
bottom: 15px;
width: 100%;
}
.foot-ul {
width: 100%;
}
.foot-ul li {
width: 100%;
text-align: center;
color: #666;
}
.note-help {
color: #999999;
font-size: 12px;
line-height: 130%;
margin-top: 5px;
width: 100%;
display: block;
}
#btn-dd {
margin: 20px;
text-align: center;
}
.foot-ul {
width: 100%;
}
.one_line {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #eeeeee;
width: 100%;
margin-left: 20px;
}
.am-header {
display: -webkit-box;
display: -ms-flexbox;
display: box;
width: 100%;
position: relative;
padding: 7px 0;
-webkit-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
background: #1D222D;
height: 50px;
text-align: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
box-pack: center;
-webkit-box-align: center;
-ms-flex-align: center;
box-align: center;
}
.am-header h1 {
-webkit-box-flex: 1;
-ms-flex: 1;
box-flex: 1;
line-height: 18px;
text-align: center;
font-size: 18px;
font-weight: 300;
color: #fff;
}
</style>
</head>
<body text=#000000 bgColor="#ffffff" leftMargin=0 topMargin=4>
<header class="am-header">
<h1>支付宝手机网站支付接口快速通道(接口名:alipay.trade.wap.pay)</h1>
</header>
<div id="main"> <!-- 可以在这里看到这个请求的名是 pay 所以Controller中就需要一个接受pay的请求方法();-->
<form name=alipayment action="pay" method=post target="_blank">
<div id="body" style="clear:left">
<dl class="content">
<dt>商户订单号:</dt>
<dd>
<input id="WIDout_trade_no" name="WIDout_trade_no" />
</dd>
<hr class="one_line">
<dt>订单名称:</dt>
<dd>
<input id="WIDsubject" name="WIDsubject" />
</dd>
<hr class="one_line">
<dt>付款金额:</dt>
<dd>
<input id="WIDtotal_amount" name="WIDtotal_amount" />
</dd>
<hr class="one_line" />
<dt>商品描述:</dt>
<dd>
<input id="WIDbody" name="WIDbody" />
</dd>
<hr class="one_line">
<dt></dt>
<dd id="btn-dd">
<span class="new-btn-login-sp">
<button class="new-btn-login" type="submit"
style="text-align:center;">确 认</button>
</span> <span class="note-help">如果您点击“确认”按钮,即表示您同意该次的执行操作。</span>
</dd>
</dl>
</div>
</form>
<div id="foot">
<ul class="foot-ul">
<li>支付宝版权所有 2015-2018 ALIPAY.COM</li>
</ul>
</div>
</div>
</body>
</html>
com.wsm.controller 创建控制层
当前连接支付宝, 所做的控制响应~AlipayConfig.java
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.wsm.config.AlipayConfig; //包名位置根据自己的来~
@Controller
public class PayController {
//商家的代码区:
@RequestMapping("/pay") //接受页面请求的方法,产生订单...
@ResponseBody
public void pay(HttpServletRequest request, HttpServletResponse response) {
if (request.getParameter("WIDout_trade_no") != null) {
try {
//获取订单中的信息,进行处理生成订单!这里我并没有进行什么操作知识一个测试...
// 商户订单号,商户网站订单系统中唯一订单号,必填
String out_trade_no = new String(request.getParameter("WIDout_trade_no").getBytes("ISO-8859-1"), "UTF-8");
// 订单名称,必填
String subject = new String(request.getParameter("WIDsubject").getBytes("ISO-8859-1"), "UTF-8");
// 付款金额,必填
String total_amount = new String(request.getParameter("WIDtotal_amount").getBytes("ISO-8859-1"), "UTF-8");
// 商品描述,可空
String body = new String(request.getParameter("WIDbody").getBytes("ISO-8859-1"), "UTF-8");
// 超时时间 可空
String timeout_express = "2m";
// 销售产品码 必填
String product_code = "QUICK_WAP_PAY";
//手动输出一个订单名称
System.out.println(subject);
// SDK 公共请求类,包含公共请求参数,以及封装了签名与验签,开发者无需关注签名与验签
// 调用RSA签名方式
AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL,AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY,AlipayConfig.FORMAT, AlipayConfig.CHARSET,AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();
// 封装请求支付信息
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo(out_trade_no);
model.setSubject(subject);
model.setTotalAmount(total_amount);
model.setBody(body);
model.setTimeoutExpress(timeout_express);
model.setProductCode(product_code);
alipay_request.setBizModel(model);
// 设置异步通知地址
alipay_request.setNotifyUrl(AlipayConfig.notify_url);
// 设置同步地址
alipay_request.setReturnUrl(AlipayConfig.return_url);
// form表单生产
String form = "";
// 调用SDK生成表单
form = client.pageExecute(alipay_request).getBody();
response.setContentType("text/html;charset="+ AlipayConfig.CHARSET);
response.getWriter().write(form);// 直接将完整的表单html输出到页面
response.getWriter().flush();
response.getWriter().close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@RequestMapping("/myreturn") // 获取支付宝GET过来反馈信息,商户就可以进行下一步的操作: 订单状态更换..记录存储数据库等操作;
@ResponseBody
public void myreturn(HttpServletRequest request,HttpServletResponse response) {
try {
Map<String, String> params = new HashMap<String, String>();
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
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] + ",";
}
// 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
// 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
// 商户订单号
String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
// 支付宝交易号
String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
//手动输出订单号 和交易号
System.out.println("out_trade_no:" + out_trade_no);
System.out.println("trade_no:" + trade_no);
// 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
// 计算得出通知验证结果
// boolean AlipaySignature.rsaCheckV1(Map<String, String> params,
// String publicKey, String charset, String sign_type)
boolean verify_result = AlipaySignature.rsaCheckV1(params,AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET,"RSA2");
if (verify_result) {// 验证成功
//
// 请在这里加上商户的业务逻辑程序代码
// 该页面可做页面美工编辑
response.getWriter().println("success<br/>");
//
// ——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
//调用订单业务类的修改订单的支付方式
//........
} else {
// 该页面可做页面美工编辑
response.getWriter().println("error<br/>");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
这里的一个订单号只能使用一次, 这个支付宝后台会有对应的判断
注意这里的:第一次支付需要输入登录账户 密码 支付密码都在沙盒账户提供的模拟用户..
支付宝的支付大致流程就是如此…
查看虚拟的 商家
/用户
余额会发送对应的更改!
当然支付宝还提供了更多的功能:使用商家开发
短信验证
准备工作
应用程序实现:发送短信的
其实并不难,而是需要注册绑定一个短信平台~
本人使用的是 云通讯
一般企业都会进行购买, 个人应用就算了…
该平台还有更多的绑定操作, 语音验证啥的...
代码
导入所需Jar包 CCP_REST_SMS_SDK_JAVA_v2.6.3r.jar
创建一个 com.wsm.note 验证~
SendSMSService.java
import com.cloopen.rest.sdk.CCPRestSmsSDK;
public class SendSMSService {
//定义发送短信方法: 指定手机号 发送的内容
public void send(String phone, String msg) {
try {
CCPRestSmsSDK sdk = new CCPRestSmsSDK();
//指定平台的 ip 端口
sdk.init("app.cloopen.com", "8883");
//指定: 主账户id 授权令牌
sdk.setAccount("请输入自己的主账户id ","请输入自己的授权令牌");
//指定:AppID
sdk.setAppId("请输入自己的AppID~~~");
HashMap map = sdk.sendTemplateSMS(phone, "1", new String[] { msg });
System.out.println(map);
} catch (Exception e) {
e.printStackTrace();
}
}
//main主程序运行~~
public static void main(String[] args) {
SendSMSService sms = new SendSMSService();
//生成随机数;
int code = (int)(Math.random()*10000);
System.out.println(code);
//指定手机号 发送的内容
sms.send("请输入自己的测试手机号~~~", code+"");
}
}
run 运行;
因为是测试的所以, 都是该平台的模板~就是验证码! 不交钱有就不错了
可以把这些验证码存在 Redis中并设置时间~
时间到期则不允许登录…实现验证码登录的验证操作…