2019独角兽企业重金招聘Python工程师标准>>>

一、请求charge对象

  1. package com.bra.modules.util.pingplusplus;
  2. import com.bra.common.utils.SystemPath;
  3. import com.pingplusplus.Pingpp;
  4. import org.springframework.stereotype.Service;
  5. import java.io.File;
  6. /**
  7. * Created by Afon on 16/4/26.
  8. */
  9. @Service
  10. public class PingPlusPlusService {
  11. /**
  12. * Pingpp 管理平台对应的 API Key
  13. */
  14. private final static String apiKey = "";
  15. /**
  16. * Pingpp 管理平台对应的应用 ID
  17. */
  18. private final static String appId = "";
  19. /**
  20. * 你生成的私钥路径
  21. */
  22. private final static String privateKeyFilePath = File.separator+SystemPath.getClassPath()+"res"+ File.separator+"rsa_private_key.pem";
  23. public static String charge(String orderNo,int amount,String subject,String body,String channel,String clientIP){
  24. // 设置 API Key
  25. Pingpp.apiKey = apiKey;
  26. // 设置私钥路径,用于请求签名
  27. Pingpp.privateKeyPath = privateKeyFilePath;
  28. PingPlusCharge charge=new PingPlusCharge(appId);
  29. String chargeString=charge.createCharge(orderNo,amount,subject,body,channel,clientIP);
  30. return chargeString;
  31. }
  32. }

二、生成charge 对象

  1. package com.bra.modules.util.pingplusplus;
  2. import com.pingplusplus.exception.PingppException;
  3. import com.pingplusplus.model.Charge;
  4. import java.util.Calendar;
  5. import java.util.HashMap;
  6. import java.util.Map;
  7. /**
  8. * Created by Afon on 16/4/26.
  9. */
  10. public class PingPlusCharge {
  11. private String appId;
  12. PingPlusCharge(String appId) {
  13. this.appId = appId;
  14. }
  15. public String createCharge(String orderNo, int amount, String subject, String body, String channel, String clientIP) {
  16. /**
  17. * 或者直接设置私钥内容
  18. Pingpp.privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" +
  19. "... 私钥内容字符串 ...\n" +
  20. "-----END RSA PRIVATE KEY-----\n";
  21. */
  22. Map<String, Object> chargeMap = new HashMap<String, Object>();
  23. chargeMap.put("amount", amount);
  24. chargeMap.put("currency", "cny");
  25. chargeMap.put("subject", subject);
  26. chargeMap.put("body", body);
  27. chargeMap.put("order_no", orderNo);
  28. chargeMap.put("channel", channel);
  29. Calendar cal = Calendar.getInstance();
  30. cal.add(Calendar.MINUTE, 15);//15分钟失效
  31. long timestamp = cal.getTimeInMillis()/ 1000L;
  32. chargeMap.put("time_expire", timestamp);
  33. chargeMap.put("client_ip", clientIP); // 客户端 ip 地址(ipv4)
  34. Map<String, String> app = new HashMap<String, String>();
  35. app.put("id", appId);
  36. chargeMap.put("app", app);
  37. String chargeString = null;
  38. try {
  39. //发起交易请求
  40. Charge charge = Charge.create(chargeMap);
  41. // 传到客户端请先转成字符串 .toString(), 调该方法,会自动转成正确的 JSON 字符串
  42. chargeString = charge.toString();
  43. } catch (PingppException e) {
  44. e.printStackTrace();
  45. }
  46. return chargeString;
  47. }
  48. }

