ping++ 支付

一.最近要开发支付,考虑到以后接入的支付类型比较多,如常用的,微信,支付宝,银联,以及后期需要接入qq,京东,易宝支付等。为了以后统一管理支付,就考虑使用ping++ 支付,提供了统一的支付接口。

    下面我介绍下,利用ping++ 接入支付宝的支付功能。

二.请求服务器 支付接口 orderpay.

    1.配置:ping++ api key ,appId,webhooksParse

    2.在ping++ 官网 找到 rsa private key ,官网提供的是rsc pacs#1 ,这里需要转成 pkcs8,我是利用在线的一个网站转换 : http://tool.chacuo.net/cryptrsapkcs1pkcs8

    3.创建charge对象,这里着重要说明的是 获取客户端ip,这也是官网demo 未强调的点,对于不了解代理请求转发的小伙伴来说,这里又会遇到大坑,项目不上线 不知道,一上线支付就调用不起来,根源就在

    x-forwarded-for  获取客户端IP这里。给一个地址介绍下x-forwarded-for :http://www.360doc.com/content/12/0409/15/1073512_202198496.shtml,他最终结果是将所有的代理过的ip地址全拼接在一起,而我        们需要的是最开始发起支付请求的客户端IP。下面是代码部分:

    

 1 public String orderpay(){
 2           //live   LIVE_API_BASE = "https://api.pingxx.com";
 3            //Pingpp.overrideApiBase(PingppTestData.getApiBase());
 4          Pingpp.apiKey = Cont.API_KEY_LIVE;
 5          // 建议使用 PKCS8 编码的私钥,可以用 openssl 将 PKCS1 转成 PKCS8
 6          //Pingpp.privateKey = PingppTestData.getPKCS8PrivateKey();
 7          
 8         // Pingpp.DEBUG = true; 
 9          //PKCS8,建议使用 PKCS8 编码的私钥,可以用 openssl 将 PKCS1 转成 PKCS8 
10          Pingpp.privateKey = "-----BEGIN PRIVATE KEY-----\n"+
12                     "此处填入pkcs8 私钥\n"+
13                     "-----END PRIVATE KEY-----\n";
14          
15          //私钥
16          //Pingpp.privateKeyPath = ApiCommonAction.class.getClassLoader().getResource("res").getPath()+"/pingpp_private_key.pem";18          String paramObj = getRequest().getParameter("paramObj");
19          if(!StringUtil.isEmpty(paramObj)){
20              if(new JsonParser().parse(paramObj).isJsonObject()){
21                  JsonObject jsonobj = new JsonParser().parse(paramObj).getAsJsonObject();23                  String amount = jsonobj.get("price").getAsString();
24                  //此处支付时,需将价格 转成 以分为单位
25                    //int price = (int) (Double.valueOf(amount) * 100);// 支付时  100 代表 1块。
26                    int price = (int) (Double.valueOf(amount) * 100);// 支付时  100 代表 1块。
27                    String order_no = jsonobj.get("orderNo").getAsString();
28                    String orderId = jsonobj.get("orderId").getAsString();
29                    String payType = jsonobj.get("paytype").getAsString();
30                    
31                    String channel = "";
32                    //支付宝
33                    if(!StringUtil.isEmpty(payType) && "1".equals(payType)){
34                        channel = "alipay";
35                        
36                    }else if(!StringUtil.isEmpty(payType) && "2".equals(payType)){//微信
37                        channel = "wx";
38                    }else{
39                        setJsonString(AppJSON.errReq("支付类型不能为空!"));
40                        return "ajax";
41                    }
42                    
43                    String remoteAddr = getRequest().getRemoteAddr();45                    
46                    String ip = getRequest().getHeader("x-forwarded-for");
47                  if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
48                      ip = getRequest().getHeader("Proxy-Client-IP");
49                  }
50                  if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
51                      ip = getRequest().getHeader("WL-Proxy-Client-IP");
52                  }
53                  if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
54                      ip = getRequest().getRemoteAddr();
55                  }
56                  
57                  if(!StringUtil.isEmpty(ip)){
58                       String[] iparr = ip.trim().split(",");
59                       ip = iparr[0];
60                  }
61                  
62                    System.out.println("客户端++  ip="+ip);
63                    
64                    //String client_ip = "127.0.0.1";//host.substring(0,host.indexOf(":"));
65                    String client_ip = ip;
66                    
67                    //subject 和 body 参数用来在用户付款、以及在第三方支付软件的账单显示。从订单表中获取
68                    String subject = "预定服务";
69                    String body = "支付订单费用";
70                    
71                    Charge charge = this.createCharge(orderId,price,order_no,channel,client_ip, subject, body);
72                    if(charge!=null){
73                        System.out.println("========ping++ chargeId=  "+charge.getId());
74                        // 传到客户端请先转成字符串 .toString(), 调该方法,会自动转成正确的 JSON 字符串
75                        
76                        //以"X"结尾,则标识需求订单,
77                        if(order_no.endsWith("X")){
78                          //业务处理82                        
}else{ 83 //业务处理87
}
88 String chargeString = charge.toString(); 89 90 setJsonString(AppJSON.succReq("请求成功", chargeString)); 91 } 92 } 93 94 }else{ 95 setJsonString(AppJSON.errParas("支付 paramObj不能为空"));return "ajax"; 96 } 97 98 return "ajax"; 99 }

