For paid membership with recurring payment mechanism by using credit card. The User Recurring Subscription module provides following features:

  • One step payment on user registration page without leaving the site.
  • Free trial period.
  • Update notification when credit card expire.
  • User can update credit card information.
  • Cancel recurring profile.

Note
The User recurring subscription module is only store last 4 digit of credit card number and expiration date.

Module Link:
https://www.drupal.org/sandbox/ratanphp/2304373

git clone --branch 7.x-1.x http://git.drupal.org/sandbox/ratanphp/2304373.git

Reviews of other projects

Comments

ratanphp’s picture

Issue summary: View changes
PA robot’s picture

Status: Needs review » Needs work

There are some errors reported by automated review tools, did you already check them? See http://pareview.sh/pareview/httpgitdrupalorgsandboxratanphp2304373git

We are currently quite busy with all the project applications and we prefer projects with a review bonus. Please help reviewing and put yourself on the high priority list, then we will take a look at your project right away :-)

Also, you should get your friends, colleagues or other community members involved to review this application. Let them go through the review checklist and post a comment that sets this issue to "needs work" (they found some problems with the project) or "reviewed & tested by the community" (they found no major flaws).

I'm a robot and this is an automated message from Project Applications Scraper.

ratanphp’s picture

Issue summary: View changes
ratanphp’s picture

Status: Needs work » Needs review
ratanphp’s picture

Issue tags: +PAreview: review bonus
er.pushpinderrana’s picture

Status: Needs review » Needs work

@ratanphp, thanks for contribution!

