个人网站实现支付宝支付

学习Java web,对于电商支付应用…应该比较频繁;

前期准备沙箱环境

首先要登录支付宝~

android 支付宝 短信 支付宝支付短信_支付宝


进入管理中心, 阿里巴巴提供的开发者中心控制台

开发选择中选择 研发服务

  • 这里提供了一些沙盒模型. 可以进行测试模拟交易。。。

android 支付宝 短信 支付宝支付短信_支付宝_02

沙盒应用:

android 支付宝 短信 支付宝支付短信_支付宝_03


这里的RSA2密钥最好设置下,我已经设置好了,所以便有了支付宝公钥(公钥是对外公开的,私钥是自己保留的具体的不多做解释)

工具的话官方都有提供:

android 支付宝 短信 支付宝支付短信_Java应用_04

android 支付宝 短信 支付宝支付短信_java_05

使用商户公钥——获取支付宝公钥但是私钥还是要保存的, 自己还需要用私钥来建立连接....将公钥放进保存即可自动生成 支付宝公钥

android 支付宝 短信 支付宝支付短信_支付宝_06

android 支付宝 短信 支付宝支付短信_Java应用_07

ok, 环境准备好了就是写代码了…

了解支付宝支付流程

android 支付宝 短信 支付宝支付短信_短信验证_08


一共有三个角色: 用户 商家服务/客户端 支付宝服务/客户端

  • 1:用户 通过 商家客户端
  • 2:请求一个支付宝付款
  • 3:商家服务 生成一个带签名的订单发送给商家客户端 这个签名订单 唯一标识了这个订单
  • 4:客户端通过这个订单向app sdk请求付款
  • 5.6.7.8:支付成功后支付宝向前端返回支付成功结果,
  • 9:并且向服务器发送一个支付通知
  • 10.11:服务器接收通知并且验证是否是支付宝发送的成功结果

商家app需要做的很简单:

  • 向自己的服务器请求一个订单,
  • 接收到订单后,向支付宝sdk发情一个支付请求:根据用户对支付做出的操作... 支付宝服务器/客户端,返回响应的数据进行处理…订单状态更改…记录数据库…
  • 交易结束后返回一个成功或者失败

创建一个Myelipse 项目:

android 支付宝 短信 支付宝支付短信_java_09

开发环境

myelipse2014
SpringMVC 工程…需要引入Spring的环境;
jdk1.8

需要Jar

android 支付宝 短信 支付宝支付短信_支付宝_10

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();
		}
	}
}

这里的一个订单号只能使用一次, 这个支付宝后台会有对应的判断

android 支付宝 短信 支付宝支付短信_支付宝_11


注意这里的:第一次支付需要输入登录账户 密码 支付密码都在沙盒账户提供的模拟用户..

android 支付宝 短信 支付宝支付短信_支付宝_12


android 支付宝 短信 支付宝支付短信_短信验证_13


支付宝的支付大致流程就是如此…

查看虚拟的 商家/用户 余额会发送对应的更改!

android 支付宝 短信 支付宝支付短信_短信验证_14

当然支付宝还提供了更多的功能:使用商家开发

android 支付宝 短信 支付宝支付短信_支付宝_15

短信验证

准备工作

应用程序实现:发送短信的

其实并不难,而是需要注册绑定一个短信平台~

本人使用的是 云通讯

android 支付宝 短信 支付宝支付短信_android 支付宝 短信_16


一般企业都会进行购买, 个人应用就算了…

该平台还有更多的绑定操作, 语音验证啥的...

android 支付宝 短信 支付宝支付短信_android 支付宝 短信_17

代码

导入所需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 运行;

android 支付宝 短信 支付宝支付短信_短信验证_18


因为是测试的所以, 都是该平台的模板~就是验证码! 不交钱有就不错了

android 支付宝 短信 支付宝支付短信_短信验证_19


可以把这些验证码存在 Redis中并设置时间~

时间到期则不允许登录…实现验证码登录的验证操作…