【问题标题】:Grails and PayPal (Express Checkout)Grails 和 PayPal(快速结帐)
【发布时间】:2011-06-16 02:13:20
【问题描述】:

有两个适用于 Grails 的 PayPal 插件,first I found is a year old,而且似乎运行良好。 second it a bit older and apparently not compatible with 1.1+

如果我决定不使用现有插件,为 Grails 实现简单快速结帐流程的最佳方法是什么?我不完全确定如何使用 PayPal API,而且他们的文档目前在迁移到 X.com 后变得一团糟。

【问题讨论】:

    标签: grails paypal express-checkout


    【解决方案1】:

    这是我从 Paypal 插件中显示的 IPN 控制器,以匹配 Paypal IPN 要求。它正在生产中。

    package com.risguru.plugin.ipn
    
    import com.risguru.plugin.shoppingcart.IOrderService
    
    class PaymentController {
    
    IOrderService orderService
    
    def config = grailsApplication.config.grails.paypal
    
    static allowedMethods = [buy: 'POST', notify: 'POST']
    static defaultAction = 'index'
    def index = {
        redirect(controller:'company', action:'index')
    }
    
    def notify = {
        log.debug "Received IPN notification from PayPal Server ${params}"
        try {
            def config = grailsApplication.config.com.risguru.plugin.ipn
            def server = config.server
            def receiver = params.email ?: config.receiver
    
            if (!server || !receiver) throw new IllegalStateException("Paypal misconfigured! You need to specify the Paypal server URL and/or account email. Refer to documentation.")
    
            params.cmd = "_notify-validate"
            def queryString = params.toQueryString()[1..-1]
    
            log.debug "Sending back query $queryString to PayPal server $server"
            def url = new URL(server)
            def conn = url.openConnection()
            conn.doOutput = true
            def writer = new OutputStreamWriter(conn.getOutputStream())
            writer.write queryString
            writer.flush()
    
            def result = conn.inputStream.text?.trim()
    
            log.debug "Got response from PayPal IPN $result"
    
            def purchaseOrder = orderService.getOrderByTransactionID(params.transactionId)
    
            if (purchaseOrder && result == 'VERIFIED') {
                if (params.receiver_email != receiver) {
                    log.warn """WARNING: receiver_email parameter received from PayPal does not match configured e-mail. This request is possibly fraudulent!
                             REQUEST INFO: ${params}
                                            """
                }
                else {
                    request.purchaseOrder = purchaseOrder
                    def status = params.payment_status
                    if (purchaseOrder.paymentStatus != PaymentStatus.COMPLETE && purchaseOrder.paymentStatus != PaymentStatus.CANCELLED) {
                        if (purchaseOrder.paypalTransactionId && purchaseOrder.paypalTransactionId == params.txn_id) {
                            log.warn """WARNING: Request tried to re-use and old PayPal transaction id. This request is possibly fraudulent!
                                    REQUEST INFO: ${params} """
                        }
                        else if (status == 'Completed') {
                            purchaseOrder.paypalTransactionId = params.txn_id
                            purchaseOrder.paymentStatus = PaymentStatus.COMPLETE
                            orderService.updateOrderStatus(purchaseOrder)
                            log.info "Verified payment ${purchaseOrder.paypalTransactionId} as COMPLETE"
                        } else if (status == 'Pending') {
                            purchaseOrder.paypalTransactionId = params.txn_id
                            purchaseOrder.paymentStatus = PaymentStatus.PENDING
                            orderService.updateOrderStatus(purchaseOrder)
                            log.info "Verified payment ${purchaseOrder.paypalTransactionId} as PENDING"
                        } else if (status == 'Failed') {
                            purchaseOrder.paypalTransactionId = params.txn_id
                            purchaseOrder.paymentStatus = PaymentStatus.FAILED
                            orderService.updateOrderStatus(purchaseOrder)
                            log.info "Verified payment ${purchaseOrder.paypalTransactionId} as FAILED"
                        }
                    }
                }
            }
            else {
                log.error "Error with PayPal IPN response: [$result] and Payment: [${purchaseOrder?.transactionId}]"
            }
        } catch (Exception e) {
            log.error '"**************************************************************************'
            log.error e
            log.error '"**************************************************************************'
        } finally {
            render "OK" // Paypal needs a response, otherwise it will send the notification several times!
        }
    }
    
    def success = {
        log.info "Received IPN success from PayPal Server ${params}"
        def uniqueKey = orderService.completeAndGetUniqueKeyByTransactionID(params.transactionId)
        if (!uniqueKey){
            response.sendError 403
            return
        }
        log.info "Purchase Order complete for ${params.transactionId}"
        flash.orderStatus = OrderStatus.COMPLETE
        flash.transactionId = params.transactionId
        flash.uniqueKey = uniqueKey
        if (params.returnAction || params.returnController) {
            def args = [:]
            if (params.returnAction) args.action = params.returnAction
            if (params.returnController) args.controller = params.returnController
            args.params = params
            redirect(args)
        }
        else {
            chain(action:'termOfUse')
        }
    }
    
    def cancel = {
        params?.each { key, value ->
            println "[${key}]\t=\t${value}\t::${value?.class?.name}"
        }
        log.info "Cancel Order for ${params.transactionId}"
        def status = orderService.cancelOrder(params.transactionId)
        if (!status){
            response.sendError 403
        }
        flash.orderStatus = OrderStatus.CANCEL
        flash.transactionId = params.transactionId
        if (params.cancelAction || params.cancelController) {
            def args = [:]
            if (params.cancelAction) args.action = params.cancelAction
            if (params.cancelController) args.controller = params.cancelController
            args.params = params
            redirect(args)
        }
        else {
            chain(action:'termOfUse')
        }
    }
    
    def termOfUse = {
        if (flash.orderStatus == OrderStatus.COMPLETE || flash.orderStatus == OrderStatus.CANCEL){
            return ['transactionId':flash.transactionId, 'uniqueKey':flash.uniqueKey, message:params.message]
        }
    
        def transactionId = params.transactionId ?: flash.transactionId
        def uniqueKey = params.uniqueKey ?: flash.uniqueKey
    
        def orderStatus = orderService.checkOrderStatus(transactionId)
        if (OrderStatus.COMPLETE == orderStatus){
            log.debug "Purchase Order complete for ${transactionId}"
            flash.transactionId = transactionId
            flash.orderStatus = OrderStatus.COMPLETE
            flash.uniqueKey = uniqueKey
        } else {
            def order = orderService.createOrder(uniqueKey)
            switch (order.paymentStatus) {
                case PaymentStatus.FREE:
                    flash.transactionId = order.transactionId
                    flash.uniqueKey = uniqueKey
                    flash.orderStatus = OrderStatus.FREE
                    break
                case PaymentStatus.INVALID:
                    flash.transactionId = order.transactionId
                    flash.uniqueKey = uniqueKey
                    flash.orderStatus = OrderStatus.INVALID
                    break
                case PaymentStatus.PENDING:
                    flash.transactionId = order.transactionId
                    flash.uniqueKey = uniqueKey
                    flash.orderStatus = OrderStatus.CHARGE
                    break
                default:
                    response.sendError 403
            }
        }
    
        return ['transactionId':transactionId, 'uniqueKey':uniqueKey, message:params.message]
    }
    
    def buy = {
        if (params.disagree){
            return chain(action:'cancel', params:params)
        }
        def config = grailsApplication.config.com.risguru.plugin.ipn
        def server = config.server
        def receiver = params.email ?: config.receiver
        if (!server || !receiver) throw new IllegalStateException("Paypal misconfigured! You need to specify the Paypal server URL and/or account email. Refer to documentation.")
    
        def order = orderService.getOrderByTransactionID(params.transactionId)
        if (!order){
            response.sendError 403
        }
    
        def commonParams = [transactionId: order.transactionId]
    
        def notifyURL = g.createLink(absolute: true, controller: 'payment', action: 'notify', params: commonParams).encodeAsURL()
        def successURL = g.createLink(absolute: true, controller: 'payment', action: 'success', params: commonParams).encodeAsURL()
        def cancelURL = g.createLink(absolute: true, controller: 'payment', action: 'cancel', params: commonParams).encodeAsURL()
    
        def url = new StringBuffer("$server?")
        url << "cmd=_xclick&"
        //      url << "business=${config.business}&"
        url << "business=${receiver}&"
        url << "item_name=${order.items[0].itemName}&"
        url << "item_number=${order.items[0].itemNumber}&"
        url << "quantity=${order.items[0].quantity}&"
        url << "amount=${order.items[0].unitPrice}&"
        url << "tax=${order.tax}&"
        url << "currency_code=${order.currency}&"
        if (config.test_ipn) {
            url << "test_ipn=1&"
        }
        if (config.page_style){
            url << "page_style=${config.page_style}&"
        }
        url << "notify_url=${notifyURL}&"
        url << "return=${successURL}&"
        url << "cancel_return=${cancelURL}"
    
        log.debug "Redirection to PayPal with URL: $url"
    
        redirect(url: url)
    }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-12-07
      • 2013-03-05
      • 2017-11-22
      • 2011-08-30
      • 2011-08-10
      • 2016-07-10
      • 2017-07-15
      • 2023-04-08
      • 2012-10-08
      相关资源
      最近更新 更多