三.创建支付对象 charge

   1.指定 支付使用的appid

   2.调用 charge对象的create 方法,创建支付对象。

 1 public Charge createCharge(String orderId,int price,String orderNo,String channel,String clent_ip,String subject,String body){
 2         //String appId = PingppTestData.getAppID();
 3         String appId = Cont.API_ID;
 5         Charge charge = null;
 6         Map<String, Object> chargeMap = new HashMap<String, Object>();
 7         chargeMap.put("amount", price);//订单总金额, 人民币单位:分(如订单总金额为 1 元,此处请填 100)
 8         chargeMap.put("currency", "cny");
 9         chargeMap.put("subject", subject);
10         chargeMap.put("body", body);
11         chargeMap.put("order_no", orderNo);// 推荐使用 8-20 位,要求数字或字母,不允许其他字符
12         chargeMap.put("channel", channel);// 支付使用的第三方支付渠道取值,请参考:https://www.pingxx.com/api#api-c-new
13         
14         Calendar cal = Calendar.getInstance();  
15         cal.add(Calendar.MINUTE, 5);//5分钟失效  
16         long timestamp = cal.getTimeInMillis()/ 1000L;  
17         chargeMap.put("time_expire", timestamp);
18         Timer timer = new Timer();
19         //发起一个定时任务,半小时后自动触发,取消订单流程
20        //以"X"结尾,则标识需求订单,
21         if(orderNo.endsWith("X")){
22             //需求订单
23             timer.schedule(new DemandlobbyNoPayCancel(Long.valueOf(orderId)), 1000 * 60 * 5);
24         }else{
25             //普通订单
26             timer.schedule(new OrderNoPayCancel(Long.valueOf(orderId)), 1000 * 60 * 5);
27         }
28         
29         chargeMap.put("client_ip", clent_ip); // 发起支付请求客户端的 IP 地址,格式为 IPV4,如: 127.0.0.1
30         Map<String, String> app = new HashMap<String, String>();
31         app.put("id", appId);
32         chargeMap.put("app", app);
33 
34         Map<String, Object> extra = new HashMap<String, Object>();
35 //            extra.put("success_url", "http://127.0.0.1/succeeded");
36         chargeMap.put("extra", extra);
37         try {
38             // 发起 charge 创建请求
39             charge = Charge.create(chargeMap);
40 
41         } catch (APIConnectionException e) {
42             e.printStackTrace();
43         } catch (ChannelException e) {
44             e.printStackTrace();
45         } catch (RateLimitException e) {
46             e.printStackTrace();
47         } catch (AuthenticationException e) {
48             e.printStackTrace();
49         } catch (APIException e) {
50             e.printStackTrace();
51         } catch (InvalidRequestException e) {
52             e.printStackTrace();
53         }
54 
55         return charge;
56     }

