Browse Source

init from phab

xielq 4 years ago
parent
commit
0f372b3cb2

+ 0 - 0
README.md


+ 50 - 0
build.gradle

@@ -0,0 +1,50 @@
+buildscript {
+    ext {
+        springBootVersion = '1.4.4.RELEASE'
+    }
+    repositories {
+        mavenLocal()
+        mavenCentral()
+    }
+    dependencies {
+        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
+    }
+}
+
+group 'com.uas.cloud.mall'
+version '1.0-SNAPSHOT'
+
+apply plugin: 'java'
+apply plugin: 'org.springframework.boot'
+
+repositories {
+    mavenLocal()
+    jcenter()
+    maven {
+        url 'http://10.10.101.21:8081/artifactory/libs-release'
+    }
+    maven {
+        url 'http://10.10.101.21:8081/artifactory/libs-snapshot'
+    }
+    mavenCentral()
+}
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
+
+dependencyManagement {
+    imports {
+        mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Camden.SR5'
+    }
+}
+
+dependencies {
+    compile ("org.springframework.cloud:spring-cloud-starter-eureka")
+    compile("org.springframework.boot:spring-boot-starter-web")
+    compile("org.springframework.boot:spring-boot-starter-data-jpa")
+    compile("com.uas.cloud.mall:commons:0.0.1"){
+        exclude(module: 'servlet-api')
+    }
+    compile ("io.springfox:springfox-swagger2:2.4.0")
+    compile ("io.springfox:springfox-swagger-ui:2.4.0")
+    runtime("com.oracle:ojdbc6:11.2.0")
+}

+ 2 - 0
settings.gradle

@@ -0,0 +1,2 @@
+rootProject.name = 'mall-payment-service'
+

+ 12 - 0
src/main/java/com/uas/cloud/mall/payment/Application.java

@@ -0,0 +1,12 @@
+package com.uas.cloud.mall.payment;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+public class Application {
+
+    public static void main(String[] args) {
+        new SpringApplicationBuilder(Application.class).web(true).run(args);
+    }
+}

+ 17 - 0
src/main/java/com/uas/cloud/mall/payment/ApplicationContextConfig.java

@@ -0,0 +1,17 @@
+package com.uas.cloud.mall.payment;
+
+import com.uas.cloud.commons.web.context.ApplicationContextRegister;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Created by huhui on 2017/3/7.
+ */
+@Configuration
+public class ApplicationContextConfig {
+
+    @Bean
+    public ApplicationContextRegister applicationContextRegister() {
+        return new ApplicationContextRegister();
+    }
+}

+ 48 - 0
src/main/java/com/uas/cloud/mall/payment/SwaggerConfig.java

@@ -0,0 +1,48 @@
+package com.uas.cloud.mall.payment;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.context.request.async.DeferredResult;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+/**
+ * Created by huhui on 2017/3/4.
+ */
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+
+    @Bean
+    public Docket serviceApi(){
+        return new Docket(DocumentationType.SWAGGER_2)
+                .groupName("internal-api")
+                .genericModelSubstitutes(DeferredResult.class)
+                .useDefaultResponseMessages(false)
+                .forCodeGeneration(true)
+                .pathMapping("/")  // base,最终调用接口后会和paths拼接在一起
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.uas.cloud.mall.payment")) // 扫描的包,建议配置写Controller的包
+                .paths(PathSelectors.regex("/*.*"))//   过滤的接口,根据正则表达式来匹配
+                .build()
+                .apiInfo(apiInfo());
+    }
+
+    private ApiInfo apiInfo(){
+        ApiInfo apiInfo = new ApiInfo("大标题(一般写服务名称)",// 大标题
+                "小标题(对服务的描述)",// 小标题
+                "版本(比如0.1)", // 版本
+                "服务地址URL", // 服务地址URL
+                "作者(该服务编写者)", //作者
+                " 链接显示文字()", // 链接显示文字
+                "网站链接(www.baidu.com)" //网站链接
+        );
+        return apiInfo;
+    }
+
+}

+ 84 - 0
src/main/java/com/uas/cloud/mall/payment/api/PaymentController.java

@@ -0,0 +1,84 @@
+package com.uas.cloud.mall.payment.api;
+
+import com.uas.cloud.commons.domain.PageInfo;
+import com.uas.cloud.commons.domain.PageParams;
+import com.uas.cloud.mall.payment.domain.Payment;
+import com.uas.cloud.mall.payment.service.PaymentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/payment")
+public class PaymentController {
+
+    @Autowired
+    private PaymentService paymentService;
+
+    /**
+     *   支付参数签名加密
+     *
+     *   @param orderid        订单号
+     *   @param ensurePrice    付款金额
+     *   @param subject        商品描述
+     */
+    @RequestMapping(value = "/paymentSign", method = RequestMethod.GET)
+    public Map<String,String>  paymentSign(String orderid, String ensurePrice, String subject){
+        return paymentService.paymentSign(orderid, ensurePrice, subject);
+    }
+
+    /**
+     *   验证银盛支付异步通知,是否付款成功
+     *
+     *   @param request        银盛请求信息
+     */
+    @RequestMapping(value = "/ysepayNotify", method = RequestMethod.POST)
+    public String ysepayNotify(HttpServletRequest request) throws ParseException {
+        return paymentService.ysepayNotify(request);
+    }
+
+    /**
+     *   发起退款
+     *
+     *   @param orderid        订单号
+     *   @param reid           退款单号
+     *   @param refundMoney   退款金额
+     *   @param refundReason  退款原因
+     */
+    @RequestMapping(value = "/refund", method = RequestMethod.POST)
+    public String refund(String orderid, String reid, String refundMoney, String refundReason) throws ParseException, IOException {
+        return paymentService.refund(orderid, reid, refundMoney, refundReason);
+    }
+
+    /**
+     *  查询银盛余额
+     *
+     */
+    @RequestMapping(value = "/account", method = RequestMethod.GET)
+    public Map<String, String> account() throws IOException {
+        return paymentService.account();
+    }
+
+    /**
+     *  查询交易记录表
+     *  @param params       分页信息
+     *  @param keyword      关键字
+     *  @param fromDate     起始日期
+     *  @param toDate       结束日期
+     *
+     */
+
+    @RequestMapping(value = "/queryPayment", method = RequestMethod.GET)
+    public Page<Payment> queryPayment(PageParams params, String keyword, Long fromDate, Long toDate){
+        PageInfo pageInfo = new PageInfo(params);
+        return paymentService.queryPayment(pageInfo,keyword,fromDate,toDate);
+    }
+
+}