Manual Review:
1. Your module looks so complex but did not contains hook_help(), it should be there.
2. In user_recurring_subscription.module file, most of functions lacking comments like user_recurring_subscription_load() and user_recurring_subscription_form_user_register_form_alter() etc, as it should be.
3. At most of places you are using SELECT query with '*' instead of fetching specific fields, please add your comment on this.
4. In user_recurring_subscription_nvp_to_array() function, you are passing curl response, it should be sanitized using check_plain or some other recommend functions for safe output.
5. In following function you are calling user_recurring_subscription_profile() function where you checked if (!empty($profile->profile_id)) { but

function user_recurring_subscription_user_view($account, $view_mode, $langcode) {
  $profile = user_recurring_subscription_profile($account->uid);
  if (!empty($profile->profile_id)) {
  ....
  }
}

this function does not return object in every case as you have used return statement inside if condition. I think either you use isset instead of !empty in above function and also return some variable outside if statement in below function.

function user_recurring_subscription_profile($uid) {
  if (!empty($uid)) {
    $object = db_query('SELECT * FROM {recurring} WHERE uid=:uid', array(':uid' => $uid))->fetchObject();
    return $object ;
  }
}

6.You are using db_update function but still using UPDATE command that looks wired. Please fix it.

function user_recurring_subscription_user_delete($account) {
  $profile = user_recurring_subscription_profile($account->uid);
  if (!empty($profile->profile_id)) {
   if (user_recurring_subscription_profile_cancel($profile_id)) {
      db_update('UPDATE {recurring} SET status=:status WHERE profile_id=:profile_id', array(':status' => 2, ':profile_id' => $profile->profile_id));
    }
  }
} 

You must follow correct method to use this db_update(). It should be something like this:

if (user_recurring_subscription_profile_cancel($profile_id)) {
      db_update('recurring')
       ->fields(array(
    'status' => 2,
  ))
  ->condition('profile_id', $profile->profile_id)
  ->execute();
    }

Also user_recurring_subscription.test file is empty yet, I think you are planning to write some test cases for your module. This is good thing as your module little bit complex. Go ahead!

Thanks Again!

ratanphp’s picture

Status: Needs work » Needs review

@er.pushpinderrana: thank you so much for your valuable feed back. I fixed pointed issue instead of point 5.

Point 1: hook_help is now implemented
Point 2 : Add comments for each function.
Point 3 : I am using those functions in generic way so whenever I need complete information then I can call these function.
Point 4 : Implement check_plain
Point 5 : I use !empty because this function checks both condition whether variable is set or not and variable has assign some value or not.
Point 6 : Fixed

Once again thank you so much @er.pushpinderrana. Please review it again.

er.pushpinderrana’s picture

Looks Great Improvement!

Automated Review

Still number of notices are reported by http://pareview.sh/pareview/httpgitdrupalorgsandboxratanphp2304373git.
Coder Sniffer has found some issues with your code (please check the Drupal coding standards).

Manual Review

Individual user account
Yes: Follows the guidelines for individual user accounts.
No duplication
Yes: Does not cause module duplication and fragmentation.
Master Branch
Yes: Follows the guidelines for master branch.
Licensing
Yes: Follows the licensing requirements
3rd party code
Yes: Follows the guidelines for 3rd party code.
README.txt
Yes: Follows the guidelines for in-project documentation and the README.txt Template.
Code long/complex enough for review
Yes: Follows the guidelines for project length and complexity.
Secure code
Yes: Using check_plain and other recommended function required for safe output.
Coding style & Drupal API usage
Looks Good.

- You are using placeholder in all your custom queries that's quite good.
- Good use of inline comments.
- Readme.txt file contains small information, it would be good to extended it little bit more.

Currently there is no blocker from my end except automated reviews report. It would be good if you fix these on priority and let other reviewer reviews your code.

Personally I'll move this to RTBC once these issues get fixed!

Thanks again for contribution!

mpdonadio’s picture

Status: Needs review » Postponed (maintainer needs more info)

Module duplication and fragmentation is a huge problem on drupal.org and we prefer collaboration over competition. Can you outline how this is different than existing subscription modules, in particular ones that integrate with either Ubercart or Drupal Commerce?

ratanphp’s picture

Status: Postponed (maintainer needs more info) » Needs review

@mpdonadio, thanks for your review.

This module is different from ubercard and Drupal commerce. I have pointed out some feature that makes User recurring subscription module different from other modules.

1. ubercart provides recurring facility with PayPal Pro to create recurring payment via credit card. But PayPal close support for this PayPal Pro (WPP). I have given this feature in User Recurring subscription module that provides full management of recurring profile using PayFlow Pro. Currently this feature is not available in any of existing module and also this payment gateway is not available with existing module.

2. There is no feature available to manage coupons during the creation of recurring profile and also coupon-apply feature in-between the recurring profile. User recurring subscription provides all these features that are missing in existing modules.

3. User recurring subscription module provide one more feature i.e dynamic free trial. This feature encourage user to use trial period so no charges will be incurred in your paypal account.

4. User recurring subscription module provide one step subscription process on registration form.

5. User recurring subscription does not store any user sensitive information except profile id provided by PayFlow Pro.

6. Ubercart and Drupal commerce has no time window option for recurring profiles. So user roles are automatically expired on billing date and time.

I almost explained above all major feature of User recurring subscription module that makes this module unique and I am sure this module would be too useful once it get published.

Your feedback would be highly appreciated. I am trying to make this module too robust and flexible.

Thanks you for your valuable time.

mpdonadio’s picture

Assigned: Unassigned » mpdonadio

Assigning to myself for next review.

mpdonadio’s picture

Assigned: mpdonadio » Unassigned
Status: Needs review » Needs work
Issue tags: +PAreview: security

Automated Review

Review of the 7.x-1.x branch (commit e67cf42):

Lots of PAReview errors and warnings: http://pareview.sh/pareview/httpgitdrupalorgsandboxratanphp2304373git

Please go through these and see what are real and what are false, and also read https://www.drupal.org/coding-standards

Manual Review

Individual user account
Yes: Follows the guidelines for individual user accounts.
No duplication
Maybe: Does not cause module duplication and fragmentation. There are some corssover with UC and Commerce, but also differences
I would say no to duplication, but I want other admins to weigh in before final review.
Master Branch
Yes: Follows the guidelines for master branch.
Licensing
Yes: Follows the licensing requirements
3rd party code
No: Doesn't follows the guidelines for 3rd party code. Where did the logos come from? Those are all registerred trademarks. They need to go.
README.txt/README.md
No: Doesn't follow the guidelines for in-project documentation and the README Template.

There is no info on how to use or confgure this, or how it works.

Code long/complex enough for review
Yes: Follows the guidelines for project length and complexity.
Secure code
No. If "no", list security issues identified.

In user_recurring_subscription_menu(), The administration menu callback should probably use "administer site configuration" - which implies the user can change something - rather than "access administration pages" which is about viewing but not changing configurations. A separate permission would be good, too.

md5() should not be used for anything security related. You should use drupal_hmac_base64() instead. Can you just use drupal_get_token() instead?

Is there no other way to use the Payflow API other than storing the username and password in the database? The password would be in plain text this way.

In your template file, you should really do the plaining in a preprocess. You should use placeholders intead of string concatenation with t(). I can't totally trace this out, but I think fee, price, and interval unit(?) may be going straight to output from user input.
The t() will plain these for you.

Coding style & Drupal API usage
You should leverage classes namedspaced to your module instead of IDs for CSS. Yours are too generic and may have namespace clash.

(+) Your variables aren't namespaced to your module. What if someone want to make a spearate payflow module?

Do any of those configuration options need to be required? If so, use #required in the form.

Do you mean "vendor" instead of "vandor"?

In theme_user_recurring_subscription_card_cvv_help(), Drupal behaviors are generally preferred over onclicks. You may also want to look into ctools modals instead of a popup.

When making links in t(), it is best to just pass in the URL. See https://api.drupal.org/api/drupal/includes%21common.inc/function/l/7

(+) In user_recurring_subscription_permission, your permission is too vague, both the machine name and title. You should also add a description.

user_recurring_subscription_currency_array() needs a proper docblock.

What is user_recurring_subscription_load() doing? That is a node hook. See https://api.drupal.org/api/drupal/modules!node!node.api.php/function/hoo...

Your schemas should have indexes for the columns that reference foreign keys (uid, etc).

user_recurring_subscription_form_user_register_form_alter implements hook_form_FORM_ID_alter().

Using #attached is preferred over drupal_load_css().

You should use drupal_http_request() instead of curl(), and drupal_http_build_query() for building up the query string.

Use ip_address() instead of $_SERVER['REMOTE_ADDR'];

Use REQUEST_TIME instead of time().

Don't check_plain() in user_recurring_subscription_nvp_to_array(), you only plain for output. See https://www.drupal.org/node/28984

In user_recurring_subscription_user_view(), build up a render array instead of calling theme() directly.

In user_recurring_subscription_add_form(), #default_value already gets plained. See link above.

Why are you resetting the $form_state['values']['description'] in user_recurring_subscription_add_form_validate()?

user_recurring_subscription_cvv_info() is not a good idea. Either use inline help or a ctools modal.

user_recurring_subscription_card_form() is a form builder, not a hook_form.

What is the array_walk for in user_recurring_subscription_card_form_validate? You don't seem to be outputting any of that.

I also may be dense here, but I don't see how the role that the user is purchasing actually gets saved to their account, or removed when they cancel the subscription? There are no calls to user_save() anywhere.

The starred items (*) are fairly big issues and warrant going back to Needs Work. Items marked with a plus sign (+) are important and should be addressed before a stable project release. The rest of the comments in the code walkthrough are recommendations.

user_recurring_subscription_manage() should return a render array and not themed output.

I decided to not do a second visual pass through this like I typically do, as the above list is substantial enough.

If added, please don't remove the security tag, we keep that for statistics and to show examples of security problems.

This review uses the Project Application Review Template.

ratanphp’s picture

@mpdonadio
Thankyou for your review and valuable feedback!
I am done with all your suggested points, please review.

1. 3rd party code
Replace cvv icon with help mark (?).

2. README.txt/README.md
Add more details about this module.

3. Secure code
- In user_recurring_subscription_menu(), The administration menu callback should probably use "administer site configuration" - which implies the user can change something - rather than "access administration pages" which is about viewing but not changing configurations. A separate permission would be good, too. DONE

- md5() should not be used for anything security related. You should use drupal_hmac_base64() instead. Can you just use drupal_get_token() instead? DONE

- Is there no other way to use the Payflow API other than storing the username and password in the database? The password would be in plain text this way.
[We have to store in our database because while making call to create recurring profile with user deatils the PayFlow API needs username and password information.]

- In your template file, you should really do the plaining in a preprocess. You should use placeholders intead of string concatenation with t(). I can't totally trace this out, but I think fee, price, and interval unit(?) may be going straight to output from user input.The t() will plain these for you. DONE

4. Coding style & Drupal API usage
- You should leverage classes namedspaced to your module instead of IDs for CSS. Yours are too generic and may have namespace clash.(+) Your variables aren't namespaced to your module. What if someone want to make a spearate payflow module? DONE

- Do any of those configuration options need to be required? If so, use #required in the form. DONE.

- Do you mean "vendor" instead of "vandor"? DONE

- (+) In user_recurring_subscription_permission, your permission is too vague, both the machine name and title. You should also add a description. DONE

- user_recurring_subscription_currency_array() needs a proper docblock. DONE

- What is user_recurring_subscription_load() doing?
[This function is hook_load. Used in menu call %user_recurring_subscription.]

- Your schemas should have indexes for the columns that reference foreign keys (uid, etc). DONE

- Using #attached is preferred over drupal_load_css(). DONE

- You should use drupal_http_request() instead of curl(), and drupal_http_build_query() for building up the query string. DONE

- Use ip_address() instead of $_SERVER['REMOTE_ADDR'];. Use REQUEST_TIME instead of time(). DONE

- Don't check_plain() in user_recurring_subscription_nvp_to_array(), you only plain for output. DONE

- In user_recurring_subscription_add_form(), #default_value already gets plained. See link above. DONE

- user_recurring_subscription_cvv_info() is not a good idea. Either use inline help or a ctools modal. DONE

- user_recurring_subscription_card_form() is a form builder, not a hook_form. DONE

- What is the array_walk for in user_recurring_subscription_card_form_validate? You don't seem to be outputting any of that.
[Remove and add simple check_plain.]

- I also may be dense here, but I don't see how the role that the user is purchasing actually gets saved to their account, or removed when they cancel the subscription? There are no calls to user_save() anywhere.
[Adding hook_cron. Cron is resposnible to renew and expire subscription associted roles for users.]

- user_recurring_subscription_manage() should return a render array and not themed output. DONE

Thanks again!

ratanphp’s picture

Status: Needs work » Needs review
mpdonadio’s picture

Assigned: Unassigned » mpdonadio

Assigning to myself for next review.

mpdonadio’s picture

Status: Needs review » Needs work

Started review, but realized that the logos are still in the repo (the images/ subdirectory). Where did they come from? Those are all registered trademarks, so I think they need to go unless you can point to acceptable language that says they are usable.

I will continue with a review of a1d3c1b in the meantime. This is a decently length module, so it will take a little while.

ratanphp’s picture

Status: Needs work » Needs review

@mpdonadio
Thankyou for your review and valuable feedback!
I have done with removing of credit card logo images. Now this module is using another site url to show cvv help information.

Thanks Again!

mpdonadio’s picture

Assigned: mpdonadio » Unassigned
Status: Needs review » Needs work

Sorry for the delay, but with volunteer efforts, life/work gets in the way sometimes...

Automated Review

Git default branch is not set, see the documentation on setting a default branch.
Review of the 7.x-1.x branch (commit a1d3c1b):

  • DrupaSecure barfed, but it looks like Coder was clean.
  • No automated test cases were found, did you consider writing Simpletests or PHPUnit tests? This is not a requirement but encouraged for professional software development.

This automated report was generated with PAReview.sh, your friendly project application review script. You can also use the online version to check your project. You have to get a review bonus to get a review from me.

Manual Review

See previous review in #12 for non-code related points.

Menu permissions are better.

Token is better.

I am going to defer on the password thing for a second opionion, but I think this is OK if there is no option and the documentation
clearly states that the username and password is stored in the database.

Variable names look better.

(+) I still think your permission machine names could be better.

Blocking issues from #12 have been addressed.

Make form fields required instead of validating them to be not empty.

You should use form_set_value() instead of directly updating $form_state['values'] in user_recurring_subscription_add_form_validate(). It also doesn't seem like you really need to do this?

(*) You also don't need to filter_xss() there. You filter when you output. https://www.drupal.org/node/28984

(*) You don't need to check_plain() in user_recurring_subscription_form_validate(). These are not being output here.

(+) I don't see what you are updating form state in user_recurring_subscription_form_submit(). Can't you just use one submit handler?

(*) In user_recurring_subscription_recurring(), it looks like $subscription->title goes from user input to output directly. This is XSS prone.

ratanphp’s picture

Status: Needs work » Needs review

@mpdonadio
Thankyou for your review and valuable feedback!
I have done with following points:

(+) I still think your permission machine names could be better. DONE

Make form fields required instead of validating them to be not empty. DONE

You should use form_set_value() instead of directly updating $form_state['values'] in user_recurring_subscription_add_form_validate(). It also doesn't seem like you really need to do this? DONE

(*) You also don't need to filter_xss() there. You filter when you output. DONE

(*) You don't need to check_plain() in user_recurring_subscription_form_validate(). These are not being output here. DONE

(+) I don't see what you are updating form state in user_recurring_subscription_form_submit(). Can't you just use one submit handler?
In the registration process this module first create recurring profile and after sucess user_save function is executed. The second submit handler is called after user_save so that system get user id and associate it with recurring profile id and store in recurring table.

(*) In user_recurring_subscription_recurring(), it looks like $subscription->title goes from user input to output directly. This is XSS prone. DONE

Thanks again!

mpdonadio’s picture

Status: Needs review » Reviewed & tested by the community

Automated Review

Git default branch is not set, see the documentation on setting a default branch.

Review of the 7.x-1.x branch (commit 588fe0d):

>No automated test cases were found, did you consider writing Simpletests or PHPUnit tests? This is not a requirement but encouraged for professional software development.

This automated report was generated with PAReview.sh, your friendly project application review script. You can also use the online version to check your project. You have to get a review bonus to get a review from me.

Manual Review

My blocking issues from #19 have been addressed.

I am not seeing any additional blocking issues, so I am setting RTBC. It needs a second set of eyes from a review admin, though, before approval.

mpdonadio’s picture

Status: Reviewed & tested by the community » Fixed

OK, 13 days w/o further comments. No committed changes since my review in #20, so...

Thanks for your contribution, ratanphp!

I updated your account so you can promote this to a full project and also create new projects as either a sandbox or a "full" project.

Here are some recommended readings to help with excellent maintainership:

You can find lots more contributors chatting on IRC in #drupal-contribute. So, come hang out and stay involved!

Thanks, also, for your patience with the review process. Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.

Thanks to the dedicated reviewer(s) as well.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.