四.支付回调方法

   1.回调地址,是在ping++ 官网配置,官网提供 test 和 live 两版本,开发过程先用test 做回调地址配置,测通后,项目正式上线改成live模式.

   2.回调地址进行业务处理,回调方法获取event type类型,是支付成功,还是退款成功或者红包发送成功..... 具体可参考 ping++ 开发api: https://www.pingxx.com/api#events-事件

   3.贴出我的回调处理方法代码,这里主要会发生的签名验签的错误,那么遇到这种情况,你还是要核对下,是否直接使用了ping++的私钥 并没有转成 pkcs8 加密方式,或者直接拷入了ping++的公钥....

 1 public String webhooksParseCharge(){
 2           HttpServletRequest request  = getRequest();
 3           HttpServletResponse response = getResponse();
 4         try {
 5             request.setCharacterEncoding("UTF8");
 6         } catch (UnsupportedEncodingException e1) {
 7             e1.printStackTrace();
 8         }  
 9         //获取头部所有信息  
10         Enumeration<String> headerNames = request.getHeaderNames();  
11         String signature=null;  
12         while (headerNames.hasMoreElements()) {  
13             String key = (String) headerNames.nextElement();  
14             String value = request.getHeader(key);  
15             if("x-pingplusplus-signature".equals(key)){  
16                 signature=value;  
17             }  
18         }  
19  
20         // 获得 http body 内容  
21        StringBuffer eventJson=new StringBuffer();  
22        BufferedReader reader= null;  
23         try {  
24             reader = request.getReader();  
25             do{  
26                 eventJson.append(reader.readLine());  
27             }while(reader.read()!=-1);  
28             reader.close();  
29         } catch (IOException e) {  
30             e.printStackTrace();  
31         }  
32         
33         JSONObject event=JSONObject.fromObject(eventJson.toString()); 
34         System.out.println("=========event=========== "+event);
35         boolean verifyRS=false;  
36         try {  
37             PublicKey publicKey = WebhooksVerifyService.getPubKey();  
38             System.out.println("============公钥============"+publicKey);  
39             verifyRS = WebhooksVerifyService.verifyData(eventJson.toString(),signature,publicKey);  
40             System.out.println("============== 是否签名验证成功! "+ verifyRS);
41             //verifyRS = true;
42         } catch (Exception e) {  
43             e.printStackTrace();  
44         }  
45    
46         if(verifyRS) {  
47             // charge.succeeded    支付对象,支付成功时触发。
48             // refund.succeeded    退款对象,退款成功时触发。
49             if ("charge.succeeded".equals(event.get("type"))) {  
50                 JSONObject data = JSONObject.fromObject(event.get("data").toString());  
51                 JSONObject object = JSONObject.fromObject(data.get("object").toString()); 
52                 
53                 String channel = (String) object.get("channel");  
54                 String payType = null;  
55                 int amountFen = (int) object.get("amount");  
56                 //交易流水号
57                 String transaction_no = object.get("transaction_no")+"";
58                         
59                 Double amountYuan = amountFen * 1.0 / 100;//ping++扣款,精确到分,而数据库精确到元  
60                 Double weiXinInput = null;  
61                 Double aliPayInput = null;  
62                 Double bankCardInput = null;  
63                 
64                 if ("wx".equals(channel)) {  
65                     payType = "2";//支付类型(1:支付宝2微信)  
66                     weiXinInput = amountYuan;  
67                 } else if ("alipay".equals(channel)) {  
68                     payType = "1";  
69                     aliPayInput = amountYuan;  
70                 } 
71                 
72                 String orderNo = (String) object.get("order_no");                  
73                 // 支付成功业务处理
74             }else if("refund.succeeded".equals(event.get("type"))){//退款事件
75                 // 退款业务处理
76                 
77             }  
78             
79         }else{  
80             System.out.println("签名验证失败");
81             setJsonString(AppJSON.errReq("签名验证失败!"));
82         }  
83           
84           return "ajax";
85       }

五. 关于ping++ 支付先介绍到这里,后期有先关支付类技术 我会逐步跟进,如此文大家有什么问题,请留言联系我,很乐意解决大家的问题。

     另外郑重说明 本篇文章是个人原创,如需转载请标注原文地址。

转载于:https://www.cnblogs.com/sumingk/articles/7966234.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
支付系统设计白皮书》是支付学院所出版的一本关于支付系统设计的指南手册。这本白皮书主要围绕着如何设计和构建一个高效、安全、可扩展的支付系统展开讨论。 首先,白皮书对支付系统的概念进行了详细阐述,介绍了支付系统的基本原理、功能和作用。它探讨了不同类型的支付系统,包括传统的纸质现金支付、电子支付和移动支付等,并分析了它们的优缺点以及在不同场景下的适用性。 然后,白皮书重点关注支付系统的设计原则和关键要素。它提供了一些建议和指导原则,例如如何确保支付系统的安全性,保护用户的隐私信息;如何设计可靠的支付通道和交易处理系统,以便处理大量的交易;如何优化支付系统的性能,提高用户体验等等。 此外,白皮书还详细介绍了支付系统的技术架构和关键技术。它列举了常见的支付系统架构模型,如中心化模型、分布式模型和区块链模型,并比较了它们的特点和适用场景。它还讨论了支付系统的安全技术,包括加密算法、身份验证、防止欺诈行为的方法等等。 最后,白皮书还提供了一些实践案例和经验分享,以供读者参考。这些案例涵盖了不同行业和不同规模的支付系统设计和实施,从而为读者提供了一些实际操作的指导。 总之,《支付系统设计白皮书》是一本非常实用的指南,适用于支付系统相关从业人员、学生和研究人员。它为读者提供了全面的理论知识和实践经验,帮助读者了解支付系统的设计原则和技术,并指导读者在实际应用中设计和构建具有高性能和安全性的支付系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值