IOS支付,java后端代码

提示: 近期公司业务中APP新增了苹果内购支付,首次对接IOS支付,在此做记录。简单研究后发现,IOS支付和国内的微信支付宝支付流程有点不一样,IOS支付成功后也是依赖IOS APP客户端回调后台服务器,回调时携带IOS支付成功后的支付凭证等信息给服务器,跟微信支付宝不同的是微信和支付宝是通过他们的服务器通过REST API的方式回调,这可能和苹果是全球跨国企业,但有的国家对隐私做的比较严,不想暴露服务器的地址,所以才采用的这种方式,下面直接上代码

文章目录

  • IOS支付,java后端代码
  • 一、IOS需要在苹果系统中添加内购项目
  • 二、IOS支付成功之后客户端回调服务端代码
    • 1.Controller代码
    • 2.service代码
    • 3.IPayNotifyPo封装类
    • 4.IosVerifyUtil工具类
    • 5.Result返回客户端封装类
    • 6.pom文件

一、IOS需要在苹果系统中添加内购项目

注意:ios支付的金额是固定金额,跟支付宝微信不同的是,微信支付宝可以随意的输入金额。ios开发人员需要在苹果内购系统中配置好内购项目。
后端也要在数据库中配置跟ios内购项目相同的东西,以便在开发过程中能跟ios统一,结果如下:

 {"id": "1","product_id": "001","rmb_price": 1,},{"id": "2","product_id": "002","rmb_price": 6,},{"id": "3","product_id": "003","rmb_price": 12,}

二、IOS支付成功之后客户端回调服务端代码

注释:里边可能会涉及一些业务 需要自己来更改

1.Controller代码