三、webhook

  1. @RequestMapping(value = "webhooks")
  2. @ResponseBody
  3. public void webhooks ( HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException  {
  4. /*System.out.println("ping++ webhooks");*/
  5. request.setCharacterEncoding("UTF8");
  6. //获取头部所有信息
  7. Enumeration headerNames = request.getHeaderNames();
  8. String signature=null;
  9. while (headerNames.hasMoreElements()) {
  10. String key = (String) headerNames.nextElement();
  11. String value = request.getHeader(key);
  12. if("x-pingplusplus-signature".equals(key)){
  13. signature=value;
  14. }
  15. }
  16. /*System.out.println("signature"+signature);*/
  17. // 获得 http body 内容
  18. StringBuffer eventJson=new StringBuffer();
  19. BufferedReader reader= null;
  20. try {
  21. reader = request.getReader();
  22. do{
  23. eventJson.append(reader.readLine());
  24. }while(reader.read()!=-1);
  25. } catch (IOException e) {
  26. e.printStackTrace();
  27. }
  28. reader.close();
  29. JSONObject event=JSON.parseObject(eventJson.toString());
  30. boolean verifyRS=false;
  31. try {
  32. PublicKey publicKey= WebhooksVerifyService.getPubKey();
  33. /*  System.out.println(publicKey);*/
  34. verifyRS=WebhooksVerifyService.verifyData(eventJson.toString(),signature,publicKey);
  35. } catch (Exception e) {
  36. e.printStackTrace();
  37. }
  38. if(verifyRS) {
  39. /*System.out.println("签名验证成功");*/
  40. if ("charge.succeeded".equals(event.get("type"))) {
  41. JSONObject data = JSON.parseObject(event.get("data").toString());
  42. JSONObject object = JSON.parseObject(data.get("object").toString());
  43. String orderId = (String) object.get("order_no");
  44. /*System.out.println("orderId:"+orderId);*/
  45. String channel = (String) object.get("channel");
  46. String payType = null;
  47. int amountFen = (int) object.get("amount");
  48. Double amountYuan = amountFen * 1.0 / 100;//ping++扣款,精确到分,而数据库精确到元
  49. Double weiXinInput = null;
  50. Double aliPayInput = null;
  51. Double bankCardInput = null;
  52. if ("wx".equals(channel)) {
  53. payType = "4";//支付类型(1:储值卡,2:现金,3:银行卡,4:微信,5:支付宝,6:优惠券,7:打白条;8:多方式付款;9:微信个人,10:支付宝(个人))
  54. weiXinInput = amountYuan;
  55. } else if ("alipay".equals(channel)) {
  56. payType = "5";
  57. aliPayInput = amountYuan;
  58. } else if ("upacp".equals(channel) || "upacp_wap".equals(channel) || "upacp_pc".equals(channel)) {
  59. payType = "3";
  60. bankCardInput = amountYuan;
  61. }
  62. Double couponInput;
  63. ReserveVenueCons order = reserveAppVenueConsService.get(orderId);
  64. if (order != null) {
  65. Double orderPrice = order.getShouldPrice();
  66. couponInput = orderPrice - amountYuan;//订单金额-ping++扣款 等于优惠金额
  67. Boolean bool = reserveAppVenueConsService.saveSettlement(order, payType, amountYuan,
  68. 0.0, bankCardInput, weiXinInput, aliPayInput, couponInput);
  69. if (bool) {
  70. /*  System.out.println("订单结算成功");*/
  71. response.setStatus(200);
  72. //return "订单结算成功";
  73. } else {
  74. /* System.out.println("订单结算失败");*/
  75. //return "订单结算失败";
  76. response.setStatus(500);
  77. }
  78. } else {
  79. /* System.out.println("该订单不存在");*/
  80. //return "该订单不存在";
  81. response.setStatus(500);
  82. }
  83. }
  84. }else{
  85. /*System.out.println("签名验证失败");*/
  86. //return "签名验证失败";
  87. response.setStatus(500);
  88. }
  89. }

四、WebhooksVerifyService

  1. package com.bra.modules.util.pingplusplus;
  2. import com.bra.common.utils.SystemPath;
  3. import org.apache.commons.codec.binary.Base64;
  4. import java.io.*;
  5. import java.security.*;
  6. import java.security.spec.X509EncodedKeySpec;
  7. /**
  8. * Created by sunkai on 15/5/19. webhooks 验证签名示例
  9. *
  10. * 该实例演示如何对 Ping++ webhooks 通知进行验证。
  11. * 验证是为了让开发者确认该通知来自 Ping++ ,防止恶意伪造通知。用户如果有别的验证机制,可以不进行验证签名。
  12. *
  13. * 验证签名需要 签名、公钥、验证信息,该实例采用文件存储方式进行演示。
  14. * 实际项目中,需要用户从异步通知的 HTTP header 中读取签名,从 HTTP body 中读取验证信息。公钥的存储方式也需要用户自行设定。
  15. *
  16. *  该实例仅供演示如何验证签名,请务必不要直接 copy 到实际项目中使用。
  17. *
  18. */
  19. public class WebhooksVerifyService {
  20. private static String pubKeyPath = File.separator+ SystemPath.getClassPath()+"res"+ File.separator+"pingpp_public_key.pem";
  21. private static String eventPath = File.separator+SystemPath.getClassPath()+"res"+ File.separator+"webhooks_raw_post_data.json";
  22. private static String signPath = File.separator+SystemPath.getClassPath()+"res"+ File.separator+"signature.txt";
  23. /**
  24. * 验证 webhooks 签名,仅供参考
  25. * @param args
  26. * @throws Exception
  27. */
  28. public static void main(String[] args) throws Exception {
  29. runDemos();
  30. }
  31. public static void runDemos() throws Exception {
  32. // 该数据请从 request 中获取原始 POST 请求数据, 以下仅作为示例
  33. String webhooksRawPostData = getStringFromFile(eventPath);
  34. System.out.println("------- POST 原始数据 -------");
  35. System.out.println(webhooksRawPostData);
  36. // 签名数据请从 request 的 header 中获取, key 为 X-Pingplusplus-Signature (请忽略大小写, 建议自己做格式化)
  37. String signature = getStringFromFile(signPath);
  38. System.out.println("------- 签名 -------");
  39. System.out.println(signature);
  40. boolean result = verifyData(webhooksRawPostData, signature, getPubKey());
  41. System.out.println("验签结果:" + (result ? "通过" : "失败"));
  42. }
  43. /**
  44. * 读取文件, 部署 web 程序的时候, 签名和验签内容需要从 request 中获得
  45. * @param filePath
  46. * @return
  47. * @throws Exception
  48. */
  49. public static String getStringFromFile(String filePath) throws Exception {
  50. FileInputStream in = new FileInputStream(filePath);
  51. InputStreamReader inReader = new InputStreamReader(in, "UTF-8");
  52. BufferedReader bf = new BufferedReader(inReader);
  53. StringBuilder sb = new StringBuilder();
  54. String line;
  55. do {
  56. line = bf.readLine();
  57. if (line != null) {
  58. if (sb.length() != 0) {
  59. sb.append("\n");
  60. }
  61. sb.append(line);
  62. }
  63. } while (line != null);
  64. return sb.toString();
  65. }
  66. /**
  67. * 获得公钥
  68. * @return
  69. * @throws Exception
  70. */
  71. public static PublicKey getPubKey() throws Exception {
  72. String pubKeyString = getStringFromFile(pubKeyPath);
  73. pubKeyString = pubKeyString.replaceAll("(-+BEGIN PUBLIC KEY-+\\r?\\n|-+END PUBLIC KEY-+\\r?\\n?)", "");
  74. byte[] keyBytes = Base64.decodeBase64(pubKeyString);
  75. // generate public key
  76. X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
  77. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  78. PublicKey publicKey = keyFactory.generatePublic(spec);
  79. return publicKey;
  80. }
  81. /**
  82. * 验证签名
  83. * @param dataString
  84. * @param signatureString
  85. * @param publicKey
  86. * @return
  87. * @throws NoSuchAlgorithmException
  88. * @throws InvalidKeyException
  89. * @throws SignatureException
  90. */
  91. public static boolean verifyData(String dataString, String signatureString, PublicKey publicKey)
  92. throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, UnsupportedEncodingException {
  93. byte[] signatureBytes = Base64.decodeBase64(signatureString);
  94. Signature signature = Signature.getInstance("SHA256withRSA");
  95. signature.initVerify(publicKey);
  96. signature.update(dataString.getBytes("UTF-8"));
  97. return signature.verify(signatureBytes);
  98. }
  99. }

转载于:https://my.oschina.net/rightemperor/blog/886562

Ping++ 支付接口对接相关推荐

  1. 第三方银联支付接口对接_聊聊三方支付对接那点事儿(附Demo)

    每一个做过支付对接的少年上辈子都是折翼的天使.--题记 三方支付对接是一件比较有意思的事儿,今天就拿这个话题来掰扯掰扯.相信每个做过支付对接的小伙伴都有段血与火的经历,那段日子只有痛苦与煎熬,恨不得大 ...

  2. 特殊格式的 汇潮支付接口对接

    在公司业务中,对接汇潮支付,--------该需求是调用汇潮的支付接口,他们作为中台,由他们调用支付宝接口 在异步回调的时候,遇到了"参数通过 post 方式提交, Content-Type ...

  3. 支付宝支付接口对接的总结

    本周工作最大的困难还是支付宝支付接口的对接. 遇到主要的问题是两个:1. 发送订单给支付宝接口,接口验证签名失败. 2.支付宝付款结束后,发送信息给网站接收方进行二次验签,还是签名过不了.验签的方式是 ...

  4. Paypal REST API Java 版 PC端商城支付接口对接。

    引言: 同类文借鉴链接:http://blog.csdn.net/change_on/article/details/73881791(对此博主万分感谢) Paypal账号注册网址:https://w ...

  5. Java支付宝支付接口对接(app端)

    前言:大致说一下流程,其实支付宝官方文档写的很清楚了,还有就是下面我写的一些描述可能转载了其他博客的内容. 用户在app端提交订单--->选择支付方式即支付宝付款(调用了商家端的付款接口,调用之 ...

  6. 【项目】关于杉德支付接口对接

    文章目录 前言 对接杉德的一键快捷支付 杉德的商家中心 代码 问题 参考文献 前言 该支付就是调用他们的支付页面,绑卡无需我们操作,所有支付操作都有他们控制.对接的支付是,一键快捷支付,参考的文档是他 ...

  7. C#微信公众号支付接口对接

    这次是第二次对接微信公众号的支付了,第一次代码写的很乱,没有找现成的SDK,感觉里面乱七八糟的东西太多不够清爽,而我仅仅是做一个小功能,对接又不复杂干脆自己做. 不想重复做轮子的朋友可以参考一下:Se ...

  8. 第四方汇聚支付接口对接Php

    2020年08月24日 下午15:06:07 原文链接:http://note.youdao.com/noteshare?id=315218dd673a75d8d378a50e5c1644a4& ...

  9. 富友支付接口对接不是必填的值如何处理

    1.拿注册接口举例子 正常需要的签名明文: back_notify_url+"|"+bank_nm+"|"+capAcntNo+"|"+ce ...

最新文章

  1. c 高级函数的简单用法
  2. 使用 Firefox攻击Web2.0应用(一)
  3. python封装方法有几种_python之--------封装
  4. sql server数据库导入导出bcp方法
  5. Day Two(Beta)
  6. sbt笔记二 Running
  7. SPH(光滑粒子流体动力学)流体模拟实现二:SPH算法(2)-粒子受力分析
  8. Smali语法汇总(一)
  9. [iOS] 响应式编程开发-ReactiveCocoa(二)
  10. 软件基本功:工作目标经常变化,要及时跟进
  11. ai人工智能的本质和未来_人工智能简介:这就是未来
  12. 最大公约数与最小公倍数求法 C语言版
  13. Windows10快捷键合集
  14. STM32F7 硬件IIC驱动
  15. Macbook电池优化的七种建议
  16. 数据为王,聚数学院引领大数据新时代
  17. RGB排列和Pentile排列有什么区别
  18. 三菱FX3G_24MT PLC、GS2110_WTBD_N触摸屏实现伺服位置控制编程实例
  19. 《安士全书》原文及白话版
  20. Java游戏服务器代码热更新

热门文章

  1. liunx 命令 之 mkdir 与 touch
  2. fftw3 嵌入式linux安装,Ubuntu18.04下快速的安装UHD与GnuRadio并连接USRP设备
  3. linux 64 mysql下载官网_Linux下安装MySQL5.7
  4. Spring Boot 2 Webflux的全局异常处理
  5. 【亲测有效】运行docker ps 出现Got permission denied问题的解决方案
  6. 春季:@Component与@Bean
  7. Android Studio - 如何更改Android SDK路径
  8. win11关机后主机依旧运行怎么办 Windows11关机后主机依旧运行的解决方法
  9. win11杜比视界音效怎么打开 window11开启杜比视界音效的步骤方法
  10. 计算机一级信息技术基础知识,计算机一级考试之信息技术基础.doc