+ 272 - 0
src/main/java/com/uas/cloud/mall/payment/domain/Payment.java

@@ -0,0 +1,272 @@
+package com.uas.cloud.mall.payment.domain;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "trade$ysepay")
+public class Payment implements Serializable {
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = 1L;
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "trade$payment_gen")
+    @SequenceGenerator(name = "trade$payment_gen", sequenceName = "trade$payment_seq", allocationSize = 1)
+    @Column(name = "id")
+    private Long id;
+
+    /**
+     * 交易流水号
+     */
+    @Column(name = "yse_id", unique = true)
+    private String yseid;
+
+    /**
+     * 订单号
+     */
+    @Column(name = "yse_out_trade_no", unique = true)
+    private String orderid;
+
+    /**
+     * 交易状态
+     */
+    @Column(name = "yse_state")
+    private String state;
+
+    /**
+     * 银盛支付交易流水号
+     */
+    @Column(name = "yse_trade_no")
+    private String tradeNo;
+
+    /**
+     * 付款成功金额
+     */
+    @Column(name = "yse_total_amount")
+    private String totalAmount;
+
+    /**
+     * 付款金额入账日期
+     */
+    @Column(name = "yse_payment_account_date")
+    private Date paymentAccountDate;
+
+    /**
+     * 付款成功异步通知时间
+     */
+    @Column(name = "yse_notify_time")
+    private Date notifyTime;
+
+    /**
+     * 付款成功异步通知类型
+     */
+    @Column(name = "yse_notify_type")
+    private String notifyType;
+
+    /**
+     * 签名类型
+     */
+    @Column(name = "yse_sign_type")
+    private String signType;
+
+    /**
+     * 付款签名
+     */
+    @Column(name = "yse_payment_sign")
+    private String paymentSign;
+
+    /**
+     * 退款金额
+     */
+    @Column(name = "yse_refund_amount")
+    private String refundAmount;
+
+    /**
+     * 退款入账时间
+     */
+    @Column(name = "yse_refund_account_date")
+    private Date refundAccountDate;
+
+    /**
+     * 退款签名
+     */
+    @Column(name = "yse_refund_sign")
+    private String refundSign;
+
+    /**
+     * 退款号
+     */
+    @Column(name = "yse_refundid")
+    private String refundId;
+
+    public Payment() {
+
+    }
+
+    public Payment(String yseid, String orderid, String state, String tradeNo, String totalAmount,
+                            Date paymentAccountDate, Date notifyTime, String notifyType, String signType, String paymentSign) {
+        super();
+        this.yseid = yseid;
+        this.orderid = orderid;
+        this.state = state;
+        this.tradeNo = tradeNo;
+        this.totalAmount = totalAmount;
+        this.paymentAccountDate = paymentAccountDate;
+        this.notifyTime = notifyTime;
+        this.notifyType = notifyType;
+        this.signType = signType;
+        this.paymentSign = paymentSign;
+    }
+
+    public Payment(String yseid, String orderid, String refundId, String state, String tradeNo,
+                            String totalAmount, Date paymentAccountDate, String refundAmount, Date refundAccountDate,
+                            String refundSign) {
+        super();
+        this.yseid = yseid;
+        this.orderid = orderid;
+        this.refundId = refundId;
+        this.state = state;
+        this.tradeNo = tradeNo;
+        this.totalAmount = totalAmount;
+        this.paymentAccountDate = paymentAccountDate;
+        this.refundAmount = refundAmount;
+        this.refundAccountDate = refundAccountDate;
+        this.refundSign = refundSign;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getYseid() {
+        return yseid;
+    }
+
+    public void setYseid(String yseid) {
+        this.yseid = yseid;
+    }
+
+    public String getOrderid() {
+        return orderid;
+    }
+
+    public void setOrderid(String orderid) {
+        this.orderid = orderid;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+
+    public String getTradeNo() {
+        return tradeNo;
+    }
+
+    public void setTradeNo(String tradeNo) {
+        this.tradeNo = tradeNo;
+    }
+
+    public String getTotalAmount() {
+        return totalAmount;
+    }
+
+    public void setTotalAmount(String totalAmount) {
+        this.totalAmount = totalAmount;
+    }
+
+    public Date getPaymentAccountDate() {
+        return paymentAccountDate;
+    }
+
+    public void setPaymentAccountDate(Date paymentAccountDate) {
+        this.paymentAccountDate = paymentAccountDate;
+    }
+
+    public Date getNotifyTime() {
+        return notifyTime;
+    }
+
+    public void setNotifyTime(Date notifyTime) {
+        this.notifyTime = notifyTime;
+    }
+
+    public String getNotifyType() {
+        return notifyType;
+    }
+
+    public void setNotifyType(String notifyType) {
+        this.notifyType = notifyType;
+    }
+
+    public String getSignType() {
+        return signType;
+    }
+
+    public void setSignType(String signType) {
+        this.signType = signType;
+    }
+
+    public String getPaymentSign() {
+        return paymentSign;
+    }
+
+    public void setPaymentSign(String paymentSign) {
+        this.paymentSign = paymentSign;
+    }
+
+    public String getRefundAmount() {
+        return refundAmount;
+    }
+
+    public void setRefundAmount(String refundAmount) {
+        this.refundAmount = refundAmount;
+    }
+
+    public Date getRefundAccountDate() {
+        return refundAccountDate;
+    }
+
+    public void setRefundAccountDate(Date refundAccountDate) {
+        this.refundAccountDate = refundAccountDate;
+    }
+
+    public String getRefundSign() {
+        return refundSign;
+    }
+
+    public void setRefundSign(String refundSign) {
+        this.refundSign = refundSign;
+    }
+
+    public static long getSerialversionuid() {
+        return serialVersionUID;
+    }
+
+    public String getRefundId() {
+        return refundId;
+    }
+
+    public void setRefundId(String refundId) {
+        this.refundId = refundId;
+    }
+
+    @Override
+    public String toString() {
+        return "TradeRecordChart [id=" + id + ", yseid=" + yseid + ", orderid=" + orderid + ", state=" + state + ", tradeNo=" + tradeNo
+                + ", totalAmount=" + totalAmount + ", paymentAccountDate=" + paymentAccountDate + ", notifyTime=" + notifyTime
+                + ", notifyType=" + notifyType + ", signType=" + signType + ", paymentSign=" + paymentSign + ", refundAmount="
+                + refundAmount + ", refundAccountDate=" + refundAccountDate + ", refundSign=" + refundSign + ", refundId=" + refundId + "]";
+    }
+}

+ 12 - 0
src/main/java/com/uas/cloud/mall/payment/repository/PaymentRepository.java

@@ -0,0 +1,12 @@
+package com.uas.cloud.mall.payment.repository;
+
+import com.uas.cloud.mall.payment.domain.Payment;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface PaymentRepository extends JpaSpecificationExecutor<Payment>, JpaRepository<Payment, Long> {
+
+    public Payment findByOrderid(String orderid);
+}

+ 87 - 0
src/main/java/com/uas/cloud/mall/payment/service/PaymentService.java

@@ -0,0 +1,87 @@
+
+package com.uas.cloud.mall.payment.service;
+
+import com.uas.cloud.commons.domain.PageInfo;
+import com.uas.cloud.mall.payment.domain.Payment;
+import org.springframework.data.domain.Page;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.Map;
+
+public interface PaymentService {
+
+    /**
+     *   支付参数签名加密
+     *
+     *   @param orderid        订单号
+     *   @param ensurePrice    付款金额
+     *   @param subject        商品描述
+     */
+    Map<String, String> paymentSign(String orderid,String ensurePrice, String subject);
+
+
+    /**
+     *   验证银盛支付异步通知,是否付款成功
+     *
+     *   @param request        请求银盛请求信息
+     */
+    String ysepayNotify(HttpServletRequest request) throws ParseException;
+
+
+    /**
+     *   保存交易信息
+     *
+     *   @param payment   交易信息
+     */
+    void save(Payment payment);
+
+    /**
+     *   退款请求参数加密
+     *
+     *   @param orderid        订单号
+     *   @param reid           退款单号
+     *   @param refundMoney   退款金额
+     *   @param refundReason  退款原因
+     */
+    Map<String, String> refundSign(String orderid,String reid, String refundMoney, String refundReason);
+
+
+    /**
+     *   发起退款
+     *
+     *   @param orderid        订单号
+     *   @param reid           退款单号
+     *   @param refundMoney   退款金额
+     *   @param refundReason  退款原因
+     */
+    String refund(String orderid,String reid, String refundMoney, String refundReason) throws ParseException, IOException;
+
+
+    /**
+     *   查询银盛余额请求参数加密
+     *
+     */
+    Map<String,String> accountSign();
+
+
+    /**
+     *   查询银盛余额
+     *
+     */
+    Map<String,String> account() throws IOException;
+
+     /**
+     * 查询交易记录表
+     *
+     * @param pageInfo     分页信息
+     * @param keyword      关键字
+     * @param fromDate     起始日期
+     * @param toDate       结束日期
+     */
+    public Page<Payment> queryPayment(PageInfo pageInfo, String keyword, Long fromDate, Long toDate);
+
+}
+

+ 284 - 0
src/main/java/com/uas/cloud/mall/payment/service/impl/PaymentServiceImpl.java

@@ -0,0 +1,284 @@
+package com.uas.cloud.mall.payment.service.impl;
+
+import com.uas.cloud.commons.domain.PageInfo;
+import com.uas.cloud.commons.persistence.criteria.PredicateUtils;
+import com.uas.cloud.commons.util.FastjsonUtils;
+import com.uas.cloud.commons.util.OkHttpUtils;
+import com.uas.cloud.mall.payment.domain.Payment;
+import com.uas.cloud.mall.payment.repository.PaymentRepository;
+import com.uas.cloud.mall.payment.service.PaymentService;
+import com.uas.cloud.mall.payment.util.ApipaySubmit;
+import com.uas.cloud.mall.payment.util.DirectPayConfig;
+import okhttp3.Response;
+import org.apache.commons.collections.map.HashedMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+@Service
+public class PaymentServiceImpl implements PaymentService{
+
+    @Autowired
+    private PaymentRepository paymentRepository;
+
+    @Override
+    public  Map<String,String> paymentSign(String orderid,String ensurePrice, String subject){
+
+        Map<String, String> map = new HashMap<>();
+
+        // 获取当前时间
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String timestamp = sdf.format(new Date());
+
+        map.put("out_trade_no", orderid);
+        map.put("total_amount", ensurePrice);
+        map.put("subject", subject);
+        map.put("timestamp", timestamp);
+        map.put("method", DirectPayConfig.METHOD);
+        map.put("charset", DirectPayConfig.DEFAULT_CHARSET);
+        map.put("sign_type", DirectPayConfig.SIGN_TYPE);
+        map.put("version", DirectPayConfig.VERSION);
+        map.put("business_code", DirectPayConfig.BUSINESS_CODE);
+        map.put("timeout_express", DirectPayConfig.TIMEOUT_EXPRESS);
+        map.put("notify_url", DirectPayConfig.NOTIFY_URL);
+        map.put("return_url", DirectPayConfig.RETURN_URL);
+        map.put("partner_id", DirectPayConfig.PARTNER_ID);
+        map.put("seller_id", DirectPayConfig.SELLER_ID);
+        map.put("seller_name", DirectPayConfig.SELLER_NAME);
+
+        // 生成签名后的参数
+        Map<String, String> sPara = ApipaySubmit.buildRequestPara(map);
+
+        return  sPara;
+    }
+
+    @Override
+    public String ysepayNotify(HttpServletRequest request) throws ParseException {
+
+        Map<String, String> params = new HashMap<>();
+        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] + ",";
+            }
+            System.out.println("name:" + name + " value:" + valueStr);
+            params.put(name, valueStr);
+        }
+
+        // 验证 params 签名
+        boolean paramsResult = ApipaySubmit.verifySign(params);
+        String trade_status = request.getParameter("trade_status");
+
+        if(paramsResult){
+            System.out.println("异步通知验证签名成功");
+            if(trade_status.equals("TRADE_SUCCESS")){
+                // 保存付款成功交易信息
+                SimpleDateFormat sdf_nt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                SimpleDateFormat sdf_ad = new SimpleDateFormat("yyyyMMdd");
+                String yseid = "pay";
+              /*  String yseid = EncodingRulesConstant.YSEPAY.replace("_TIMESTAP_NUMBER", createNumberService.getTimeNumber("trade$ysepay", 8));*/
+                String orderid = params.get("out_trade_no");
+                String tradeNo = params.get("trade_no");
+                String totalAmount = params.get("total_amount");
+                Date paymentAccountDate = sdf_ad.parse(params.get("account_date"));
+                Date notifyTime = sdf_nt.parse(params.get("notify_time"));
+                String notifyType = params.get("notify_type");
+                String signType = params.get("sign_type");
+                String paymentSign = params.get("sign");
+                Payment payment = new Payment(yseid, orderid, "已付款", tradeNo, totalAmount, paymentAccountDate, notifyTime, notifyType, signType, paymentSign);
+                save(payment);
+                return "success";
+            }else {
+                return "fail";
+            }
+        }
+        return "fail";
+    }
+
+    @Override
+    public void save(Payment payment){
+        paymentRepository.save(payment);
+    }
+
+    @Override
+    public Map<String, String> refundSign(String orderid, String reid, String refundMoney, String refundReason){
+
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("out_trade_no", orderid);
+        params.put("out_request_no", reid);
+        params.put("refund_amount", refundMoney);
+        params.put("refund_reason", refundReason);
+        String biz_content = FastjsonUtils.toJson(params);
+
+        // 生成当前时间
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String timestamp = sdf.format(new Date());
+
+        // 待签名参数
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("biz_content", biz_content);
+        map.put("timestamp", timestamp);
+        map.put("method", "ysepay.online.trade.refund");
+        map.put("charset", DirectPayConfig.DEFAULT_CHARSET);
+        map.put("sign_type", DirectPayConfig.SIGN_TYPE);
+        map.put("version", DirectPayConfig.VERSION);
+        map.put("partner_id", DirectPayConfig.PARTNER_ID);
+
+        // 生成签名后的参数
+        Map<String, String> sPara = ApipaySubmit.buildRequestPara(map);
+
+        return sPara;
+    }
+
+    @Override
+    public String refund(String orderid, String reid, String refundMoney, String refundReason) throws ParseException, IOException {
+
+        Map<String, String> sPara = new HashMap<String, String>();
+        sPara = refundSign(orderid, reid, refundMoney, refundReason);
+
+        String url = "https://openapi.ysepay.com/gateway.do";
+        Response response = OkHttpUtils.sendPost(url, sPara);
+
+        // 银盛官方同步返回信息
+        String reponseText = response.body().string();
+        String refundInfo = FastjsonUtils.parseObject(reponseText).getString("ysepay_online_trade_refund_response");
+
+        // 获取验证签名加密字符串原文
+        String subStr = reponseText.substring(1, reponseText.length() - 1);
+        int firstIndex = subStr.indexOf('{');
+        int lastIndex = subStr.lastIndexOf('}');
+        String responseBody = subStr.substring(firstIndex, lastIndex + 1);
+        String charset = DirectPayConfig.DEFAULT_CHARSET;
+        String sign = FastjsonUtils.parseObject(reponseText).getString("sign");
+
+        // 验证签名以及msg是否为成功
+        boolean paramsResult = ApipaySubmit.verifySign(sign, responseBody, charset);
+        String msg = FastjsonUtils.parseObject(refundInfo).getString("msg");
+
+        if(paramsResult){
+            System.out.println("同步签名验证成功");
+            if(msg.equals("Success")){
+                // 保存退款信息
+                SimpleDateFormat sdf_rad = new SimpleDateFormat("yyyy-MM-dd");
+                String yseid = "refund";
+             /*   String yseid = EncodingRulesConstant.YSEPAY.replace("_TIMESTAP_NUMBER", createNumberService.getTimeNumber("trade$ysepay", 8));*/
+                String tradeNo = FastjsonUtils.parseObject(refundInfo).getString("trade_no");
+                String totalAmount = paymentRepository.findByOrderid(orderid).getTotalAmount();
+                Date paymentAccountDate = paymentRepository.findByOrderid(orderid).getPaymentAccountDate();
+                String refundAmount = FastjsonUtils.parseObject(refundInfo).getString("refund_amount");
+                Date refundAccountDate = sdf_rad.parse(FastjsonUtils.parseObject(refundInfo).getString("account_date"));
+                String refundSign = FastjsonUtils.parseObject(reponseText).getString("sign");
+                Payment payment = new Payment(yseid, orderid, reid, "已退款", tradeNo, totalAmount, paymentAccountDate, refundAmount, refundAccountDate, refundSign);
+                save(payment);
+                return "success";
+            }
+        }
+        return "fail";
+    }
+
+    @Override
+    public Map<String,String> accountSign(){
+
+        // 业务参数转为JSON格式
+        Map<String, String> params = new HashMap<String, String>();
+        params.put("user_code", DirectPayConfig.SELLER_ID);
+        params.put("user_name", DirectPayConfig.SELLER_NAME);
+        params.put("account_no", "0000400025744626");
+        String biz_content = FastjsonUtils.toJson(params);
+
+        // 生成当前时间
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String timestamp = sdf.format(new Date());
+
+        // 待签名参数
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("biz_content", biz_content);
+        map.put("timestamp", timestamp);
+        map.put("method", "ysepay.online.user.account.get");
+        map.put("charset", DirectPayConfig.DEFAULT_CHARSET);
+        map.put("sign_type", DirectPayConfig.SIGN_TYPE);
+        map.put("version", DirectPayConfig.VERSION);
+        map.put("partner_id", DirectPayConfig.PARTNER_ID);
+
+        // 生成查询银盛账户余额请求参数map(加上签名)
+        Map<String, String> sPara = ApipaySubmit.buildRequestPara(map);
+
+        return sPara;
+    }
+
+    @Override
+    public Map<String,String> account() throws IOException {
+
+        Map<String, String> sPara = new HashMap<String, String>();
+        sPara = accountSign();
+
+        String url = "https://openapi.ysepay.com/gateway.do";
+        Response response = OkHttpUtils.sendPost(url, sPara);
+
+        String reponseText = response.body().string();
+        String accountInfo = FastjsonUtils.parseObject(reponseText).getString("ysepay_online_user_account_get_response");
+
+        // 获取验证签名加密字符串原文
+        String subStr = reponseText.substring(1, reponseText.length() - 1);
+        int firstIndex = subStr.indexOf('[');
+        int lastIndex = subStr.lastIndexOf(']');
+        String responseBody = subStr.substring(firstIndex, lastIndex + 1);
+        String charset = DirectPayConfig.DEFAULT_CHARSET;
+        String sign = FastjsonUtils.parseObject(reponseText).getString("sign");
+
+        // 验证签名以及msg是否为成功
+        boolean paramsResult = ApipaySubmit.verifySign(sign, responseBody, charset);
+        String info = FastjsonUtils.fromJsonArray(accountInfo).getString(0);
+        String msg = FastjsonUtils.parseObject(info).getString("msg");
+
+        if(paramsResult){
+            System.out.println("同步签名验证成功");
+            if(msg.equals("Success")){
+                Map<String, String> map = new HashMap<>();
+                map.put("accountInfo", accountInfo);
+                return map;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Page<Payment> queryPayment(final PageInfo pageInfo, String keyword, Long fromDate, Long toDate){
+        if (StringUtils.hasText(keyword)) {
+            // 输入订单号,按订单号查询
+            pageInfo.filter("orderid", keyword);
+        }
+        if (fromDate != null) {// 输入开始时间,按付款生成时间查询
+            pageInfo.expression(PredicateUtils.gte("paymentAccountDate", new Date(fromDate), false));
+        }
+        if (toDate != null) {// 输入截至时间,按付款生成时间查询
+            pageInfo.expression(PredicateUtils.lte("paymentAccountDate", new Date(toDate), false));
+        }
+
+        return paymentRepository.findAll(new Specification<Payment>() {
+            @Override
+            public Predicate toPredicate(Root<Payment> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
+                query.where(pageInfo.getPredicates(root, query, builder));
+                return null;
+            }
+        },pageInfo);
+
+    };
+}
+

+ 92 - 0
src/main/java/com/uas/cloud/mall/payment/util/ApipaySubmit.java

@@ -0,0 +1,92 @@
+package com.uas.cloud.mall.payment.util;
+
+import java.io.InputStream;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.core.io.FileSystemResource;
+
+public class ApipaySubmit {
+	/**
+	 * api请求的签名工具方法,把请求参数按照字符排序拼接,然后进行RAS加密
+	 *
+	 * @param request
+	 * @param sParaTemp
+	 * @return
+	 * @see
+	 */
+	public static String sign(HttpServletRequest request, Map<String, String> sParaTemp) {
+		Map<String, String> sPara = SignUtils.paraFilter(sParaTemp);
+		String signResult = null;
+		InputStream pfxCertFileInputStream = null;
+
+		try {
+			pfxCertFileInputStream = new FileSystemResource(DirectPayConfig.PATH_PARTER_PKCS12).getInputStream();
+			signResult = SignUtils.rsaSign(sPara, sParaTemp.get("charset"), pfxCertFileInputStream);
+		} catch (Exception e) {
+			throw new RuntimeException("签名失败,请检查证书文件是否存在,密码是否正确");
+		}
+
+		return signResult;
+	}
+
+	/**
+	 * API验证签名工具,把签名值,请求字符编码,返回结果(json body)传递过来进行验证签名
+	 *
+	 * @param sign
+	 * @param responseBody
+	 * @param charset
+	 * @return
+	 * @see
+	 */
+	public static boolean verifySign(String sign, String responseBody, String charset) {
+		InputStream publicCertFileInputStream = null;
+		boolean isSign;
+
+		try {
+			publicCertFileInputStream = new FileSystemResource(DirectPayConfig.PATH_YSEPAY_PUBLIC_CERT)
+					.getInputStream();
+			isSign = SignUtils.rsaCheckContent(publicCertFileInputStream, responseBody, sign, charset);
+		} catch (Exception e) {
+			throw new RuntimeException("验证签名失败,请检查银盛公钥证书文件是否存在");
+		}
+
+		return isSign;
+	}
+
+	public static Map<String, String> buildRequestPara(Map<String, String> sParaTemp) {
+		Map<String, String> sPara = SignUtils.paraFilter(sParaTemp);
+		InputStream pfxCertFileInputStream = null;
+
+		try {
+			pfxCertFileInputStream = new FileSystemResource(DirectPayConfig.PATH_PARTER_PKCS12).getInputStream();
+			String mysign = SignUtils.rsaSign(sPara, sParaTemp.get("charset"), pfxCertFileInputStream);
+			sPara.put("sign", mysign);
+		} catch (Exception e) {
+			throw new RuntimeException("签名失败,请检查证书文件是否存在,密码是否正确");
+		}
+
+		return sPara;
+	}
+
+	public static boolean verifySign(Map<String, String> params) {
+		InputStream publicCertFileInputStream = null;
+		boolean isSign;
+
+		try {
+			publicCertFileInputStream = new FileSystemResource(DirectPayConfig.PATH_YSEPAY_PUBLIC_CERT)
+					.getInputStream();
+			String sign = "";
+			if (params.get("sign") != null) {
+				sign = params.get("sign");
+			}
+			System.out.println("公钥的地址" + DirectPayConfig.PATH_YSEPAY_PUBLIC_CERT);
+			isSign = SignUtils.rsaCheckContent(publicCertFileInputStream, params, sign, DirectPayConfig.DEFAULT_CHARSET);
+		} catch (Exception e) {
+			throw new RuntimeException("验证签名失败,请检查银盛公钥证书文件是否存在");
+		}
+
+		return isSign;
+	}
+}

+ 56 - 0
src/main/java/com/uas/cloud/mall/payment/util/DirectPayConfig.java

@@ -0,0 +1,56 @@
+package com.uas.cloud.mall.payment.util;
+
+import com.uas.cloud.commons.web.context.PathUtils;
+import org.springframework.beans.factory.annotation.Value;
+
+import java.io.File;
+
+public class DirectPayConfig {
+    // 合作商家私钥pkcs12证书路径
+	public static final String PATH_PARTER_PKCS12 = PathUtils.getFilePath() + "src"+ File.separator + "main" + File.separator+ "resources" + File.separator + "cert"  + File.separator + "yrsc.pfx";
+
+	// 合作商家私钥pkcs12证书密码
+	public static final String PASSWORD_PARTNER_PKCS12 = "yrscyr";
+
+	// 银盛公钥pkcs12证书路径
+	public static final String PATH_YSEPAY_PUBLIC_CERT = PathUtils.getFilePath() + "src"+ File.separator + "main" + File.separator+ "resources" + File.separator + "cert"  + File.separator + "businessgate.cer";
+
+	// rsa算法名
+	public static final String RSA_ALGORITHM = "SHA1WithRSA";
+
+	/******************* 请求数据需要用到的参数 ******************/
+
+	// 银盛前台同步通知跳转地址
+	public static final String NOTIFY_URL="http://218.17.158.219:9090/platform-b2c/api/payment/ysepayNotify";
+
+	// 银盛后台异步通知地址
+	public static final String RETURN_URL ="http://218.17.158.219:9090/platform-b2c/user#/home/myOrder_todo?state=tobedeliver";
+
+	// 用户号(商户号)
+	public static final String PARTNER_ID = "yrsc";
+
+	// 收款方银盛支付用户号
+	public static final String SELLER_ID = "yrsc";
+
+	// 收款方银盛支付客户名
+	public static final String SELLER_NAME = "深圳市优软商城科技有限公司";
+
+	// 字符编码
+	public static final String DEFAULT_CHARSET = "utf-8";
+
+	// 接口名称
+	public static final String METHOD = "ysepay.online.directpay.createbyuser";
+
+	// 签名类型
+	public static final String SIGN_TYPE = "RSA";
+
+	// 接口版本
+	public static final String VERSION = "3.0";
+
+	// 未付款交易的超时时间
+	public static final String TIMEOUT_EXPRESS = "3d";
+
+	// 业务代码
+	public static final String BUSINESS_CODE = "01000010";
+
+}

+ 218 - 0
src/main/java/com/uas/cloud/mall/payment/util/SignUtils.java

@@ -0,0 +1,218 @@
+package com.uas.cloud.mall.payment.util;
+
+import java.io.InputStream;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.codec.binary.Base64;
+
+public class SignUtils {
+	// static {
+	// Security.addProvider(
+	// new org.bouncycastle.jce.provider.BouncyCastleProvider());
+	// }
+
+	// 缓存公钥和私钥
+	public static Map<String, Object> certMap = new java.util.concurrent.ConcurrentHashMap<String, Object>();
+
+	/**
+	 * 除去数组中的空值和签名参数
+	 * 
+	 * @param sArray
+	 *            签名参数组
+	 * @return 去掉空值与签名参数后的新签名参数组
+	 */
+	public static Map<String, String> paraFilter(Map<String, String> sArray) {
+
+		Map<String, String> result = new HashMap<String, String>();
+
+		if (sArray == null || sArray.size() <= 0) {
+			return result;
+		}
+
+		for (String key : sArray.keySet()) {
+			String value = sArray.get(key);
+			if (value == null || StringUtils.isEmpty(value) || key.equalsIgnoreCase("sign")) {
+				continue;
+			}
+			result.put(key, value);
+		}
+
+		return result;
+	}
+
+	/**
+	 * 
+	 * @param sortedParams
+	 * @return
+	 */
+	public static String getSignContent(Map<String, String> sortedParams) {
+		StringBuffer content = new StringBuffer();
+		List<String> keys = new ArrayList<String>(sortedParams.keySet());
+		Collections.sort(keys);
+		int index = 0;
+		for (int i = 0; i < keys.size(); i++) {
+			String key = keys.get(i);
+			String value = sortedParams.get(key);
+			if (StringUtils.areNotEmpty(key, value)) {
+				content.append((index == 0 ? "" : "&") + key + "=" + value);
+				index++;
+			}
+		}
+		return content.toString();
+	}
+
+	public static String rsaSign(String content, String charset, InputStream pfxCertFileInputStream) throws Exception {
+		try {
+			System.out.println("进入签名方法:content[" + content + "], charset[" + charset + "]");
+			PrivateKey priKey = getPrivateKeyFromPKCS12(DirectPayConfig.PASSWORD_PARTNER_PKCS12,
+					pfxCertFileInputStream);
+
+			java.security.Signature signature = java.security.Signature.getInstance(DirectPayConfig.RSA_ALGORITHM);
+
+			signature.initSign(priKey);
+
+			if (StringUtils.isEmpty(charset)) {
+				signature.update(content.getBytes());
+			} else {
+				signature.update(content.getBytes(charset));
+			}
+
+			byte[] signed = signature.sign();
+
+			String sign = new String(Base64.encodeBase64(signed), charset);
+
+			System.out.println("进入签名方法:content[" + content + "], charset[" + charset + "], sign[" + sign + "]");
+
+			return sign;
+		} catch (Exception e) {
+			System.out.println("签名失败:content[" + content + "], charset[" + charset + "]");
+			throw new Exception("RSAcontent = " + content + "; charset = " + charset, e);
+		}
+	}
+
+	public static String rsaSign(Map<String, String> params, String charset, InputStream pfxCertFileInputStream)
+			throws Exception {
+		String signContent = getSignContent(params);
+
+		return rsaSign(signContent, charset, pfxCertFileInputStream);
+	}
+
+	public static boolean rsaCheckContent(InputStream publicCertFileInputStream, Map<String, String> params,
+			String sign, String charset) throws Exception {
+		String content = StringUtils.createLinkString(SignUtils.paraFilter(params));
+
+		return rsaCheckContent(publicCertFileInputStream, content, sign, charset);
+	}
+
+	public static boolean rsaCheckContent(InputStream publicCertFileInputStream, String content, String sign,
+			String charset) throws Exception {
+		System.out.println("进入验证签名方法: content[" + content + "], sign[" + sign + "], charset[" + charset + "]");
+		boolean bFlag = false;
+		try {
+			java.security.Signature signetcheck = java.security.Signature.getInstance(DirectPayConfig.RSA_ALGORITHM);
+			signetcheck.initVerify(getPublicKeyFromCert(publicCertFileInputStream));
+			signetcheck.update(content.getBytes(charset));
+			if (signetcheck.verify(Base64.decodeBase64(sign.getBytes(charset)))) {
+				bFlag = true;
+			}
+
+			System.out.println("进入验证签名方法: content[" + content + "], sign[" + sign + "], charset[" + charset
+					+ "], result[" + bFlag + "]");
+		} catch (Exception e) {
+			System.out.println("验证签名异常" + ": content[" + content + "], sign[" + sign + "], charset[" + charset + "]");
+			throw new Exception("验证签名异常");
+		}
+
+		return bFlag;
+	}
+
+	/**
+	 * 读取公钥,x509格式
+	 * 
+	 * @param password
+	 * @param ins
+	 * @return
+	 * @throws Exception
+	 * @see
+	 */
+	public static PublicKey getPublicKeyFromCert(InputStream ins) throws Exception {
+		PublicKey pubKey = (PublicKey) certMap.get("PublicKey");
+		if (pubKey != null) {
+			return pubKey;
+		}
+
+		try {
+			CertificateFactory cf = CertificateFactory.getInstance("X.509");
+			Certificate cac = cf.generateCertificate(ins);
+			pubKey = cac.getPublicKey();
+			certMap.put("PublicKey", pubKey);
+		} catch (Exception e) {
+			if (ins != null)
+				ins.close();
+			throw e;
+		} finally {
+			if (ins != null) {
+				ins.close();
+			}
+		}
+
+		return pubKey;
+	}
+
+	/**
+	 * 读取PKCS12格式的key(私钥)pfx格式
+	 * 
+	 * @param password
+	 * @param ins
+	 * @return
+	 * @throws Exception
+	 * @see
+	 */
+	public static PrivateKey getPrivateKeyFromPKCS12(String password, InputStream ins) throws Exception {
+		PrivateKey priKey = (PrivateKey) certMap.get("PrivateKey");
+		if (priKey != null) {
+			return priKey;
+		}
+
+		KeyStore keystoreCA = KeyStore.getInstance("PKCS12");
+		try {
+			// 读取CA根证书
+			keystoreCA.load(ins, password.toCharArray());
+
+			Enumeration<?> aliases = keystoreCA.aliases();
+			String keyAlias = null;
+			if (aliases != null) {
+				while (aliases.hasMoreElements()) {
+					keyAlias = (String) aliases.nextElement();
+					// 获取CA私钥
+					priKey = (PrivateKey) (keystoreCA.getKey(keyAlias, password.toCharArray()));
+					if (priKey != null) {
+						certMap.put("PrivateKey", priKey);
+						break;
+					}
+				}
+			}
+		} catch (Exception e) {
+			if (ins != null)
+				ins.close();
+			throw e;
+		} finally {
+			if (ins != null) {
+				ins.close();
+			}
+		}
+
+		return priKey;
+	}
+
+}

+ 77 - 0
src/main/java/com/uas/cloud/mall/payment/util/StringUtils.java

@@ -0,0 +1,77 @@
+package com.uas.cloud.mall.payment.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class StringUtils {
+	/**
+	 * 判断字符数组是否为空
+	 */
+	public static boolean areNotEmpty(String... values) {
+		boolean result = true;
+		if (values == null || values.length == 0) {
+			result = false;
+		} else {
+			for (String value : values) {
+				result &= !isEmpty(value);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
+	 * 
+	 * @param params
+	 *            需要排序并参与字符拼接的参数组
+	 * @return 拼接后字符串
+	 */
+	public static String createLinkString(Map<String, String> params) {
+
+		List<String> keys = new ArrayList<String>(params.keySet());
+		Collections.sort(keys);
+
+		String prestr = "";
+
+		for (int i = 0; i < keys.size(); i++) {
+			String key = keys.get(i);
+			String value = params.get(key);
+
+			if (i == keys.size() - 1) {// ƴ��ʱ�����������һ��&�ַ�
+				prestr = prestr + key + "=" + value;
+			} else {
+				prestr = prestr + key + "=" + value + "&";
+			}
+		}
+
+		return prestr;
+	}
+
+	/**
+	 * 判断字符串是否为空
+	 * <ul>
+	 * <li>isEmpty(null) = true</li>
+	 * <li>isEmpty("") = true</li>
+	 * <li>isEmpty("   ") = true</li>
+	 * <li>isEmpty("abc") = false</li>
+	 * </ul>
+	 * 
+	 * @param value
+	 *            目标字符串
+	 * @return true/false
+	 */
+	public static boolean isEmpty(String value) {
+		int strLen;
+		if (value == null || (strLen = value.length()) == 0) {
+			return true;
+		}
+		for (int i = 0; i < strLen; i++) {
+			if ((Character.isWhitespace(value.charAt(i)) == false)) {
+				return false;
+			}
+		}
+		return true;
+	}
+}

+ 22 - 0
src/main/resources/application.yml

@@ -0,0 +1,22 @@
+spring:
+  appliction:
+    name: mall-payment-service
+  jpa:
+    properties :
+      hibernate :
+        hbm2ddl :
+          auto : update
+  datasource:
+    url: jdbc:oracle:thin:@192.168.253.6:1521:orcl
+    username: uuplatformdemo
+    password: selectuuplatform
+    driver-class-name: oracle.jdbc.driver.OracleDriver
+
+server:
+  port: 20150
+
+security:
+  basic:
+    enabled: false
+
+

+ 7 - 0
src/main/resources/bootstrap-dev.yml

@@ -0,0 +1,7 @@
+spring:
+  cloud:
+    config:
+      profile: dev
+      label: master
+      uri: http://configserver:28001/
+

+ 6 - 0
src/main/resources/bootstrap-prod.yml

@@ -0,0 +1,6 @@
+spring:
+  cloud:
+    config:
+      profile: prod
+      label: master
+      uri: http://configserver:28001/

+ 6 - 0
src/main/resources/bootstrap-test.yml

@@ -0,0 +1,6 @@
+spring:
+  cloud:
+    config:
+      profile: test
+      label: master
+      uri: http://configserver:28001/

+ 9 - 0
src/main/resources/bootstrap.yml

@@ -0,0 +1,9 @@
+spring:
+  application:
+    name: mall-payment-service
+  cloud:
+#    config:
+#      profile: dev
+#      label: master
+#      uri: http://10.10.100.23:28001/
+

BIN
src/main/resources/cert/businessgate.cer


BIN
src/main/resources/cert/yrsc.cer


BIN
src/main/resources/cert/yrsc.pfx