/*** IOS支付成功后通过APP回调服务器** @param iPayNotifyPo* @return*/@ApiOperation("ios支付成功后验证结果")@RequestMapping(value = "iPayNotify/", method = RequestMethod.POST)@ResponseBodypublic Result<Object> iPayNotify(@RequestBody IPayNotifyPo iPayNotifyPo) {logger.info("ios支付成功后验证结果[前端传递的ios支付参数:{}]", iPayNotifyPo.toString());String receipt = iPayNotifyPo.getTransactionReceipt();// 拿到收据的MD5String receiptMd5 = SecureUtil.md5(receipt);// 查询数据库,看是否是己经验证过的该支付收据boolean existsIOSReceipt = paymentService.isExistsIOSReceipt(receiptMd5);if (existsIOSReceipt) {return Result.error("该充值已完成");}// 1.先线上测试    发送平台验证String verifyResult = IosVerifyUtil.buyAppVerify(receipt, 1);logger.info("1,苹果返回的参数:{}]", verifyResult);if (verifyResult == null) {// 苹果服务器没有返回验证结果logger.info("苹果服务器没有返回验证结果");return Result.error("订单没有找到");} else {// 苹果验证有返回结果JSONObject job = JSONUtil.parseObj(verifyResult);logger.info("2,[苹果验证返回的json串:{}]", job.toString());String states = job.getStr("status");if ("21007".equals(states)) {logger.debug("是沙盒环境,应沙盒测试,否则执行下面");// 是沙盒环境,应沙盒测试,否则执行下面// 2.再沙盒测试  发送平台验证verifyResult = IosVerifyUtil.buyAppVerify(receipt, 0);job = JSONUtil.parseObj(verifyResult);logger.debug("3,沙盒环境验证返回的json字符串=" + job.toString());states = job.getStr("status");}if ("0".equals(states)) { // 前端所提供的收据是有效的    验证成功logger.debug("前端所提供的收据是有效的    验证成功");String r_receipt = job.getStr("receipt");JSONObject returnJson = JSONUtil.parseObj(r_receipt);String in_app = returnJson.getStr("in_app");/*** in_app说明:* 验证票据返回的receipt里面的in_app字段,这个字段包含了所有你未完成交易的票据信息。也就是在上面说到的APP完成交易之后,这个票据信息,就会从in_app中消失。* 如果APP不完成交易,这个票据信息就会在in_app中一直保留。(这个情况可能仅限于你的商品类型为消耗型)** 知道了事件的原委,就很好优化解决了,方案有2个* 1.对票据返回的in_app数据全部进行处理,没有充值的全部进行充值* 2.仅对最新的充值信息进行处理(我们采取的方案)** 因为采用一方案:* 如果用户仅进行了一次充值,该充值未到账,他不再进行充值了,那么会无法导致。* 如果他通过客服的途径已经进行了补充充值,那么他在下一次充值的时候依旧会把之前的产品票据带回,这时候有可能出现重复充值的情况** 以上说明是我在网上找到的,可以查看原文* https://www.cnblogs.com/widgetbox/p/8241333.html*/JSONArray jsonArray = JSONUtil.parseArray(in_app);if (jsonArray.size() > 0) {int index = 0;JSONObject o = JSONUtil.parseObj(jsonArray.get(index));String transaction_id = o.getStr("transaction_id"); // 订单号String product_id = o.getStr("product_id"); // 产品id,也就是支付金额String purchase_date_ms = o.getStr("purchase_date_ms"); // 支付时间/*** 此处为业务代码,可以根据自己的业务来进行开发* */// 添加支付金额Result<Object> iosChargeSuccess = paymentService.iosChargeSuccess(transaction_id, product_id, purchase_date_ms, receiptMd5, iPayNotifyPo.getMoneyId(), iPayNotifyPo.getUserId());return iosChargeSuccess;}} else {return Result.error("收到数据有误");}}return Result.ok();}

2.service代码

里边涉及到的业务,可以根据自己的需求来进行开发

/*** 看是否是己经验证过的该支付收据* @param receiptMd5* @return*/public boolean isExistsIOSReceipt(String receiptMd5);
/*** IOS支付* @param transaction_id 订单号* @param product_id 产品id,也就是支付金额* @param purchase_date_ms 支付时间* @param receiptMd5 拿到收据的MD5* @param moneyId 金额id*/public Result<Object> iosChargeSuccess(String transaction_id, String product_id, String purchase_date_ms, String receiptMd5,String moneyId,String userId);

3.IPayNotifyPo封装类

public class IPayNotifyPo {@ApiModelProperty("苹果支付凭证")private String transactionReceipt;@ApiModelProperty("苹果支付单号")private String payId;@ApiModelProperty("用户id")private String userId;@ApiModelProperty("金额id")private String moneyId;
}

4.IosVerifyUtil工具类

package com.tools.payment.ios;import javax.net.ssl.*;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Locale;/*** @desc: 苹果IAP内购验证工具类* @author: wyq* @date: 2022/07/25 17:11*/
public class IosVerifyUtil {private static class TrustAnyTrustManager implements X509TrustManager {public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[]{};}}private static class TrustAnyHostnameVerifier implements HostnameVerifier {public boolean verify(String hostname, SSLSession session) {return true;}}// 沙盒环境private static final String url_sandbox = "https://sandbox.itunes.apple.com/verifyReceipt";// 生产环境private static final String url_verify = "https://buy.itunes.apple.com/verifyReceipt";/*** 苹果服务器验证** @param receipt 账单* @return null 或返回结果 沙盒 https://sandbox.itunes.apple.com/verifyReceipt* @url 要验证的地址*/public static String buyAppVerify(String receipt, int type) {//环境判断 线上/开发环境用不同的请求链接String url = "";if (type == 0) {url = url_sandbox; //沙盒测试} else {url = url_verify; //线上测试}//String url = EnvUtils.isOnline() ?url_verify : url_sandbox;try {SSLContext sc = SSLContext.getInstance("SSL");sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());URL console = new URL(url);HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();conn.setSSLSocketFactory(sc.getSocketFactory());conn.setHostnameVerifier(new TrustAnyHostnameVerifier());conn.setRequestMethod("POST");// conn.setRequestProperty("content-type", "text/json");conn.setRequestProperty("Content-Type", "application/json");conn.setRequestProperty("Proxy-Connection", "Keep-Alive");conn.setDoInput(true);conn.setDoOutput(true);BufferedOutputStream hurlBufOus = new BufferedOutputStream(conn.getOutputStream());String str = String.format(Locale.CHINA, "{\"receipt-data\":\"" + receipt + "\"}");//拼成固定的格式传给平台hurlBufOus.write(str.getBytes());hurlBufOus.flush();InputStream is = conn.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(is));String line = null;StringBuffer sb = new StringBuffer();while ((line = reader.readLine()) != null) {sb.append(line);}return sb.toString();} catch (Exception ex) {System.out.println("苹果服务器异常");ex.printStackTrace();}return null;}/*** 用BASE64加密** @param str* @return*/public static String getBASE64(String str) {byte[] b = str.getBytes();String s = null;if (b != null) {s = new sun.misc.BASE64Encoder().encode(b);}return s;}
}

5.Result返回客户端封装类

package com.tools.result;import java.util.List;
import java.util.Map;public class Result<T> {/*** 成功标志*/private boolean success = true;/*** 返回代码*/private Integer code = 0;/*** 返回处理消息*/private String message = "操作成功!";/*** 返回数据对象 result*/private T result;/*** 时间戳*/private long timestamp = System.currentTimeMillis();public Result() {}public boolean isSuccess() {return success;}public void setSuccess(boolean success) {this.success = success;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getResult() {return result;}public void setResult(T result) {this.result = result;}public long getTimestamp() {return timestamp;}public void setTimestamp(long timestamp) {this.timestamp = timestamp;}public Result<T> error500(String message) {this.setMessage(message);this.setCode(500);this.setSuccess(false);return this;}public Result<T> success(String message) {this.setMessage(message);this.setCode(200);this.setSuccess(true);return this;}public static Result<Object> ok() {Result<Object> r = new Result<Object>();r.setMessage("操作成功");r.setCode(200);r.setSuccess(true);return r;}public static Result<Object> ok(String msg) {Result<Object> r = new Result<Object>();r.setMessage(msg);r.setCode(200);r.setSuccess(true);r.setResult(null);return r;}public static Result<Object> ok(Map data) {Result<Object> r = new Result<Object>();r.setCode(200);r.setMessage("操作成功");r.setSuccess(true);r.setResult(data);return r;}public static Result<Object> ok(Map data,String msg) {Result<Object> r = new Result<Object>();r.setCode(200);r.setMessage(msg);r.setSuccess(true);r.setResult(data);return r;}public static Result<Object> ok(List data) {Result<Object> r = new Result<Object>();r.setCode(200);r.setSuccess(true);r.setResult(data);return r;}public static Result<List<?>> okl(List<?> data) {Result<List<?>> r = new Result<List<?>>();r.setCode(200);r.setSuccess(true);r.setResult(data);return r;}public static Result<Object> ok(Object data) {Result<Object> r = new Result<Object>();r.setCode(200);r.setSuccess(true);r.setResult(data);return r;}public static Result<Object> error(String msg) {return error(403, msg);}public static Result<Object> error(int code, String msg) {Result<Object> r = new Result<Object>();r.setCode(code);r.setSuccess(false);r.setMessage(msg);return r;}public static Result<Object> error(Map data,String msg) {Result<Object> r = new Result<Object>();r.setCode(403);r.setMessage(msg);r.setSuccess(false);r.setResult(data);return r;}/*** 无权限访问返回结果*/public static Result<Object> noauth(String msg) {return error(401, msg);}/*** 无权限访问返回结果*/public static Result<List<?>> noauth() {Result<List<?>> r = new Result<List<?>>();r.setCode(401);r.setSuccess(false);r.setMessage("您没有该接口的权限!");return r;}
}

6.pom文件

<!-- 工具包:https://hutool.cn/docs/ --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>4.6.1</version></dependency>

IOS支付,java后端代码相关推荐

  1. 微信小程序支付 Java后端代码详解

    微信小程序发起支付 Java后台处理代码---- 直接上代码吧! 我把自己的业务逻辑代码删了,但是都有注释的 莫慌! package com.mvc.controller;import java.io ...

  2. JAVA后端代码打包_Jenkins持续构建打包后端服务流程详解

    背景运用场景及思路 1.为响应后端开发人员需求,提升项目开发过程效率,选择Jenkins持续构建,进行导包启动一键持续集成 思路: 使用jenkins自带,立即构建->SVN拉取代码,通过Jen ...

  3. 三方 app微信支付 java后端实现

    废话不多说,直接上代码 生成prepay_id给前段返回 (如果是web端的就把 return 改成 (WebUtil.response(),如果是APP就直接用不用变) 这个写的一个Dome连接地址 ...

  4. APP 微信支付java后台代码(解决支付失败返回-1)

    开发之前的准备工作: APP支付申请条件 申请成为APP支付商户需要满足以下条件: 1.APP支付商户,须拥有微信开放平台(http://open.weixin.qq.com)的APPID: 2.AP ...

  5. 微信小程序开发-微信支付功能【WxMaService 获取openid,WxPayService建微信订单,接收微信支付异步通知回调方法,附有完整前后端代码】

    前提:对小程序开发有一定的基础:小程序已发布使用,已开通微信支付,关联商户号. 微信小程序平台:小程序平台 微信开发者文档:开发者文档 微信小程序支付API 地址:微信支付文档地址 微信支付平台:微信 ...

  6. 微信支付-java实现微信支付-后端篇

    微信支付系列文章 微信支付-java后端实现 微信支付-vue 前端实现 java demo: 下载地址文章底部 技术栈 Spring boot java XML (微信在http协议中数据传输方案) ...

  7. Java后端处理video快进快退播放以及断点续传的原理和代码

    video 快进快退的原理: 通过对所在服务器上的流媒体进行skip操作,然后再response的header里设置相应的Content-Range以及其他属性,来控制视频流的快进快退的功能. 断点续 ...

  8. 微信小程序支付 java

    话不多说,直接开撸. 支付流程步骤: 1)首先调用wx.login方法获取code,通过code获取openid: 2)java后台调用统一下单支付接口(这里会进行第一次签名),用来获取prepay_ ...

  9. 微信小程序--搭建linux服务器并部署java后端程序2021

    本文介绍:如何将java后端代码部署到阿里云的以CentOS7为操作系统轻量应用服务器上 前后历经一周时间搭建好服务器,成功在浏览器中访问后端代码,欣慰

最新文章

  1. poj1625Censored!(AC自动机+dp)
  2. 植物根系微生物组的调控入选中科院科技创新亮点成果筛选
  3. 从零开始入门 K8s | 应用配置管理
  4. 每天一道LeetCode-----找到给定数组的连续子数组,使这个子数组的和最大,要求复杂度为O(n)
  5. 7-3 凸多边形最优三角剖分 (10 分)(思路+详解+分析题意+动态规划)Come Baby!!!!!!!!!
  6. Python之路,week03 - Python基础3
  7. php点加等于0,php 做数学运算时结果为0的原因
  8. [转载] JAVA数组实现学生成绩统计
  9. python实训的意义_[Python] 一个让我更加清楚地理解了字典的实验……
  10. Tips--tensorboard在win系统中jupyter notebook上打开方式
  11. 报错,Field cardTypeService in cn.yihuazt.cols.controller.CardTypeController required a bean of type ‘c
  12. Intel 64/x86_64/IA-32/x86处理器 - SIMD指令集 - SSE扩展(8) - 数据类型转换指令
  13. Codeigniter分页类代码实例
  14. 通过组织发展来推动组织变革
  15. Objective-c官方文档 怎么自定义类
  16. 每天CookBook之Python-004
  17. 如果同时需要两张表,但其中一个表中没有另一个表中的字段,该如何正确使用
  18. 苦劝学弟学妹们,explain一定要学明白,以后有大用途
  19. 2019考研数学汤家凤张宇李永乐复习资料
  20. 无法启动此程序,因为计算机中丢失 的解决办法

热门文章

  1. Java、JSP中华美食网网站设计
  2. 计算机专业会不会经常打字,经常用电脑打字,都懒得写字,根本不想写,请问有什么坏处吗?感觉打的字数量比写的字要多很多...
  3. filter的request增强
  4. 图解跨域请求、反向代理原理,对前端更友好的反向代理服务器 - Caddy
  5. Android13 Launcher3 锁定Hotseat栏,apk无法替换与生成文件夹
  6. Python“鉴黄”小程序,自动识别检测物体的颜色
  7. CKA OFFCIAL TEST准备工作考试说明练习题
  8. matlab中怎样设计梯度线圈,梯度线圈组件的制作方法
  9. java 编程 pdf linux_Linux编程技术详解.pdf
  10. python二级备考一轮要点记录